If your MCP server uses OAuth, every directory thinks it has zero tools A developer discovered that remote MCP servers protected by OAuth appear to have zero tools in directories like Glama, Smithery, and mcp.directory, because directory crawlers cannot authenticate and receive an empty tool list. The developer's fix is to make handshake methods such as tools/list public while keeping privileged operations behind auth, and they urge the MCP ecosystem to adopt this pattern to prevent servers from being invisible. We shipped a remote MCP server, registered it everywhere, and then noticed something odd: every directory listed it as having no tools at all . Not the wrong tools. Not a stale count. Zero. glama's API returned this: { "name": "FrameThrower MCP Server", "attributes": "author:official", "hosting:remote-capable" , "tools": } Smithery's page rendered the same nothing. So did mcp.directory. Four working tools, and every discovery surface in the ecosystem said the server did nothing. If you run a remote MCP server behind OAuth 2.1, this is almost certainly happening to you too, and nothing in your logs will tell you. An MCP client discovers what a server can do by calling tools/list . That's a normal JSON-RPC method, and if you wrapped your handler in auth — which the docs and every example encourage — then tools/list is behind auth along with everything else. Our handler looked like this: js const authed = withMcpAuth auth, req, session = { const userId = session?.userId ?? session?.user?.id if userId return new Response 'Unauthorized', { status: 401 } return callerStore.run { userId }, = handler req } export { authed as GET, authed as POST, authed as DELETE } Correct, and completely sensible. Every tool call spends credits, so every tool call needs a user. But a directory crawler has no account. It performs the handshake, gets a 401, and records what it can see — which is a name, a URL, and an empty capability list. It cannot tell the difference between "this server requires auth" and "this server does nothing". The most telling part was Smithery's scanner log: scan Discovering server metadata... scan Server metadata discovered OAuth required . scan Connecting to MCP server... scan Authentication required. Please authorize at: https://connect.smithery.ai/... It stopped dead. Only after a human clicked through an interactive OAuth authorization did it get: scan Capabilities found: 4 tools. Its scanner found all four — but that result came from a one-off human authorization, and it isn't what the public page renders. So the listing still told visitors the server had no capabilities. MCP directories are the discovery layer. Someone browsing for a server reads the tool list to decide whether to install it. A listing with no tools isn't a weak listing, it's a dead one — and every directory that mirrors another directory copies the emptiness forward. You can register on every registry that exists and still be invisible. Describing what a server offers is not a privileged operation. Calling those tools is. So split them: / The handshake methods a directory crawler needs to read our tool list. Describing what a server offers is not privileged; everything that spends credits or touches user data stays behind the token. / const PUBLIC METHODS = new Set 'initialize', 'notifications/initialized', 'ping', 'tools/list', async function isPublicHandshake req: Request : Promise