feat(typescript): support MCP protocol 2026-07-28 via @modelcontextprotocol/client v2 - #642
Conversation
…otocol/client v2 MCPToolProvider now prefers the v2 SDK (@modelcontextprotocol/client, new optional peerDependency) when installed, constructing its Client with versionNegotiation mode "auto": the server/discover probe reaches 2026-07-28 servers and falls back to the legacy initialize handshake for older ones. With only @modelcontextprotocol/sdk v1 installed the code path is byte-identical to before — the untouched v1 test suite is the regression proof. All result shapes the provider reads are casing-equal across majors (verified against the published 2.0.0 tarball), so only imports and two construction sites differ; v2 SSE headers go through requestInit since the v2 transport has no top-level headers option. Closes #633 Code written by Claude (Fable 5), architected and approved by @cornelcroi.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04493671b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| serverConfig.headers | ||
| ? { requestInit: { headers: serverConfig.headers } } | ||
| : undefined |
There was a problem hiding this comment.
Forward SSE headers to the initial event-stream request
When the v2 client is selected and an SSE server requires authentication on its initial event-stream GET (including the documented Authorization-header configuration), requestInit applies these headers only to the POST channel, leaving the GET unauthenticated. Such servers reject the connection before tools can be listed, whereas the v1 path forwarded the configured headers; the v2 transport must also attach them to the event-source fetch.
Useful? React with 👍 / 👎.
Issue Link
Closes #633
Summary
The MCP 2026-07-28 spec (stateless core,
server/discover, routing headers, caching) is only implemented by the new v2 SDK package split — the old@modelcontextprotocol/sdktops out at 1.30.0 and stays on 2025-11-25.MCPToolProvidernow prefers@modelcontextprotocol/client(new optional peerDependency) when installed, constructing itsClientwithversionNegotiation: { mode: "auto" }: modern servers are reached via theserver/discoverprobe, legacy servers via the automaticinitializefallback. With only the v1 SDK installed the code path is byte-identical to today.Changes
ensureConnected()tries@modelcontextprotocol/client(root exports +/stdiosubpath) first, falls back to the existing v1 imports; neither installed → error naming both options.versionNegotiation: { mode: "auto" }; v1 construction unchanged.requestInit: { headers }(the v2 class has no top-levelheadersoption; GET-stream headers remain [TypeScript] MCPToolProvider sse transport passes headers option that SSEClientTransport ignores #640's scope). stdio and streamable-http construction shapes are identical across majors — verified against the published 2.0.0 tarball, as are all result shapes the provider reads (inputSchema,isError,structuredContent,_meta), so downstream code is untouched.package.json:@modelcontextprotocol/client >=2.0.0added as optional peer (v2 ships CJS builds; Node >= 20 applies only to users who install it).mcpToolProviderV2.test.ts(v2 preferred over v1, client options, all three transports, list/call flow, disconnect) +mcpToolProviderV2Partial.test.ts(v2 root present but/stdiomissing). The existing v1 suite is untouched and passing — that is the backward-compat proof. 44/44, lint clean.User experience
Nothing else changes — same
MCPToolProvider.create([...]), and each server's protocol era is negotiated automatically.typescript-expert review: APPROVED (both suggested items applied).
Checklist
Code written by Claude (Fable 5), architected and approved by @cornelcroi.