How to Connect an AI Agent to an MCP Server (Python Client)
Updated 2026-10-15
Claude Desktop and Cursor are MCP clients, but your own agent can be one too. This guide connects a Python agent to any stdio MCP server, converts the server’s tools into LLM tool definitions, and routes tool calls back to the server.
Prerequisites
- Python 3.10+,
pip install mcp openai - An MCP server to connect to. We use the one from Build an MCP server in Python, but any stdio server works (for example
npx -y @modelcontextprotocol/server-filesystem /tmp).
Steps
1. Open a client session
# mcp_agent.py
import asyncio, json
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from openai import OpenAI
SERVER = StdioServerParameters(command="python", args=["server.py"])
llm = OpenAI()
2. Convert MCP tools to OpenAI tool definitions
MCP tools already carry a JSON Schema in inputSchema, so the mapping is direct:
def to_openai_tools(mcp_tools):
return [{"type": "function", "function": {
"name": t.name,
"description": t.description or "",
"parameters": t.inputSchema}} for t in mcp_tools]
3. Run the agent loop, calling tools through the session
async def main(goal: str):
async with stdio_client(SERVER) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = (await session.list_tools()).tools
print("Tools:", [t.name for t in tools])
messages = [{"role": "user", "content": goal}]
for _ in range(8):
msg = llm.chat.completions.create(model="gpt-4.1-mini", messages=messages,
tools=to_openai_tools(tools)).choices[0].message
if not msg.tool_calls:
print(msg.content); return
messages.append(msg)
for call in msg.tool_calls:
result = await session.call_tool(call.function.name,
json.loads(call.function.arguments or "{}"))
text = "\n".join(c.text for c in result.content if c.type == "text")
messages.append({"role": "tool", "tool_call_id": call.id, "content": text})
asyncio.run(main("What's the weather in Lisbon right now?"))
4. Run it
python mcp_agent.py
The client launches the server as a subprocess, lists its tools, and the model calls current_weather with Lisbon’s coordinates.
5. Connect to a remote (HTTP) server instead
from mcp.client.streamable_http import streamablehttp_client
async with streamablehttp_client("https://example.com/mcp") as (read, write, _):
async with ClientSession(read, write) as session:
...
Using a framework instead
- OpenAI Agents SDK:
from agents.mcp import MCPServerStdioand passmcp_servers=[...]toAgent. - LangChain/LangGraph: the
langchain-mcp-adapterspackage loads MCP tools as LangChain tools.
Common errors
McpError: Connection closed right away: the server crashed on start. Run its command by hand to see the traceback.
result.isError is true: the tool raised an exception. The error text is in result.content. Pass it back to the model so it can correct its arguments.
Hangs on initialize(): the server writes non-protocol text to stdout. Servers must log to stderr only.