By Sagar Shankaran, Founder of CallSphere
Master MCPServerStdio for connecting agents to local tool servers via standard I/O, including subprocess management, npx-based servers, filesystem operations, and automatic lifecycle handling.
Key takeaways
MCPServerStdio is the simplest MCP transport. Your agent spawns the MCP server as a child process, then communicates with it by writing JSON-RPC messages to the process's stdin and reading responses from stdout. No network, no ports, no HTTP — just pipes.
This makes Stdio ideal for local development, filesystem tools, database access on the same machine, and any scenario where the tool server runs alongside the agent.
from agents.mcp import MCPServerStdio
# The params dict mirrors how you would run the command in a terminal
server = MCPServerStdio(
name="Filesystem",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"],
},
)
The params object accepts:
flowchart LR
HOST(["MCP host<br/>Claude Desktop or IDE"])
CLIENT["MCP client"]
subgraph SERVERS["MCP Servers"]
S1["Filesystem server"]
S2["GitHub server"]
S3["Postgres server"]
SX["Custom tool server"]
end
LLM["LLM session"]
OUT(["Grounded action"])
HOST <--> CLIENT
CLIENT <-->|stdio or HTTP+SSE| S1
CLIENT <--> S2
CLIENT <--> S3
CLIENT <--> SX
CLIENT --> LLM --> OUT
style HOST fill:#f1f5f9,stroke:#64748b,color:#0f172a
style CLIENT fill:#4f46e5,stroke:#4338ca,color:#fff
style OUT fill:#059669,stroke:#047857,color:#fff
npx, python, node)When you enter the async with block, MCPServerStdio spawns the subprocess and performs the MCP initialization handshake:
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
import asyncio
from agents import Agent, Runner
from agents.mcp import MCPServerStdio
async def main():
server = MCPServerStdio(
name="SQLite",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sqlite",
"--db-path", "/tmp/my-database.db"],
},
)
async with server:
# At this point, the subprocess is running and tools are discovered
# The server has reported its available tools via the MCP handshake
agent = Agent(
name="Database Assistant",
instructions="Help users query and manage the SQLite database.",
mcp_servers=[server],
)
result = await Runner.run(
agent,
input="What tables exist in the database? Show me the schema.",
)
print(result.final_output)
# Exiting the async with block kills the subprocess cleanly
asyncio.run(main())
The most common pattern uses npx to run MCP servers published as npm packages. The -y flag auto-confirms the install prompt:
# Filesystem access
fs_server = MCPServerStdio(
name="Filesystem",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
},
)
# Git operations
git_server = MCPServerStdio(
name="Git",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-git",
"--repository", "/path/to/repo"],
},
)
# GitHub API (requires GITHUB_TOKEN env var)
github_server = MCPServerStdio(
name="GitHub",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": "ghp_your_token_here"},
},
)
# PostgreSQL queries
postgres_server = MCPServerStdio(
name="Postgres",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres",
"postgresql://user:pass@localhost:5432/mydb"],
},
)
You can also write MCP servers in Python using the mcp package:
# my_tools_server.py
from mcp.server.fastmcp import FastMCP
import httpx
mcp = FastMCP("My Custom Tools")
@mcp.tool()
async def get_weather(city: str) -> str:
"""Get current weather for a city."""
async with httpx.AsyncClient() as client:
resp = await client.get(
"https://api.weatherapi.com/v1/current.json",
params={"key": "YOUR_KEY", "q": city},
)
data = resp.json()
current = data["current"]
return f"{city}: {current['temp_c']}C, {current['condition']['text']}"
@mcp.tool()
def calculate_bmi(weight_kg: float, height_m: float) -> str:
"""Calculate BMI given weight in kg and height in meters."""
bmi = weight_kg / (height_m ** 2)
category = (
"underweight" if bmi < 18.5
else "normal" if bmi < 25
else "overweight" if bmi < 30
else "obese"
)
return f"BMI: {bmi:.1f} ({category})"
if __name__ == "__main__":
mcp.run(transport="stdio")
Connect this server to your agent:
custom_server = MCPServerStdio(
name="Custom Tools",
params={
"command": "python",
"args": ["my_tools_server.py"],
"cwd": "/path/to/server",
},
)
The filesystem MCP server is one of the most useful. It provides these tools:
The path argument to the server defines the allowed root directory. The server will refuse to access files outside this directory, providing a security boundary:
async def file_management_agent():
server = MCPServerStdio(
name="Filesystem",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem",
"/home/user/projects"],
},
)
async with server:
agent = Agent(
name="Project Organizer",
instructions="""You help organize project files.
You can read, create, move, and search files.
Always explain what you are doing before making changes.
Never delete files without explicit confirmation.""",
mcp_servers=[server],
)
result = await Runner.run(
agent,
input="Find all Python files in the project and create an index.md listing them with their first docstring",
)
print(result.final_output)
MCPServerStdio handles the full subprocess lifecycle:
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
async withIf the subprocess crashes mid-conversation, the SDK raises an error that you can catch and handle:
async def resilient_agent():
server = MCPServerStdio(
name="Tools",
params={"command": "npx", "args": ["-y", "my-mcp-server"]},
)
try:
async with server:
agent = Agent(
name="Resilient Agent",
instructions="Help users with their tasks.",
mcp_servers=[server],
)
result = await Runner.run(agent, input="Do something useful")
print(result.final_output)
except Exception as e:
print(f"MCP server error: {e}")
# Fall back to agent without MCP tools, or restart the server
Pass secrets to MCP servers via environment variables, never as command-line arguments (which are visible in process listings):
server = MCPServerStdio(
name="GitHub",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"],
"PATH": os.environ["PATH"], # Inherit PATH for npx resolution
},
},
)
Note that when you specify env, it replaces the entire environment. You typically want to include PATH so the subprocess can find npx and node.
Running multiple Stdio servers is straightforward — each gets its own subprocess:
async def multi_tool_agent():
fs = MCPServerStdio(
name="Files",
params={"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]},
)
db = MCPServerStdio(
name="Database",
params={"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sqlite",
"--db-path", "/workspace/data.db"]},
)
git = MCPServerStdio(
name="Git",
params={"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-git",
"--repository", "/workspace"]},
)
async with fs, db, git:
agent = Agent(
name="Full-Stack Dev",
instructions="""You are a development assistant with access to
the filesystem, a SQLite database, and git.
Use these tools to help developers with their tasks.""",
mcp_servers=[fs, db, git],
)
result = await Runner.run(
agent,
input="Read the schema from schema.sql, create the tables in the database, then commit the changes",
)
print(result.final_output)
MCPServerStdio is the workhorse transport for local development and single-machine deployments. It is fast, simple, and requires no infrastructure beyond the subprocess itself.

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
OpenAI's Frontier platform makes model-native orchestration the default. What that means for agent builders, voice/chat buyers, and the build-vs-buy decision.
How to design a multi-agent system using MCP for tools and A2A for cross-vendor coordination, with a CallSphere voice agent as a participating node.
The 2026 desktop AI agent landscape — ServiceNow Project Arc, Anthropic Claude offerings, OpenAI agents, and Google Mariner. A buyer's map.
May 2026's biggest agent-architecture shift: planning, tool selection, and self-correction move inside the model. Framework code shrinks. Here is what changes.
A three-way comparison of Gemini Enterprise, Anthropic managed agents and OpenAI Frontier Platform after Cloud Next 2026 — strengths, gaps, buyer fit.
Anthropic's May 2026 push positions Claude as a vertical platform for financial services. The strategic positioning versus OpenAI and Google.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco