MCP Servers

Connecting and configuring Model Context Protocol (MCP) servers to extend agent capabilities.

Overview

MCP integration allows swarm to connect to external tool servers using the Model Context Protocol. Tools from MCP servers are registered in the tool registry with prefixed names and appear as regular tools to all agents.

How It Works

  1. Startup — The orchestrator reads mcpServers from your configuration and connects to each server
  2. Discovery — Each server's tools are listed and registered with prefixed names: mcp__<server>__<tool>
  3. Execution — When an agent calls an MCP tool, the McpProxyTool routes the call to the correct server
  4. Shutdown — All MCP servers are gracefully shut down when the session ends

MCP servers are started once per orchestrator session and shared across all agents.

Step 1: Add MCP Servers to Configuration

Add the mcpServers section to your project config in ~/.swarm/settings.json:

{
  "version": 2,
  "/home/user/my-project": {
    "agents": [ ... ],
    "mcpServers": {
      "server-name": {
        "transport": { ... },
        "env": { ... }
      }
    }
  }
}

Each server has a unique name (the key) and a configuration object with transport and optional env fields.

Step 2: Choose a Transport

Swarm supports three MCP transport types:

Stdio Transport

Spawns a child process and communicates via JSON-RPC over stdin/stdout. Best for locally installed tools.

{
  "mcpServers": {
    "filesystem": {
      "transport": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
      }
    }
  }
}
FieldTypeRequiredDescription
type"stdio"YesTransport discriminator
commandStringYesCommand to execute
argsString[]NoCommand arguments

HTTP Transport

Connects over Streamable HTTP. Best for remote servers with request-response semantics.

{
  "mcpServers": {
    "github": {
      "transport": {
        "type": "http",
        "url": "https://api.example.com/mcp/",
        "headers": {
          "Authorization": "Bearer ${GITHUB_TOKEN}"
        }
      }
    }
  }
}
FieldTypeRequiredDescription
type"http"YesTransport discriminator
urlStringYesServer URL
headersMap<String, String>NoHTTP headers

SSE Transport

Connects over Server-Sent Events (legacy EventSource). Best for servers that push updates.

{
  "mcpServers": {
    "events": {
      "transport": {
        "type": "sse",
        "url": "https://sse.example.com/events",
        "headers": {
          "X-Token": "abc123"
        }
      }
    }
  }
}
FieldTypeRequiredDescription
type"sse"YesTransport discriminator
urlStringYesSSE endpoint URL
headersMap<String, String>NoHTTP headers

Step 3: Configure Environment Variables (Optional)

MCP servers launched via stdio transport can receive environment variables:

{
  "mcpServers": {
    "database": {
      "transport": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@bytebase/dbhub"]
      },
      "env": {
        "DB_URL": "sqlite:///path/to/db",
        "DB_READ_ONLY": "true"
      }
    }
  }
}

The env map is injected into the child process environment when the server is spawned.

Step 4: Use MCP Tools

Once configured, MCP tools appear in the agent's tool registry with prefixed names:

mcp__<server_name>__<tool_name>

For example, a server named github that exposes a search_repos tool creates:

mcp__github__search_repos

Agents can call these tools like any other tool. The McpProxyTool handles routing the call to the correct server, serializing the input as JSON-RPC, and returning the result.

Tool Discovery

Each MCP server advertises its tools via the tools/list JSON-RPC method. Swarm calls this during startup and registers each tool with:

  • Name: mcp__<server>__<tool> (prefixed to avoid conflicts with built-in tools)
  • Description: As provided by the server
  • Input schema: As provided by the server

Permission Integration

MCP tools respect the permission system. You can allow or deny specific MCP tools:

{
  "permissions": {
    "allow": ["mcp__filesystem__read_file(*)"],
    "deny": ["mcp__filesystem__write_file(*)"]
  }
}

JSON-RPC Protocol

Swarm communicates with MCP servers using JSON-RPC 2.0. The key message exchanges:

Initialize

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "clientInfo": { "name": "swarm", "version": "0.1.0" }
  }
}

// Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-03-26",
    "capabilities": { "tools": {} },
    "serverInfo": { "name": "server-name", "version": "1.0" }
  }
}

List Tools

// Request
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }

// Response
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "search_repos",
        "description": "Search GitHub repositories",
        "inputSchema": { "type": "object", "properties": { ... } }
      }
    ]
  }
}

Call Tool

// Request
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "search_repos",
    "arguments": { "query": "swarm" }
  }
}

// Response
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      { "type": "text", "text": "Found 3 repositories..." }
    ]
  }
}

Complete Example

A configuration with two MCP servers:

{
  "version": 2,
  "/home/user/my-project": {
    "agents": [
      {
        "name": "backend",
        "prompt": "You are a backend engineer with access to the database and filesystem tools."
      }
    ],
    "mcpServers": {
      "filesystem": {
        "transport": {
          "type": "stdio",
          "command": "npx",
          "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
        }
      },
      "database": {
        "transport": {
          "type": "stdio",
          "command": "npx",
          "args": ["-y", "@bytebase/dbhub"]
        },
        "env": {
          "DB_URL": "sqlite:///home/user/my-project/data.db"
        }
      }
    }
  }
}

This gives the backend agent access to:

  • mcp__filesystem__read_file
  • mcp__filesystem__write_file
  • mcp__filesystem__list_directory
  • mcp__database__query
  • mcp__database__list_tables
  • (and any other tools the servers expose)

Error Handling

  • Failed server: If an MCP server fails to start, swarm logs a warning and continues. Other servers and agents are not affected.
  • Failed tool listing: If tools/list fails for a server, its tools are not registered but the server remains connected.
  • Tool call error: Transport and JSON-RPC errors are returned as tool execution errors to the agent.
  • Transport retry: Transport errors are retried once before being returned as failures.

Troubleshooting

"Failed to connect to MCP server"

  • Verify the command is installed and in your PATH (for stdio transport)
  • Check that the URL is reachable (for http/sse transport)
  • Review the server's stderr output in swarm logs

Tools not appearing

  • Ensure the server's tools/list response is valid
  • Check that the server name doesn't contain characters that would break the prefix format
  • Verify the server completes initialization within the timeout

Permission denied for MCP tools

MCP tools use the prefixed name format for permission rules. Use mcp__<server>__<tool>(*) in your permission rules.