- 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 Type Generation
You have a running MCP server and you call its tools through createMCPClient, but nothing checks the tool names you reference at compile time. By the end of this guide you'll have generated per-server interface types from the live server and wired them into createMCPClient, narrowing discovered tool names to the server's literal names and compile-checking pool config keys — with zero runtime overhead. This is Mode 3 of MCP type safety. (Tool arguments stay untyped on the discovery path — for Zod-validated, TypeScript-typed arguments, combine with the tools([toolDefinition(...)]) overload.)
The generate CLI introspects a live MCP server and emits TypeScript interface types that you pass as a generic to createMCPClient / createMCPClients.
1. Create mcp.config.ts#
Declare each server you want to generate types for. The defineConfig helper gives the config file full type checking 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',
})createMCPClient tries protocol 2026-07-28 first. If the server does not support that protocol, the client uses the 2025 initialize handshake. The generator uses this handshake.
Package names for an @modelcontextprotocol/sdk import are in MCP SDK packages.
2. Run the generator#
npx @tanstack/ai-mcp generateThe CLI connects to each declared server, introspects its tools, resources, and prompts, and writes the result to outFile.
3. Inspect the output#
The generator emits one interface per server plus a combined pool map:
// 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 generated types at runtime#
Pass the generated type as a generic to createMCPClient (single server) or createMCPClients (pool). Tool names are narrowed to the literal types declared by the server, so a typo is a compile error.
Single 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']Multi-server 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',
},
})
// Config keys are constrained to the declared servers — a typo is a compile error
const tools = await pool.tools()Now that tool names and pool keys are compile-checked, hand the generated client to chat(). See Managed MCP with chat() to let chat() own discovery and lifecycle.