Skip to content

Inconsistent resource_metadata handling between C# and TypeScript MCP SDKs #860

@shays10

Description

@shays10

Hi team,

I ran into an inconsistency that I believe is worth discussing, unless I am missing something on my side.

Bug Description
According to MCP Spec:

MCP servers MUST implement OAuth 2.0 Protected Resource Metadata (RFC9728)

According to RFC 9728:

This specification introduces a new parameter in the WWW-Authenticate HTTP response header field to indicate the protected resource metadata URL:
resource_metadata:
The URL of the protected resource metadata.

In the csharp-sdk, resource_metadata is mandatory

if (resourceMetadataUrl == null)
{
    throw new McpException("The WWW-Authenticate header does not contain a resource_metadata parameter");
}

It also serves as the source of truth for the .well-known URL of the MCP server.


In the typescript-sdk, the behavior differs significantly.

resource_metadata is optional

const wwwAuthValue = resourceMetadataUrl
  ? `Bearer error="${error.errorCode}", error_description="${error.message}", resource_metadata="${resourceMetadataUrl}"`
  : `Bearer error="${error.errorCode}", error_description="${error.message}"`;

If resource_metadata is missing, the SDK attempts multiple fallback methods to determine the .well-known URL

if (opts?.metadataUrl) {
  url = new URL(opts.metadataUrl);
} else {
  // Try path-aware discovery first
  const wellKnownPath = buildWellKnownPath(wellKnownType, issuer.pathname);
  url = new URL(wellKnownPath, opts?.metadataServerUrl ?? issuer);
  url.search = issuer.search;
}

When resource_metadata is present, it is used as the .well-known URL.
However, many MCP hosts miss this detail during SDK integration, which causes broken code exchange flows. For example, see Inspector issue #576. Cursor also omits this parameter.

Now that path-aware .well-known behavior has been introduced, I find this even more confusing 🙂
What is the correct approach? Should an MCP server developer include the resource_metadata parameter, or is it acceptable to omit it if one of the path-aware .well-known fallbacks already resolves to the correct URL? (Which will result in broken OAuth flow for csharp-sdk..)

I apologize if this issue is not in the correct repo..I wasn’t entirely sure whether it should be filed under typescript-sdk or csharp-sdk. I opened it here because, if I am interpreting the RFC correctly, the csharp-sdk appears to implement it more strictly, as the resource_metadata URL does not seem to be optional.

Thanks!

To Reproduce
MCP server that do not send resource_metadata in the WWW-Authenticate header. Works for MCP Inspector, Cursor. Broken for VSCode.

Expected behavior
Should produce similar behavior across all SDKs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions