How to Integrate Agent Reach with Custom MCP Servers Beyond Exa
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, you can extend this architecture to any custom service by following the patterns established in 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 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).
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:
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 (lines 36-43).
Here is a minimal implementation:
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:
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. As defined in 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:
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 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:
python -m agent_reach.cli doctor
As implemented in 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(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(lines 23-30): Shows how a production channel probesmcporterand expects an MCP config entry.agent_reach/channels/base.py(lines 29-71): Defines the abstractChannelbase class withcheck(),ordered_backends(), andactive_backendattributes.agent_reach/core.py(lines 39-42): Contains theAgentReach.doctor_report()method that aggregates channel health checks.agent_reach/cli.py: Entry point for thedoctorcommand 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()andcall_tool()following the pattern inagent_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 inagent_reach/channels/exa_search.py. - Verify with doctor by running
python -m agent_reach.cli doctorto 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 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) 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 aggregates these checks via AgentReach.doctor_report() (lines 39-42 in 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →