McpServer
Builds Model Context Protocol (MCP) servers with Effect.
The McpServer service stores the tools, resources, resource templates,
prompts, completions, initialized clients, and outgoing notifications exposed
by a server. This module also includes the server runner, custom protocol,
stdio, and HTTP layers, registration helpers, and APIs that let handlers ask
the connected client for structured input or read its advertised
capabilities.
Accessors
clientCapabilities
Accesses the current client's capabilities.
Signature
declare const clientCapabilities: Effect.Effect<ClientCapabilities, never, McpServerClient>Collects structured input from the current MCP client and decodes the
accepted response with schema.
Details
Accepted content is decoded with the supplied schema, declined requests fail
with ElicitationDeclined, and canceled requests interrupt the effect.
Signature
declare const elicit: <S extends Schema.ConstraintEncoder<Record<string, unknown>, unknown>>(options: { readonly message: string; readonly schema: S;}) => Effect.Effect<S["Type"], ElicitationDeclined, McpServerClient | S["DecodingServices"]>Handlers
registerPrompt
Registers an MCP prompt from an Effect program.
When to use
Use when you are already inside an Effect program with an McpServer
service and need to add a prompt handler directly.
Details
Parameters are decoded with the supplied schema, completion handlers encode per-parameter suggestions, and string prompt content is converted into a user text message.
See
- prompt for the layer-based prompt registration wrapper
Signature
declare function registerPrompt<E, R, Params extends Fields = {}, Completions extends { [K in string | number | symbol]: (input: string, context: { readonly arguments?: { [key: string]: string; };} | undefined) => Effect<Array<Params[K]>, any, any> } = {}>(options: { readonly annotations?: Context<never>; readonly completion?: ValidateCompletions<Completions, Extract<keyof Params, string>>; readonly content: (params: Params) => Effect<string | Array<PromptMessage>, E, R>; readonly description?: string; readonly name: string; readonly parameters?: Params;}): Effect<void, never, McpServer | Exclude<R, McpServerClient> | Exclude<DecodingServices<Params>, McpServerClient>>registerResource
Registers an MCP resource or resource template from an Effect program.
When to use
Use when you are already inside an Effect program with an McpServer
service and need to add a concrete resource or URI-template resource
directly.
See
- resource for the layer-based resource registration wrapper
Signature
declare const registerResource: { <E, R>(options: { readonly annotations?: Context.Context<never>; readonly audience?: ReadonlyArray<"user" | "assistant">; readonly content: Effect.Effect<typeof ReadResourceResult.Type | string | Uint8Array, E, R>; readonly description?: string; readonly mimeType?: string; readonly name: string; readonly priority?: number; readonly uri: string; }): Effect<void, never, McpServer | Exclude<R, McpServerClient>>; <Schemas extends readonly Array<Constraint>>(segments: TemplateStringsArray, ...schemas: Schemas): <E, R, Completions extends Partial<ResourceCompletions<Schemas>> = {}>(options: { readonly annotations?: Context.Context<never>; readonly audience?: ReadonlyArray<"user" | "assistant">; readonly completion?: ValidateCompletions<Completions, keyof ResourceCompletions<Schemas>>; readonly content: (uri: string, ...params: { [K in keyof Schemas]: Schemas[K]["Type"] }) => Effect.Effect<typeof ReadResourceResult.Type | string | Uint8Array, E, R>; readonly description?: string; readonly mimeType?: string; readonly name: string; readonly priority?: number; }) => Effect<void, never, McpServer | Exclude<R, McpServerClient> | Exclude<Schemas[number]["DecodingServices"], McpServerClient> | Exclude<Schemas[number]["EncodingServices"], McpServerClient> | Exclude<Completions[keyof Completions] extends (input: string) => Ret ? Ret extends Effect<_A, _E, _R> ? _R : never : never, McpServerClient>>;}registerToolkit
Registers a Toolkit with the McpServer.
Signature
declare const registerToolkit: <Tools extends Record<string, Tool.Any>>(toolkit: Toolkit.Toolkit<Tools>) => Effect.Effect<void, never, McpServer | Tool.HandlersFor<Tools> | Exclude<Tool.HandlerServices<Tools>, McpServerClient>>Layers
Creates a layer that starts an MCP server over an existing
RpcServer.Protocol and provides the McpServer and McpServerClient
services.
When to use
Use when you already have a custom or externally provided
RpcServer.Protocol and want to start an MCP server as part of a layer
graph.
Details
The returned layer forks run(options) in the layer scope and merges
McpServer.layer, so registration layers can use the McpServer service
while the server is running.
Gotchas
Unlike layerStdio and layerHttp, this layer does not install a concrete
transport. The surrounding layer graph must provide RpcServer.Protocol.
See
- run for the effect form used by this layer
- layerStdio for a stdio-backed layer that installs the MCP protocol and NDJSON-RPC serialization
- layerHttp for an HTTP-backed layer that registers with
HttpRouterand installs JSON-RPC serialization
Signature
declare function layer(options: { readonly description?: string; readonly extensions?: { [key: `${string}/${string}`]: Json; }; readonly icons?: readonly Array<Icon>; readonly name: string; readonly protocols: readonly [ProtocolAdapter<ProtocolVersion>, ProtocolAdapter<ProtocolVersion>]; readonly version: string; readonly websiteUrl?: string;}): Layer<McpServerClient | McpServer, IllegalArgumentError, Protocol>Registers a Streamable HTTP MCP endpoint at options.path.
When to use
Use to expose an MCP server through an existing HttpRouter.
Details
POST serves JSON-RPC and accepted notification-only requests return 202.
Unsupported protocol versions return 400; methods without MCP handlers
return 405. Requests carrying an Origin header are rejected unless the
exact origin appears in allowedOrigins; Origin-less non-browser clients
remain valid. The surrounding HTTP server remains responsible for binding
to an appropriate interface and installing authentication.
layerHttp always implements the single-endpoint Streamable HTTP topology.
Using v2024_11_05 here is a custom compatibility transport for that
revision's schema. It does not implement the historical two-endpoint
HTTP+SSE transport, GET SSE, event resumption, session expiry, or client
session termination.
See
- layerStdio for exposing the server over stdio
- layer for the base MCP server layer without a transport protocol
Signature
declare function layerHttp(options: { readonly allowedOrigins?: readonly Array<string>; readonly description?: string; readonly extensions?: { [key: `${string}/${string}`]: Json; }; readonly icons?: readonly Array<Icon>; readonly name: string; readonly path: PathInput; readonly protocols: readonly [ProtocolAdapter<ProtocolVersion>, ProtocolAdapter<ProtocolVersion>]; readonly version: string; readonly websiteUrl?: string;}): Layer<McpServerClient | McpServer, IllegalArgumentError, HttpRouter>layerStdio
Creates a layer that runs an MCP server over standard input and output.
When to use
Use when an MCP client launches the server as a subprocess and communicates through newline-delimited JSON-RPC messages.
Details
The selected protocol adapter controls the dated RPC schemas and JSON-RPC
batch policy. The layer provides McpServer and McpServerClient and
requires Stdio.
See
Signature
declare function layerStdio(options: { readonly description?: string; readonly extensions?: { [key: `${string}/${string}`]: Json; }; readonly icons?: readonly Array<Icon>; readonly name: string; readonly protocols: readonly [ProtocolAdapter<ProtocolVersion>, ProtocolAdapter<ProtocolVersion>]; readonly version: string; readonly websiteUrl?: string;}): Layer<McpServerClient | McpServer, IllegalArgumentError, Stdio>Creates a layer that registers an MCP prompt.
When to use
Use to compose prompt registration into an MCP server layer.
Details
Parameters are decoded with the supplied schema, completion handlers encode per-parameter suggestions, and string prompt content is converted into a user text message.
See
- registerPrompt for the Effect-level prompt registration API
Signature
declare function prompt<E, R, Params extends Fields = {}, Completions extends { [K in string | number | symbol]: (input: string, context: { readonly arguments?: { [key: string]: string; };} | undefined) => Effect<Array<Params[K]["Type"]>, any, any> } = {}>(options: { readonly annotations?: Context<never>; readonly completion?: ValidateCompletions<Completions, Extract<keyof Params, string>>; readonly content: (params: View<Params>) => Effect<string | Array<PromptMessage>, E, R>; readonly description?: string; readonly name: string; readonly parameters?: Params;}): Layer<never, never, Exclude<R, McpServerClient> | Exclude<DecodingServices<Params>, McpServerClient>>Creates a layer that registers an MCP resource or resource template.
When to use
Use to compose resource registration into an MCP server layer.
See
- registerResource for the Effect-level resource registration API
Signature
declare const resource: { <E, R>(options: { readonly audience?: ReadonlyArray<"user" | "assistant">; readonly content: Effect.Effect<typeof ReadResourceResult.Type | string | Uint8Array, E, R>; readonly description?: string; readonly mimeType?: string; readonly name: string; readonly priority?: number; readonly uri: string; }): Layer<never, never, Exclude<R, McpServerClient>>; <Schemas extends readonly Array<Constraint>>(segments: TemplateStringsArray, ...schemas: Schemas): <E, R, Completions extends Partial<ResourceCompletions<Schemas>> = {}>(options: { readonly audience?: ReadonlyArray<"user" | "assistant">; readonly completion?: ValidateCompletions<Completions, keyof ResourceCompletions<Schemas>>; readonly content: (uri: string, ...params: { [K in keyof Schemas]: Schemas[K]["Type"] }) => Effect.Effect<typeof ReadResourceResult.Type | string | Uint8Array, E, R>; readonly description?: string; readonly mimeType?: string; readonly name: string; readonly priority?: number; }) => Layer<never, never, Exclude<R, McpServerClient> | Exclude<Completions[keyof Completions] extends (input: string) => Ret ? Ret extends Effect<_A, _E, _R> ? _R : never : never, McpServerClient>>;}Registers an AiToolkit with the McpServer.
Signature
declare function toolkit<Tools extends Record<string, Any>>(toolkit: Toolkit<Tools>): Layer<never, never, HandlersFor<Tools> | Exclude<HandlerServices<Tools>, McpServerClient>>Models
ResourceCompletions type
Completion-handler map for a resource URI template.
Details
Each schema interpolation contributes a parameter key, using an explicit
Param name when present or paramN otherwise, and each handler returns
candidate values for that parameter.
Signature
type ResourceCompletions<Schemas extends ReadonlyArray<Schema.Constraint>> = { [K in Extract<keyof Schemas, `${number}`>]: (input: string, context: CompletionContext) => Effect.Effect<Array<Schemas[K]["Type"]>, any, any> }Running
Runs an MCP server over the current RpcServer.Protocol.
Details
The server performs initialization and session handling, serves registered tools, resources, and prompts, and forwards queued server notifications to initialized clients.
Signature
declare const run: (options: { readonly description?: string; readonly extensions?: ServerExtensions; readonly icons?: ReadonlyArray<McpSchema.Icon>; readonly name: string; readonly protocols: Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>; readonly version: string; readonly websiteUrl?: string;}) => Effect.Effect<never, Cause.IllegalArgumentError, McpServer | RpcServer.Protocol>Services
Service that stores and serves an MCP server's registered tools, resources, prompts, completions, and outgoing notifications.
Details
Handlers use this service to register capabilities and resolve incoming MCP requests.
Signature
declare class McpServer extends Shape<"effect/ai/McpServer", { readonly addPrompt: (options: { readonly annotations: Context<never>; readonly completions: Record<string, (input: string, context: CompletionContext) => Effect.Effect<CompleteResult, InternalError, McpServerClient>>; readonly handle: (params: Record<string, string>) => Effect<GetPromptResult, InvalidParams | InternalError, McpServerClient>; readonly prompt: Prompt; }) => Effect<void>; readonly addResource: (options: { readonly annotations: Context<never>; readonly handle: Effect<ReadResourceResult, InternalError, McpServerClient>; readonly resource: Resource; }) => Effect<void>; readonly addResourceTemplate: (options: { readonly annotations: Context<never>; readonly completions: Record<string, (input: string, context: CompletionContext) => Effect.Effect<CompleteResult, InternalError>>; readonly handle: (uri: string, params: Array<string>) => Effect<ReadResourceResult, InvalidParams | InternalError, McpServerClient>; readonly routerPath: string; readonly template: ResourceTemplate; }) => Effect<void>; readonly addTool: (options: { readonly annotations: Context<never>; readonly handle: (payload: any) => Effect<CallToolResult, InvalidParams | InternalError, McpServerClient>; readonly tool: Tool; }) => Effect<void>; readonly callTool: (requests: { readonly _meta?: { readonly progressToken?: string | number; }; readonly arguments?: { [key: string]: any; }; readonly name: string; }) => Effect<CallToolResult, InvalidParams | InternalError, McpServerClient>; readonly completion: (complete: { readonly argument: { readonly name: string; readonly value: string; }; readonly context?: { readonly arguments?: { [key: string]: string; }; }; readonly ref: ResourceReference | PromptReference; }) => Effect<CompleteResult, InvalidParams | InternalError, McpServerClient>; readonly findResource: (uri: string) => Effect<ReadResourceResult, McpErrorBase | InvalidParams | InternalError, McpServerClient>; readonly getPromptResult: (request: { readonly _meta?: { readonly progressToken?: string | number; }; readonly arguments?: { [key: string]: string; }; readonly name: string; readonly title?: string; }) => Effect<GetPromptResult, InvalidParams | InternalError, McpServerClient>; readonly initializedClients: Set<number>; readonly notifications: { "notifications/cancelled": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly reason?: string; readonly requestId: string | number; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/message": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly data: any; readonly level: "error" | "debug" | "info" | "notice" | "warning" | "critical" | "alert" | "emergency"; readonly logger?: string; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/progress": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly message?: string; readonly progress: number; readonly progressToken: string | number; readonly total?: number; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/prompts/list_changed": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; } | undefined, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/resources/list_changed": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; } | undefined, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/resources/updated": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly uri: string; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/tools/list_changed": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; } | undefined, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; }; readonly notifyElicitationComplete: (options: { readonly clientId: number; readonly elicitationId: string; }) => Effect<void>; readonly prompts: readonly Array<{ readonly annotations: Context<never>; readonly prompt: Prompt; }>; readonly resources: readonly Array<{ readonly annotations: Context<never>; readonly resource: Resource; }>; readonly resourceTemplates: readonly Array<{ readonly annotations: Context<never>; readonly template: ResourceTemplate; }>; readonly tools: readonly Array<{ readonly annotations: Context<never>; readonly tool: Tool; }>;}, this> { constructor(_: never); static readonly layer: Layer<McpServerClient | McpServer>; static readonly make: Effect<{ readonly addPrompt: (options: { readonly annotations: Context<never>; readonly completions: Record<string, (input: string, context: CompletionContext) => Effect.Effect<CompleteResult, InternalError, McpServerClient>>; readonly handle: (params: Record<string, string>) => Effect<GetPromptResult, InvalidParams | InternalError, McpServerClient>; readonly prompt: Prompt; }) => Effect<void>; readonly addResource: (options: { readonly annotations: Context<never>; readonly handle: Effect<ReadResourceResult, InternalError, McpServerClient>; readonly resource: Resource; }) => Effect<void>; readonly addResourceTemplate: (options: { readonly annotations: Context<never>; readonly completions: Record<string, (input: string, context: CompletionContext) => Effect.Effect<CompleteResult, InternalError>>; readonly handle: (uri: string, params: Array<string>) => Effect<ReadResourceResult, InvalidParams | InternalError, McpServerClient>; readonly routerPath: string; readonly template: ResourceTemplate; }) => Effect<void>; readonly addTool: (options: { readonly annotations: Context<never>; readonly handle: (payload: any) => Effect<CallToolResult, InvalidParams | InternalError, McpServerClient>; readonly tool: Tool; }) => Effect<void>; readonly callTool: (requests: { readonly _meta?: { readonly progressToken?: string | number; }; readonly arguments?: { [key: string]: any; }; readonly name: string; }) => Effect<CallToolResult, InvalidParams | InternalError, McpServerClient>; readonly completion: (complete: { readonly argument: { readonly name: string; readonly value: string; }; readonly context?: { readonly arguments?: { [key: string]: string; }; }; readonly ref: ResourceReference | PromptReference; }) => Effect<CompleteResult, InvalidParams | InternalError, McpServerClient>; readonly findResource: (uri: string) => Effect<ReadResourceResult, McpErrorBase | InvalidParams | InternalError, McpServerClient>; readonly getPromptResult: (request: { readonly _meta?: { readonly progressToken?: string | number; }; readonly arguments?: { [key: string]: string; }; readonly name: string; readonly title?: string; }) => Effect<GetPromptResult, InvalidParams | InternalError, McpServerClient>; readonly initializedClients: Set<number>; readonly notifications: { "notifications/cancelled": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly reason?: string; readonly requestId: string | number; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/message": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly data: any; readonly level: "error" | "debug" | "info" | "notice" | "warning" | "critical" | "alert" | "emergency"; readonly logger?: string; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/progress": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly message?: string; readonly progress: number; readonly progressToken: string | number; readonly total?: number; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/prompts/list_changed": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; } | undefined, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/resources/list_changed": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; } | undefined, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/resources/updated": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; readonly uri: string; }, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; "notifications/tools/list_changed": <AsQueue extends boolean = false, Discard = false>(input: { readonly _meta?: { [key: string]: unknown; }; } | undefined, options?: { readonly context?: Context<never>; readonly discard?: Discard; readonly headers?: Input; }) => Effect<Discard extends true ? void : void, Discard extends true ? never : never, never>; }; readonly notifyElicitationComplete: (options: { readonly clientId: number; readonly elicitationId: string; }) => Effect<void>; readonly prompts: readonly Array<{ readonly annotations: Context<never>; readonly prompt: Prompt; }>; readonly resources: readonly Array<{ readonly annotations: Context<never>; readonly resource: Resource; }>; readonly resourceTemplates: readonly Array<{ readonly annotations: Context<never>; readonly template: ResourceTemplate; }>; readonly tools: readonly Array<{ readonly annotations: Context<never>; readonly tool: Tool; }>; }, never, Scope>;}Utility Types
ValidateCompletions type
Utility type that validates a completion-handler record against the allowed parameter keys.
Signature
type ValidateCompletions<Completions, Keys extends string> = Completions & { [K in keyof Completions]: K extends Keys ? (input: string, context: CompletionContext) => any : never }