[BUG] claude mcp list reports "✔ Connected" for unauthorized stateless claude.ai connectors

Status Open
Reported on v2.1.222
Maintainer reply None cached
Activity 0 comments · opened Aug 5, 2026

Summary

claude mcp list prints ✔ Connected for a claude.ai connector with stateless: true even when the server-side state for that account is eligible: false, eligibility_reason: "disconnected". The label reports reachability, not authorization, so a user auditing which connectors can reach their data is told a connector is connected when the account holds no grant and the connector exposes no callable tool.

Claude Code 2.1.222, macOS (darwin 25.5.0), claude.ai auth (Team seat).

Cause

The status function returns Connected on any successful tools/list:

if (r.type === "connected") {
  if (r.capabilities.tools) {
    try { await hyd(r, {timeout: 5000}) }              // tools/list
    catch (n) { if (isListAuthError(n)) return {status: "! Needs authentication"} }
  }
  return {status: `${Ue.tick} Connected`}
} else if (r.type === "needs-auth") return {status: "! Needs authentication"}

A stateless connector answers tools/list without any authorization, so this branch is reached for connectors the account is not connected to. The eligible and eligibility_reason fields already fetched from /v1/mcp_servers are carried into the config as eligible / ineligibleReason but do not participate in the displayed status.

Reproduction

Any stateless: true claude.ai connector whose account state is disconnected reproduces it. The Google-hosted connectors are stateless and their endpoints are publicly readable, so the handshake can be confirmed with no credentials at all:

$ curl -s -o /dev/null -w '%{http_code}\n' -X POST https://gmailmcp.googleapis.com/mcp/v1 \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json, text/event-stream' \
    -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}'
200

tools/list likewise returns 200 with the full tool array unauthenticated. For contrast, a stateful connector (https://mcp.linear.app/mcp) returns 401 on initialize.

Meanwhile /v1/mcp_servers reports, for the same Gmail connector:

Gmail            stateless=True   eligible=False  reason=disconnected      tools=0

and claude mcp list reports:

claude.ai Gmail: https://gmailmcp.googleapis.com/mcp/v1 - ✔ Connected

Expected vs actual

Expected: a connector the account is not connected to is not labelled Connected.

Actual: it is labelled ✔ Connected, and /customize/connectors simultaneously shows nothing connected, so the CLI and the web UI disagree about the same account state.

Impact

This is a security-hygiene reporting problem rather than an access problem. Nothing is actually exposed, since the connector holds no grant and lists no tools for the account. But claude mcp list is the natural command for answering "what can reach my data", and its answer here is wrong in the direction that causes unnecessary alarm and wasted investigation. Confirming that the reported connection did not exist required reading the compiled bundle and querying /v1/mcp_servers directly.

Suggested fix

Either surface eligible / eligibility_reason in the status for claude.ai connectors, or separate the two facts in the label, for example reachable, not authorized versus Connected. A stateless connector that answers tools/list to strangers should not be reported the same way as an authorized one.

Non-issues

To be clear about what is not being reported: stateless: true is not itself a defect, and the Google MCP endpoints serving tool descriptors publicly is their design rather than a leak. The defect is only that reachability is presented as connection state.

View original on GitHub ↗