-
Notifications
You must be signed in to change notification settings - Fork 66
Serve /mcp on dual protocol lanes: stateless 2026-07-28 + instrumented legacy, with CIMD and tool metadata #1237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
44 changes: 44 additions & 0 deletions
44
docs/contributing/decisions/0005-mcp-dual-lane-stateless-migration.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # 0005: MCP dual-lane serving with metrics-driven legacy retirement | ||
|
|
||
| - **Status:** accepted | ||
| - **Date:** 2026-08-05 | ||
|
|
||
| ## Context | ||
|
|
||
| MCP protocol revision `2026-07-28` made the protocol stateless: the `initialize` | ||
| handshake and `Mcp-Session-Id` header are removed and every request carries its | ||
| own `_meta` envelope. The Cloudflare Agents SDK deprecated and feature-froze | ||
| `McpAgent`, which hosts kody's `/mcp` as a sessionful Durable Object on MCP SDK | ||
| v1. Nearly all installed MCP clients still speak 2025-era revisions, so dropping | ||
| the sessionful path outright would break real traffic, while staying on | ||
| `McpAgent` alone pins kody to a frozen stack. | ||
|
|
||
| ## Decision | ||
|
|
||
| Serve `/mcp` as two lanes behind one route and one shared tool registration | ||
| (`packages/worker/src/mcp/register-tools.ts`): 2025-era requests keep the | ||
| `McpAgent` Durable Object lane unchanged, and `2026-07-28` envelope requests are | ||
| served by a per-request stateless SDK v2 server | ||
| (`packages/worker/src/mcp/stateless-lane.ts`). Routing uses the SDK's own | ||
| `isLegacyRequest` predicate, and every authenticated request records a lane data | ||
| point to the `MCP_PROTOCOL_EVENTS` Analytics Engine dataset — deliberately not | ||
| the primary D1 database (aggregate-only readout, off the hot path; consistent | ||
| with [0002](./0002-data-placement.md)). The legacy lane is removed when the | ||
| metrics show its traffic has gone (a sustained window of zero or negligible | ||
| legacy-lane requests from real clients), not on a calendar date. | ||
|
|
||
| ## Consequences | ||
|
|
||
| Modern clients get stateless serving with no MCP session Durable Object on the | ||
| request path (the account write lease taken at the auth boundary is unchanged | ||
| and applies to both lanes — it is the deletion-safety guard every kody surface | ||
| takes, not MCP session state), while every existing client keeps byte-identical | ||
| behavior. Tool definitions cannot drift between lanes, but the two SDK | ||
| generations meet at a typed seam (`asMcpToolServer` in | ||
| `packages/worker/src/mcp/mcp-registration-agent.ts`) that a future SDK bump must | ||
| revisit. Retiring the legacy lane later also deletes the `mcp_agent_sessions` | ||
| registry, the `MCP_OBJECT` Durable Object, and the session purge path. Tasks | ||
| (the `io.modelcontextprotocol/tasks` extension) are deliberately not implemented | ||
| yet: the SDK v2 ships the vocabulary without a runtime, no major client supports | ||
| it, and execute's idempotency-key + `run_get` flow already covers the need; | ||
| revisit when a major host ships task support. |
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
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
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
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Remove the account Durable Object from the modern request path.
handleStatelessMcpRequestruns insidewithAccountWriteLease. The supplied lease implementation callsacquireDoAccountWriteLeaseAndWrite. Every modern request therefore depends on an account Durable Object. This defeats the stated stateless, no-Durable-Object lane design and adds a lease availability dependency totools/listand other read-only requests.packages/worker/src/mcp-auth.ts#L273-L293: Dispatch the modern branch outsidewithAccountWriteLease. Apply any required account-deletion protection at the specific mutating tool boundary.docs/contributing/architecture/request-lifecycle.md#L54-L63: Keep the no-Durable-Object statement only after the modern branch bypasses the lease. Otherwise document the account Durable Object hop.docs/contributing/decisions/0005-mcp-dual-lane-stateless-migration.md#L32-L34: Keep the no-Durable-Object consequence only after the modern branch bypasses the lease. Otherwise revise the decision record.📍 Affects 3 files
packages/worker/src/mcp-auth.ts#L273-L293(this comment)docs/contributing/architecture/request-lifecycle.md#L54-L63docs/contributing/decisions/0005-mcp-dual-lane-stateless-migration.md#L32-L34🤖 Prompt for AI Agents