Your remote MCP server is "connected" and still returns 401 A developer explains that remote MCP servers can report as "connected" while still returning 401 on tool calls, because discovery methods like initialize and tools/list are deliberately open while tools/call requires a credential. The writeup provides a three-step curl diagnostic that separates connectivity from authorization, warning that tools/list returns 200 regardless of the credential supplied and therefore cannot serve as an auth check. There is a specific kind of bug report that shows up in every remote MCP rollout, and it always sounds the same: I added the server. It shows as connected. It lists tools. Then the first real call fails with 401. Nothing is broken. The server is fine, the client is fine, and the credential is fine. What is wrong is the mental model — the one most of us carried over from local stdio servers, where "connected" meant "ready." For a remote MCP server, reachability and authorization are two different things , and the first one does not imply the second. Discovery is deliberately open. Execution is not. A hosted MCP endpoint usually exposes the discovery half of the protocol without any credential at all, because that is what directory crawlers, liveness probes and humans-with-a-browser need: | What the client does | Credential needed | Typical result without one | |---|---|---| | initialize | no | 200 | | tools/list | no | 200 + the tool list | | tools/call | yes | 401 with WWW-Authenticate | That asymmetry is what makes the failure feel like a client bug. The client's "connected" indicator is driven by initialize and tools/list , both of which succeed with no credential at all. The lights are green, and the thing still cannot do any work. So the first diagnostic question is never "is it connected?" It is: "which half of the protocol is failing?" If listing works and calling 401s, you are missing a credential, not a connection. The symmetric mistake is to conclude the token is expired and go re-issue a pass. Before you do that, check two things, because both produce an identical-looking 401: Bearer