# MCP & A2A Integration Guide

OpenFang implements both the **Model Context Protocol (MCP)** and **Agent-to-Agent (A2A)** protocol, enabling deep interoperability with external tools, IDEs, and other agent frameworks.

## Table of Contents

- [Part 1: MCP (Model Context Protocol)](/content/docs/mcp-a2a#part-1-mcp-model-context-protocol/index.html)
    - [Overview](/content/docs/mcp-a2a#mcp-overview/index.html)
    - [MCP Client -- Connecting to External Servers](/content/docs/mcp-a2a#mcp-client/index.html)
    - [MCP Server -- Exposing OpenFang via MCP](/content/docs/mcp-a2a#mcp-server/index.html)
    - [Configuration Examples](/content/docs/mcp-a2a#mcp-configuration-examples/index.html)
    - [API Endpoints](/content/docs/mcp-a2a#mcp-api-endpoints/index.html)
- [Part 2: A2A (Agent-to-Agent Protocol)](/content/docs/mcp-a2a#part-2-a2a-agent-to-agent-protocol/index.html)
    - [Overview](/content/docs/mcp-a2a#a2a-overview/index.html)
    - [Agent Card](/content/docs/mcp-a2a#agent-card/index.html)
    - [A2A Server](/content/docs/mcp-a2a#a2a-server/index.html)
    - [A2A Client](/content/docs/mcp-a2a#a2a-client/index.html)
    - [Task Lifecycle](/content/docs/mcp-a2a#task-lifecycle/index.html)
    - [API Endpoints](/content/docs/mcp-a2a#a2a-api-endpoints/index.html)
    - [Configuration](/content/docs/mcp-a2a#a2a-configuration/index.html)
- [Security](/content/docs/mcp-a2a#security/index.html)

## Part 1: MCP (Model Context Protocol)

### MCP Overview

The Model Context Protocol (MCP) is a JSON-RPC 2.0 based protocol that standardizes how LLM applications discover and invoke tools. OpenFang supports MCP in both directions:

- **As a client**: OpenFang connects to external MCP servers (GitHub, filesystem, databases, Puppeteer, etc.) and makes their tools available to all agents.
- **As a server**: OpenFang exposes its own agents as MCP tools, so IDEs like Cursor, VS Code, and Claude Desktop can call OpenFang agents directly.

OpenFang implements MCP protocol version `2024-11-05`.

**Source files:**
- Client: `crates/openfang-runtime/src/mcp.rs`
- Server handler: `crates/openfang-runtime/src/mcp_server.rs`
- CLI server: `crates/openfang-cli/src/mcp.rs`
- Config types: `crates/openfang-types/src/config.rs` (`McpServerConfigEntry`, `McpTransportEntry`)

### MCP Client

The MCP client (`McpConnection` in `openfang-runtime`) allows OpenFang to connect to any MCP-compatible server and use its tools as if they were built-in.

#### Configuration

MCP servers are configured in `config.toml` using the `[[mcp_servers]]` array:

```toml
[[mcp_servers]]
name = "github"
timeout_secs = 30
env = ["GITHUB_PERSONAL_ACCESS_TOKEN"]

[mcp_servers.transport]
type = "stdio"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
```

#### Advanced MCP Server Configuration

Each entry maps to a `McpServerConfigEntry` struct:

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `String` | required | Display name, used in tool namespacing |
| `transport` | `McpTransportEntry` | required | How to connect (stdio or SSE) |
| `timeout_secs` | `u64` | `30` | JSON-RPC request timeout |
| `env` | `Vec<String>` | `[]` | Env vars to pass through to the subprocess |

#### Transport Types

OpenFang supports two MCP transports, defined by `McpTransport`:

**Stdio** -- Spawns a subprocess and communicates via stdin/stdout with newline-delimited JSON-RPC:

```toml
[mcp_servers.transport]
type = "stdio"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
```

**SSE** -- Connects to a remote HTTP endpoint and sends JSON-RPC via POST:

```toml
[mcp_servers.transport]
type = "sse"
url = "https://mcp.example.com/api"
```

#### Tool Connectivity Lifecycle

The `McpConnection` struct manages the lifetime of the connection:

```rust
pub struct McpConnection {
    config: McpServerConfig,
    tools: Vec<ToolDefinition>,
    transport: McpTransportHandle,  // Stdio or SSE
    next_id: u64,                   // JSON-RPC request counter
}
```

When the connection is dropped, stdio subprocesses are automatically killed via `Drop`:

```rust
impl Drop for McpConnection {
    fn drop(&mut self) {
        if let McpTransportHandle::Stdio { ref mut child, .. } = self.transport {
            let _ = child.start_kill();
        }
    }
}
```

### MCP Server

OpenFang can also act as an MCP server, exposing its agents as callable tools to external MCP clients.

#### How It Works

Each OpenFang agent becomes an MCP tool named `openfang_agent_{name}` (with hyphens replaced by underscores). The tool accepts a single `message` string parameter and returns the agent's response.

For example, an agent named `code-reviewer` becomes the MCP tool `openfang_agent_code_reviewer`.

#### Supported JSON-RPC Methods

| Method | Description |
| --- | --- |
| `initialize` | Handshake; returns server capabilities and info |
| `notifications/initialized` | Client confirmation; no response |
| `tools/list` | Returns all available tools with names, descriptions, and input schemas |
| `tools/call` | Executes a tool and returns the result |

#### Task Lifecycle

An `A2aTask` tracks the full lifecycle of a cross-agent interaction.

| Status | Description |
| --- | --- |
| `Submitted` | Task received but not yet started |
| `Working` | Task is being actively processed by the agent |
| `Completed` | Task finished successfully |
| `Cancelled` | Task was cancelled by the caller |
| `Failed` | Task encountered an error |

## Part 2: A2A (Agent-to-Agent Protocol)

### A2A Overview

The Agent-to-Agent (A2A) protocol enables cross-framework agent interoperability, allowing agents built with different frameworks to discover each other's capabilities and exchange tasks.

OpenFang implements A2A in both directions:

- **As a server**: Publishes Agent Cards describing each agent's capabilities, accepts task submissions, and tracks task lifecycle.
- **As a client**: Discovers external A2A agents at boot time, sends tasks to them, and polls for results.

### Agent Card

An Agent Card is a JSON document that describes an agent's identity, capabilities, and supported interaction modes. It is served at the well-known path `/.well-known/agent.json` per the A2A specification.

Example card:

```json
{
  "name": "code-reviewer",
  "description": "Reviews code for bugs, security issues, and style",
  "url": "http://127.0.0.1:50051/a2a",
  "version": "0.1.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false,
    "stateTransitionHistory": true
  },
  "skills": [
    {
      "id": "file_read",
      "name": "file read",
      "description": "Can use the file_read tool",
      "tags": ["tool"],
      "examples": []
    }
  ],
  "defaultInputModes": ["text"],
  "defaultOutputModes": ["text"]
}
```

### A2A API Endpoints

| Method | Path | Auth | Description |
| --- | --- | --- | --- |
| `GET` | `/.well-known/agent.json` | Public | Agent Card for the primary agent |
| `POST` | `/a2a/tasks/send` | Public | Submit a task to an agent |

### A2A Configuration

A2A is configured in `config.toml` under the `[a2a]` section:

```toml
[a2a]
enabled = true
listen_path = "/a2a"

[[a2a.external_agents]]
name = "research-agent"
url = "https://research.example.com"
```

### Security

#### MCP Security

- **Subprocess Sandboxing**: Stdio MCP servers run with `env_clear()` to prevent leaking secrets to untrusted MCP server processes.
- **Request Timeout**: All MCP requests have a configurable timeout (default 30 seconds) to prevent hung connections.

#### A2A Security

- **Rate Limiting**: A2A endpoints go through the same GCRA rate limiter as all other API endpoints.
- **Task Store Bounds**: The `A2aTaskStore` is bounded with FIFO eviction of completed/failed/cancelled tasks, preventing memory exhaustion from task accumulation.
