- MCP Server ToolsUpdated
- Managed MCP with chat()Updated
- Manual MCPUpdated
- MCP Type GenerationUpdated
- MCP Client InputUpdated
- MCP Server Tools: AdvancedNew
- MCP EventsNew
- MCP AppsUpdated
- Serve Tools over HTTPUpdated
- Serve Resources and PromptsUpdated
- Ask for InputUpdated
- Draft Text from a ToolUpdated
- MCP Server TasksUpdated
- MCP Server AuthUpdated
- MCP Server SessionsUpdated
- MCP Server on stdioUpdated
Persistence (Advanced)
- GenerationsUpdated
- Realtime Voice ChatUpdated
- Text-to-SpeechUpdated
- TranscriptionUpdated
- Transcription: AdvancedNew
- Voice CreationUpdated
- Audio RecordingUpdated
- Audio GenerationUpdated
- Image GenerationUpdated
- Image Generation: AdvancedNew
- Video GenerationUpdated
- Video Generation: AdvancedNew
- Live GenerationUpdated
- World GenerationUpdated
- Generation HooksUpdated
- OverviewUpdated
- Quick StartUpdated
- ProvidersUpdated
- HarnessesUpdated
- Harness AuthUpdated
- WorkspaceUpdated
- ToolsUpdated
- PolicyUpdated
- Lifecycle & SnapshotsUpdated
- Portable SnapshotsUpdated
- Keep Files After ReloadUpdated
- Save a Named VersionUpdated
- Branch From a VersionUpdated
- Send a Frozen FileUpdated
- Let the Agent Save and ForkUpdated
- Pick Which Files to KeepUpdated
- What a Snapshot StoresUpdated
- Instance DurabilityUpdated
- Durable RunsUpdated
- EventsUpdated
Sandboxes (Advanced)
- Runtime ContextUpdated
- Bring Your Own KeyUpdated
- Debug LoggingUpdated
- Multimodal ContentUpdated
- Files APIUpdated
- Per-Model Type SafetyUpdated
- Runtime Adapter SwitchingUpdated
- Tree-ShakingUpdated
- Extend AdapterUpdated
- Extend Adapter: AdvancedNew
- Typed Pre-Configured OptionsUpdated
- Test with a Fake ModelUpdated
- Prompt CachingUpdated
- Mid-Conversation ChangesUpdated
- Approval Flow ProcessingUpdated
MCP Server Tools
createMCPClient connects to an MCP server. Pass that client to chat() in the mcp option.
Note
MCP tools run on the server. Call createMCPClient in a server route or a serverless function, never in browser code.
Servers can also push signed webhooks through the experimental MCP Events extension. See MCP Events. A Start app that subscribes and receives a delivery is in Subscribe to MCP Events.
Quick setup#
You need a working chat first. If you do not have one, start with the Quick Start.
- Install the MCP client:
npm i @tanstack/ai-mcp @modelcontextprotocol/clientpnpm add @tanstack/ai-mcp @modelcontextprotocol/clientyarn add @tanstack/ai-mcp @modelcontextprotocol/clientbun add @tanstack/ai-mcp @modelcontextprotocol/client- In your chat route, connect to the server and pass the client to chat(). Change the URL to the URL of your MCP server:
// src/routes/api.chat.ts (TanStack Start)
import { createFileRoute } from '@tanstack/react-router'
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { createMCPClient } from '@tanstack/ai-mcp'
export const Route = createFileRoute('/api/chat')({
server: {
handlers: {
POST: async ({ request }) => {
const { messages, threadId } = await request.json()
const mcp = await createMCPClient({
transport: {
type: 'http',
url: 'https://my-mcp-server.example.com/mcp',
},
})
// chat() finds the tools and closes the client when the run ends.
const stream = chat({
adapter: openaiText('gpt-6.1-sol'),
messages,
threadId,
mcp: { clients: [mcp] },
})
return toServerSentEventsResponse(stream)
},
},
},
})- Keep your client code. useChat reads this endpoint the same way as any other chat endpoint:
// src/components/Chat.tsx
import { useChat } from '@tanstack/ai-react'
import { fetchServerSentEvents } from '@tanstack/ai-client'
export function Chat() {
const { messages, sendMessage, status } = useChat({
connection: fetchServerSentEvents('/api/chat'),
threadId: 'support-chat',
})
return (
<div>
{messages.map((m) => (
<div key={m.id}>
<strong>{m.role}:</strong>{' '}
{m.parts.find((p) => p.type === 'text')?.content}
</div>
))}
<button
onClick={() => sendMessage({ content: 'Hello' })}
disabled={status === 'streaming'}
>
Send
</button>
</div>
)
}Now ask the model something that needs one of the server tools. The model calls the tool, your server runs it on the MCP server, and the answer streams back.
How it works#
- createMCPClient connects to the server. It tries protocol 2026-07-28 first. If the server does not support it, the client uses the 2025 handshake.
- chat({ mcp }) asks each client for its tools before the first model call.
- When the model calls a tool, chat() sends the call to the MCP server and gives the result back to the model.
- When the run ends, chat() closes the client. This happens on success, on error, and on abort.
Note
MCP tool arguments have the type unknown at compile time. The client checks them against the JSON Schema of the server at runtime.
Connect to your server#
Pick the transport that your server uses.
HTTP (Streamable HTTP) is the usual choice for a remote server. Add headers when the server needs a token:
import { createMCPClient } from '@tanstack/ai-mcp'
const mcp = await createMCPClient({
transport: {
type: 'http',
url: 'https://my-mcp-server.example.com/mcp',
headers: { Authorization: `Bearer ${process.env.MCP_TOKEN}` },
},
})SSE is for servers that use the older SSE transport:
import { createMCPClient } from '@tanstack/ai-mcp'
const mcp = await createMCPClient({
transport: {
type: 'sse',
url: 'https://my-mcp-server.example.com/sse',
headers: { Authorization: `Bearer ${process.env.MCP_TOKEN}` },
},
})stdio starts a local MCP process. It works in Node.js only. It has its own import path, so edge bundles do not include Node modules:
import { stdioTransport } from '@tanstack/ai-mcp/stdio'
import { createMCPClient } from '@tanstack/ai-mcp'
const mcp = await createMCPClient({
transport: stdioTransport({
command: 'node',
args: ['./my-mcp-server.js'],
env: { API_KEY: process.env.API_KEY ?? '' },
}),
})For OAuth, custom transports, and timeouts, see MCP Server Tools: Advanced.
What to read next#
- Hide tools or ask the user first. A server can expose tools that write or delete data. See Limit and Gate Tools.
- Many servers, warm connections, or a flaky server. See Managed MCP with chat().
- Typed tool arguments, resources, and prompts. See Manual MCP.
- Compile-checked tool names. See MCP Type Generation.
- The server asks the user for input during a tool call. See MCP Client Input.
Note
This page is about MCP on your server. To expose browser actions to a browser agent, see WebMCP Tools. WebMCP calls go to the browser agent, and they do not become tool results in a TanStack chat run.
Package names for an @modelcontextprotocol/sdk import are in MCP SDK packages.
Advanced#
Every option of the client is on MCP Server Tools: Advanced: OAuth, timeouts, the three modes of type safety, tool annotations, pools, lifecycle, tool names, lazy discovery, and the error reference.