What a 401 Means to an MCP Client A developer explains why MCP clients reject key-protected servers with 401 errors: spec-compliant clients treat a 401 as a signal to begin OAuth, fetching Protected Resource Metadata and performing dynamic client registration rather than accepting a pasted API key. The fix is to enable Microsoft Entra ID authentication on Azure Functions MCP servers, which disables key-based access and advertises Protected Resource Metadata so clients can discover the authorization server. Twice in this series, a client refused to connect to a working MCP server, and both refusals looked like bugs until they turned out to be the specification doing its job. The first was in MCP vs API Is the Wrong Question https://dev.to/steefjan wiggers 34a415b/mcp-vs-api-is-the-wrong-question-392f . The Functions-hosted MCP server was protected by its mcp extension system key, and Claude Code, VS Code, and MCP Inspector all connected happily with the key in an x-functions-key header. Then I tried adding the same server as a connector in the Claude desktop app, and it failed with "Couldn't register with the sign-in service." The second was in the APIM setup in the repo https://github.com/steefjan1/mcp-vs-api-azure-functions/tree/main/infra/apim : MCP Inspector, pointed at the gateway without its subscription key attached, reported "Dynamic Client Registration rejected HTTP 404 ." Different clients, different servers, the same wall. This post explains what that wall is and how to take it down properly with Microsoft Entra ID. To a developer, a 401 means "add credentials and retry." To a client that implements the MCP authorization specification https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization , a 401 means something more specific: start OAuth. The client fetches the server's Protected Resource Metadata to learn which authorization server protects it, registers itself with that authorization server dynamic client registration , and walks the user through a sign-in and consent flow. No step in that sequence involves asking a human to paste a key into a header field. That is why both failures happened. My key-protected servers returned 401 without any Protected Resource Metadata behind them, the clients went looking for an OAuth story that did not exist, and the attempt died at registration with a 404. The clients were not broken. They were refusing to work around a server that spoke half a protocol. Which splits the MCP client world cleanly in two. Developer tools like Claude Code, VS Code, and MCP Inspector let you attach arbitrary headers, so a shared key works, the way it always has for developers who read documentation. End-user clients like the Claude desktop app deliberately offer no header escape hatch: the spec flow is the only flow. Keys are for tools; OAuth is for people. The Functions MCP extension supports built-in authentication with Entra ID as the identity provider, and the setup has become almost anticlimactic. In the Azure portal, the function app now has an AI preview tab with an Authentication section and a "Turn on MCP authentication" button. Give the Entra app registration a name, save, and it creates the registration, wires up App Service authentication, adds the required settings, and disables key-based access to the MCP endpoint in one step. The manual route shows what that button actually does, and it is worth seeing once. Key access is turned off by setting the webhook authorization level to anonymous, because the platform's authentication layer now stands in front of it: az functionapp config appsettings set --name