/**
 * 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, McpClientOptions, McpCallToolResult } 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<Record<string, unknown>>;
    /**
     * 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<Record<string, unknown>>;
    /**
     * Async handler that runs when the agent calls this tool. Receives
     * the args the LLM produced; returns a string or an MCP result envelope.
     * Strings retain the existing behavior in text mode; envelopes use the
     * same result decoder as the real client.
     *
     * Defaults to `async () => '[mock result]'` when omitted — useful
     * when the consumer cares about wiring not behavior.
     */
    readonly handler?: (args: Record<string, unknown>, 
    /**
     * The request's `_meta` bag, exactly as the real client would send it —
     * `{ agentfootprint: { time } }` on a call handed `ctx.time` (the time
     * layer), absent otherwise. A handler that ignores it behaves as before.
     */
    request: {
        readonly _meta?: Readonly<Record<string, unknown>>;
    }) => Promise<string | McpCallToolResult>;
}
export interface MockMcpClientOptions {
    /** Logical server name. Surfaces in observability + error messages. */
    readonly name?: string;
    /** Tools exposed by the mock server. */
    readonly tools: readonly MockMcpTool[];
    /** Same result decoding as mcpClient. A string handler becomes one text
     * block; return McpCallToolResult to exercise structuredContent or isError. */
    readonly resultMode?: McpClientOptions['resultMode'];
}
/**
 * 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;
