Persistence (Advanced)
- Build your first harness
- Host options
- Send and show media
- Connect clients
- Write a client in any language
- Access and tenants
- Run in the terminal
- Deploy a harness
- Send inputs safely
- Run a tool without a model
- Durable sessions
- Run background work on workers
- List, rename, and fork sessions
- Lifecycle and retention
- Run side effects once
- Wait for a person
- Build on the session log
- Control how a turn ends
- Store settings per thread
- Compact a long session
- Fork and reset a thread
- One log for a session tree
- Write a plugin
- Track usage and cost
- Ask before risky tool calls
- Give your agent coding tools
- Sandbox and extend the coding tools
- Run the coding tools for many threads
- Undo a turn
- Build a coding agent
- Delegate to coding agents
- Switch between agent profiles
- Auth and connectors
- Share a thread between people
- Connect model providers
- Build your own UI
- Code mode in a harness
- Work until a goal is met
- Run agents from a harness
- Hand off a conversation
- Add skills
- Use MCP servers
- Give your agent a computer
- Use from any MCP client
- Use a harness from an editor (ACP)
- Overview
- Quick Start
- ProvidersUpdated
- Harnesses
- Harness Auth
- Workspace
- Tools
- Policy
- Lifecycle & Snapshots
- Portable Snapshots
- Keep Files After Reload
- Save a Named Version
- Branch From a Version
- Send a Frozen File
- Let the Agent Save and Fork
- Pick Which Files to Keep
- What a Snapshot Stores
- Instance Durability
- Durable Runs
- Events
Sandboxes (Advanced)
- Runtime Context
- Bring Your Own Key
- Keep Keys on the Server
- Debug Logging
- Multimodal Content
- Files API
- Per-Model Type Safety
- Runtime Adapter Switching
- Tree-Shaking
- Extend Adapter
- Extend Adapter: Advanced
- Typed Pre-Configured Options
- Test with a Fake Model
- Prompt Caching
- Mid-Conversation Changes
- Approval Flow Processing
MCP Type Generation
Generate TypeScript types from a live MCP server and pass them to createMCPClient. A wrong tool name is then a type error.
You get:
- Tool names narrowed to the literal names of the server.
- Compile-checked config keys on a pool.
- No runtime cost.
Tool arguments stay unknown on this path. For typed arguments, also use the tools([toolDefinition(...)]) form.
1. Create mcp.config.ts#
List each server that you want types for. defineConfig gives the file type checks and autocomplete.
// mcp.config.ts
import { defineConfig } from '@tanstack/ai-mcp'
export default defineConfig({
servers: {
github: {
transport: { type: 'http', url: 'https://github-mcp.example.com/mcp' },
},
linear: {
transport: { type: 'http', url: 'https://linear-mcp.example.com/mcp' },
prefix: 'linear', // must match runtime createMCPClient({ prefix })
},
},
outFile: './mcp-types.generated.ts',
})2. Run the generator#
npx @tanstack/ai-mcp generateThe CLI connects to each server, reads its tools, resources, and prompts, and writes the types to outFile. It uses the same handshake as createMCPClient: protocol 2026-07-28 first, then the 2025 handshake.
3. Read the output#
The generator writes one interface for each server, plus a map for the pool:
// AUTO-GENERATED by `npx @tanstack/ai-mcp generate`. Do not edit.
import type { ServerDescriptor } from '@tanstack/ai-mcp'
export interface GithubServer extends ServerDescriptor {
tools: {
'search_repositories': { input: { query: string; limit?: number }; output: unknown }
'create_issue': { input: { repo: string; title: string; body?: string }; output: unknown }
}
resources: {}
prompts: {}
capabilities: { tools: {} } & Record<string, unknown>
}
export interface LinearServer extends ServerDescriptor {
tools: {
'linear_create_issue': { input: { title: string; teamId: string }; output: unknown }
}
resources: {}
prompts: {}
capabilities: { tools: {} } & Record<string, unknown>
}
export interface MCPServers extends Record<string, ServerDescriptor> {
'github': GithubServer
'linear': LinearServer
}4. Use the types#
Pass the type as a generic to createMCPClient (one server) or createMCPClients (a pool).
One server:
import type { GithubServer } from './mcp-types.generated'
import { createMCPClient } from '@tanstack/ai-mcp'
const mcp = await createMCPClient<GithubServer>({
transport: { type: 'http', url: process.env.GITHUB_MCP_URL! },
})
const tools = await mcp.tools()
// Each tool name is narrowed from GithubServer['tools']A pool:
import type { MCPServers } from './mcp-types.generated'
import { createMCPClients } from '@tanstack/ai-mcp'
const pool = await createMCPClients<MCPServers>({
github: { transport: { type: 'http', url: process.env.GITHUB_MCP_URL! } },
linear: {
transport: { type: 'http', url: process.env.LINEAR_MCP_URL! },
prefix: 'linear',
},
})
// The config keys must be declared servers. A typo is a compile error.
const tools = await pool.tools()Now a misspelled tool name or pool key fails the type check. To give the typed client to chat(), see Managed MCP with chat().
Package names for an @modelcontextprotocol/sdk import are in MCP SDK packages.