[BUG] Claude Code marks an anonymous MCP server authenticated when it lists a tool
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
In Claude Code's /mcp detail view, an anonymous HTTP MCP server was labeled Auth: not authenticated when it listed zero tools and Auth: authenticated when it listed one tool. The server has no OAuth metadata or authentication endpoint, and no authentication action occurred. Returning to zero tools restored Auth: not authenticated.
This was reproduced in one Claude profile with fresh CLI processes. The observation shows that a nonempty tool list is sufficient to produce the authenticated label in that profile; it does not establish every condition that may affect the label.
What Should Happen?
The /mcp Auth label should reflect whether the server was authenticated. A tool list returned without authentication should not make the label say authenticated.
Error Messages/Logs
No error was shown. The unexpected result is the `/mcp` detail row: `Auth: authenticated` for the one-tool run.
Steps to Reproduce
- Save the following server as
fake-mcp.mjsand the JSON block asmcp-config.jsonin the same directory.
{"mcpServers":{"anonymous-label-test":{"type":"http","url":"http://127.0.0.1:18765/mcp"}}}
import { createServer } from 'node:http'
const count = Number(process.argv[2] ?? 0)
if (![0, 1].includes(count)) throw new Error('tool count must be 0 or 1')
const port = 18765
const tool = { name: 'example', description: 'Return a fixed test value', inputSchema: { type: 'object', properties: {} } }
createServer(async (req, res) => {
if (req.url !== '/mcp') { res.writeHead(404).end(); return }
if (req.method !== 'POST') { res.writeHead(405, { Allow: 'POST' }).end(); return }
let body = ''
for await (const chunk of req) body += chunk
let message
try { message = JSON.parse(body) } catch { res.writeHead(400).end(); return }
const { id, method } = message
if (id == null) { res.writeHead(202).end(); return }
let result
if (method === 'initialize') {
result = { protocolVersion: '2025-06-18', capabilities: { tools: { listChanged: false } }, serverInfo: { name: 'anonymous-label-test', version: '1.0.0' } }
} else if (method === 'tools/list') {
result = { tools: count ? [tool] : [] }
} else if (method === 'tools/call') {
result = { content: [{ type: 'text', text: 'example' }] }
} else if (method === 'ping') {
result = {}
} else {
res.writeHead(200, { 'Content-Type': 'application/json' }).end(JSON.stringify({ jsonrpc: '2.0', id, error: { code: -32601, message: 'Method not found' } }))
return
}
res.writeHead(200, { 'Content-Type': 'application/json' }).end(JSON.stringify({ jsonrpc: '2.0', id, result }))
}).listen(port, '127.0.0.1', () => console.log(`fake MCP listening on 127.0.0.1:${port}; tools=${count}`))
- Start the server with
node fake-mcp.mjs 0. - In another terminal, run
claude --strict-mcp-config --mcp-config ./mcp-config.json, open/mcp, and selectanonymous-label-test. - Record the Auth row, then exit Claude Code and stop the server.
- Start the same server with
node fake-mcp.mjs 1. Run the same Claude command in a fresh process with the same config and profile, then inspect the Auth row again. - Exit Claude Code, stop the server, and repeat with
node fake-mcp.mjs 0.
Observed in Claude Code 2.1.286:
| tools/list response | /mcp status | /mcp Auth row |
|---|---|---|
| 0 tools | connected, no tools | not authenticated |
| 1 tool | connected, 1 tool | authenticated |
| 0 tools, repeated after the 1-tool run | connected, no tools | not authenticated |
The server response's tool count is the only changed variable. It has no OAuth metadata, login, token endpoint, or authentication action.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.286
Platform
Other
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
This report covers the /mcp Auth label only. It does not claim that account/session-token effects were tested.
Related reports describe different status mismatches: #96738 shows Auth: ✔ while the MCP status is failed after OAuth; #17152 reports not authenticated for an HTTP server using a bearer-token header; #26917 concerns surfacing a sign-in requirement when tool discovery is unauthorized. This reproduction uses no OAuth and changes only the anonymous tool count.