Repository navigation
fix(ai-mcp): send Mcp-Param headers on spec 2026 tool calls - #1871
AlemTuzlak merged 1 commit into
Conversation
Spec 2026 tools/call went through a raw transport send, so the SDK never added the Mcp-Param-* headers from the x-mcp-header schema fields. Route those calls (and the input_required retry) through Client.callTool with the listed input schema, and delete the raw request path. Closes #1794
🦋 Changeset detectedLatest commit: 52732c8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
|
View your CI Pipeline Execution ↗ for commit 52732c8
☁️ Nx Cloud last updated this comment at |
Coverage✅ Coverage held across 1 compared package(s). Each package is measured twice in this job — on this PR and on its merge-base with
|
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-cloudflare
@tanstack/ai-code-mode
@tanstack/ai-code-mode-snippets
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-compaction
@tanstack/ai-computer-local
@tanstack/ai-computer-playwright
@tanstack/ai-computer-sandbox
@tanstack/ai-computer-use
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-e2b
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-llmgateway
@tanstack/ai-lovable
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-octane
@tanstack/ai-ollama
@tanstack/ai-ollaya
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-reactor
@tanstack/ai-remix
@tanstack/ai-sandbox
@tanstack/ai-sandbox-blaxel
@tanstack/ai-sandbox-boxd
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-e2b
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-railway
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-upstash-box
@tanstack/ai-sandbox-vercel
@tanstack/ai-skills
@tanstack/ai-solid
@tanstack/ai-svelte
@tanstack/ai-typesafe
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vertex
@tanstack/ai-vue
@tanstack/ai-worldlabs
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
@tanstack/svelte-ai-devtools
commit: |
Spec 2026-07-28 tool calls from
@tanstack/ai-mcpdid not send theMcp-Param-*headers that a tool'sx-mcp-headerschema fields ask for. Strict servers, such as GitHub's remote MCP server, reject those calls with HTTP 400 and error-32020. This PR sends spec 2026 tool calls through the SDKClient.callToolwith the listed input schema, so the SDK adds the headers.🎯 Changes
callMcpToolsends spec 2026 calls, and theinput_requiredretry, throughclient.callTool. It passestoolDefinition: { name, inputSchema }.tools(),tools([defs]), andMCPClient.callTool()pass the listed tool'sinputSchemato the call.transport.sendpath (rawRequest, the transport tap, and the_metaenvelope copy). The SDK now does timeout, abort, and progress for these calls.@tanstack/ai-mcp. No docs change: no page describes this behavior.✅ Checklist
pnpm run test:pr, or these tests do not apply to this pull request.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.🚀 Release Impact
Root cause
Issue. On a spec 2026-07-28 connection, a tool with an
x-mcp-headerargument fails on strict servers. TheMcp-Param-*header is missing, so the server returns 400 /-32020. Tools without those arguments work, so a basic smoke test does not show the bug.Cause.
callMcpToolinpackages/ai-mcp/src/tools.tssent spec 2026tools/callthroughrawRequest, which callstransport.send(message)directly. OnlyClient.callToolbuilds theMcp-Param-*headers from the tool schema. The raw path skipped it. The SDK does not export its header builder.Fix. Spec 2026 calls go through
Client.callToolwithtoolDefinition: { name, inputSchema }. The SDK readsx-mcp-headerfrom that schema and sends the headers. The definition has nooutputSchema, so the SDK skips its output check. That check would reject aninput_requiredresult.Possible alternatives
listTools()on spec 2026, and callcallToolwith notoolDefinition. This is the spec 2025 path. The SDK output check then runs and rejects aninput_requiredresult from a tool with anoutputSchema.rawRequestand pass headers totransport.send(message, { headers }). The SDK does not exportbuildMcpParamHeaders, so this copies the SDK header and encoding rules. More code, and it can drift from the SDK.Testing
Commands run
createMCPClient→tools()→execute({ region: 'eu' }), assert theMcp-Param-Regionheader):main(3e84606af): fails.tsc --noEmitonpackages/ai-mcp: no new errors in the changed files.pnpm test:prand the fullai-mcpunit suite. CI runs them.Manual test
main, connectcreateMCPClientto a spec 2026 server whose tool declaresregion: { type: 'string', 'x-mcp-header': 'Region' }. Call the tool. The request has noMcp-Param-Regionheader.Mcp-Param-Region: eu, and a strict server accepts it.How this PR makes testing easy
tests/client.test.ts→spec 2026 Mcp-Param headers: a strict fixture server rejects a missing or wrong header. It coverstools()andMCPClient.callTool().tests/tools.test.ts→callMcpTool — spec 2026 calls: checks thetoolDefinitionand the signal passed to the SDK, and theinputResponses/requestStateretry.Linked issues
Closes #1794
Risk / rollback
Low to medium. Spec 2026 tool calls now use the SDK request path, not a raw send. Timeout, abort, and progress now come from the SDK. In a browser, the SDK does not send
Mcp-Param-*headers (the SDK decides this). Rollback: revert this PR.Summary by CodeRabbit
Mcp-Param-*headers for arguments designated by the server, improving compatibility with the 2026-07-28 MCP specification.