McpClient
Connects to MCP servers with scoped Effect clients.
Clients discover tools, prompts, resources and Agent Skills using the protocol revision
selected by their transport. callTool returns tool-reported errors as results; supplying a schema
turns them into a ToolError reason that retains the original result. Transport and
protocol failures fail the Effect. Interactive server requests, subscriptions, OAuth
and retries are not included.
Constructors
Creates a Streamable HTTP transport with request-owned JSON or SSE responses.
Signature
declare const http: (options: { readonly headers?: Readonly<Record<string, string>>; readonly maxMessageBytes?: ByteSize.Input; readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>; readonly url: string | URL;}) => Effect.Effect<Transport, McpClientError, HttpClient.HttpClient | Scope.Scope>Constructs and connects a client using the supplied MCP transport service and its protocol adapter.
Details
name, version and the optional title, description, websiteUrl and
icons identify the client to the server. timeout defaults to 60 seconds
and bounds initialization and each complete listTools, listPrompts,
listResources, listSkills or readResourceDirectory scan.
discoveryLimits sets the default scan limits of 100 pages and 10,000
items. callTool, getPrompt, readResource, getSkill and
readSkillResource have no deadline unless their own timeout option is
supplied.
extensions selects the protocol extensions the client declares. With
skills: true it declares the Skills extension (SEP-2640) and enables
listSkills, getSkill, readResourceDirectory and readSkillResource;
without it they fail with a ConfigurationError. They run only against a
server that declares the extension too, and skill entries are checked
against its rules. readSkillResource checks digests with SHA-256 on
crypto.subtle.
Schema decoding requires the schema's services from the caller.
Signature
declare const make: (options: { readonly description?: string; readonly discoveryLimits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly extensions?: { readonly skills?: boolean; }; readonly icons?: ReadonlyArray<McpSchema.Icon>; readonly name: string; readonly timeout?: Duration.Input; readonly title?: string; readonly version: string; readonly websiteUrl?: string;}) => Effect.Effect<McpClient, McpClientError, Scope.Scope | Transport>Starts a scoped subprocess using newline-delimited JSON-RPC.
Signature
declare const stdio: (options: { readonly command: ChildProcess.Command; readonly maxMessageBytes?: ByteSize.Input; readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>;}) => Effect.Effect<Transport, McpClientError, ChildProcessSpawner | Scope.Scope>Binds remote tools using the standard Toolkit implementation.
Details
Pass a prefix such as "reports__" or an options object. Tools are discovered
unless an approved tools snapshot is supplied. Remote JSON Schemas are
advertised as-is, and model tool names must be 1โ64 ASCII letters, digits,
underscores or hyphens. Build a new toolkit to pick up remote changes.
By default results are text and failures fail the Effect.
resultMode: "complete" returns the full CallToolResult and sends its
content to the model as text and file parts. failureMode: "return" returns
typed failures, including transport errors, to the model; ToolError keeps
the failed result. Type arguments that select a non-default mode require the
matching option.
timeout bounds each tool call. trustAnnotations copies server hints into
tool annotations but never sets approval. transformTool receives each
annotated tool before binding and must return a tool derived from it, e.g.
with setNeedsApproval, annotate or addDependency, keeping its name,
schemas and failure mode.
Signature
declare function toolkit(client: McpClient, prefix?: string): Effect<WithHandler<Record<string, Tool<string, { readonly failure: typeof McpClientError; readonly failureMode: "error"; readonly parameters: Unknown; readonly success: String;}, never, Execution>>>, McpClientError>declare function toolkit<ResultMode extends "text" | "complete" = "text", FailureMode extends FailureMode = "error", Requirements = never>(client: McpClient, options: { readonly prefix?: string; readonly timeout?: Input; readonly tools?: readonly Array<Tool>; readonly transformTool?: (tool: RemoteTool<ResultMode, FailureMode>, descriptor: Tool) => RemoteTool<ResultMode, FailureMode, Requirements>; readonly trustAnnotations?: boolean;} & [ResultMode] extends ["text"] ? { readonly resultMode?: "text";} : { readonly resultMode: ResultMode;} & [FailureMode] extends ["error"] ? { readonly failureMode?: "error";} : { readonly failureMode: FailureMode;}): Effect<WithHandler<Record<string, RemoteTool<ResultMode, FailureMode, Requirements>>>, McpClientError>Guards
Returns whether a value is an MCP client.
Signature
declare function isMcpClient(value: unknown): value is McpClientLayers
Provides a connected MCP client over Streamable HTTP using the HTTP client.
Signature
declare const layerHttp: (options: { readonly description?: string; readonly discoveryLimits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly extensions?: { readonly skills?: boolean; }; readonly headers?: Readonly<Record<string, string>>; readonly icons?: ReadonlyArray<McpSchema.Icon>; readonly maxMessageBytes?: ByteSize.Input; readonly name: string; readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>; readonly timeout?: Duration.Input; readonly title?: string; readonly url: string | URL; readonly version: string; readonly websiteUrl?: string;}) => Layer.Layer<McpClient, McpClientError, HttpClient.HttpClient>Example Providing an HTTP client connection
import { Layer } from "effect"import { McpClient, McpProtocol } from "effect/ai"import { FetchHttpClient } from "effect/http"
const ClientLayer = McpClient.layerHttp({ name: "report-workflow", version: "1.0.0", protocol: McpProtocol.v2026_07_28, url: "http://localhost:3000/mcp"}).pipe(Layer.provide(FetchHttpClient.layer))Provides a connected MCP client over stdio using the child process spawner.
Signature
declare const layerStdio: (options: { readonly command: ChildProcess.Command; readonly description?: string; readonly discoveryLimits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly extensions?: { readonly skills?: boolean; }; readonly icons?: ReadonlyArray<McpSchema.Icon>; readonly maxMessageBytes?: ByteSize.Input; readonly name: string; readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>; readonly timeout?: Duration.Input; readonly title?: string; readonly version: string; readonly websiteUrl?: string;}) => Layer.Layer<McpClient, McpClientError, ChildProcessSpawner>Models
A scoped connection to one MCP server.
Signature
interface McpClient { readonly "~effect/ai/McpClient": "~effect/ai/McpClient"; readonly callTool: { (params: { readonly arguments?: { [key: string]: any; }; readonly schema?: undefined; readonly tool: Tool; }, options?: { readonly timeout?: Input; }): Effect<CallToolResult, McpClientError>; <S extends Top>(params: { readonly arguments?: { [key: string]: any; }; readonly schema: S; readonly tool: Tool; }, options?: { readonly timeout?: Input; }): Effect<S["Type"], McpClientError, S["DecodingServices"]>; <S extends Top = never>(params: { readonly arguments?: { [key: string]: any; }; readonly schema?: S; readonly tool: Tool; }, options?: { readonly timeout?: Input; }): Effect<CallToolResult | S["Type"], McpClientError, S["DecodingServices"]>; }; readonly capabilities: ServerCapabilities; readonly getPrompt: (params: { readonly arguments?: { [key: string]: string; }; readonly prompt: Prompt; }, options?: { readonly timeout?: Input; }) => Effect<GetPromptResult, McpClientError>; readonly getSkill: (params: { readonly uri: string; }, options?: { readonly timeout?: Input; }) => Effect<Skill, McpClientError>; readonly instructions?: string; readonly listPrompts: (options?: { readonly limits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly timeout?: Input; }) => Effect<readonly Array<Prompt>, McpClientError>; readonly listResources: (options?: { readonly limits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly timeout?: Input; }) => Effect<readonly Array<Resource>, McpClientError>; readonly listSkills: (options?: { readonly limits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly onInvalidSkill?: (invalid: { readonly entry: unknown; readonly error: McpClientError; }) => Effect<void>; readonly timeout?: Input; }) => Effect<readonly Array<Skill>, McpClientError>; readonly listTools: (options?: { readonly limits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly timeout?: Input; }) => Effect<readonly Array<Tool>, McpClientError>; readonly protocolVersion: ProtocolVersion; readonly readResource: (params: { readonly uri: string; }, options?: { readonly timeout?: Input; }) => Effect<ReadResourceResult, McpClientError>; readonly readResourceDirectory: (params: { readonly uri: string; }, options?: { readonly limits?: { readonly maxItems?: number; readonly maxPages?: number; }; readonly timeout?: Input; }) => Effect<readonly Array<Resource>, McpClientError>; readonly readSkillResource: (params: { readonly skill: Skill; readonly uri: string; }, options?: { readonly timeout?: Input; }) => Effect<ReadResourceResult, McpClientError>; readonly serverInfo: Implementation | undefined;}ProtocolVersion
typeSupported MCP wire protocol revisions.
Signature
type ProtocolVersion = "2025-11-25" | "2026-07-28"RemoteTool
typeNative tool bound to a remote MCP descriptor with configurable result and failure modes.
Signature
type RemoteTool<ResultMode extends "text" | "complete" = "text", FailureMode extends Tool.FailureMode = "error", Requirements = never> = FailureMode extends Tool.FailureMode ? Tool.Tool<string, { readonly failure: typeof McpClientError; readonly failureMode: FailureMode; readonly parameters: typeof Schema.Unknown; readonly success: { readonly complete: typeof McpSchema.CallToolResult; readonly text: typeof Schema.String; }[ResultMode];}, Requirements> : neverExchanges JSON-RPC messages with one MCP server using its protocol adapter.
Signature
interface Transport { readonly "~effect/ai/McpClient/Transport": "~effect/ai/McpClient/Transport"; readonly isCallable: (tool: Tool) => boolean; readonly notify: (message: JsonRpcNotification) => Effect<void, McpClientError>; readonly protocol: ProtocolAdapter<ProtocolVersion>; readonly request: (message: { readonly id: string | number; readonly jsonrpc: "2.0"; readonly method: string; readonly params?: { [key: string]: unknown; }; }, tool?: Tool) => Effect<JsonRpcResponse, McpClientError>;}Services
Service tag for applications that provide one default MCP connection.
Signature
declare const McpClient: Context.Service<McpClient, McpClient>Annotation containing the remote descriptor used to bind an MCP tool.
Details
The descriptor is server-provided and should be treated as untrusted.
Signature
declare class ToolDescriptor extends Shape<"effect/ai/McpClient/ToolDescriptor", Tool, this> { constructor(_: never);}Service supplied by the built-in MCP transport constructors and layers.
Details
Transport construction owns cleanup through its Effect scope.
Signature
declare const Transport: Context.Service<Transport, Transport>