Skip to content

fix(routes): pass every plugin route through transformRouteSchema - #300

Open
mcollina wants to merge 1 commit into
mainfrom
fix/72-openapi-hide-routes
Open

mcollina wants to merge 1 commit into
mainfrom
fix/72-openapi-hide-routes

Conversation

@mcollina

Copy link
Copy Markdown
Member

Problem

Issue #72 asks for a way to keep the MCP routes out of an OpenAPI document generated with @fastify/swagger, since they end up in types generated with openapi-fetch. The transformRouteSchema option (#183) covers most of this: returning { ...schema, hide: true }, or a tag matching swagger's hiddenTag, hides POST/DELETE /mcp. I tested it against app.swagger() and found that some routes the plugin registers skip the transformer, so they still appear in the spec:

  • GET /mcp when enableSSE is off (the route that returns 405). With default options, /mcp was always in the spec.
  • When authorization is enabled: /.well-known/oauth-protected-resource*, /.well-known/mcp-resource-health and the OPTIONS /.well-known/* preflight route.
  • When oauth2Client is configured: the /oauth/* routes and the Client ID Metadata Document route.

Fix

  • All of these routes now go through transformRouteSchema. New route IDs: wellKnown.protectedResourceMetadata, wellKnown.resourceHealth, wellKnown.preflight, oauth.authorize|callback|refresh|validate|status|register|logout, oauth.clientIdMetadataDocument. The 405 GET /mcp route uses the existing mcp.get ID.
  • The well-known and OAuth routes pass their existing querystring/body/response schemas to the transformer. The README tells users to spread them.
  • The schema helpers moved from src/routes/mcp.ts to src/routes/route-schema.ts, so the other plugins can use them too.
  • README: added a "Hiding MCP routes from OpenAPI / Swagger" example (hide: true, or the X-HIDDEN tag), extended the route ID table, and removed the note that OAuth/well-known routes are not customized.
  • @fastify/swagger is added as a devDependency. test/openapi-hide-routes.test.ts checks that app.swagger() lists no plugin paths with SSE on and off, with authorization, and with oauth2Client.

Behaviour change

A transformer now runs for more routes than before: 3 calls instead of 2 with default options, and more when authorization is enabled. If a transformer assumed it only sees mcp.* IDs, it now also receives wellKnown.* and oauth.* IDs.

Fixes #72

🤖 Generated with Claude Code

https://claude.ai/code/session_01UF4S3w7iA83V9DVsasLJzM

transformRouteSchema already lets users hide the MCP transport routes
from @fastify/swagger with `hide: true` or a hidden tag, but several
routes the plugin registers bypassed it and still leaked into the
generated OpenAPI document (and into types generated from it):

- GET /mcp when enableSSE is off (the 405 route)
- /.well-known/oauth-protected-resource*, /.well-known/mcp-resource-health
  and the OPTIONS /.well-known/* preflight route when authorization is on
- the /oauth/* client routes and the Client ID Metadata Document route
  when oauth2Client is configured

All of them now go through the transformer with their own route IDs.
The helpers moved from routes/mcp.ts to routes/route-schema.ts so the
well-known, OAuth route and OAuth client plugins can share them.
@fastify/swagger is added as a devDependency to test the generated spec.

Fixes #72

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UF4S3w7iA83V9DVsasLJzM

This branch has not been deployed

No deployments
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.

OpenAPI types break

1 participant