refactor(mcp): use SDK transport directly, drop custom transport layer#936
Draft
mattzcarey wants to merge 7 commits intomainfrom
Draft
refactor(mcp): use SDK transport directly, drop custom transport layer#936mattzcarey wants to merge 7 commits intomainfrom
mattzcarey wants to merge 7 commits intomainfrom
Conversation
…eHTTPServerTransport Kill the custom WorkerTransport, WS bridging, and legacy SSE transport. McpAgent now handles HTTP directly in the DO using the SDK transport. createMcpHandler requires a factory function to prevent CVE-2026-25536 (cross-client data leak from server/transport reuse). init() replaced with onStart() to match the standard Agent pattern. Custom elicitInput removed in favor of the SDK's server.server.elicitInput() with relatedRequestId via extra. Deletes ~5,400 lines of custom transport code.
|
commit: |
… API Keeps the McpAgent API structurally similar to the previous version. Also adds deprecated WorkerTransport alias for easier migration.
…kers Ajv's default validator uses new Function() which is blocked in Workers. Inject @cfworker/json-schema based validator in both McpAgent and createMcpHandler so elicitation schema validation works on the edge.
createMcpHandler now accepts a pre-connected transport for stateful mode. McpAgent._setupMcp() creates the handler once and onRequest() delegates to it.
CORS response headers are now always added by createMcpHandler in both stateful and stateless modes. serve() only handles OPTIONS preflight to avoid creating a DO for preflight requests.
This reverts commit c7f9aa9.
Remove unused imports, fix oxfmt formatting.
Contributor
|
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.
Summary
Rewrites the MCP server implementation to use the SDK's
WebStandardStreamableHTTPServerTransportdirectly, removing the customWorkerTransportand WebSocket bridging layer.WorkerTransport,McpSSETransport,StreamableHTTPServerTransport, and all WS bridging codeWebStandardStreamableHTTPServerTransport, handles HTTP viaonRequest()usingcreateMcpHandlerwith the transport optioncreateMcpHandlerrequires a factory function — prevents CVE-2026-25536 (cross-client data leak from reusing server/transport instances)createMcpHandleraccepts atransportoption — for stateful mode (McpAgent), pass a pre-connected transport; for stateless mode, fresh server+transport per requestCfWorkerJsonSchemaValidatorinjected automatically — both McpAgent andcreateMcpHandlerinject the Workers-compatible JSON schema validator so elicitation works on the edge (Ajv'snew Function()is blocked)elicitInput— use the SDK's built-inserver.server.elicitInput()with{ relatedRequestId: extra.requestId }WorkerTransportre-exported as deprecated alias for easier migrationpackages/agents/MCP_MIGRATION_GUIDE.mdArchitecture
CVE-2026-25536 Mitigation
McpAgent: one DO per session = one server + one transport per client, no cross-client sharingcreateMcpHandler: factory-only signature makes it impossible to reuse a server across requestsCORS Handling
createMcpHandlerdirectly): handler owns full CORS (OPTIONS + response headers). PasscorsOptionstocreateMcpHandler.McpAgent.serve()):serve()owns full CORS (OPTIONS preflight + response headers). PasscorsOptionstoserve().Breaking Changes
See
packages/agents/MCP_MIGRATION_GUIDE.mdfor full details:serveSSE(),mount())WorkerTransportremoved (deprecated alias available)createMcpHandleroptions simplifiedcreateMcpHandlerrequires a factory functionMcpAgent.serve()options simplifiedTest plan
npm run buildpassesoxfmt) and linting (oxlint) passexamples/mcpand test with MCP clientexamples/mcp-workerstateless handler works