Every connection failure ends with the same line,
Error connecting to the MCP server: and the target. The line that names the cause is above it.
Some failures also print a Python traceback from the HTTP library; its last
line carries the underlying error, such as certificate is expired.
The sections are ordered by how often each outcome appeared when mcpscore
audited the 13,695 remote endpoints listed in the official MCP registry in
August 2026: authentication 24.6%, unreachable 9.5%, payment required 3.0%,
not MCP 2.2%, no completed handshake 1.1%, rate limited 0.8%.
The server requires authentication
Symptom:401 or 403 without credentials. This is
not an error. mcpscore scores what it can observe without a session: TLS,
the WWW-Authenticate challenge and the OAuth discovery metadata.
Fix: pass a credential to audit behind the gate:
--fail-under, with exit code 3, because a
score from ten checks cannot demonstrate a threshold:
The server rejected your credentials
Symptom:--token, --header or $MCPSCORE_TOKEN, and the
server still answered 401 or 403.
Fix: check that the token is current and has the scopes the server
requires. --token sends it as Authorization: Bearer; a server that
expects another header needs --header 'X-Api-Key: ...' instead.
The server is unreachable
Symptom:nodename nor servname provided, or not known for DNS, All connection attempts failed for a closed port, and
certificate is expired or certificate is not trusted for TLS. Add -v to
see the full traceback.
Fix: check the URL from the same machine with
curl -sS -o /dev/null -w '%{http_code}\n' https://your-server.example/mcp.
If curl fails the same way, the problem is the network or the certificate,
not mcpscore. A certificate error is a real finding: MCP clients refuse that
server too.
The server answered with an HTTP error
Symptom:401 or 403. The common ones:
To see what the server says to a
POST, send it the request that opens
a session. Servers on 2025-11-25 and earlier start with initialize:
protocolVersion and serverInfo
(Lifecycle §Initialization).
A modern-only 2026-07-28 server has no initialize and may reject it. Ask
it with server/discover, which every modern server implements:
supportedVersions and its
capabilities
(Lifecycle §Protocol Version Negotiation).
If both requests fail, the endpoint is not an MCP server.
The endpoint is not an MCP server
Symptom:Expected response with content type 'text/event-stream', got 'text/html'.
Cause: the URL answered, but not with MCP. It is usually a website, a
REST API or a proxy’s error page on the right host but the wrong path.
Fix: find the MCP endpoint path in the server’s docs and audit that
URL. The curl request in the previous section shows what the URL returns.
The server redirected
Symptom:http:// to https://, or to another host, is not followed.
Fix: audit the URL the message names. If that URL is http:// while
yours was https://, the server sits behind a TLS-terminating proxy it does
not trust; the message suggests the https:// form to try.
The handshake timed out
Symptom:Connection timeout for server: when the TCP connection never opened.
Cause: the server accepted the connection and did not complete the MCP
handshake within 30 seconds, or the host dropped the connection attempt.
Cold-starting serverless hosts and servers that do slow work in their
startup code hit this.
Fix: re-run once the server is warm. If it times out every time, move
slow startup work out of the initialize path.
A local server does not start
These come from--stdio and from a .py or .js target, which mcpscore
launches itself.
Symptom: Command not found: 'my-server'. Please ensure it is installed and on PATH.
Cause: the first word after --stdio is not an executable on PATH,
and not an existing file.
Fix: use the full path, such as --stdio ./bin/my-server, or install the
command.
Symptom: 'server.py' is a script, not an executable command. Launch it with its interpreter: --stdio python server.py
Cause: --stdio runs a command, and a script without a shebang and the
executable bit is not one.
Fix: run the command the message prints. For a Python script it also
prints the uv run form to use inside a uv project.
Symptom: Permission denied launching './server'. Make it executable (chmod +x) or launch it with its interpreter
Cause: the file exists but is not executable.
Fix: chmod +x ./server, or put its interpreter first.
Symptom: Server script not found: ./server.py
Cause: the .py or .js target path does not exist.
Fix: check the path relative to the directory you run mcpscore from.
Symptom:
server stderr: prefix.
Fix: read the server stderr: lines. They usually name a missing file,
a missing dependency or a missing environment variable. Pass variables with
--env NAME.
The command line was rejected
Symptom: the usage summary, then a line starting withUsage error:,
exit code 1. For example:
--stdio takes the rest of the command
line, so every mcpscore option must come before it. All flags are listed in
the CLI reference.
A gate failed
Symptom: the audit completes, thenGate failed — and exit code 3:
--fail-under; or
the readiness percentage is below --fail-under-readiness; or a rule at or
above a [gate] fail_on severity failed.
Fix: the failed rules are the ❌ lines above the score, each with a
Fix: line. Improve your score covers the rules most
servers fail. To change what the gate counts, see
Configure rules.
A failed --smoke check exits 4 with Gate failed — --smoke: 2 smoke check(s) failed. Smoke mode explains each check.
What’s next
- Audit a server behind auth for
--token,--headerand--oauth. - Improve your score once the audit runs.
- CLI reference for every flag.