Skip to content

fix: accept null introspection_endpoint in OAuthMetadataSchema#1923

Open
billyriaz wants to merge 1 commit intomodelcontextprotocol:mainfrom
billyriaz:fix/introspection-endpoint-null
Open

fix: accept null introspection_endpoint in OAuthMetadataSchema#1923
billyriaz wants to merge 1 commit intomodelcontextprotocol:mainfrom
billyriaz:fix/introspection-endpoint-null

Conversation

@billyriaz
Copy link
Copy Markdown

Problem

Some OAuth authorization servers return introspection_endpoint: null in their /.well-known/oauth-authorization-server metadata rather than omitting the field entirely. This is valid per RFC 7662 — the field is optional and null should be treated the same as absent.

The current schema uses z.string().optional() which accepts undefined but rejects null, causing OAuth flow initiation to fail with:

Invalid input: expected string, received null
  path: ["introspection_endpoint"]

Fix

Change z.string().optional() to z.string().nullish() for introspection_endpoint. This accepts string | null | undefined, correctly handling servers that explicitly set the field to null.

Reproduction

Connect any MCP client to an OAuth server whose /.well-known/oauth-authorization-server returns "introspection_endpoint": null. The OAuth flow fails immediately at metadata validation before the authorization redirect is attempted.

Example metadata that triggers the bug:

{
  "issuer": "https://example.com",
  "authorization_endpoint": "https://example.com/oauth/authorize",
  "token_endpoint": "https://example.com/oauth/token",
  "introspection_endpoint": null,
  "registration_endpoint": "https://example.com/oauth/register"
}

Some OAuth authorization servers (e.g. Dotdigital's MCP server) return
introspection_endpoint: null in their .well-known/oauth-authorization-server
metadata rather than omitting the field entirely.

The current schema uses z.string().optional() which accepts undefined but
rejects null, causing OAuth flow initiation to fail with:
  "Invalid input: expected string, received null"

Changing to z.string().nullish() accepts both undefined and null, which
aligns with RFC 7662 where introspection_endpoint is optional and a server
returning null should be treated the same as not including it.
@billyriaz billyriaz requested a review from a team as a code owner April 17, 2026 12:04
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 17, 2026

⚠️ No Changeset found

Latest commit: 9f3448f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 17, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@1923

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@1923

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@1923

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@1923

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@1923

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@1923

commit: 9f3448f

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant