# `cleveragents.mcp` — Model Context Protocol The `mcp` package bridges external MCP servers into the CleverAgents `ToolRegistry`. It handles server lifecycle (lazy start, auto-stop, health monitoring), tool discovery, invocation with JSON Schema validation, sandbox path rewriting, and skill refresh notifications. See [ADR-029](../adr/ADR-029-model-context-protocol.md) for design rationale. --- ## `MCPServerConfig` ```python from cleveragents.mcp import MCPServerConfig config = MCPServerConfig( name="my-server", transport="stdio", command="python", args=["-m", "my_mcp_server"], env={"API_KEY": "..."}, ) ``` | Field | Type | Description | |-------|------|-------------| | `name` | `str` | Server identifier | | `transport` | `str` | `"stdio"` \| `"sse"` \| `"streamable-http"` | | `command` | `str \| None` | Spawn command (stdio only) | | `args` | `list[str]` | Command-line arguments | | `env` | `dict[str, str]` | Environment variables | | `url` | `str \| None` | Server URL (sse/http only) | | `headers` | `dict[str, str]` | HTTP headers (sse/http only) | --- ## `MCPToolAdapter` The primary integration point. Manages the full lifecycle of an MCP server connection. ```python from cleveragents.mcp import MCPToolAdapter, MCPServerConfig from cleveragents.tool import ToolRegistry config = MCPServerConfig(name="bash-tools", transport="stdio", command="uvx", args=["mcp-server-bash"]) adapter = MCPToolAdapter(config) await adapter.connect() tools = await adapter.discover_tools() registry = ToolRegistry() adapter.register_tools(registry) # bulk-register with source="mcp" result = await adapter.invoke("bash", {"command": "ls -la"}) await adapter.disconnect() ``` ### Methods | Method | Description | |--------|-------------| | `connect()` | Start server process / open HTTP session | | `disconnect()` | Clean shutdown | | `discover_tools(filter)` | Enumerate tools from the server | | `invoke(name, arguments)` | Call a tool with input validation | | `register_tools(registry)` | Bulk-register discovered tools | --- ## `MCPToolDescriptor` ```python class MCPToolDescriptor(BaseModel): name: str description: str input_schema: dict[str, Any] # JSON Schema annotations: dict[str, Any] ``` Descriptor for a tool discovered from an MCP server. --- ## `MCPToolResult` ```python class MCPToolResult(BaseModel): success: bool content: Any error: str | None = None ``` --- ## `MCPCapabilityMetadata` ```python class MCPCapabilityMetadata(BaseModel): tools: bool resources: bool prompts: bool raw_capabilities: dict[str, Any] ``` Full capability information returned during the MCP initialize handshake. --- ## `McpClient` Manages a single MCP server connection with lazy start and auto-stop. ```python from cleveragents.mcp import McpClient, McpClientConfig client_config = McpClientConfig(server=server_config, auto_stop_idle_secs=60) client = McpClient(client_config) async with client: tools = await client.list_tools() ``` ### `McpClientState` Enum: `STOPPED`, `STARTING`, `RUNNING`, `STOPPING`, `ERROR`. --- ## `McpRegistry` Namespace-isolated registry of `McpClient` instances. Prevents duplicate server registrations and provides lookup by server name. ```python from cleveragents.mcp import McpRegistry reg = McpRegistry() reg.register("my-server", client) client = reg.get("my-server") ``` --- ## `MCPRefreshHook` Wires MCP `notifications/tools/list_changed` events to `SkillRegistry.refresh_all()` so that skill registrations stay in sync when an MCP server's tool list changes at runtime. ```python from cleveragents.mcp import MCPRefreshHook hook = MCPRefreshHook(skill_registry) adapter.on_tools_changed(hook.on_tools_changed) ``` --- ## `SandboxPathRewriter` Rewrites absolute host paths in MCP tool arguments and results to sandbox-relative paths, preventing path traversal outside the sandbox root. ```python from cleveragents.mcp import SandboxPathRewriter, SandboxPathRewriterConfig rewriter = SandboxPathRewriter( SandboxPathRewriterConfig(sandbox_root="/sandbox", host_root="/home/user/project") ) rewritten_args = rewriter.rewrite_args(tool_args) ```