import type { ToolDefinition } from '../types/messages.js'; import { type McpElicitationRequest, type McpElicitationResult, type McpRoot, type McpSamplingRequest, type McpSamplingResult, type McpTransport } from './protocol.js'; /** * What a server says a tool does, as MCP's tool annotations: hints, which a client trusts only as far * as it trusts the server. A hint left out takes the specification's default. */ export interface McpToolAnnotations { /** A name for people. */ title?: string; /** It changes nothing. Defaults to false. */ readOnlyHint?: boolean; /** When it changes things, it may destroy or overwrite them, not only add. Defaults to true. */ destructiveHint?: boolean; /** Calling it again with the same arguments changes nothing more. Defaults to false. */ idempotentHint?: boolean; /** It reaches things beyond the server, such as the web. Defaults to true. */ openWorldHint?: boolean; } /** A tool an MCP server offers. */ export interface McpToolDescriptor { /** The tool's name. */ name: string; /** What the tool does, for the model. */ description?: string; /** JSON Schema for the arguments. */ inputSchema?: Record; /** What the server says the tool does. */ annotations?: McpToolAnnotations; } /** * The capabilities an MCP tool declares, from what its server says of it in its annotations, so a * permission policy decides it as it decides any tool: * - `mcp.read:/` for a tool that only reads; * - `mcp.write:/` for one that changes things but destroys nothing; * - `mcp.destructive:/` for one that may destroy or overwrite; * - and `network`, beside it, for one that reaches beyond its server. * * A hint left out takes the specification's default: not read-only, destructive, and open. A tool * with no annotations at all declares nothing, `undefined`, so a policy decides it as undeclared. */ export declare function mcpToolCapabilities(tool: McpToolDescriptor, server: string): string[] | undefined; /** Options for `McpClient.toNexusTools()`. */ export interface McpToolsOptions { /** Put before each tool's name with an underscore, so two servers' `search` tools differ. */ prefix?: string; /** * The capabilities each tool declares: `true` reads them from the server's annotations, with * `mcpToolCapabilities()`, under the server's name (the prefix, or the name the server gives); a * function decides them per tool. Without it, a tool declares none, as before 2.17. */ capabilities?: boolean | ((tool: McpToolDescriptor) => readonly string[] | undefined); /** The server's name in each capability, when `capabilities` is `true`. Defaults to the prefix. */ server?: string; } /** A resource an MCP server offers. */ export interface McpResourceDescriptor { /** The resource's URI. */ uri: string; /** A readable name. */ name?: string; /** What the resource contains. */ description?: string; /** Its MIME type. */ mimeType?: string; } /** One piece of content from an MCP server: text, or base64 data with a MIME type. */ export interface McpContent { /** `text`, `image`, `resource`, or another type the server defines. */ type: string; /** The text, for text content. */ text?: string; /** Base64 data, for binary content. */ data?: string; /** MIME type of `data`. */ mimeType?: string; [key: string]: unknown; } /** What a tool call returned. */ export interface McpToolResult { /** The result, as content parts. */ content: McpContent[]; /** True when the tool reported a failure rather than a result. */ isError?: boolean; } /** Options for an MCP client. */ export interface McpClientOptions { /** Name and version this client reports in the handshake. */ clientInfo?: { name: string; version: string; }; /** How long a request waits before failing. Defaults to 30 seconds. */ timeoutMs?: number; /** * When the transport closes, as an SSE stream that ends or a server process that exits does, the * next request opens it again and repeats the handshake, since the server's session went with it. * Requests in flight still fail, and a client closed with `close()` stays closed. Needs a transport * that can open again: `createStdioTransport` starts a new process, `createSseTransport` with * `reopen` a new stream. */ reconnect?: boolean; /** * Answers a server's `sampling/createMessage` with this client's model, so a server's tool can ask * for a completion: `samplingFrom(ai, { model })` is one. Declared to the server when given; * without it, a server's request for one is refused. */ sampling?: (request: McpSamplingRequest, context: { signal: AbortSignal; }) => McpSamplingResult | Promise; /** * Answers a server's `elicitation/create`, a question for the person using this client, with the * form of its answer. Declared to the server when given; without it, a request is refused. */ elicitation?: (request: McpElicitationRequest, context: { signal: AbortSignal; }) => McpElicitationResult | Promise; /** * The roots a server may work within, answered to its `roots/list`. Declared to the server when * given; `rootsChanged()` tells it they changed. */ roots?: () => McpRoot[] | Promise; } /** * Talks to an MCP server. * * This is how the package reaches a tool ecosystem without maintaining its own catalogue of * integrations: anything exposed over MCP — a filesystem server, a database, an internal service — * becomes tools an agent can call, through `toNexusTools()`. */ export declare class McpClient { private readonly transport; private readonly options; private readonly pending; private nextId; /** Where each progress token's reports go, while its tool call runs. */ private readonly progress; private initialized; private connecting; private serverInfo; /** Who hears that the server's tools changed. */ private readonly toolsChanged; /** Who hears each of the server's notifications, by method. */ private readonly listeners; /** Requests the server is waiting on this client for, by id, so a cancellation stops them. */ private readonly answering; private stopped; constructor(transport: McpTransport, options?: McpClientOptions); /** * Hears each `notifications/tools/list_changed` the server sends: its tools are no longer what * `listTools()` returned. Returns a function that stops hearing. */ onToolsChanged(handler: () => void): () => void; /** Hears each `notifications/prompts/list_changed`: the server's prompts changed. Returns a function that stops hearing. */ onPromptsChanged(handler: () => void): () => void; /** Hears each `notifications/resources/list_changed`: the server's resources changed. Returns a function that stops hearing. */ onResourcesChanged(handler: () => void): () => void; /** * Hears each `notifications/resources/updated`, for a resource this client subscribed to with * `subscribeResource()`: its URI. Returns a function that stops hearing. */ onResourceUpdated(handler: (uri: string) => void): () => void; /** Asks the server to say when a resource changes, by `onResourceUpdated()`. */ subscribeResource(uri: string): Promise; /** Stops hearing that a resource changed. */ unsubscribeResource(uri: string): Promise; /** Tells the server this client's roots changed, so it lists them again. */ rootsChanged(): Promise; private listen; /** * Performs the handshake and returns the server's name and version. Called automatically by the * first request that needs it; requests made together share one handshake. */ connect(): Promise<{ name?: string; version?: string; }>; private handshake; /** Lists the server's tools. */ listTools(): Promise; /** * Calls a tool. A tool that fails reports `isError` rather than throwing; a protocol failure * throws `McpError`. */ callTool(name: string, args?: Record, options?: { progress?: (progress: { progress: number; total?: number; message?: string; }) => void; }): Promise; /** Lists the server's resources. */ listResources(): Promise; /** Reads a resource's content. */ readResource(uri: string): Promise; /** Lists the server's prompts. */ listPrompts(): Promise>; /** Renders a prompt with arguments into messages. */ getPrompt(name: string, args?: Record): Promise>; /** * The server's tools, ready for `createAgent` or `ToolExecutor`. * * Names are prefixed when asked, because two servers can both offer `search` and a model has to be * able to tell them apart. */ toNexusTools(options?: McpToolsOptions): Promise; /** Closes the connection and rejects every request still waiting. */ close(): Promise; private request; private notify; private receive; /** Answers one request the server sent, with its result or why not. */ private answer; private settle; private failAll; } /** Launches a local MCP server as a child process and talks to it over stdin and stdout. */ export interface StdioClientOptions { /** Executable to run. */ command: string; /** Its arguments. */ args?: string[]; /** Environment variables for the process. */ env?: Record; /** Working directory for the process. */ cwd?: string; /** * Which of this process's environment variables the server inherits, besides `env`. By default, * only what a process needs to start: the path, the home and temporary directories, the user, the * locale and terminal, the Windows system variables, proxies, and certificate settings. A server is * often third-party code, and must not see this process's API keys or database URLs. A list adds * the variables it names, `true` passes the whole environment, as releases before 2.4 did, and * `false` passes nothing but `env`. */ inheritEnv?: boolean | readonly string[]; } /** * The environment a server process starts with. Names compare without case, as Windows compares * them, and `LC_` locale settings are kept with the rest of the locale. */ export declare function serverEnvironment(source: Record, options?: Pick): Record; /** * Runs an MCP server as a child process and speaks to it over its stdin and stdout. * * The transport most MCP servers ship with. `node:child_process` is imported lazily, so a browser * or edge build that only uses the HTTP transport never reaches for it. When the process exits, the * transport closes; started again, it runs a new one. */ export declare function createStdioTransport(options: StdioClientOptions): McpTransport; /** Connects to a remote MCP server over HTTP. */ export interface HttpClientOptions { /** The server's endpoint. */ url: string; /** Headers sent with every request, such as authorization. */ headers?: Record; /** Replaces the global `fetch`. */ fetch?: typeof globalThis.fetch; /** * Holds a `GET` stream open once the server names a session, for what the server sends of its own * accord: notifications that its tools or resources changed, and requests outside any call. A server * that answers it with 405 does not offer one, and none is opened. Off by default. */ listen?: boolean; } /** * Speaks to an MCP server over streamable HTTP, MCP's transport since 2025-03-26: a `POST` per * message, answered as JSON or as a stream of events the transport reads as they come, so a server * may report progress and ask this client for something in the middle of a call. With `listen`, a * `GET` stream carries what the server sends of its own accord. It keeps the session the server * names, sends the protocol version on every request, and ends the session when it closes. */ export declare function createHttpTransport(options: HttpClientOptions): McpTransport; /** Connects to a remote MCP server over HTTP with Server-Sent Events, the transport before streamable HTTP. */ export interface SseClientOptions { /** The server's event stream: a `GET` here opens it, and the server names where to post messages. */ url: string; /** Headers sent with the stream's request and with every message, such as authorization. */ headers?: Record; /** Replaces the global `fetch`. */ fetch?: typeof globalThis.fetch; /** How long to wait for the server to name where messages go, in milliseconds. Defaults to 10 seconds. */ timeoutMs?: number; /** * Opens a new stream when the next message is sent after the stream ended, rather than staying * closed. The server starts a new session on it, so an `McpClient` with `reconnect` greets it again. */ reopen?: boolean; } /** * Speaks to an MCP server over HTTP with Server-Sent Events, as MCP's 2024-11-05 transport: one * long `GET` the server answers on, and a `POST` per message to the endpoint the stream names * first. The endpoint must be on the stream's own origin, so a server cannot send the messages, and * their headers, anywhere else. When the stream ends, the transport closes; with `reopen`, the next * message opens a new one. */ export declare function createSseTransport(options: SseClientOptions): McpTransport;