# How to Integrate Agent Reach with Custom MCP Servers Beyond Exa

> Integrate Agent Reach with custom MCP servers by exposing a JSON-RPC 2.0 endpoint and registering it with mcporter. Learn how to connect beyond Exa and enhance your server's capabilities.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: how-to-guide
- Published: 2026-06-26

---

**You integrate Agent Reach with custom MCP servers by exposing a JSON-RPC 2.0 endpoint that implements the Meta-Command Protocol, registering it with `mcporter`, and optionally creating a Channel subclass that probes the configuration to activate the backend.**

Agent Reach uses the **Meta-Command Protocol (MCP)** as a thin bridge between its channel logic and external services. While the repository ships with built-in Exa search integration via [`agent_reach/channels/exa_search.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa_search.py), you can extend this architecture to any custom service by following the patterns established in [`agent_reach/integrations/mcp_server.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/integrations/mcp_server.py).

## Understanding the MCP Architecture

Agent Reach's MCP integration relies on two core components. First, [`agent_reach/integrations/mcp_server.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/integrations/mcp_server.py) registers Agent Reach status as an MCP tool and exposes it via JSON-RPC 2.0 over HTTP (lines 27-34). Second, channel implementations like the Exa search channel probe `mcporter` and read MCP configuration to determine backend availability (lines 23-30 in [`agent_reach/channels/exa_search.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa_search.py)).

To hook a custom MCP server into this ecosystem, you must expose a compatible endpoint, register it with `mcporter`, and ensure Agent Reach can verify its availability.

## Step 1: Install Agent Reach with MCP Support

Before implementing custom integrations, install the package with MCP extras:

```bash
pip install "agent-reach[mcp]"

```

This installs the `mcp` Python package required to run the built-in MCP server and communicate with any MCP endpoint.

## Step 2: Implement Your Custom MCP Server

Create a JSON-RPC 2.0 HTTP service following the MCP specification. Your server must implement `list_tools()` to advertise available tools and `call_tool(name, arguments)` to execute them, similar to the built-in server implementation in [`agent_reach/integrations/mcp_server.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/integrations/mcp_server.py) (lines 36-43).

Here is a minimal implementation:

```python
from mcp.server import Server
from mcp.types import Tool, TextContent
import json

def create_server():
    server = Server("my-mcp")
    
    @server.list_tools()
    async def list_tools():
        return [
            Tool(
                name="my_search",
                description="Search my custom index",
                inputSchema={"type": "object", "properties": {"q": {"type": "string"}}},
            )
        ]

    @server.call_tool()
    async def call_tool(name: str, arguments: dict):
        if name == "my_search":
            result = {"hits": ["item1", "item2"]}
            text = json.dumps(result, ensure_ascii=False, indent=2)
            return [TextContent(type="text", text=text)]
        return [TextContent(type="text", text=f"Unknown tool: {name}")]

    return server

if __name__ == "__main__":
    import asyncio
    from mcp.server.stdio import stdio_server
    
    async def main():
        srv = create_server()
        async with stdio_server() as (read, write):
            await srv.run(read, write, srv.create_initialization_options())
    
    asyncio.run(main())

```

Run this server with `python my_mcp_server.py`, ensuring it listens on a stable URL such as `http://localhost:18061/mcp`.

## Step 3: Register the Endpoint with mcporter

Once your server is running, register it with Agent Reach's configuration tool:

```bash
mcporter config add myservice http://localhost:18061/mcp

```

Replace `myservice` with a short identifier that you will reference in your Channel subclass. This mirrors the Exa registration pattern, where `mcporter config add exa https://mcp.exa.ai/mcp` enables the Exa channel to discover its backend.

## Step 4: Create a Custom Channel Subclass

To officially recognize your MCP server as an active backend, create a new Channel subclass in [`agent_reach/channels/myservice.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/myservice.py). As defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) (lines 29-71), the Channel base class requires you to implement a `check()` method that probes `mcporter` to verify the endpoint is reachable.

Here is a complete template:

```python
from agent_reach.probe import probe_command
from .base import Channel

class MyServiceChannel(Channel):
    name = "myservice"
    description = "Custom MCP-backed service"
    backends = ["MyService via mcporter"]
    tier = 0

    def can_handle(self, url: str) -> bool:
        # Optional: return True for URLs your service can handle

        return False

    def check(self, config=None):
        self.active_backend = None
        probe = probe_command(
            "mcporter", ["config", "list"], timeout=10, package="mcporter"
        )
        if probe.status == "missing":
            return "off", "Install mcporter and add your MCP endpoint."
        if probe.status == "broken":
            return "error", "mcporter is broken – reinstall it."
        if "myservice" in probe.output.lower():
            self.active_backend = self.backends[0]
            return "ok", "MyService MCP is configured and reachable."
        return "off", "mcporter is installed but MyService not configured."

```

Add this file to [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) to ensure discovery by the core system. The `probe_command` function verifies that your service appears in `mcporter config list` before marking the backend as active.

## Step 5: Verify Integration with the Doctor Command

Validate that Agent Reach recognizes your custom MCP server by running:

```bash
python -m agent_reach.cli doctor

```

As implemented in [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py) (lines 39-42), the `doctor_report()` method invokes each channel's `check()` method. The output should list your service under "Active backends," confirming that downstream AI agents can invoke your MCP tools via `mcporter call myservice.mytool`.

## Key Integration Files

Understanding these source files helps debug custom integrations:

- **[`agent_reach/integrations/mcp_server.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/integrations/mcp_server.py)** (lines 27-34): Provides the built-in MCP "status" tool and demonstrates the JSON-RPC 2.0 server structure.
- **[`agent_reach/channels/exa_search.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa_search.py)** (lines 23-30): Shows how a production channel probes `mcporter` and expects an MCP config entry.
- **[`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py)** (lines 29-71): Defines the abstract `Channel` base class with `check()`, `ordered_backends()`, and `active_backend` attributes.
- **[`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py)** (lines 39-42): Contains the `AgentReach.doctor_report()` method that aggregates channel health checks.
- **[`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py)**: Entry point for the `doctor` command that displays backend status.

## Summary

- **Install MCP dependencies** using `pip install "agent-reach[mcp]"` to enable protocol support.
- **Expose a JSON-RPC 2.0 endpoint** implementing `list_tools()` and `call_tool()` following the pattern in [`agent_reach/integrations/mcp_server.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/integrations/mcp_server.py).
- **Register with mcporter** using `mcporter config add <name> <url>` to make the endpoint discoverable.
- **Subclass Channel** in `agent_reach/channels/` to probe the configuration and mark the backend as active, mirroring the pattern in [`agent_reach/channels/exa_search.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/exa_search.py).
- **Verify with doctor** by running `python -m agent_reach.cli doctor` to confirm your custom MCP server appears in the health report.

## Frequently Asked Questions

### What is the MCP protocol in Agent Reach?

The **Meta-Command Protocol (MCP)** is a thin bridge between Agent Reach's channel logic and external services. It uses JSON-RPC 2.0 over HTTP to allow AI agents to invoke tools exposed by external servers. The protocol is implemented in [`agent_reach/integrations/mcp_server.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/integrations/mcp_server.py) and consumed by channels that probe `mcporter` for configuration.

### Do I need to create a Channel subclass for every custom MCP server?

While you can register an MCP endpoint with `mcporter` without creating a Channel, **implementing a Channel subclass is recommended** for full integration. The Channel class (defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py)) provides the `check()` method that determines whether the backend is available, allowing the `doctor` command to report status and enabling the tiered backend selection logic.

### How does Agent Reach verify that my MCP server is running?

Agent Reach verifies MCP servers through the `mcporter` command-line tool. Your Channel's `check()` method should call `probe_command("mcporter", ["config", "list"], ...)` to confirm the endpoint is registered. The `doctor` command in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) aggregates these checks via `AgentReach.doctor_report()` (lines 39-42 in [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py)) to display active backends.

### Can I use stdio transport instead of HTTP for my MCP server?

The provided examples use **stdio transport** via `mcp.server.stdio` for simplicity, but production deployments typically expose HTTP endpoints. Agent Reach's `mcporter` configuration expects HTTP URLs (e.g., `http://localhost:18061/mcp`). Ensure your server implements the same JSON-RPC 2.0 protocol regardless of transport, matching the interface defined in [`agent_reach/integrations/mcp_server.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/integrations/mcp_server.py).