How MCP Integration with Claude Code Works for Ouroboros Plugin Commands

MCP integration with Claude Code enables Ouroboros to expose plugin commands as JSON-RPC tools that external agents can discover and invoke, using the ClaudeCodeAdapter to bridge MCP tool requests with the Claude Code Max-Plan SDK for LLM completions.

The Q00/ouroboros repository implements a Modular Compute Platform (MCP) server that transforms local workflow commands into discoverable remote tools. This architecture allows external MCP clients to execute Ouroboros plugin commands like ouroboros_execute_seed while leveraging Claude Code's Max-Plan authentication and model capabilities through a dedicated adapter layer.

Architecture Overview

The integration follows a layered pipeline that separates transport concerns from LLM execution. When a user invokes ooo run seed.yaml or a remote client calls ouroboros_execute_seed, the request flows through four distinct stages before reaching the Claude Code LLM.


CLI (or remote MCP client)
   │
   ▼
MCPClientManager  ← discovers MCP servers
   │
   ▼
MCPToolProvider  ← builds tool definitions & conflict handling
   │
   ▼
OrchestratorRunner (or MCP server handler)
   │
   ├─ ExecuteSeedHandler ──► ClaudeCodeAdapter (LLM request)
   └─ QAToolHandler      ──► ClaudeCodeAdapter (LLM request)
   │
   ▼
MCPToolResult → JSON-RPC response → CLI / remote client

The MCPClientManager handles server connections, while the MCPToolProvider converts raw MCP tools into agent-callable definitions with timeout and retry policies. Tool handlers like ExecuteSeedHandler instantiate a ClaudeCodeAdapter to perform the actual LLM request, bridging the JSON-RPC transport layer with Claude Code's Python SDK.

Core Components

MCPClientManager manages persistent connections to one or more MCP servers and enumerates available tools. Located in src/ouroboros/mcp/client/manager.py, this component provides the list_all_tools() method that returns MCPToolDefinition objects from all connected servers.

MCPToolProvider wraps the client manager's output as agent-callable tools suitable for the Ouroboros orchestrator. Found in src/ouroboros/orchestrator/mcp_tools.py, it implements get_tools() for conflict resolution and call_tool() for execution with automatic retries.

ClaudeCodeAdapter implements the LLM-side integration using the Claude Code Max-Plan SDK. Defined in src/ouroboros/providers/claude_code_adapter.py, this adapter handles authentication automatically and exposes complete() methods that translate Ouroboros prompts into Claude Code SDK calls.

ExecuteSeedHandler serves as the entry point for the ouroboros_execute_seed MCP tool. Located in src/ouroboros/mcp/tools/definitions.py (lines 61-86 and 119-132), it parses seed YAML and instantiates the orchestrator runner with a fresh ClaudeCodeAdapter when no explicit LLM adapter is supplied.

QAToolHandler implements the qa tool for post-execution quality checks. Found in src/ouroboros/mcp/tools/qa.py, it constructs QA-specific system prompts and delegates to ClaudeCodeAdapter for evaluation.

OrchestratorRunner coordinates the full workflow across interview, execution, and evaluation phases. Defined in src/ouroboros/orchestrator/runner.py, it receives a ClaudeAgentAdapter (which may wrap ClaudeCodeAdapter) to process LLM requests within the workflow context.

The Execution Flow: From MCP Discovery to LLM Completion

Tool Discovery via MCPClientManager

The process begins when the MCP client manager establishes connections to configured servers. The manager retrieves available tools through the list_all_tools() method, which aggregates capabilities from all connected MCP endpoints.


# In MCPClientManager

tools = await self._manager.list_all_tools()

This discovery mechanism enables dynamic tool availability without hardcoding command definitions in the client.

Building Agent-Callable Tools with MCPToolProvider

Once discovered, tools pass through the MCPToolProvider class to become compatible with the Ouroboros orchestrator. The get_tools() method performs three critical transformations:

  • Conflict detection: Identifies duplicate tool names between built-in and server-provided tools, logging conflicts via ToolConflict
  • Prefixing: Optionally applies a tool_prefix (e.g., mcp_) to avoid namespace collisions
  • Schema wrapping: Converts raw MCP definitions into MCPToolInfo objects with JSON-schema parameters
provider = MCPToolProvider(mcp_manager, tool_prefix="mcp_")
available_tools = await provider.get_tools(builtin_tools=["list_sessions"])

The provider also configures execution policies including a 30-second default timeout and exponential backoff retry logic using the stamina library.

Handling Tool Execution: ExecuteSeedHandler

When an MCP client invokes ouroboros_execute_seed, the server routes the JSON-RPC request to ExecuteSeedHandler.handle(). This handler performs four sequential operations:

  1. Parses the seed YAML into a Seed object
  2. Instantiates a ClaudeCodeAdapter with max_turns=1 for fast evaluation if no adapter is provided
  3. Creates an OrchestratorRunner with permission_mode="acceptEdits" and a fresh EventStore
  4. Executes the workflow and returns the result as MCPToolResult
from ouroboros.providers.claude_code_adapter import ClaudeCodeAdapter

# Inside ExecuteSeedHandler.handle (lines 119-132)

llm_adapter = ClaudeCodeAdapter(max_turns=1)

runner = OrchestratorRunner(
    adapter=ClaudeAgentAdapter(permission_mode="acceptEdits"),
    event_store=event_store,
    console=Console(stderr=True),
)

The handler in src/ouroboros/mcp/tools/definitions.py automatically bridges the MCP transport layer with the orchestrator's internal execution model.

LLM Integration via ClaudeCodeAdapter

All LLM-side logic ultimately resolves through ClaudeCodeAdapter. When the orchestrator calls the adapter's query method, the adapter constructs ClaudeAgentOptions and invokes the Claude Code SDK's query function:


# Inside ClaudeCodeAdapter._make_completion

from claude_agent_sdk import ClaudeAgentOptions, query
options = ClaudeAgentOptions(system_prompt=..., max_turns=self.max_turns)
response = query(prompt, options)

This design centralizes authentication handling, allowing the Max-Plan SDK to manage credentials while Ouroboros focuses on prompt construction and result parsing.

Reliability and Error Handling

The MCP integration layer implements robust failure management through the MCPToolProvider.call_tool() method in src/ouroboros/orchestrator/mcp_tools.py.

Conflict Resolution: The get_tools() method detects name collisions between built-in tools and MCP-provided tools, recording conflicts in ToolConflict objects without crashing the discovery process.

Retry Policy: The _call_with_retry() method (lines 55-61) decorates the underlying MCP call with stamina.retry, configured with:

  • Minimum wait: 0.5 seconds (RETRY_WAIT_MIN)
  • Maximum wait: 5 seconds (RETRY_WAIT_MAX)
  • Maximum attempts: 3 retries (MAX_RETRIES)
  • Retryable exceptions: MCPConnectionError and asyncio.TimeoutError

Error Conversion: All MCP client errors transform into structured MCPToolError objects via Result.err, preventing uncaught exceptions from propagating to the orchestrator.

Timeout Management: A default 30-second timeout (DEFAULT_TOOL_TIMEOUT) applies to all tool invocations unless explicitly overridden in the provider configuration.

Practical Implementation Example

The following client-side implementation demonstrates connecting to an MCP server, discovering Ouroboros tools, and executing a seed workflow:

import asyncio
from ouroboros.mcp.client.manager import MCPClientManager
from ouroboros.orchestrator.mcp_tools import MCPToolProvider

async def run_seed():
    # Connect to MCP server(s)

    manager = MCPClientManager()
    await manager.add_server({"url": "http://localhost:8000"})
    await manager.connect_all()

    # Wrap tools for the orchestrator

    provider = MCPToolProvider(manager)
    await provider.get_tools()               # discover + conflict-resolve

    # Call the seed-execution tool

    result = await provider.call_tool(
        "ouroboros_execute_seed",
        {
            "seed_content": "name: hello_world\nsteps: []",
            "model_tier": "medium",
            "max_iterations": 5,
        },
    )
    if result.is_ok:
        print("Execution finished:", result.value.output)
    else:
        print("Tool error:", result.error)

asyncio.run(run_seed())

On the server side, ExecuteSeedHandler automatically instantiates the ClaudeCodeAdapter and processes the LLM request upon receiving the tool invocation.

Summary

  • MCPClientManager in src/ouroboros/mcp/client/manager.py handles server discovery and connection management for MCP servers.
  • MCPToolProvider converts raw MCP tools into orchestrator-compatible definitions with automatic retry logic and conflict detection.
  • ClaudeCodeAdapter bridges tool handlers to the Claude Code Max-Plan SDK, managing authentication and completion requests.
  • ExecuteSeedHandler and QAToolHandler serve as the primary entry points for plugin commands, automatically instantiating LLM adapters when needed.
  • The integration provides 30-second timeouts, exponential backoff retries, and structured error handling via MCPToolResult wrappers.

Frequently Asked Questions

What is MCP integration in Ouroboros?

MCP integration refers to the Modular Compute Platform implementation that exposes Ouroboros workflows as JSON-RPC tools discoverable by external agents. According to the Q00/ouroboros source code, this allows the ooo CLI and remote clients to invoke plugin commands like ouroboros_execute_seed through a standardized protocol while maintaining compatibility with the Claude Code LLM backend.

How does ClaudeCodeAdapter authenticate with Claude Code?

The ClaudeCodeAdapter class relies on the Claude Code Max-Plan SDK to handle authentication automatically. As implemented in src/ouroboros/providers/claude_code_adapter.py, the adapter imports ClaudeAgentOptions and query from claude_agent_sdk, delegating credential management to the underlying SDK rather than handling tokens directly within Ouroboros.

What happens when MCP tool names conflict?

MCPToolProvider.get_tools() detects conflicts between built-in tools and server-provided tools during the discovery phase. Conflicts are recorded in ToolConflict objects and logged via structlog, while the provider applies optional prefixes (such as mcp_) to disambiguate tool names without crashing the discovery process.

How does Ouroboros handle MCP tool timeouts and failures?

The system implements a multi-layered reliability strategy: MCPToolProvider.call_tool() enforces a 30-second default timeout (DEFAULT_TOOL_TIMEOUT), while the _call_with_retry() method uses the stamina library to retry failed connections up to 3 times with exponential backoff between 0.5 and 5 seconds. All failures convert to MCPToolError objects wrapped in Result.err rather than raising uncaught exceptions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →