@tanstack/ai-mcp
Version:
Host-side Model Context Protocol client for TanStack AI: discover and run MCP server tools, resources, and prompts in any adapter's chat() loop, with generated end-to-end types.
63 lines (62 loc) • 3.77 kB
TypeScript
import { Client, ClientOptions } from '@modelcontextprotocol/sdk/client/index.js';
import { TransportConfig } from './transport.js';
import { AnyToolDefinition, AutomaticDescriptor, DescriptorTools, MCPClientOptions, MappedServerTools, ServerDescriptor, ToolsOptions } from './types.js';
import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
import { GetPromptResult, Prompt, ReadResourceResult, Resource, ResourceTemplate } from '@modelcontextprotocol/sdk/types.js';
export interface MCPClient<TServer extends ServerDescriptor = AutomaticDescriptor> {
readonly capabilities: TServer['capabilities'];
/**
* Auto-discovery: every server tool as a ServerTool. With a generated
* descriptor, tool names are typed as the descriptor's name literals;
* args/results stay untyped — use the `tools(defs)` overload for typed args.
*
* Both overloads yield {@link McpServerTool}s, so `tool.metadata.mcp` (the
* server's title / annotations) is typed without an annotation or a cast.
*/
tools: {
(options?: ToolsOptions): Promise<DescriptorTools<TServer>>;
/**
* Explicit: bind these TanStack toolDefinitions to the server (typed +
* validated, allowlist). Note: when the client has a `prefix`, the
* runtime tool name is `${prefix}_${def.name}` while the static `TName`
* stays the unprefixed definition name.
*/
<const TDefs extends ReadonlyArray<AnyToolDefinition>>(defs: TDefs, options?: ToolsOptions): Promise<MappedServerTools<TDefs>>;
};
resources: () => Promise<Array<Resource>>;
readResource: (uri: string) => Promise<ReadResourceResult>;
resourceTemplates: () => Promise<Array<ResourceTemplate>>;
prompts: () => Promise<Array<Prompt>>;
getPrompt: (name: string, args?: Record<string, string>) => Promise<GetPromptResult>;
callTool: (name: string, args?: Record<string, unknown>) => Promise<Awaited<ReturnType<Client['callTool']>>>;
/**
* The ORIGINAL connection descriptor this client was created from — the
* `transport` input and `prefix` passed to `createMCPClient`. Used by
* `createMcpAppCallHandler` to reconnect per-call (serverless-safe) without
* a separate transport-config map.
*
* `transport` is `undefined` when the client was built from a ready-made
* `Transport` instance rather than a serializable config — either via
* `createMCPClientFromTransport` (test-only) or `createMCPClient({ transport:
* <instance> })`. A live `Transport` instance is single-use and cannot be
* reconnected, so only serializable `TransportConfig`s are retained here.
*/
getInfo: () => {
transport: TransportConfig | undefined;
prefix: string | undefined;
/**
* The options this client was built with, so a caller that reconstructs it
* from this descriptor keeps them. Without it a rebuilt client silently
* reverts to the SDK defaults — including the AJV validator that edge
* runtimes cannot compile.
*
* Optional so an existing hand-rolled `MCPClient` keeps compiling.
*/
clientOptions?: ClientOptions;
};
close: () => Promise<void>;
[Symbol.asyncDispose]: () => Promise<void>;
}
export declare function createMCPClient<TServer extends ServerDescriptor = AutomaticDescriptor>(options: MCPClientOptions): Promise<MCPClient<TServer>>;
/** Test-only: connect directly from a transport instance (skips resolveTransport). */
export declare function createMCPClientFromTransport<TServer extends ServerDescriptor = AutomaticDescriptor>(transport: Transport, prefix?: string, clientOptions?: ClientOptions): Promise<MCPClient<TServer>>;