# 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](./mcp-advanced#mode-2-explicit-definitions).

## 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

```bash
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()](./mcp-managed).

Package names for an `@modelcontextprotocol/sdk` import are in [MCP SDK packages](../migration/mcp-sdk).
