If a hosted MCP endpoint returns 401 to an unauthenticated POST, catalogues that check
the URL they list will record the server as down. It does not matter that the server is healthy and
that a real client with a token works perfectly. The prober never gets a token.
That is what happened here. Four connectors were published with a red dot and the title
"Server is not responding", and a second directory's remote-server entry could not be filed at
all, because POST https://mcp.zovo.one/mcp/<name> answered:
HTTP 401
www-authenticate: Bearer realm="mcp.zovo.one", error="invalid_token"
{"error":"unauthorized","message":"This endpoint needs a token..."}
The endpoints were up the whole time. They simply refused to say so.
Split the JSON-RPC methods into the ones that cannot touch a user's data and the ones that can. Answer the first group with no credential. Keep the second group behind auth.
| Method | Needs a token? | Why |
|---|---|---|
initialize | No | Negotiates protocol version and capabilities. Reads nothing. |
notifications/initialized | No | An acknowledgement with no payload. |
tools/list | No | Returns schemas that are already public in your registry manifest. |
prompts/list, resources/list, resources/templates/list | No | Declarations, not content. |
ping | No | Liveness. |
tools/call | Yes | Runs code against a tenant's stored data. |
resources/read | Yes | Returns content, which is the thing you are protecting. |
Measured against the live endpoint on 2026-09-09, with no Authorization header and no
token in the path:
POST /mcp/invoice {"method":"initialize"} -> 200 serverInfo mcp-invoice 0.21.0
POST /mcp/invoice {"method":"tools/list"} -> 200 13 tools
POST /mcp/invoice {"method":"resources/list"} -> 200 resource declarations
POST /mcp/invoice {"method":"ping"} -> 200 {}
POST /mcp/invoice {"method":"tools/call"} -> 401 unauthorized
Authorization: Bearer <wrong token>, tools/list -> 401 unknown_token
The last line is the one that keeps this honest. A credential that is present but wrong is still rejected. The unauthenticated path is only reachable when no credential was offered at all, so a bad token is never quietly downgraded to anonymous discovery.
Three properties make the open half safe, and each is checkable rather than asserted.
server.json
manifest in the official registry and on the product pages of this site.An independent measurement filed on the registry's issue tracker as modelcontextprotocol/registry#1626 on 2026-09-07 probed every listed entry that declares a network endpoint. Of 16,305 endpoints:
Outcome of a bare initialize then tools/list | Count | Share |
|---|---|---|
Answered tools/list unauthenticated | 9,532 | 58.5% |
| Required authentication | 4,135 | 25.4% |
| Answered HTTP but not MCP | 1,401 | 8.6% |
| Unreachable | 1,043 | 6.4% |
| Timed out | 103 | 0.6% |
| Returned a JSON-RPC error | 91 | 0.6% |
So a quarter of listed remote servers refuse the handshake a prober sends, and the majority answer it. If you are in the quarter, a directory has no way to tell you apart from the 6.4 percent that are genuinely gone.
Glama's published methodology, section 2.2, read 2026-09-09, describes its connector introspection as "tools/list, resources/list, prompts/list, and full schema capture", run on a continuous schedule rather than once at ingest. That is the same list as the table above, which is not a coincidence: those are the methods that describe a server rather than use it.
After the change here, the same connector listing carried zero occurrences of "not responding" and every health dot was green, with 25 connectors scored instead of 4.
Some servers genuinely cannot. A gateway that resolves a tenant before it can enumerate tools has nothing truthful to say to an anonymous caller. Two options remain. Publish a stdio package or a bundle alongside the remote entry, so a catalogue that cannot reach the URL can still list the installable form. Or serve a fixed, tenant-independent tool list to unauthenticated callers and let the real list arrive after auth, which is honest as long as the anonymous list is a subset.
Sources: the live endpoint at mcp.zovo.one, probed 2026-09-09 with the exact requests
shown; the method split and rate limit read from remote/src/index.ts in this repository;
registry issue 1626 for the population figures; glama.ai/mcp/methodology section 2.2 for the
introspection exchange. This project runs a hosted MCP endpoint for every server it
publishes and hit this defect on all of them.
Only the tool schemas, and those are already public if you are listed anywhere: the registry manifest, your documentation and any directory entry all carry them. What must stay closed is tools/call and resources/read, because those touch stored data rather than describing it.
The specification's authorization flow expects a 401 with a WWW-Authenticate header pointing at the resource metadata, and a client that understands OAuth will follow it. A directory health prober usually does not. If you need OAuth, publish an installable package too, so a catalogue has something it can verify.
Per-IP is the right key because there is no identity to use. 120 an hour was chosen here as more than any prober needs and less than a usable free tier. The list is served from module scope with no storage read, so the cost of a request on this path is small.
Send one POST with Content-Type application/json, Accept including both application/json and text/event-stream, and a body of {"jsonrpc":"2.0","id":1,"method":"tools/list"}. No Authorization header. If you get anything other than 200 with a tools array, a directory sees your server as broken.
No, and that was the trap here. GET returned 200 with a description page while POST returned 401, so a shallow check passed and the real handshake failed. Probe with the method a client would actually send.
All MCP servers and prices · All guides · Buy the bundle $39