/** * MCP client bridge for the reviewer agent. * * Connects the servers described by `McpServerConfig` (see `@weareikko/agent-context`), * lists their tools, keeps only the read-only ones, and wraps each as a pi * `AgentTool` named `mcp____`. The bridge enforces a per-call * timeout, a result size cap, and a per-review call budget shared by every MCP * tool. A server that fails to connect is reported as `unavailable` and never * aborts the review. * * The reviewer processes attacker-controlled MR content, so only tools that * declare themselves read-only (`annotations.readOnlyHint === true` and not * `destructiveHint`, see `isReadOnlyMcpTool`) are exposed. */ import type { AgentTool } from '@earendil-works/pi-agent-core'; import type { ImageContent, TextContent } from '@earendil-works/pi-ai'; import { type CallToolResult, type McpTransport } from '@earendil-works/pi-mcp'; import { type McpServerConfig, type McpServerSource } from '@weareikko/agent-context'; import { type Logger } from './logger.js'; /** Default per-call timeout. A server config may lower or raise it, up to `MAX_MCP_TIMEOUT_MS`. */ export declare const DEFAULT_MCP_TIMEOUT_MS = 30000; /** * Timeout for connect and `tools/list`. Deliberately not overridable by a server * definition: both run before the agent loop starts, so they are outside the * review timeout and a large per-server `timeout` must not stall the pipeline. */ export declare const MCP_CONNECT_TIMEOUT_MS = 30000; /** Default number of MCP tool calls allowed per review, across all servers. */ export declare const DEFAULT_MCP_CALL_BUDGET = 40; /** Default cap on the content returned by one MCP tool call, text and image bytes together. */ export declare const DEFAULT_MCP_MAX_RESULT_CHARS = 200000; /** Cap on image blocks kept from one MCP tool call, whatever the size budget allows. */ export declare const MAX_MCP_IMAGE_BLOCKS = 4; /** Connection outcome for one configured server, rendered in the summary footer. */ export interface McpServerStatus { name: string; source: McpServerSource; status: 'connected' | 'unavailable'; /** Original (server-side) names of the tools exposed to the reviewer. */ tools: string[]; /** Calls made during the review. Updated in place by the bridge. */ calls: number; } export interface ConnectMcpServersOptions { logger?: Logger; /** Per-call timeout when the server config does not set one. */ timeoutMs?: number; /** Total MCP calls allowed per review, across every server and tool. */ callBudget?: number; /** Cap on the text returned by one call; longer results are truncated. */ maxResultChars?: number; /** * Supported library extension point (also the test seam): build the transport * for a config instead of the real stdio/http one. See `docs/mcp.md`. */ createTransport?: (config: McpServerConfig) => McpTransport; /** * The enclosing review's diagnostic run id. When set, connect/list-tools/call * are traced on the `mcp.connect` / `mcp.tools` / `mcp.call` diagnostics * channels (see `src/diagnostics.ts`); omitted (e.g. ad hoc library use, most * tests) means no diagnostics events are published. */ runId?: string; } export interface McpConnection { tools: AgentTool[]; servers: McpServerStatus[]; /** Close every connected client. Safe to call more than once. */ close(): Promise; } /** `mcp____`, with characters outside `[A-Za-z0-9_-]` replaced. */ export declare function mcpToolName(server: string, tool: string): string; /** The safe subset of `env`, skipping exported shell functions (`() { …`). */ export declare function inheritedMcpEnvironment(env?: NodeJS.ProcessEnv): Record; /** Build the real transport for a server config. */ export declare function createMcpTransport(config: McpServerConfig): McpTransport; /** * Convert an MCP `tools/call` result into pi tool content. Text-like blocks are * joined into one text block; images follow. Server output is untrusted and * unbounded, so `maxChars` caps the whole result — the joined text first, then * each image's base64 payload against what the text left — and at most * `MAX_MCP_IMAGE_BLOCKS` images survive. Dropped images leave a note in the text * so the agent knows something was there. The cap applies on the error path too: * a result the server flagged as an error throws the same capped text, so the * agent loop records a bounded error tool result. */ export declare function formatMcpToolResult(result: CallToolResult, maxChars: number): (TextContent | ImageContent)[]; /** * Connect every configured server, list its tools, and bridge the read-only * ones. Never throws for a server failure: the server is reported as * `unavailable` and the review continues with the others. */ export declare function connectMcpServers(configs: readonly McpServerConfig[], options?: ConnectMcpServersOptions): Promise; //# sourceMappingURL=mcp.d.ts.map