/** * mockMcpClient — in-memory MCP client for development and tests. * * const slack = mockMcpClient({ * tools: [ * { * name: 'send_message', * description: 'Post a message to a channel', * inputSchema: { type: 'object' }, * handler: async ({ text }) => `Posted: ${text}`, * }, * ], * }); * * const agent = Agent.create({ provider: mock({ reply: 'ok' }) }) * .tools(await slack.tools()) * .build(); * * Pattern: Adapter (GoF) — produces an `McpClient` with the same shape * as `mcpClient(opts)` but driven by an in-memory tool table * instead of the MCP SDK + transport. Drop-in for development: * start with `mockMcpClient`, swap to `mcpClient` once the * real server is ready. * * Why public: `mcpClient`'s `_client` injection is `@internal` because * the SDK shape isn't a stable public surface. `mockMcpClient` exposes * a curated tool-handler shape that's tied to OUR Tool contract instead * — stable, documented, and the right level of abstraction for * mock-first development. */ import type { McpClient } from './types.js'; /** A scripted tool exposed by the mock MCP server. */ export interface MockMcpTool { /** Tool name as the LLM sees it. */ readonly name: string; /** Description surfaced to the LLM via the tool schema. */ readonly description?: string; /** * JSON-schema-like input schema. Passed through to the agent's tool * registry verbatim — same as a real MCP server's `listTools()`. */ readonly inputSchema: Readonly>; /** * MCP's extensibility bag, exactly as a real server would send it (9.71.0). * * agentfootprint's tool DECLARATIONS — `argumentsFrom`, `resultKind`, * `owner`, `resultClass`, `resultCeiling` — ride under the `agentfootprint` * key here, and this mock reads them through the SAME defensive reader * `mcpClient` uses. So a rail armed by a remotely-declared tool can be * developed and tested before the real server exists, and so can the * unhappy path: put a malformed declaration in and watch the field get * dropped, the warning name the rule, and the tool register anyway. * * ```ts * mockMcpClient({ * name: 'fleet-mcp', * tools: [{ * name: 'backup_status', * inputSchema: { type: 'object', properties: { machine: { type: 'string' } } }, * _meta: { agentfootprint: { argumentsFrom: ['fleet_report'] } }, * }], * }); * ``` * * Omitted → the registered `Tool` carries no declarations, exactly as * before this existed. */ readonly _meta?: Readonly>; /** * Async handler that runs when the agent calls this tool. Receives * the args the LLM produced; returns the string result the agent * sees as the tool-result message. * * Defaults to `async () => '[mock result]'` when omitted — useful * when the consumer cares about wiring not behavior. */ readonly handler?: (args: Record) => Promise; } export interface MockMcpClientOptions { /** Logical server name. Surfaces in observability + error messages. */ readonly name?: string; /** Tools exposed by the mock server. */ readonly tools: readonly MockMcpTool[]; } /** * Build an in-memory `McpClient`. Useful when you want to develop * against MCP semantics without spawning subprocesses, hitting the * network, or installing `@modelcontextprotocol/sdk`. Same `McpClient` * shape as `mcpClient(opts)` — code that consumes one accepts the other. */ export declare function mockMcpClient(options: MockMcpClientOptions): McpClient; //# sourceMappingURL=mockMcpClient.d.ts.map