Skip to main content
MCP interactions involve network communication, subprocess management, and protocol negotiation. Definable provides specific exception types for each failure mode so you can handle errors precisely.

Error Hierarchy

All MCP errors inherit from MCPError:
ExceptionReason
MCPConnectionErrorFailed to connect to server
MCPTimeoutErrorRequest or connection timed out
MCPProtocolErrorInvalid JSON-RPC or protocol violation
MCPToolNotFoundErrorRequested tool does not exist
MCPServerNotFoundErrorServer name not in configuration
MCPResourceNotFoundErrorResource URI not found
MCPPromptNotFoundErrorPrompt name not found

Handling Connection Errors

from definable.mcp import MCPToolkit, MCPConfig, MCPServerConfig
from definable.mcp.errors import MCPConnectionError, MCPTimeoutError

config = MCPConfig(servers=[
    MCPServerConfig(name="my-server", transport="stdio", command="my-mcp-server"),
])

try:
    async with MCPToolkit(config=config) as toolkit:
        agent = Agent(model=model, toolkits=[toolkit])
        output = await agent.arun("Do something")
except MCPConnectionError as e:
    print(f"Could not connect to MCP server: {e}")
except MCPTimeoutError as e:
    print(f"Connection timed out: {e}")

Handling Tool Errors

from definable.mcp.errors import MCPToolNotFoundError

try:
    result = await client.call_tool("my-server", "nonexistent_tool", {})
except MCPToolNotFoundError as e:
    print(f"Tool not found: {e}")

Handling Server Not Found

from definable.mcp.errors import MCPServerNotFoundError

try:
    tools = await client.list_tools("unknown-server")
except MCPServerNotFoundError as e:
    print(f"Server not configured: {e}")

Automatic Reconnection

By default, MCP connections automatically reconnect on failure:
MCPServerConfig(
    name="my-server",
    transport="stdio",
    command="my-mcp-server",
    reconnect_on_failure=True,     # Default
    max_reconnect_attempts=3,      # Default
)
Reconnection uses exponential backoff. If all attempts fail, an MCPConnectionError is raised.

Timeout Configuration

Set timeouts at the server level:
MCPServerConfig(
    name="slow-server",
    transport="http",
    url="https://mcp.example.com/mcp",
    connect_timeout=60.0,    # Time to establish connection
    request_timeout=120.0,   # Time for each request
)

Graceful Degradation

When using multiple MCP servers, handle failures for individual servers:
config = MCPConfig(servers=[
    MCPServerConfig(name="primary", transport="stdio", command="server-a"),
    MCPServerConfig(name="fallback", transport="stdio", command="server-b"),
])

client = MCPClient(config)
await client.connect()

# Connect to servers individually for resilience
for server_name in ["primary", "fallback"]:
    try:
        await client.connect_server(server_name)
        print(f"Connected to {server_name}")
    except MCPConnectionError:
        print(f"Failed to connect to {server_name}, skipping")

Protocol Errors

Protocol errors indicate a bug in the MCP server or an incompatible protocol version:
from definable.mcp.errors import MCPProtocolError

try:
    result = await client.call_tool("server", "tool", {"arg": "value"})
except MCPProtocolError as e:
    print(f"Protocol error: {e}")
    # This usually means the server returned an invalid JSON-RPC response
If you encounter MCPProtocolError consistently, check that the MCP server is using a compatible version of the protocol and that the transport type matches the server’s expectations.