Skip to content

McpTools

Harness tools over MCP: register a conversation’s tools (or any list, such as an extension’s tools) with an effect/ai McpServer, so an MCP client can list and call them.

import { CodingTools, type Ids, McpTools } from "@effective-harness/core"
import * as McpProtocol from "effect/ai/McpProtocol"
import * as McpServer from "effect/ai/McpServer"
import * as Layer from "effect/Layer"
declare const conversationId: Ids.ConversationId
// Serve the root conversation's coding tools over stdio, in its environment and working directory.
const Mcp = McpTools.layer({ conversationId, tools: CodingTools.CodingTools.tools }).pipe(
Layer.provideMerge(McpServer.layerStdio({ name: "harness", version: "1.0.0", protocols: [McpProtocol.v2025_11_25] }))
)

A call runs the tool’s execute directly, not as a durable pi.tool task: nothing is written to the conversation’s transcript, the beforeTool / afterTool hooks do not run, and a crash does not replay the call. The ToolCall service it gets builds the conversation’s environment (ExecEnvBuilder, with the agent’s cwd), commits through the Session without task attribution, reads committed state, collects diagnostics into the result (as the harness renders them) and ignores streamed output and details. Its taskId is 0 and conversation is not available.

Without tools, the conversation’s agent is resolved at registration for the listing and again at each call, so a call uses the current version of a tool, and a tool the agent no longer offers answers with an error result.

Since v0.0.0


What to expose.

Signature

export interface Options {
/** The conversation whose environment, state and (without `tools`) agent the calls use. */
readonly conversationId: ConversationId
/** Expose these tools instead of the conversation's resolved ones, for example an extension's `tools`. */
readonly tools?: ReadonlyArray<Tool.Any> | undefined
}

Source

Since v0.0.0

The services a call runs with.

Signature

type Services = Session.Session | Registry | Settings | ExecEnvBuilder

Source

Since v0.0.0

Register the tools when the layer is built, providing McpServer.McpServer.layer (shared with the transport layer that serves it, such as McpServer.layerStdio or McpServer.layerHttp).

Signature

declare const layer: (options: Options) => Layer.Layer<never, ReadError, Services>

Source

Since v0.0.0

Register the tools with the McpServer in context.

Signature

declare const register: (options: Options) => Effect.Effect<void, ReadError, McpServer.McpServer | Services>

Source

Since v0.0.0

A tool’s result as an MCP CallToolResult: text and image parts in order, then the diagnostics as the harness renders them (<harness> block).

Signature

declare const toCallToolResult: (
result: Tool.Result & { readonly diagnostics?: ReadonlyArray<ToolDiagnostic> }
) => McpSchema.CallToolResult

Source

Since v0.0.0