sequenceDiagram
participant A as Agent
participant M as MCPTools
participant S as MCP Server
A->>M: get_tools()
M->>S: Connect via stdio
S->>M: List of tools
M->>A: FunctionTool objects
Note over A: Agent runs...
A->>M: Call tool(args)
M->>S: Connect + call_tool
S->>M: Result
M->>A: String result
9 MCP Client
Model Context Protocol (MCP) — standardized tool servers for agents.
Note
Code Reference: code/v0.6/src/agentsilex/mcp.py
9.1 What is MCP?
MCP is a protocol (by Anthropic) for tool servers that agents can connect to:
Agent ←→ MCP Client ←→ MCP Server ←→ External Service
Benefits:
- Standardized — One protocol, many tools
- Reusable — Same server works with any MCP client
- Isolated — Tools run in separate processes
- Ecosystem — Growing library of pre-built servers
9.2 Converting MCP Tools to FunctionTool
First, we need to convert MCP tools to our FunctionTool format (mcp.py):
from mcp import types as mcp_types
from agentsilex.function_tool import FunctionTool
def mcp_tool_as_function_tool(mcp_tool: mcp_types.Tool, func: Callable) -> FunctionTool:
return FunctionTool(
name=mcp_tool.name,
description=mcp_tool.description,
function=func,
parameters_specification=mcp_tool.inputSchema,
)MCP tools already have name, description, and JSON schema — we just wrap them.
9.3 The MCPTools Class
import asyncio
from typing import List
import json
from mcp import ClientSession, StdioServerParameters
from mcp import types as mcp_types
from mcp.client.stdio import stdio_client
class MCPTools:
def __init__(self, server_parameters: dict):
self.server_params = StdioServerParameters(**server_parameters)
self.tools = None
def get_tools(self) -> List[FunctionTool]:
if not self.tools:
mcp_tools = self._get_mcp_tools()
self.tools = self._build_mcp_func(mcp_tools)
return self.tools
def _get_mcp_tools(self) -> List[mcp_types.Tool]:
async def run():
async with stdio_client(self.server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
return tools.tools
return asyncio.run(run())
def _build_mcp_func(self, mcp_tools: List[mcp_types.Tool]) -> List[FunctionTool]:
def func_maker(mcp_tool: mcp_types.Tool) -> FunctionTool:
def wrapper(**kwargs):
async def run():
async with stdio_client(self.server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool(mcp_tool.name, kwargs)
return result
return asyncio.run(run())
return mcp_tool_as_function_tool(mcp_tool, wrapper)
return [func_maker(tool) for tool in mcp_tools]Key methods:
get_tools()— Returns list ofFunctionToolobjects_get_mcp_tools()— Connects to MCP server, lists available tools_build_mcp_func()— Creates wrapper functions that call the MCP server
9.4 Helper Functions
def mcp_tools(server_params) -> List[FunctionTool]:
"""Quick way to get tools from server parameters."""
mcp_tools_instance = MCPTools(server_params)
return mcp_tools_instance.get_tools()
def mcp_tool_from_config(config_path: str):
"""Load tools from a config file (supports Claude Desktop format)."""
with open(config_path) as f:
config = json.load(f)
# Support both direct format and Claude Desktop format
if "mcpServers" in config:
config = config["mcpServers"]
return mcp_tools(config)9.5 Usage Example
from agentsilex import Agent, Runner, Session
from agentsilex.mcp import mcp_tools
# Define MCP server parameters
server_params = {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-filesystem", "/tmp"],
}
# Get tools from MCP server
fs_tools = mcp_tools(server_params)
# Create agent with MCP tools
agent = Agent(
name="file_assistant",
model="gpt-4o",
instructions="You can read and write files. Use the available tools.",
tools=fs_tools,
)
# Run
session = Session()
runner = Runner(session)
result = runner.run(agent, "List files in /tmp")9.6 Config File Format
You can use a JSON config file:
{
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-filesystem", "/allowed/path"]
}Or the Claude Desktop format:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-filesystem", "/allowed/path"]
}
}
}from agentsilex.mcp import mcp_tool_from_config
tools = mcp_tool_from_config("mcp_config.json")9.7 Popular MCP Servers
| Server | Command | Tools |
|---|---|---|
| Filesystem | @anthropic/mcp-server-filesystem |
read_file, write_file, list_directory |
| GitHub | @anthropic/mcp-server-github |
search_repos, create_issue, etc. |
| PostgreSQL | @anthropic/mcp-server-postgres |
query, list_tables |
| Puppeteer | @anthropic/mcp-server-puppeteer |
navigate, screenshot, click |
9.8 How It Works
Note: Each tool call creates a new connection. This is simple but not optimized for high-frequency calls.
9.9 Combining with Regular Tools
from agentsilex import tool
from agentsilex.mcp import mcp_tools
# Regular tool
@tool
def calculate(expression: str) -> str:
"""Evaluate a math expression."""
return str(eval(expression))
# MCP tools
fs_tools = mcp_tools({"command": "npx", "args": ["..."]})
# Combine
agent = Agent(
name="assistant",
tools=[calculate] + fs_tools, # Mix both types
# ...
)9.10 Key Design Decisions
| Decision | Why |
|---|---|
| Sync wrapper around async | AgentSilex is sync-first |
| New connection per call | Simple, stateless |
| Claude Desktop config support | Easy migration |
| Returns FunctionTool | Seamless integration |
TipCheckpoint
cd code/v0.6MCP client integration complete! Connect to any MCP server.