Skip to content

feat(mcp): serve the stateless 2026-07-28 MCP protocol, and bump dependencies - #23

Merged
Plopix merged 3 commits into
mainfrom
feat/mcp-stateless-2026-07-28
Sep 30, 2026
Merged

Plopix merged 3 commits into
mainfrom
feat/mcp-stateless-2026-07-28

Conversation

@Plopix

@Plopix Plopix commented Sep 30, 2026

Copy link
Copy Markdown
Member
Q A
Branch? main
Bug fix? no
New feature? yes
BC breaks? no
Fixed tickets —

The MCP server now speaks the stateless 2026-07-28 MCP spec (no initialize handshake, no Mcp-Session-Id), and 2025 clients keep working on the same /mcp URL. This PR also bumps every dependency that can be bumped.

How it works

  • Moves to MCP SDK v2 (@modelcontextprotocol/server) and agents 0.24. Its createMcpHandler serves 2026-07-28 clients natively and answers 2025 clients through its stateless fallback (legacy: "stateless", the default). That fallback is how the server already worked, so 2025 clients see no change.
  • The 2025 lane has to stay for now: Cursor and MCP Inspector still only speak 2025, and Claude's 2026-07-28 support is still rolling out.
  • The handler now takes a server factory instead of an instance. servicesProvider already builds a fresh server per request, so the factory just returns it. responseMode: "json" replaces enableJsonResponse.
  • Session analytics: 2026-07-28 clients never send initialize, so a session now also counts on server/discover, which the SDK client sends when it connects. It's read from the Mcp-Method header, so the body is never touched. The Plausible path is unchanged. A modern client that skips discovery goes uncounted; tools/list is no substitute because clients re-send it every time their cached list expires.
  • The v2 SDK uses the project's zod, so the dual-zod @ts-expect-error in servicesProvider is gone. agents/mcp/server doesn't pull in SDK v1, and the bundle drops from 4.13 MB to 2.9 MB.
  • CLAUDE.md has a new "MCP protocol versions" section.

Dependency bumps

  • Within their major versions: zod 4.6, hono 4.13, jose 6.2.12, awilix 13.0.5, vite 8.3, wrangler 4.144, @cloudflare/vite-plugin 1.62, oxlint 1.86, tailwindcss 4.3.3.
  • New majors: graphql 17, TypeScript 7, @types/node 26. None needed code changes.
  • oxlint 1.86 flags irregular whitespace, so two comments that escaped a glob's */ with a zero-width space now write it as {*}.
  • Held back: @modelcontextprotocol/server, client and core stay pinned at exactly 2.0.0 (2.2.0 is out), because that's what agents 0.24.0, its latest release, declares as its peer.

Tested

  • bun type-check, bun test (184 pass, 5 new), bun lint, bun build.
  • Live against the dev server with a real access token, using the v2 SDK client in legacy, pinned 2026-07-28 and auto modes. Every mode connects, lists the 14 tools, returns auth-scoped data from tenant-overview, runs query-catalogue and the schema fetch, and keeps write tools hidden by default.

Not tested yet

  • Claude Code, Cursor and MCP Inspector themselves, which should be checked on a preview deploy before merging.

Notes

  • compatibility_date in wrangler.jsonc (2025-08-03) is unchanged. It affects Workers runtime behaviour, so it's a separate decision.
  • A bug found along the way, unrelated to this PR: the query corrector turns childs into id instead of children, and the retry then fails. graphql 16 behaves the same.

Move to MCP SDK v2 (@modelcontextprotocol/server) and agents 0.24, whose
createMcpHandler serves 2026-07-28 clients natively and still answers 2025
clients (initialize handshake) through its stateless fallback, on the same
/mcp endpoint. Cursor and MCP Inspector still speak only 2025.

Session analytics now also count a modern client's server/discover, read
from the Mcp-Method header, since modern clients never send initialize.

The v2 packages share the project's zod, so the dual-zod @ts-expect-error
in servicesProvider is gone.
zod 4.6, hono 4.13, jose 6.2.12, awilix 13.0.5, graphql 16.14.2, vite 8.3,
wrangler 4.144, @cloudflare/vite-plugin 1.62, oxlint 1.86, tailwindcss 4.3.3.

oxlint 1.86 flags irregular whitespace: the two comments that escaped a
glob's "*/" with a zero-width space now write it as {*}, like the rest of
analytics.ts.
No code changes needed. graphql is only used by this server, so there is
no second copy to clash with. Checked live on both protocol eras: queries,
the schema fetch and query correction behave as on graphql 16.
@Plopix
Plopix merged commit 089b4bc into main Sep 30, 2026
1 check passed
@Plopix
Plopix deleted the feat/mcp-stateless-2026-07-28 branch September 30, 2026 00:23
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