Skip to content
MCP

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.

ts
// 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

shell
npx @tanstack/ai-mcp generate

The 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:

ts
// 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:

ts
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:

ts
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.