Skip to main content
Glama
README.md
# mcp-agent-mesh

**A mesh gateway for MCP** — lets one MCP client reach N MCP servers with
prefix-based routing, health checks, circuit-breaker failover, and a
unified endpoint over both stdio and Streamable HTTP.

## What it does

`mcp-agent-mesh` aggregates multiple upstream MCP servers behind a single
logical MCP server.  Every upstream tool is exposed under a
`server_name.tool_name` prefix, so a client connecting to the mesh sees
a **single** `tools/list` containing tools from all healthy upstreams.

When a tool call fails and the server's circuit breaker opens, the mesh
automatically fails over to configured replica servers before returning
an error to the client.

## Features

| Feature | Description |
|---|---|
| **Aggregation** | `tools/list` merges every upstream server's tools into one flat list |
| **Prefix routing** | Call `math.add` and the mesh routes to the `math` server |
| **Circuit breaker** | Per-server circuit breaker with configurable threshold & timeout |
| **Health polling** | Background ping loop detects early upstream failures |
| **Failover** | Configurable failover groups let aliases take over for a failing server |
| **Dual transport** | Runs as a stdio MCP server **and** a Streamable HTTP server |
| **Timeouts + retries** | Every upstream call is wrapped in `asyncio.wait_for` |

## Architecture

```
                     ┌─────────────────────┐
  MCP client ───────►│   MeshGateway       │
                     │   (stdio / HTTP)    │
                     └────────┬───────────┘
                              │ tools/list
                              │ tools/call
                    ┌─────────┼─────────────┐
                    ▼         ▼             ▼
               ┌────────┐ ┌─────────┐ ┌─────────┐
               │ Server │ │ Server  │ │ Server  │
               │  "A"   │ │  "B"   │ │  "C"   │   (upstream MCP servers)
               └────────┘ └─────────┘ └─────────┘
```

### Modules

| Module | Responsibility |
|---|---|
| `config.py` | YAML config parsing — `ServerConfig`, `MeshConfig` |
| `health.py` | Per-server `CircuitBreaker` + `ServerHealthMonitor` (background ping) |
| `router.py` | Prefix routing (`server.tool`), failover group resolution, tool registry |
| `gateway.py` | `MeshGateway` — connects to upstreams, aggregates tool listings, routes calls, serves MCP over stdio + HTTP |

## Installation

```bash
pip install -e ".[dev]"
```

## Usage

### CLI (stdio mode)

```bash
mcp-agent-mesh --config examples/mesh.yaml --transport stdio
```

### HTTP mode

```bash
mcp-agent-mesh --config examples/mesh.yaml --transport http --host 0.0.0.0 --port 8000
```

### As a client config (Claude Code / Codex / OpenCode)

```json
{
  "mcpServers": {
    "mesh": {
      "command": "mcp-agent-mesh",
      "args": ["--config", "/path/to/mesh.yaml", "--transport", "stdio"]
    }
  }
}
```

```json
{
  "mcpServers": {
    "mesh": {
      "url": "http://127.0.0.1:8000/mcp"
    }
  }
}
```

## Configuration

See `examples/mesh.yaml` for a full example.  Key fields:

```yaml
servers:
  - name: math            # tool-name prefix
    transport: stdio       # "stdio" or "http"
    command: python        # stdio: how to spawn
    args: ["-m", "..."]
    url: http://...        # http: endpoint URL
    timeout: 30.0
    circuit_breaker_threshold: 3
    circuit_breaker_timeout: 300.0

failover_groups:
  math: [math_backup]      # failover aliases for the "math" server
```

## Testing

```bash
pytest tests/ -v
```

The test suite uses in-memory fake MCP servers (no real subprocesses
required) and covers config parsing, circuit-breaker logic, prefix
routing, tool aggregation, failover, and end-to-end gateway behaviour.

## License

MIT