Skip to content

v1→v2 upgrade path (TL;DR + codemod) ends at a server that 2026-07-28 clients cannot connect to; add a closing step or notice #2977

Open

Description

@ANcpLua

Summary

docs/migration/upgrade-to-v2.md is written as an agent skill (name: migrate-v1-to-v2), and its TL;DR is:

  1. prerequisites (Node.js 20+);
  2. run the codemod;
  3. grep for markers;
  4. type-check;
  5. format;
  6. run your tests.

Following it exactly yields a project that compiles, passes default-client tests and answers the default Inspector, but only serves the 2025 era. The codemod keeps server.connect(new StdioServerTransport()) (and maps StreamableHTTPServerTransport to NodeStreamableHTTPServerTransport). Its output says nothing about serveStdio / createMcpHandler or the 2026-07-28 opt-in.

I understand this is intentional: upgrading the package and adopting 2026-07-28 are separate steps, and the guide links support-2026-07-28.md at the top. The problem is that agents (and most people) stop at the end of the TL;DR. The result looks finished and is silently legacy-only.

#2968 moves this guide into an installable skill (skills/mcp-typescript-sdk-upgrade-to-v2/SKILL.md), so agents will load its quick path directly; the closing step belongs in that quick path too.

Reproduction (codemod 2.3.1, server 2.3.1)

v1 input:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const server = new McpServer({ name: 'demo', version: '1.0.0' });
server.registerTool('greet', { description: 'Greet a user', inputSchema: { name: z.string() } }, async ({ name }) => ({
    content: [{ type: 'text', text: `Hello ${name}` }]
}));
await server.connect(new StdioServerTransport());

Steps:

  1. npx @modelcontextprotocol/codemod@latest v1-to-v2 .
  2. Bump zod to ^4.2.0, as the codemod's warning says.
  3. npm install.
  4. tsc --noEmit, which is clean.
  5. Build.

Codemod output (relevant part):

import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { McpServer } from "@modelcontextprotocol/server";
// ...
await server.connect(new StdioServerTransport());

Connecting with Inspector 2.9.0 in each era:

protocolEra Result
legacy lists greet
modern Version negotiation failed: the server did not offer pinned protocol version 2026-07-28 via server/discover (no fallback in pin mode)

Suggestions (any one helps)

  1. Add a TL;DR step 7, "Serve the 2026-07-28 revision". Replace server.connect(new StdioServerTransport()) with serveStdio(() => createServer()), and per-request transports with createMcpHandler(() => createServer()). Verify with a client pinned to { pin: '2026-07-28' }.
  2. Have the codemod print an INFO line when it rewrites a connect(new StdioServerTransport()) or *StreamableHTTPServerTransport call site: "this entry serves 2025-era clients only; see support-2026-07-28.md#serving-the-2026-07-28-revision". The codemod already reports the Zod floor this way.
  3. Optionally, add a @mcp-codemod-error-style marker on those call sites, so the TL;DR's step 3 grep surfaces them.

Environment: Node 22.22; @modelcontextprotocol/codemod 2.3.1; @modelcontextprotocol/server 2.3.1; Inspector 2.9.0.


AI disclosure: this issue was written with Claude (Claude Code), which also ran the reproductions above. I'm accountable for it and will answer questions myself.

Activity

  1. boss477 commented on Oct 9, 2026

    @boss477

    I can take the bounded codemod part of this. I will add a post-migration notice when v1-to-v2 leaves a legacy-only stdio or Streamable HTTP server entry, with focused fixture coverage, so the fix stays independent of #2968 moving the guide. I will keep the codemod output unchanged for projects without those server entry points.

  2. ANcpLua commented on Oct 10, 2026

    @ANcpLua
    Author

    Since @boss477's #2978 covers the codemod notice (suggestion 2), I'd like to take suggestion 1, the TL;DR step 7: "Decide whether to serve 2026-07-28." It's a short paragraph saying the upgrade alone keeps connect(new StdioServerTransport()) and *StreamableHTTPServerTransport on 2025-era clients, and pointing to serveStdio / createMcpHandler as the opt-in. I'd land it in skills/mcp-typescript-sdk-upgrade-to-v2/SKILL.md after #2968 merges (I have the main-based variant too). Could you assign it to me?

    Drafted with AI assistance.

  3. added
    v2Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes
    on Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    v2Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions