feat(devframe): route-based MCP server on the dev server#85
Merged
Conversation
Expose the agent surface over the MCP Streamable-HTTP transport at `/__mcp` (relative to the base path) so an MCP client connects to the running dev/cli server and sees live tool/resource changes, rather than spawning a fresh stdio child. Opt-in via `cli.mcp` (`boolean | McpRouteOptions`) with `--mcp` / `--no-mcp` overriding per run; default off. Each client session gets its own MCP server built from the live context, correlated by the `Mcp-Session-Id` header, so listChanged notifications reach clients. The endpoint reuses the WS transport's loopback origin gate as its DNS-rebinding protection and is advertised in `__connection.json` for in-browser discovery. The `@modelcontextprotocol/sdk` peer dependency is loaded lazily, only when the route is enabled.
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Exposes a devframe's agent surface over the MCP Streamable-HTTP transport at
/__mcp(relative to the base path), so an MCP client connects to the running dev/cli server and sees live tool/resource changes — rather than spawning a fresh stdio child that boots a throwaway context.It's the same
ctx.agenttools + shared-state resources the stdiomcpcommand serves, against the live server.How
cli.mcp?: boolean | McpRouteOptionson the definition, with--mcp/--no-mcpoverriding per run; default off.McpRouteOptionscarriespath?andallowedOrigins?.createDevServermounts an h3 route atjoinURL(basePath, '__mcp')—/__mcpstandalone,/__<id>/__mcphosted — before the SPA static catch-all, and folds MCP session teardown intoStartedServer.close().mountMcpHttp()(newadapters/mcp/http.ts) drives the SDK's web-standardWebStandardStreamableHTTPServerTransport, whosehandleRequest(Request): Responsefits h3 v2's web event model. It reuses the transport-agnosticbuildMcpServerFromContext. The response is copied ontoevent.res+ body (not returned as aResponse) so a legit MCP 404 isn't swallowed by h3's Response-404 fall-through into the static handler.Mcp-Session-Id, sotools/list_changed/resources/list_changednotifications reach connected clients; sessions are torn down onDELETE/ disconnect.isAllowedOrigingate as the endpoint's DNS-rebinding protection (the external-middleware approach the SDK now recommends over its deprecated built-in host/origin flags), with the same loopback default; widen viaallowedOrigins.__connection.jsongains an optionalmcp: { path }block when enabled.@modelcontextprotocol/sdkis imported lazily — only when the route is enabled — so the core dev path never pulls it in.Design
Shaped through a grilling session; key decisions: live agent surface (not throwaway ctx), Streamable-HTTP only, stateful sessions, cli-dev + vite bridge side-car coverage, basePath-relative path, WS-parity perimeter (no bearer token), opt-in default-off.
Tests / docs
mcp-http.test.ts): initialize → session id,tools/list,tools/call, DELETE teardown + stale-id 404, cross-origin 403, and the__connection.jsonadvertise/omit cases. Existing in-memorybuildMcpServerFromContexttest retained.docs/adapters/mcp.md,docs/errors/DF0017.md, and the tsnapi public-API snapshots.pnpm lint && pnpm test && pnpm typecheck && pnpm buildall green (642 tests).This PR was created with the help of an agent.