Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
f4ac15a
chore(ai-mcp): scaffold @tanstack/ai-mcp package
AlemTuzlak Jun 3, 2026
8fa56bf
feat(ai): expose abortSignal on ToolExecutionContext
AlemTuzlak Jun 3, 2026
feca146
feat(ai-mcp): transport config types and resolver with isolated stdio
AlemTuzlak Jun 3, 2026
25d07ec
feat(ai): thread chat-run abort signal into tool execution context
AlemTuzlak Jun 3, 2026
4e742f3
feat(ai-mcp): core types and error classes
AlemTuzlak Jun 3, 2026
65caeb5
test(ai-mcp): in-memory MCP server helper
AlemTuzlak Jun 3, 2026
fc64673
feat(ai-mcp): convert MCP tool definitions to TanStack ServerTools
AlemTuzlak Jun 3, 2026
48b75b5
feat(ai-mcp): MCPClient connect, tools discovery, and lifecycle
AlemTuzlak Jun 3, 2026
7eb89dc
feat(ai-mcp): definition-binding tools() with MCPToolNotFoundError + …
AlemTuzlak Jun 3, 2026
714a616
fix(ai-mcp): type capabilities from the server descriptor generic; dr…
AlemTuzlak Jun 3, 2026
d8cd75b
fix(ai-mcp): resolve capabilities cast lint in client
AlemTuzlak Jun 3, 2026
79a34c4
style(ai-mcp): resolve eslint errors across the package
AlemTuzlak Jun 3, 2026
6229e2b
feat(ai-mcp): createMCPClients multi-server pool with auto-prefix
AlemTuzlak Jun 3, 2026
43a82a3
feat(ai-mcp): type tools() output from the generated ServerDescriptor…
AlemTuzlak Jun 3, 2026
5686864
feat(ai-mcp): mcpResourceToContentPart converter + resource test helper
AlemTuzlak Jun 3, 2026
a0c2f60
docs(skills): document MCP tools and tool-context abortSignal
AlemTuzlak Jun 3, 2026
5311cd5
docs: add MCP server support guide
AlemTuzlak Jun 3, 2026
729cb70
chore: changeset for @tanstack/ai-mcp
AlemTuzlak Jun 3, 2026
ef25059
feat(ai-mcp): client resources() / readResource() / resourceTemplates()
AlemTuzlak Jun 3, 2026
440bbdd
feat(ai-mcp): mcpPromptToMessages converter + prompt test helper
AlemTuzlak Jun 3, 2026
9fd124c
feat(ai-mcp): client prompts() / getPrompt()
AlemTuzlak Jun 3, 2026
c98000a
feat(ai-mcp): codegen config schema and loader
AlemTuzlak Jun 3, 2026
a9fc65d
feat(ai-mcp): codegen server introspection
AlemTuzlak Jun 3, 2026
1cb806f
chore(ai-mcp): sync pnpm-lock.yaml with tsup ^8.5.1 bump
AlemTuzlak Jun 4, 2026
e7b07dc
feat(ai-mcp): codegen emit of ServerDescriptor types from JSON Schema
AlemTuzlak Jun 4, 2026
b6c42ab
feat(ai-mcp): generate CLI command
AlemTuzlak Jun 4, 2026
f45e2cb
test(ai-mcp): cover loadConfig JSON fallback and missing-config error
AlemTuzlak Jun 4, 2026
954762e
test(e2e): MCP server tool discovery and execution in chat()
AlemTuzlak Jun 4, 2026
da5c7d7
docs: document MCP prompts API
AlemTuzlak Jun 4, 2026
866a9a5
fix(ai-mcp): expose defineConfig via ./cli subpath export
AlemTuzlak Jun 4, 2026
bb4c540
fix(ai-mcp): emit flat lib build and expose defineConfig from main en…
AlemTuzlak Jun 4, 2026
4e6220d
ci: apply automated fixes
autofix-ci[bot] Jun 4, 2026
16872d5
feat(ai): MCPToolSource interface and chat mcp option types
AlemTuzlak Jun 4, 2026
2a9010a
feat(ai): export MCP chat option types
AlemTuzlak Jun 4, 2026
3e9fb74
feat(ai): MCPManager — encapsulates chat mcp discovery + lifecycle
AlemTuzlak Jun 4, 2026
40e0a39
feat(ai): add mcp option to TextActivityOptions
AlemTuzlak Jun 4, 2026
c5c7b5d
feat(ai): wire MCPManager into chat() runners
AlemTuzlak Jun 4, 2026
d4c966c
test(ai): chat({ mcp }) discovery and lifecycle behavior
AlemTuzlak Jun 4, 2026
fe08737
fix(ai): remove unused serverTool import in chat-mcp test
AlemTuzlak Jun 4, 2026
864dc74
test(ai-mcp): assert MCPClient/MCPClients satisfy MCPToolSource
AlemTuzlak Jun 4, 2026
2b89988
chore: changeset for chat({ mcp })
AlemTuzlak Jun 4, 2026
12afdcd
docs(skills): document chat({ mcp })
AlemTuzlak Jun 4, 2026
3867178
docs: document chat({ mcp }) for managing MCP clients
AlemTuzlak Jun 4, 2026
a0ed9f1
test(e2e): chat({ mcp }) managed-client discovery and execution
AlemTuzlak Jun 4, 2026
0a8888d
docs(skills): fix inverted connection keep-alive semantics in examples
AlemTuzlak Jun 4, 2026
1bcbeb3
fix(ai): export MCPDuplicateToolNameError and correct cross-client co…
AlemTuzlak Jun 4, 2026
813b691
chore: ignore .test-d.ts type-test files in knip
AlemTuzlak Jun 4, 2026
d744a90
Merge remote-tracking branch 'origin/feat/mcp-support' into feat/chat…
AlemTuzlak Jun 4, 2026
0b9ea1f
feat(ai-mcp): re-export Transport type and InMemoryTransport for the …
AlemTuzlak Jun 4, 2026
adcc4bb
docs: split MCP docs into focused pages (core client, codegen, chat m…
AlemTuzlak Jun 4, 2026
18fea43
example(ts-react-chat): MCP server routes — manual, chat({ mcp }), an…
AlemTuzlak Jun 4, 2026
262cbdb
example(ts-react-chat): MCP demo page with manual/chat/pool mode sele…
AlemTuzlak Jun 4, 2026
8c5b1fb
chore(ts-react-chat): keep dependencies alphabetically sorted
AlemTuzlak Jun 4, 2026
5be236e
fix(ts-react-chat): use gpt-5.5 for MCP example routes
AlemTuzlak Jun 4, 2026
7b926c0
feat(ts-react-chat): add MCP Servers link to sidebar
AlemTuzlak Jun 4, 2026
dd5f064
fix(openai-base): strip unsupported JSON Schema formats from tool/out…
AlemTuzlak Jun 4, 2026
10858e3
chore(ts-react-chat): regenerate routeTree in canonical order
AlemTuzlak Jun 4, 2026
b8288fd
Merge remote-tracking branch 'origin/main' into feat/chat-mcp-prop
AlemTuzlak Jun 4, 2026
f515a25
feat(ts-react-chat): pass stable per-mode threadId in MCP demo for de…
AlemTuzlak Jun 4, 2026
2ad4c0a
ci: apply automated fixes
autofix-ci[bot] Jun 4, 2026
e5a7e2e
feat(ts-react-chat): render tool calls and results in MCP demo UI
AlemTuzlak Jun 4, 2026
cd20d4d
Merge remote-tracking branch 'origin/feat/mcp-support' into feat/chat…
AlemTuzlak Jun 4, 2026
75b04cf
ci: apply automated fixes
autofix-ci[bot] Jun 4, 2026
11ae5cd
test(mcp): cover structured-output runners + real pool passed into ch…
AlemTuzlak Jun 4, 2026
1dc2dea
feat(ts-react-chat): switch LLM provider in MCP demo (OpenAI/Anthropi…
AlemTuzlak Jun 4, 2026
f60eca1
Merge remote-tracking branch 'origin/feat/mcp-support' into feat/chat…
AlemTuzlak Jun 4, 2026
e0ae7e5
ci: apply automated fixes
autofix-ci[bot] Jun 4, 2026
2321906
test(e2e): cover MCP resource/prompt read + connection lifecycle (kee…
AlemTuzlak Jun 4, 2026
7421a16
feat(ts-react-chat): add /api/mcp-status endpoint and OpenRouter prov…
AlemTuzlak Jun 4, 2026
d6d4684
Merge remote-tracking branch 'origin/feat/mcp-support' into feat/chat…
AlemTuzlak Jun 4, 2026
a75d962
ci: apply automated fixes
autofix-ci[bot] Jun 4, 2026
adf3ed4
fix(ai-mcp): apply PR review fixes, document OAuth, use TanStack Star…
tombeckenham Jun 5, 2026
5359bfa
fix(ai-mcp): exclude task-required tools from discovery, throw on exp…
tombeckenham Jun 5, 2026
534ecc3
docs(mcp): rename guide pages to managed/manual, simplify examples
tombeckenham Jun 5, 2026
6baaa58
fix: apply CodeRabbit review fixes across ai-mcp, chat core, and exam…
tombeckenham Jun 5, 2026
9634321
Added extra link to the docs
tombeckenham Jun 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chat-mcp-option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/ai': minor
---

Add an `mcp` option to `chat()` for managing MCP clients directly: `chat({ mcp: { clients, connection, lazyTools, onDiscoveryError } })` discovers the given MCP clients'/pools' tools at run start, merges them into the run, and (by default, `connection: 'close'`) closes them when the run ends — or keeps them warm with `connection: 'keep-alive'`. Also exports `MCPToolSource`, `ChatMCPOptions`, `MCPConnectionPolicy`, and `MCPDuplicateToolNameError` (the error thrown when tools from separate `mcp.clients` entries collide after merging; catchable with `instanceof`).
6 changes: 6 additions & 0 deletions .changeset/mcp-server-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@tanstack/ai-mcp': minor
'@tanstack/ai': minor
---

Add `@tanstack/ai-mcp`: a host-side Model Context Protocol client. Discover and run MCP server tools (and read resources/prompts) inside any adapter's `chat()` loop, with three type-safety modes (auto-discovery, hand-written `toolDefinition()` binding, and generated end-to-end types via `npx @tanstack/ai-mcp generate`). Includes `createMCPClients` for connecting to multiple servers with auto-prefixed tool names. Also exposes `abortSignal` on `ToolExecutionContext` so long-running tools (e.g. MCP `callTool`) cancel with the chat run.
5 changes: 5 additions & 0 deletions .changeset/strip-unsupported-openai-formats.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/openai-base': patch
---

Strip JSON Schema `format` values that OpenAI's strict Structured Outputs subset rejects (e.g. `uri`, `uri-reference`, `iri`) from tool and response schemas before sending. Tools whose input schemas declare an unsupported `format` — common with MCP server tools — previously caused the entire request to fail with `400 ... '<format>' is not a valid format`. Supported formats (`date-time`, `time`, `date`, `duration`, `email`, `hostname`, `ipv4`, `ipv6`, `uuid`) are preserved, and the caller's original tool definition is never mutated.
16 changes: 16 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,22 @@
{
"label": "Lazy Tool Discovery",
"to": "tools/lazy-tool-discovery"
},
{
"label": "MCP Server Tools",
"to": "tools/mcp"
},
{
"label": "Managed MCP with chat()",
"to": "tools/mcp-managed"
},
{
"label": "Manual MCP: Tools, Resources & Prompts",
"to": "tools/mcp-manual"
},
{
"label": "MCP Type Generation",
"to": "tools/mcp-codegen"
}
]
},
Expand Down
122 changes: 122 additions & 0 deletions docs/tools/mcp-codegen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
title: MCP Type Generation
id: mcp-codegen
order: 11
description: "Generate per-server TypeScript interface types from a live MCP server and wire them into createMCPClient for typed tool names and compile-checked pool keys."
keywords:
- tanstack ai
- mcp
- model context protocol
- codegen
- type safety
- mcp.config.ts
- defineConfig
- createMCPClient
- generated types
---

You have a running MCP server and you call its tools through [`createMCPClient`](./mcp), 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](./mcp#mode-3--generated-types-createmcpclientgeneratedserver) of MCP type safety. (Tool *arguments* stay untyped on the discovery path — for Zod-validated, TypeScript-typed arguments, combine with the [`tools([toolDefinition(...)])` overload](./mcp#mode-2--explicit-definitions-clienttoolsdefs).)

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.

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

```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 generated types at runtime

Pass the generated type as a generic to [`createMCPClient`](./mcp) (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:**

```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']
```

**Multi-server 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',
},
})

// 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()`](./mcp-managed) to let `chat()` own discovery and lifecycle.
Loading
Loading