Aleph
Tools & Extensions

MCP Integration

How Aleph integrates with the Model Context Protocol for extensible tool servers

What is MCP?

The Model Context Protocol (MCP) is an open standard that defines how AI applications communicate with external tool servers. It provides a structured way for LLMs to discover and invoke tools, read resources, and retrieve prompts from external processes.

Aleph acts as an MCP client, connecting to one or more MCP servers that provide tools, resources, and prompts. This architecture lets you extend Aleph's capabilities without modifying its core — simply run an MCP server alongside Aleph.

Architecture

┌──────────────────────────────┐
│        Aleph Core            │
│                              │
│  ┌────────────────────────┐  │
│  │    McpManager (Actor)  │  │      ┌────────────────────────┐
│  │                        │──┼──────│  MCP Server: Filesystem │
│  │  ┌──────────────────┐  │  │      └────────────────────────┘
│  │  │   McpClient      │  │  │
│  │  │                  │──┼──┼──────┌────────────────────────┐
│  │  │  tool_location   │  │  │      │  MCP Server: GitHub     │
│  │  │  external_servers│  │  │      └────────────────────────┘
│  │  └──────────────────┘  │  │
│  │                        │──┼──────┌────────────────────────┐
│  │  Health monitoring     │  │      │  MCP Server: Database   │
│  │  Circuit breaker       │  │      └────────────────────────┘
│  │  Auto-restart          │  │
│  └────────────────────────┘  │
│                              │
│  ┌────────────────────────┐  │
│  │   AlephToolServer     │  │
│  │   (unified registry)  │  │
│  └────────────────────────┘  │
└──────────────────────────────┘

The integration has three layers:

  1. McpClient (src/mcp/client.rs) — Manages connections to external MCP servers, tool discovery, and tool invocation
  2. McpManager (src/mcp/manager/) — An actor that orchestrates server lifecycles with health monitoring and circuit breaker patterns
  3. McpToolWrapper (src/builtin_tools/mcp_wrapper.rs) — Wraps MCP tools as AlephToolDyn instances for registration in the AlephToolServer

Transport Types

Aleph supports three MCP transport mechanisms:

TransportUse CaseConnection
StdioLocal processesSpawns a child process, communicates via stdin/stdout
HTTPRemote serversStandard HTTP request/response
SSERemote servers with streamingServer-Sent Events for real-time updates
pub enum McpTransportType {
    Stdio,  // Subprocess communication
    Http,   // HTTP transport
    Sse,    // Server-Sent Events
}

Server Configuration

Persistent Configuration

MCP server configurations are stored in ~/.aleph/mcp_config.json:

{
  "version": 1,
  "servers": {
    "filesystem": {
      "id": "filesystem",
      "name": "Filesystem Server",
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"],
      "env": {},
      "requires_runtime": "node",
      "auto_start": true,
      "timeout_seconds": 300
    },
    "github": {
      "id": "github",
      "name": "GitHub Server",
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      },
      "requires_runtime": "node",
      "auto_start": true
    }
  }
}

Configuration Options

FieldTypeRequiredDescription
idstringYesUnique server identifier
namestringYesHuman-readable display name
transportstringYesstdio, http, or sse
commandstringStdio onlyCommand to execute
argsarrayNoCommand arguments
urlstringHTTP/SSE onlyServer endpoint URL
envobjectNoEnvironment variables
requires_runtimestringNoRequired runtime (node, python, bun)
auto_startbooleanNoStart automatically (default: true)
timeout_secondsintegerNoRequest timeout in seconds

Environment Variable Expansion

Configuration values support ${VAR} syntax for environment variable expansion:

{
  "env": {
    "API_KEY": "${MY_API_KEY}",
    "HOME": "${HOME}"
  },
  "command": "${HOME}/.local/bin/my-server"
}

Unknown variables are left as-is, so you can safely reference variables that may not be set in all environments.

McpManager Actor

The McpManager uses the actor pattern for safe concurrent server management:

// Create the actor and handle
let (actor, handle) = McpManagerActor::new(None).await?;

// Spawn the actor task
tokio::spawn(actor.run());

// Use the handle for all operations
handle.add_server(config).await?;
handle.list_servers().await?;
handle.shutdown().await?;

Server Lifecycle Commands

The manager supports the full server lifecycle via commands:

CommandDescription
AddServerRegister a new server configuration
RemoveServerRemove a server by ID
StartServerStart a stopped server
StopServerStop a running server
RestartServerRestart a specific server
ListServersList all servers with status
GetStatusGet detailed status for a server
AggregateToolsGet tools from all servers
AggregateResourcesGet resources from all servers
AggregatePromptsGet prompts from all servers
ReloadConfigReload configuration from disk
ShutdownGraceful shutdown of all servers

Event System

The manager broadcasts events to subscribers for real-time monitoring:

let mut events = handle.subscribe();
while let Ok(event) = events.recv().await {
    match event {
        McpManagerEvent::ServerStarted { server_id, tool_count, .. } => {
            println!("{} started with {} tools", server_id, tool_count);
        }
        McpManagerEvent::ServerCrashed { server_id, error, .. } => {
            eprintln!("{} crashed: {}", server_id, error);
        }
        _ => {}
    }
}

Health Monitoring

The McpManager implements a circuit breaker pattern for server health:

Healthy -> Degraded (2+ failures) -> Unhealthy (5+ failures) -> Restarting -> Healthy
                                                              -> Dead (max restarts exceeded)
StatusDescription
HealthyServer is operating normally
DegradedSome failures detected (2-4 consecutive)
UnhealthyCircuit open (5+ consecutive failures)
RestartingServer is being restarted
DeadMaximum restarts exceeded
StoppedServer intentionally stopped

Health tracking includes:

  • Consecutive failure counting
  • Restart window management (prevents restart storms)
  • Last error message retention
  • Elapsed time since last health check

Tool Discovery

When an MCP server starts, Aleph automatically discovers its tools:

// Server starts and lists its tools
let tools = connection.list_tools().await;

// Tools are registered in the tool location map
for tool in &tools {
    tool_location_map.insert(tool.name.clone(), ToolLocation::External(server_name));
}

Discovered tools are available to the agent alongside built-in tools. The AlephToolServer treats them identically — the agent does not need to know whether a tool is built-in or provided by an MCP server.

Tool Invocation

When the agent calls an MCP tool:

  1. The AlephToolServer resolves the tool name to its MCP server
  2. The McpClient sends a JSON-RPC tools/call request to the server
  3. The server executes the tool and returns a result
  4. The result is forwarded to the LLM as a tool_result
pub async fn call_tool(&self, name: &str, args: Value) -> Result<McpToolResult> {
    // Try server-prefixed tool name (e.g., "github:create_issue")
    if let Some((server_name, _)) = name.split_once(':') {
        if let Some(connection) = servers.get(server_name) {
            return connection.call_tool(name, args).await;
        }
    }

    // Try all servers
    for connection in servers.values() {
        if connection.has_tool(name).await {
            return connection.call_tool(name, args).await;
        }
    }

    Err(AlephError::McpToolNotFound(name.to_string()))
}

Resources and Prompts

Beyond tools, Aleph also supports MCP resources and prompts:

Resources

Read structured data from MCP servers:

// List available resources
let resources = client.list_resources().await;

// Read a resource by URI
let content = client.read_resource("filesystem:file:///path/to/file").await?;

The mcp_read_resource built-in tool exposes this to the agent.

Prompts

Retrieve prompt templates from MCP servers:

// List available prompts
let prompts = client.list_prompts().await;

// Get a prompt with arguments
let result = client.get_prompt("github:review_pr", Some(args)).await?;

The mcp_get_prompt built-in tool exposes this to the agent.

Sampling Support

Aleph supports MCP sampling requests, where the server asks the client (Aleph) to generate text using its LLM. This enables advanced server-side orchestration:

// Set up sampling handler
client.set_sampling_callback(|request| async {
    // Forward to Aleph's LLM provider
    let response = provider.complete(request.messages).await?;
    Ok(SamplingResponse { content: response })
}).await;

Runtime Checks

Before starting a server, Aleph verifies that the required runtime is available:

ExternalServerConfig {
    name: "my-server".to_string(),
    command: "npx".to_string(),
    args: vec!["-y", "@my/mcp-server"],
    requires_runtime: Some("node".to_string()),
    // ...
}

Supported runtimes: node, python, bun. If the runtime is not found, the server is skipped with a warning rather than failing the entire startup.

Startup Report

The start_external_servers method returns a report detailing which servers started successfully and which failed:

let report = client.start_external_servers(configs).await;

println!("Started: {:?}", report.succeeded);  // ["filesystem", "github"]
println!("Failed: {:?}", report.failed);       // [("database", "connection refused")]

if !report.all_succeeded() {
    eprintln!("Some MCP servers failed to start");
}

This allows Aleph to continue operating even when some MCP servers are unavailable.

Remote Servers

For MCP servers running on remote machines, use HTTP or SSE transport:

{
  "id": "remote-api",
  "name": "Remote API Server",
  "transport": "http",
  "url": "https://mcp.example.com/api",
  "headers": {
    "Authorization": "Bearer ${API_TOKEN}"
  },
  "timeout_seconds": 60
}
{
  "id": "streaming-server",
  "name": "Streaming Server",
  "transport": "sse",
  "url": "https://mcp.example.com/sse",
  "timeout_seconds": 300
}

When transport is set to auto, Aleph defaults to HTTP. Future versions may add automatic transport detection via capability negotiation.

Security Considerations

  • Process isolation: Stdio MCP servers run as separate processes with their own permissions
  • Environment variables: Sensitive values like API keys should use ${VAR} expansion rather than being stored in plaintext
  • Tool confirmation: MCP tools can be placed in the requireConfirmation list in tool filtering configuration
  • Network boundaries: Remote MCP servers should use HTTPS with proper authentication headers
  • Runtime validation: Required runtimes are checked before server launch to prevent arbitrary command execution

Best Practices

  1. Use auto_start: true for essential servers that should always be available
  2. Set reasonable timeouts to prevent hanging operations
  3. Specify requires_runtime to get clear error messages when dependencies are missing
  4. Use environment variables for secrets — never hardcode API keys in configuration
  5. Monitor events via the manager's event system for operational visibility
  6. Group related tools into a single MCP server to reduce connection overhead

On this page