MCP connector (mcp_servers + mcp_toolset) and MCP tunnels
Status: DOCUMENTED · BETA · LIVE_VERIFIED 2026-09-18 (i1 DeepWiki read_wiki_structure round trip on haiku 4.5 ≈ $0.003; i2 no header → 400; k13b deprecated header still works; k13 advertised mcp-client-2026-09-15 rejected).
Sources: MCP connector · Remote MCP servers · Beta Messages reference · MCP tunnels · Beta headers.
Last verified: 2026-09-18.
Request shape (header anthropic-beta: mcp-client-2025-11-20)
{"model": "claude-haiku-4-5-20251001", "max_tokens": 200,
"mcp_servers": [{"type": "url", "url": "https://mcp.deepwiki.com/mcp", "name": "deepwiki", "authorization_token": "<OAuth bearer, optional>"}], // max 20; https only; Streamable HTTP or SSE
"tools": [{"type": "mcp_toolset", "mcp_server_name": "deepwiki",
"default_config": {"enabled": true, "defer_loading": false}, // applies to all tools of the server
"configs": {"ask_question": {"enabled": true, "defer_loading": true}}, // per-tool overrides (unknown names: warning only)
"cache_control": {"type": "ephemeral"}}], // breakpoint lands on the last expanded tool
"messages": [{"role": "user", "content": "Call the read_wiki_structure tool for anthropics/anthropic-sdk-python…"}]}Validation: each mcp_servers[].name must be referenced by exactly one mcp_toolset and vice-versa; type is only url. Patterns: allowlist = default_config.enabled:false + enable specific tools; denylist = disable specific tools; precedence configs > default_config > system defaults. mcp_toolset does not accept strict or allowed_callers; MCP tools cannot be called programmatically. Only MCP tool calls are supported (no prompts/resources — use the SDK client-side helpers anthropic[mcp] / @modelcontextprotocol/sdk for those). Only publicly exposed HTTP servers: no stdio/localhost.
Deprecated shape (anthropic-beta: mcp-client-2025-04-04): mcp_servers[].tool_configuration: {enabled, allowed_tools[]} and no mcp_toolset entry — live k13b: still returns 200.
Response (live i1)
{"type":"mcp_tool_use","id":"mcptoolu_01SvS54EZae5f3nhQCKNuBu5","name":"read_wiki_structure","server_name":"deepwiki","input":{"repoName":"anthropics/anthropic-sdk-python"}}
{"type":"mcp_tool_result","tool_use_id":"mcptoolu_01SvS54EZae5f3nhQCKNuBu5","is_error":false,"content":[{"type":"text","text":"Available pages for anthropics/anthropic-sdk-python:\n\n- 1 Overview\n- 2 Installation and Setup\n…"}]}
{"type":"text","text":"The first 3 topic names are:\n\n1. Overview\n2. Installation and Setup\n3. Quick Start"}Anthropic performs initialize → tools/list → tools/call; you never answer mcp_tool_use. An mcp_tool_use left without result in a stop_reason: tool_use response (mixed with a client tool) is pending like a server_tool_use. mcp_tool_use had no caller field live. Usage: 2,367 input tokens (server tool definitions count as input). count_tokens rejects mcp_servers. Batches supported. Not ZDR-eligible; data shared with the server follows standard retention.
Beta header findings
| Header | Live |
|---|---|
| none | 400 mcp_servers: this parameter requires anthropic-beta: mcp-client-2026-09-15 (or mcp-client-2025-11-20) |
mcp-client-2026-09-15 (as advertised) |
400 Unexpected value(s) mcp-client-2026-09-15 for the anthropic-beta header — not yet accepted (LIVE_DISCOVERED inconsistency) |
mcp-client-2025-11-20 |
200 (current, documented) |
mcp-client-2025-04-04 + tool_configuration |
200 (deprecated, still served) |
Authentication
You run the OAuth flow yourself (e.g. npx @modelcontextprotocol/inspector → Quick OAuth Flow → copy access_token) and pass it as authorization_token; refresh it as needed. Connect only to trusted servers; tool results are untrusted content.
MCP tunnels (research preview)
For servers inside a private network Anthropic offers MCP tunnels (/v1/tunnels, header mcp-tunnels-2026-06-22, formerly /v1/organizations/tunnels with mcp-tunnels-2026-05-19, since 2026-05-19): a tunnel agent (Compose/Helm) runs next to your server and the connector reaches it through Anthropic's gateway. Details: sources/anthropic/pages/agents-and-tools/mcp-tunnels/* (not exercised in this run; belongs to the endpoint owner).
Mini local MCP server + how Claude would use it
examples/anthropic/mcp/mini-mcp-server.ts is a 90-line Streamable-HTTP JSON-RPC server (Node built-ins only) exposing one tool echo. Verified locally 2026-09-18:
initialize -> {"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"mini-mcp",…}}
tools/list -> {"tools":[{"name":"echo","description":"…","inputSchema":{…}}]}
tools/call -> {"content":[{"type":"text","text":"echo: PING"}],"isError":false}The connector cannot reach localhost; publish it over a tunnel (cloudflared / ngrok / MacLustr Tunnel mlt add mcp-demo.example.com <node>:8788) and then:
curl https://api.anthropic.com/v1/messages -H "x-api-key: $ANTHROPIC_API_KEY" -H "anthropic-version: 2023-06-01" -H "anthropic-beta: mcp-client-2025-11-20" \
-d '{"model":"claude-haiku-4-5-20251001","max_tokens":100,
"mcp_servers":[{"type":"url","url":"https://mcp-demo.example.com/mcp","name":"mini","authorization_token":"<MCP_TOKEN if set>"}],
"tools":[{"type":"mcp_toolset","mcp_server_name":"mini"}],
"messages":[{"role":"user","content":"Use the echo tool to echo PING and tell me what it returned."}]}'Expected: mcp_tool_use{name:"echo", server_name:"mini", input:{text:"PING"}} → mcp_tool_result{content:[{type:text,text:"echo: PING"}]}. Not run live (no public URL published during this run). Files: examples/anthropic/mcp/{mcp_connector.sh,.py,.ts,mini-mcp-server.ts,README.md}; test test_mcp_connector_deepwiki (expensive).