Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
496e8143 feat: host-side MCP client (@tanstack/ai-mcp) (#700)
* chore(ai-mcp): scaffold @tanstack/ai-mcp package
* feat(ai): expose abortSignal on ToolExecutionContext
* feat(ai-mcp): transport config types and resolver with isolated stdio
* feat(ai): thread chat-run abort signal into tool execution context
* feat(ai-mcp): core types and error classes
* test(ai-mcp): in-memory MCP server helper
* feat(ai-mcp): convert MCP tool definitions to TanStack ServerTools
* feat(ai-mcp): MCPClient connect, tools discovery, and lifecycle
* feat(ai-mcp): definition-binding tools() with MCPToolNotFoundError + duplicate detection
* fix(ai-mcp): type capabilities from the server descriptor generic; drop redundant lazy cast
* fix(ai-mcp): resolve capabilities cast lint in client
* style(ai-mcp): resolve eslint errors across the package
* feat(ai-mcp): createMCPClients multi-server pool with auto-prefix
* feat(ai-mcp): type tools() output from the generated ServerDescriptor generic
* feat(ai-mcp): mcpResourceToContentPart converter + resource test helper
* docs(skills): document MCP tools and tool-context abortSignal
* docs: add MCP server support guide
* chore: changeset for @tanstack/ai-mcp
* feat(ai-mcp): client resources() / readResource() / resourceTemplates()
* feat(ai-mcp): mcpPromptToMessages converter + prompt test helper
* feat(ai-mcp): client prompts() / getPrompt()
* feat(ai-mcp): codegen config schema and loader
* feat(ai-mcp): codegen server introspection
* chore(ai-mcp): sync pnpm-lock.yaml with tsup ^8.5.1 bump
* feat(ai-mcp): codegen emit of ServerDescriptor types from JSON Schema
* feat(ai-mcp): generate CLI command
* test(ai-mcp): cover loadConfig JSON fallback and missing-config error
* test(e2e): MCP server tool discovery and execution in chat()
* docs: document MCP prompts API
* fix(ai-mcp): expose defineConfig via ./cli subpath export
* fix(ai-mcp): emit flat lib build and expose defineConfig from main entry (no jiti in lib)
* ci: apply automated fixes
* feat(ai): MCPToolSource interface and chat mcp option types
* feat(ai): export MCP chat option types
* feat(ai): MCPManager — encapsulates chat mcp discovery + lifecycle
* feat(ai): add mcp option to TextActivityOptions
* feat(ai): wire MCPManager into chat() runners
* test(ai): chat({ mcp }) discovery and lifecycle behavior
* fix(ai): remove unused serverTool import in chat-mcp test
* test(ai-mcp): assert MCPClient/MCPClients satisfy MCPToolSource
* chore: changeset for chat({ mcp })
* docs(skills): document chat({ mcp })
* docs: document chat({ mcp }) for managing MCP clients
* test(e2e): chat({ mcp }) managed-client discovery and execution
* docs(skills): fix inverted connection keep-alive semantics in examples
* fix(ai): export MCPDuplicateToolNameError and correct cross-client collision docs
* chore: ignore .test-d.ts type-test files in knip
* feat(ai-mcp): re-export Transport type and InMemoryTransport for the custom-transport escape hatch
* docs: split MCP docs into focused pages (core client, codegen, chat mcp, manual chat integration)
* example(ts-react-chat): MCP server routes — manual, chat({ mcp }), and pool (keyless stdio reference servers)
* example(ts-react-chat): MCP demo page with manual/chat/pool mode selector
* chore(ts-react-chat): keep dependencies alphabetically sorted
* fix(ts-react-chat): use gpt-5.5 for MCP example routes
* feat(ts-react-chat): add MCP Servers link to sidebar
* fix(openai-base): strip unsupported JSON Schema formats from tool/output schemas
* chore(ts-react-chat): regenerate routeTree in canonical order
* feat(ts-react-chat): pass stable per-mode threadId in MCP demo for devtools grouping
* ci: apply automated fixes
* feat(ts-react-chat): render tool calls and results in MCP demo UI
* ci: apply automated fixes
* test(mcp): cover structured-output runners + real pool passed into chat({ mcp })
* feat(ts-react-chat): switch LLM provider in MCP demo (OpenAI/Anthropic/Gemini/Groq)
* ci: apply automated fixes
* test(e2e): cover MCP resource/prompt read + connection lifecycle (keep-alive vs close)
* feat(ts-react-chat): add /api/mcp-status endpoint and OpenRouter provider (default)
* ci: apply automated fixes
* fix(ai-mcp): apply PR review fixes, document OAuth, use TanStack Start in examples
Review fixes:
- docs: correct chat() signature (adapter: openaiText('gpt-5.5'), no top-level model)
- docs/skills: fix close-before-consume lifecycle samples — close MCP clients in
middleware terminal hooks (onFinish/onAbort/onError), not try/finally or
await using around a streaming return
- skills: repair truncated/unbalanced code fence corrupting the Provider Skills
section in tool-calling SKILL.md
- example: settle parallel createMCPClient calls in api.mcp-chat.ts and close the
connected sibling on partial failure (no leaked stdio subprocess)
- example: probe capabilities in api.mcp-status.ts instead of catch-all-ing
resources()/prompts()
- ai-mcp: name the tool in MCP isError throws; short-circuit already-aborted
signals; pool.tools() now attributes the failing server by config key
- ai(chat): correct MCPConnectionPolicy JSDoc ('close' = when the run ends;
'keep-alive' = never closed by chat())
- types: collapse redundant AutomaticDescriptor; reword DescribedTool/codegen
claims to name-only typing (args stay untyped on discovery; Mode 2 types args)
New coverage (ai-mcp 30 → 46 tests):
- isError path, abort→callTool forwarding, already-aborted short-circuit,
structuredContent preference, mcpContentToTanstack branches
- replace tautological duplicate-name test with one exercising the real guard
- connect-failure wrapping, double-close idempotency, bound-defs prefix,
pool tools() failure attribution, stdio smoke test, authProvider forwarding
- types.test-d.ts pins the descriptor name-literal guarantee
Docs additions:
- Authentication section (headers + OAuth authProvider + finishAuth caveat) in
mcp.md and the ai-mcp skill
- all MCP route examples converted from Next.js App Router to TanStack Start
(createFileRoute + server handlers); no Next.js references remain in PR files
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ai-mcp): exclude task-required tools from discovery, throw on explicit binding
Newer MCP servers (e.g. @modelcontextprotocol/server-everything's
simulate-research-query) mark tools with `execution.taskSupport: 'required'`
(experimental MCP tasks). Plain `callTool` — what @tanstack/ai-mcp uses — is
rejected by the server with -32600, so offering these tools to the model
guarantees a failed tool call.
- tools(): auto-discovery now filters task-required tools via the new
`requiresTaskExecution()` guard — the model is never offered a tool that
cannot succeed
- tools([defs]): explicitly binding a task-required tool throws the new
`MCPTaskRequiredToolError` (exported) with guidance pointing at the SDK's
tasks API
- tests: in-memory server helper registering a real task-required tool;
discovery-exclusion + binding-throws coverage (48 tests)
- e2e: in-process MCP server registers a task-required tool; spec asserts it
never reaches the discovered tool list
- docs: Mode 1 exclusion callout, Mode 2 error mention, Error Reference row
in mcp.md; matching error-list updates in the ai-mcp skill
Actual task-based execution support (client.experimental.tasks.callToolStream)
is tracked in #704.
Also includes import-order/lint cleanup in examples/ts-react-chat
api.mcp-manual.ts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(mcp): rename guide pages to managed/manual, simplify examples
- rename mcp-chat.md → mcp-managed.md ("Managed MCP with chat()") and
mcp-with-chat.md → mcp-manual.md ("Manual MCP: typed tools, resources &
prompts") — the old slugs differed only by a preposition while the real
distinction is managed vs manual lifecycle; new names match the vocabulary
already used by the e2e/example routes (api.mcp-managed-test, api.mcp-manual)
- update all ids, cross-links, link texts, and docs/config.json nav labels
- Quick Start (mcp.md) now leads with the managed mcp option (zero lifecycle
code) instead of the manual middleware-close pattern; Lifecycle section
opens with the managed escape hatch before the manual rules
- mcp-managed.md: keep one full route example (plus keep-warm, where module
vs handler placement is the point); convert the other five examples to
focused fragments showing just the client setup + chat() call; drop the
repeated 8-line body-validation boilerplate (449 → 306 lines)
- reorder sidebar/frontmatter to adoption order:
mcp → mcp-managed → mcp-manual → mcp-codegen
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: apply CodeRabbit review fixes across ai-mcp, chat core, and examples
- emit.ts: guarantee valid/unique generated identifiers, escape string
literals via JSON.stringify when emitting TypeScript
- introspect.ts: move connect() inside try/finally, guard close() from
masking the original error, drain cursor-paginated list endpoints
- prompts.ts: never produce undefined content (JSON.stringify(x ?? null))
- manager.ts: await onDiscoveryError so async handlers fail fast
- chat: combine caller + middleware abort signals so ctx.abort() reaches
running tools via ctx.abortSignal (regression test added)
- mcp routes (e2e + example): close MCP client on non-stream error paths,
bridge request aborts during setup
- mcp-demo/threads: pass remark-gfm via remarkPlugins (not rehypePlugins)
- tests: fix import/order lint errors, assert pool cleanup on failure,
cover hostile-name escaping and interface collisions in emit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Added extra link to the docs
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 496e8143 feat: host-side MCP client (@tanstack/ai-mcp) (#700)
* chore(ai-mcp): scaffold @tanstack/ai-mcp package
* feat(ai): expose abortSignal on ToolExecutionContext
* feat(ai-mcp): transport config types and resolver with isolated stdio
* feat(ai): thread chat-run abort signal into tool execution context
* feat(ai-mcp): core types and error classes
* test(ai-mcp): in-memory MCP server helper
* feat(ai-mcp): convert MCP tool definitions to TanStack ServerTools
* feat(ai-mcp): MCPClient connect, tools discovery, and lifecycle
* feat(ai-mcp): definition-binding tools() with MCPToolNotFoundError + duplicate detection
* fix(ai-mcp): type capabilities from the server descriptor generic; drop redundant lazy cast
* fix(ai-mcp): resolve capabilities cast lint in client
* style(ai-mcp): resolve eslint errors across the package
* feat(ai-mcp): createMCPClients multi-server pool with auto-prefix
* feat(ai-mcp): type tools() output from the generated ServerDescriptor generic
* feat(ai-mcp): mcpResourceToContentPart converter + resource test helper
* docs(skills): document MCP tools and tool-context abortSignal
* docs: add MCP server support guide
* chore: changeset for @tanstack/ai-mcp
* feat(ai-mcp): client resources() / readResource() / resourceTemplates()
* feat(ai-mcp): mcpPromptToMessages converter + prompt test helper
* feat(ai-mcp): client prompts() / getPrompt()
* feat(ai-mcp): codegen config schema and loader
* feat(ai-mcp): codegen server introspection
* chore(ai-mcp): sync pnpm-lock.yaml with tsup ^8.5.1 bump
* feat(ai-mcp): codegen emit of ServerDescriptor types from JSON Schema
* feat(ai-mcp): generate CLI command
* test(ai-mcp): cover loadConfig JSON fallback and missing-config error
* test(e2e): MCP server tool discovery and execution in chat()
* docs: document MCP prompts API
* fix(ai-mcp): expose defineConfig via ./cli subpath export
* fix(ai-mcp): emit flat lib build and expose defineConfig from main entry (no jiti in lib)
* ci: apply automated fixes
* feat(ai): MCPToolSource interface and chat mcp option types
* feat(ai): export MCP chat option types
* feat(ai): MCPManager — encapsulates chat mcp discovery + lifecycle
* feat(ai): add mcp option to TextActivityOptions
* feat(ai): wire MCPManager into chat() runners
* test(ai): chat({ mcp }) discovery and lifecycle behavior
* fix(ai): remove unused serverTool import in chat-mcp test
* test(ai-mcp): assert MCPClient/MCPClients satisfy MCPToolSource
* chore: changeset for chat({ mcp })
* docs(skills): document chat({ mcp })
* docs: document chat({ mcp }) for managing MCP clients
* test(e2e): chat({ mcp }) managed-client discovery and execution
* docs(skills): fix inverted connection keep-alive semantics in examples
* fix(ai): export MCPDuplicateToolNameError and correct cross-client collision docs
* chore: ignore .test-d.ts type-test files in knip
* feat(ai-mcp): re-export Transport type and InMemoryTransport for the custom-transport escape hatch
* docs: split MCP docs into focused pages (core client, codegen, chat mcp, manual chat integration)
* example(ts-react-chat): MCP server routes — manual, chat({ mcp }), and pool (keyless stdio reference servers)
* example(ts-react-chat): MCP demo page with manual/chat/pool mode selector
* chore(ts-react-chat): keep dependencies alphabetically sorted
* fix(ts-react-chat): use gpt-5.5 for MCP example routes
* feat(ts-react-chat): add MCP Servers link to sidebar
* fix(openai-base): strip unsupported JSON Schema formats from tool/output schemas
* chore(ts-react-chat): regenerate routeTree in canonical order
* feat(ts-react-chat): pass stable per-mode threadId in MCP demo for devtools grouping
* ci: apply automated fixes
* feat(ts-react-chat): render tool calls and results in MCP demo UI
* ci: apply automated fixes
* test(mcp): cover structured-output runners + real pool passed into chat({ mcp })
* feat(ts-react-chat): switch LLM provider in MCP demo (OpenAI/Anthropic/Gemini/Groq)
* ci: apply automated fixes
* test(e2e): cover MCP resource/prompt read + connection lifecycle (keep-alive vs close)
* feat(ts-react-chat): add /api/mcp-status endpoint and OpenRouter provider (default)
* ci: apply automated fixes
* fix(ai-mcp): apply PR review fixes, document OAuth, use TanStack Start in examples
Review fixes:
- docs: correct chat() signature (adapter: openaiText('gpt-5.5'), no top-level model)
- docs/skills: fix close-before-consume lifecycle samples — close MCP clients in
middleware terminal hooks (onFinish/onAbort/onError), not try/finally or
await using around a streaming return
- skills: repair truncated/unbalanced code fence corrupting the Provider Skills
section in tool-calling SKILL.md
- example: settle parallel createMCPClient calls in api.mcp-chat.ts and close the
connected sibling on partial failure (no leaked stdio subprocess)
- example: probe capabilities in api.mcp-status.ts instead of catch-all-ing
resources()/prompts()
- ai-mcp: name the tool in MCP isError throws; short-circuit already-aborted
signals; pool.tools() now attributes the failing server by config key
- ai(chat): correct MCPConnectionPolicy JSDoc ('close' = when the run ends;
'keep-alive' = never closed by chat())
- types: collapse redundant AutomaticDescriptor; reword DescribedTool/codegen
claims to name-only typing (args stay untyped on discovery; Mode 2 types args)
New coverage (ai-mcp 30 → 46 tests):
- isError path, abort→callTool forwarding, already-aborted short-circuit,
structuredContent preference, mcpContentToTanstack branches
- replace tautological duplicate-name test with one exercising the real guard
- connect-failure wrapping, double-close idempotency, bound-defs prefix,
pool tools() failure attribution, stdio smoke test, authProvider forwarding
- types.test-d.ts pins the descriptor name-literal guarantee
Docs additions:
- Authentication section (headers + OAuth authProvider + finishAuth caveat) in
mcp.md and the ai-mcp skill
- all MCP route examples converted from Next.js App Router to TanStack Start
(createFileRoute + server handlers); no Next.js references remain in PR files
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ai-mcp): exclude task-required tools from discovery, throw on explicit binding
Newer MCP servers (e.g. @modelcontextprotocol/server-everything's
simulate-research-query) mark tools with `execution.taskSupport: 'required'`
(experimental MCP tasks). Plain `callTool` — what @tanstack/ai-mcp uses — is
rejected by the server with -32600, so offering these tools to the model
guarantees a failed tool call.
- tools(): auto-discovery now filters task-required tools via the new
`requiresTaskExecution()` guard — the model is never offered a tool that
cannot succeed
- tools([defs]): explicitly binding a task-required tool throws the new
`MCPTaskRequiredToolError` (exported) with guidance pointing at the SDK's
tasks API
- tests: in-memory server helper registering a real task-required tool;
discovery-exclusion + binding-throws coverage (48 tests)
- e2e: in-process MCP server registers a task-required tool; spec asserts it
never reaches the discovered tool list
- docs: Mode 1 exclusion callout, Mode 2 error mention, Error Reference row
in mcp.md; matching error-list updates in the ai-mcp skill
Actual task-based execution support (client.experimental.tasks.callToolStream)
is tracked in #704.
Also includes import-order/lint cleanup in examples/ts-react-chat
api.mcp-manual.ts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(mcp): rename guide pages to managed/manual, simplify examples
- rename mcp-chat.md → mcp-managed.md ("Managed MCP with chat()") and
mcp-with-chat.md → mcp-manual.md ("Manual MCP: typed tools, resources &
prompts") — the old slugs differed only by a preposition while the real
distinction is managed vs manual lifecycle; new names match the vocabulary
already used by the e2e/example routes (api.mcp-managed-test, api.mcp-manual)
- update all ids, cross-links, link texts, and docs/config.json nav labels
- Quick Start (mcp.md) now leads with the managed mcp option (zero lifecycle
code) instead of the manual middleware-close pattern; Lifecycle section
opens with the managed escape hatch before the manual rules
- mcp-managed.md: keep one full route example (plus keep-warm, where module
vs handler placement is the point); convert the other five examples to
focused fragments showing just the client setup + chat() call; drop the
repeated 8-line body-validation boilerplate (449 → 306 lines)
- reorder sidebar/frontmatter to adoption order:
mcp → mcp-managed → mcp-manual → mcp-codegen
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: apply CodeRabbit review fixes across ai-mcp, chat core, and examples
- emit.ts: guarantee valid/unique generated identifiers, escape string
literals via JSON.stringify when emitting TypeScript
- introspect.ts: move connect() inside try/finally, guard close() from
masking the original error, drain cursor-paginated list endpoints
- prompts.ts: never produce undefined content (JSON.stringify(x ?? null))
- manager.ts: await onDiscoveryError so async handlers fail fast
- chat: combine caller + middleware abort signals so ctx.abort() reaches
running tools via ctx.abortSignal (regression test added)
- mcp routes (e2e + example): close MCP client on non-stream error paths,
bridge request aborts during setup
- mcp-demo/threads: pass remark-gfm via remarkPlugins (not rehypePlugins)
- tests: fix import/order lint errors, assert pool cleanup on failure,
cover hostile-name escaping and interface collisions in emit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Added extra link to the docs
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>