Skip to content

Incorrect call for resource_metadata_url #663

Closed as not planned
Closed as not planned

Description

@ocasta

Describe the bug
After a failed initial request MCP Inspector doesn't request the metadata from the supplied resource_metadata_url.

To Reproduce

  1. I have a development MCP server, HTTP Streamable configured at mydummymcp.com/mcp
  2. The initial request fails with a 401 as expected. We return a response header:

WWW-Authenticate: Bearer realm="mcp-server"

and a response body:

{
    "error": {
        "code": "AUTHENTICATION_REQUIRED",
        "message": "Authentication required to access this MCP server"
    },
    "auth": {
        "type": "oidc",
        "client_id": "XXXXYYYYZZZ",
        "resource_metadata_url": "https://mydummymcp.com/.well-known/oauth-protected-resource/",
        "scope": "openid basic"
    }
}

The next request from MCP Inspector is to https://mydummymcp.com/.well-known/oauth-protected-resource/mcp
After several failed requests (CORS requests returning 400) it tries https://mydummymcp.com/.well-known/oauth-protected-resource. We return a 301 to the because of the missing / which also leads to a CORS failure

Expected behavior
After the 401 I would expect a request to "https://mydummymcp.com/.well-known/oauth-protected-resource/"

Activity

  1. ocasta commented on Jul 31, 2025

    @ocasta
    Author

    Not sure if this behaviour is actually supported yet. MCP Authorisation workflows seem in a state of flux

    However if I change the WWW-Authenticate header to return Bearer realm="mcp-server" resource_metadata= "https://mydummymcp/.well-known/oauth-protected-resource/" it still fails in the same way with the next request being for https://mydummymcp/.well-known/oauth-protected-resource/mcp

  2. added
    authIssues and PRs related to authorization
    on Aug 3, 2025
  3. pksorensen commented on Aug 4, 2025

    @pksorensen

    linked: #675

  4. pksorensen commented on Aug 4, 2025

    @pksorensen

    @ocasta your experience the same as i, when mcp is running on "/mcp" it append mcp for some reason, not intended according to spec.

    and step 3 of https://modelcontextprotocol.io/specification/draft/basic/authorization#server-metadata-discovery where it should go when the others dont work is never happening.

  5. jkhaui commented on Aug 7, 2025

    @jkhaui

    Also experiencing the same RFC 9728 non-compliance with a subdomain-based architecture (splitting MCP & auth servers by subdomain instead of route), e.g.

    • MCP Server: mcp.my-app.com
    • Auth Server: auth.my-app.com

    Expected behaviour (per RFC 9728):

    1. GET https://mcp.my-app.com -> return 401 with WWW-Authenticate: Bearer resource_metadata="https://auth.my-app.com/.well-known/oauth-protected-resource"
    2. Inspector should fetch metadata from https://auth.my-app.com/.well-known/oauth-protected-resource and proceed with OAuth flow after discovering auth server

    Actual behaviour:

    1. Inspector completely ignores the resource_metadata pointing to the auth subdomain well-known endpoint
    2. Instead, inspector makes OPTIONS + GET requests to https://mcp.my-app.com/.well-known/oauth-protected-resource (note the subdomain - the well-known path is correct, but the subdomain SHOULD be auth.my-app.com, NOT mcp.my-app.com)

    My auth & mcp handlers are actually in the same place despite being on different subdomains, so for now I just add this hack which seems to "fix" the flow using the inspector. After it reads the well-known metadata, the oauth redirect flow kicks in.

    // MCP subdomain - handles MCP protocol at root path
    if (hostname === "mcp.my-app.com") {
    	// HACK for MCP non-compliant inspector
    	if (url.pathname === "/.well-known/oauth-protected-resource") {
    		return new Response(JSON.stringify({
    			resource: "https://mcp.my-app.com",
    			authorization_servers: ["https://auth.my-app.com"]
    		}), {
    			headers: {
    				'Content-Type': 'application/json',
    				'Access-Control-Allow-Origin': '*'
    			}
    		});
    	}
    }
    

    As an aside, recently I also had issues getting a custom remote server working with claude.ai. Here, I used /v1/mcp as my canonical URL instead of a subdomain.

    If Claude got "lost" after the initial expected 401, it would then - seemingly randomly - attempt to find endpoints itself by appending /v1/mcp to everything, e.g. my-app.com/.well-known/.../v1/mcp. Those paths clearly don't exist so it was very bizarre. Perhaps there's some logic embedded deep in the SDK to try various endpoint discovery heuristics in case of a 404.

    Anyway, just sharing my 2 cents. I don't think I really know what I'm doing or talking about after this ordeal so take it all with a grain of salt.

  6. olaservo commented on Aug 23, 2025

    @olaservo
    Member

    Hi, wanted to check if this was still reproducible in the latest version? There were several updates related to auth recently so trying to nail down which of these should still be open. Thanks!

  7. halllo commented on Sep 18, 2025

    @halllo

    @olaservo Still problematic.

    Seems related to #576.

    Like @ptc-ccrabb mentioned, the RFC9728 is pretty clear that the first request made should be to the resource itself, which will explain how it is protected. Then it should acquire the protected resource metadata based on the URI from the WWW-Authenticate. This makes so much more sense then having a set of hardcoded rules and trying out different URI permutations.

  8. g-farrow commented on Nov 6, 2025

    @g-farrow

    I am also seeing this behaviour. FWIW I also saw this behaviour in VSCode. It seems you have to design the mcp server distribution to expect this to be ignored at the moment.

  9. cliffhall commented on Aug 1, 2026

    @cliffhall
    Member

    Closing: v1 is deprecated.

    Thank you for reporting this, and apologies for the long wait for a response.

    v1 will receive security fixes only — this issue describes a functionality, compatibility, or usability problem rather than a vulnerability, so it is being closed against v1. This is not a judgment on whether the problem is real — it's a consequence of the v1 line being frozen. This is happening as part of #1872.

    If this still happens in v2, we'd genuinely like to know. v2 is a complete rewrite — three clients over a shared core — so many v1 behaviours no longer exist in the same form. Please open a fresh issue against v2 with steps to reproduce, and we'll look at it. Note that we accept external contributions as issues rather than pull requests; maintainers handle design and implementation through a prompt-driven workflow. See CONTRIBUTING.md.

    Thanks for taking the time to report it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    authIssues and PRs related to authorizationbugSomething isn't workingclosed-v1-deprecatedClosed: v1 is deprecated and accepting security fixes onlyv1

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions