# MCP Integration Guide This guide explains how to integrate Model Context Protocol (MCP) servers with the Hive Core Framework, enabling agents to use tools from external MCP servers. ## Overview The framework provides built-in support for MCP servers, allowing you to: - **Register MCP servers** via STDIO, HTTP, Unix socket, or SSE transport - **Auto-discover tools** from registered servers - **Use MCP tools** seamlessly in your agents - **Manage multiple MCP servers** simultaneously ## Quick Start ### 1. Register an MCP Server Programmatically ```python from framework.runner.runner import AgentRunner # Load your agent runner = AgentRunner.load("exports/my-agent") # Register tools MCP server runner.register_mcp_server( name="tools", transport="stdio", command="python", args=["-m", "aden_tools.mcp_server", "--stdio"], cwd="/path/to/tools" ) # Tools are now available to your agent result = await runner.run({"input": "data"}) ``` ### 2. Use Configuration File Create `mcp_servers.json` in your agent folder: ```json { "servers": [ { "name": "tools", "transport": "stdio", "command": "python", "args": ["-m", "aden_tools.mcp_server", "--stdio"], "cwd": "../tools" } ] } ``` The framework will automatically load and register these servers when you load the agent: ```python runner = AgentRunner.load("exports/my-agent") # MCP servers auto-loaded ``` ## Transport Types ### STDIO Transport Best for local MCP servers running as subprocesses: ```python runner.register_mcp_server( name="local-tools", transport="stdio", command="python", args=["-m", "my_tools.server", "--stdio"], cwd="/path/to/my-tools", env={ "API_KEY": "your-key-here" } ) ``` **Configuration:** - `command`: Executable to run (e.g., "python", "node") - `args`: List of command-line arguments - `cwd`: Working directory for the process - `env`: Environment variables (optional) ### HTTP Transport Best for remote MCP servers or containerized deployments: ```python runner.register_mcp_server( name="remote-tools", transport="http", url="http://localhost:4001", headers={ "Authorization": "Bearer token" } ) ``` **Configuration:** - `url`: Base URL of the MCP server - `headers`: HTTP headers to include (optional) ### Unix Socket Transport Best for same-host inter-process communication with lower overhead than TCP: ```python runner.register_mcp_server( name="local-ipc-tools", transport="unix", url="http://localhost", socket_path="/tmp/mcp_server.sock", headers={ "Authorization": "Bearer token" } ) ``` **Configuration:** - `url`: Base URL for HTTP requests over the socket (required, e.g., `"http://localhost"`) - `socket_path`: Absolute path to the Unix socket file (required, e.g., `"/tmp/mcp_server.sock"`) - `headers`: HTTP headers to include (optional) ### SSE Transport Best for real-time, event-driven connections using the MCP SDK's SSE client: ```python runner.register_mcp_server( name="streaming-tools", transport="sse", url="http://localhost:8000/sse", headers={ "Authorization": "Bearer token" } ) ``` **Configuration:** - `url`: SSE endpoint URL (required, e.g., `"http://localhost:8000/sse"`) - `headers`: HTTP headers for the SSE connection (optional) ## Using MCP Tools in Agents Once registered, MCP tools are available just like any other tool: ### In Node Specifications ```python from framework.builder.workflow import WorkflowBuilder builder = WorkflowBuilder() # Add a node that uses MCP tools builder.add_node( node_id="researcher", name="Web Researcher", node_type="event_loop", system_prompt="Research the topic using web_search", tools=["web_search"], # Tool from tools MCP server input_keys=["topic"], output_keys=["findings"] ) ``` ### In Agent.json Tools from MCP servers can be referenced in your agent.json just like built-in tools: ```json { "nodes": [ { "id": "searcher", "name": "Web Searcher", "node_type": "event_loop", "system_prompt": "Search for information about {topic}", "tools": ["web_search", "web_scrape"], "input_keys": ["topic"], "output_keys": ["results"] } ] } ``` ## Available Tools from tools When you register the `tools` MCP server, the following tools become available: - **web_search**: Search the web using Brave Search API - **web_scrape**: Scrape content from a URL - **file_read**: Read file contents - **file_write**: Write content to a file - **pdf_read**: Extract text from PDF files ## Environment Variables Some MCP tools require environment variables. You can pass them in the configuration: ### Via Programmatic Registration ```python runner.register_mcp_server( name="tools", transport="stdio", command="python", args=["-m", "aden_tools.mcp_server", "--stdio"], cwd="../tools", env={ "BRAVE_SEARCH_API_KEY": os.environ["BRAVE_SEARCH_API_KEY"] } ) ``` ### Via Configuration File ```json { "servers": [ { "name": "tools", "transport": "stdio", "command": "python", "args": ["-m", "aden_tools.mcp_server", "--stdio"], "cwd": "../tools", "env": { "BRAVE_SEARCH_API_KEY": "${BRAVE_SEARCH_API_KEY}" } } ] } ``` The framework will substitute `${VAR_NAME}` with values from the environment. ## Multiple MCP Servers You can register multiple MCP servers to access different sets of tools: ```json { "servers": [ { "name": "tools", "transport": "stdio", "command": "python", "args": ["-m", "aden_tools.mcp_server", "--stdio"], "cwd": "../tools" }, { "name": "database-tools", "transport": "http", "url": "http://localhost:5001" }, { "name": "analytics-tools", "transport": "http", "url": "http://analytics-server:6001" } ] } ``` All tools from all servers will be available to your agent. ## Best Practices ### 1. Use STDIO for Development STDIO transport is easier to debug and doesn't require managing server processes: ```python runner.register_mcp_server( name="dev-tools", transport="stdio", command="python", args=["-m", "my_tools.server", "--stdio"] ) ``` ### 2. Use HTTP for Production HTTP transport is better for: - Containerized deployments - Shared tools across multiple agents - Remote tool execution ```python runner.register_mcp_server( name="prod-tools", transport="http", url="http://tools-service:8000" ) ``` ### 3. Use Unix Socket for Same-Host IPC When both the agent and MCP server run on the same machine, Unix sockets avoid TCP overhead: ```python runner.register_mcp_server( name="fast-local-tools", transport="unix", url="http://localhost", socket_path="/tmp/mcp_server.sock" ) ``` ### 4. Use SSE for Streaming and Real-Time Tools SSE transport maintains a persistent connection, ideal for event-driven servers: ```python runner.register_mcp_server( name="realtime-tools", transport="sse", url="http://realtime-server:8000/sse" ) ``` ### 5. Handle Cleanup Always clean up MCP connections when done: ```python try: runner = AgentRunner.load("exports/my-agent") runner.register_mcp_server(...) result = await runner.run(input_data) finally: runner.cleanup() # Disconnects all MCP servers ``` Or use context manager: ```python async with AgentRunner.load("exports/my-agent") as runner: runner.register_mcp_server(...) result = await runner.run(input_data) # Automatic cleanup ``` ### 6. Tool Name Conflicts If multiple MCP servers provide tools with the same name, the last registered server wins. To avoid conflicts: - Use unique tool names in your MCP servers - Register servers in priority order (most important last) - Use separate agents for different tool sets ## Troubleshooting ### Connection Errors If you get connection errors with STDIO transport: 1. Check that the command and path are correct 2. Verify the MCP server starts successfully standalone 3. Check environment variables are set correctly 4. Look at stderr output for error messages ### Tool Not Found If a tool is registered but not found: 1. Verify the server registered successfully (check logs) 2. List available tools: `runner._tool_registry.get_registered_names()` 3. Check tool name spelling in your node configuration ### HTTP Server Not Responding If HTTP transport fails: 1. Verify the server is running: `curl http://localhost:4001/health` 2. Check firewall settings 3. Verify the URL and port are correct ### Unix Socket Not Connecting If Unix socket transport fails: 1. Verify the socket file exists: `ls -la /tmp/mcp_server.sock` 2. Check file permissions on the socket 3. Ensure no other process has locked the socket 4. Verify the `url` field is set (e.g., `"http://localhost"`) ### SSE Connection Issues If SSE transport fails: 1. Verify the server supports SSE at the given URL 2. Check that the `mcp` Python package is installed (`pip install mcp`) 3. Ensure the SSE endpoint is accessible: `curl http://localhost:8000/sse` 4. Check for firewall or proxy issues blocking long-lived connections ## Example: Full Agent with MCP Tools Here's a complete example of an agent that uses MCP tools: ```python import asyncio from pathlib import Path from framework.runner.runner import AgentRunner async def main(): # Create agent path agent_path = Path("exports/web-research-agent") # Load agent runner = AgentRunner.load(agent_path) # Register MCP server runner.register_mcp_server( name="tools", transport="stdio", command="python", args=["-m", "aden_tools.mcp_server", "--stdio"], cwd="../tools", env={ "BRAVE_SEARCH_API_KEY": "your-api-key" } ) # Run agent result = await runner.run({ "query": "latest developments in quantum computing" }) print(f"Research complete: {result}") # Cleanup runner.cleanup() if __name__ == "__main__": asyncio.run(main()) ``` ## See Also - [MCP_SERVER_GUIDE.md](MCP_SERVER_GUIDE.md) - Building your own MCP servers - [examples/mcp_integration_example.py](examples/mcp_integration_example.py) - More examples - [examples/mcp_servers.json](examples/mcp_servers.json) - Example configuration