Testing MCP integrations often requires running external server processes. Mock servers let you test your agent’s MCP behavior without any external dependencies.
Why Mock?
- Fast — No subprocess or network overhead
- Deterministic — Predictable responses for every test
- Isolated — No external dependencies or credentials
- CI-friendly — Works in any environment
Basic Mock Server
Create a mock by defining the tools, resources, and prompts you want to simulate:
from definable.mcp import MCPToolkit, MCPConfig, MCPServerConfig
# Create a config pointing to a mock server
# In your test, you can mock the transport layer
config = MCPConfig(servers=[
MCPServerConfig(
name="mock-server",
transport="stdio",
command="python",
args=["mock_mcp_server.py"],
),
])
Combine MockModel with a mock MCP server to test the full agent-MCP integration:
from definable.agents import Agent, MockModel, create_test_agent
from definable.mcp import MCPToolkit, MCPConfig, MCPServerConfig
async def test_agent_uses_mcp_tools():
# Setup mock MCP server
config = MCPConfig(servers=[
MCPServerConfig(
name="test-server",
transport="stdio",
command="python",
args=["path/to/mock_server.py"],
),
])
async with MCPToolkit(config=config) as toolkit:
agent = Agent(
model=MockModel(responses=["I found the file contents."]),
toolkits=[toolkit],
)
output = await agent.arun("Read the config file")
assert output.content is not None
Writing a Mock MCP Server
Create a simple Python script that implements the MCP protocol over stdio:
#!/usr/bin/env python3
"""Simple mock MCP server for testing."""
import json
import sys
def handle_request(request):
method = request.get("method")
if method == "initialize":
return {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}},
"serverInfo": {"name": "mock-server", "version": "1.0.0"},
}
if method == "tools/list":
return {
"tools": [
{
"name": "read_file",
"description": "Read a file",
"inputSchema": {
"type": "object",
"properties": {
"path": {"type": "string", "description": "File path"}
},
"required": ["path"],
},
}
]
}
if method == "tools/call":
tool_name = request["params"]["name"]
if tool_name == "read_file":
return {"content": [{"type": "text", "text": "Mock file contents"}]}
return {"error": {"code": -32601, "message": "Method not found"}}
# Read requests from stdin, write responses to stdout
for line in sys.stdin:
request = json.loads(line.strip())
result = handle_request(request)
response = {"jsonrpc": "2.0", "id": request.get("id"), "result": result}
sys.stdout.write(json.dumps(response) + "\n")
sys.stdout.flush()
Testing Tips
Use MockModel
Combine mock MCP servers with MockModel to test the full pipeline without any real API calls.
Test Tool Filtering
Verify that allowed_tools and blocked_tools configuration works correctly with your mock server.
Test Error Paths
Make your mock server return errors to verify your agent handles MCP failures gracefully.
Test Reconnection
Simulate connection drops to verify the reconnection logic works.
For simple unit tests, you may not need a full mock server. You can test agent logic with MockModel alone and test MCP integration separately with real or mock servers in integration tests.