skills/dspy-mcp/SKILL.md
Use when you need to connect DSPy agents to external MCP tool servers — databases, file systems, APIs, or any MCP-compatible service. Common scenarios - wiring MCP tools into a ReAct or CodeAct agent, discovering tools from an MCP server at runtime, converting MCP tools to DSPy tools, or building agents that use tools hosted on remote servers. Related - dspy-tools, dspy-react, dspy-codeact, ai-taking-actions. Also used for dspy.Tool.from_mcp_tool, MCP with DSPy, connect DSPy to MCP server, use MCP tools in DSPy agent, model context protocol DSPy, DSPy agent with external tools via MCP, MCP tool integration, StdioServerParameters, ClientSession, stdio_client, mcp tool discovery, async MCP connection, acall with MCP tools.
npx skillsauth add lebsral/dspy-programming-not-prompting-lms-skills dspy-mcpInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Guide the user through connecting DSPy agents to MCP (Model Context Protocol) servers, discovering tools at runtime, and wiring them into ReAct or CodeAct agents.
DSPy can consume tools from any MCP-compatible server using dspy.Tool.from_mcp_tool(). This lets your agents use tools hosted externally -- databases, file systems, web APIs, or custom services -- without writing Python wrappers for each one. The MCP server handles execution; DSPy handles reasoning.
| Use MCP when... | Use plain dspy.Tool when... | |-----------------|----------------------------| | Tools are hosted on a separate process or server | You have a simple Python function | | You want to reuse tools across multiple AI systems | The tool is specific to this DSPy program | | Tools need isolation (file system access, DB connections) | No isolation needed | | An MCP server already exists for your use case | You are building tools from scratch | | You need runtime tool discovery (tools change dynamically) | Tool set is fixed at development time |
pip install dspy mcp
MCP servers communicate via stdio. Use StdioServerParameters to configure the server command and stdio_client to establish the connection:
import dspy
from mcp import StdioServerParameters, ClientSession
from mcp.client.stdio import stdio_client
lm = dspy.LM("openai/gpt-4o-mini") # or "anthropic/claude-sonnet-4-5-20250929", etc.
dspy.configure(lm=lm)
# Configure the MCP server to connect to
server_params = StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"],
)
Inside an async context, connect to the server, list available tools, and convert them to DSPy tools:
import asyncio
async def build_agent():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Initialize the MCP connection
await session.initialize()
# Discover available tools
mcp_tools = await session.list_tools()
print(f"Found {len(mcp_tools.tools)} tools")
# Convert MCP tools to DSPy tools
dspy_tools = [
dspy.Tool.from_mcp_tool(session, tool)
for tool in mcp_tools.tools
]
# Build a ReAct agent with the discovered tools
agent = dspy.ReAct(
"question -> answer",
tools=dspy_tools,
)
# Use acall() for async tool execution
result = await agent.acall(question="List all Python files in the project")
print(result.answer)
asyncio.run(build_agent())
The converted tools work exactly like native DSPy tools:
async def run_agent_with_mcp():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
mcp_tools = await session.list_tools()
dspy_tools = [
dspy.Tool.from_mcp_tool(session, tool)
for tool in mcp_tools.tools
]
# ReAct agent
agent = dspy.ReAct(
"task -> result",
tools=dspy_tools,
max_iters=10,
)
# Must use acall() because MCP tools are async
result = await agent.acall(task="Find the largest file and summarize it")
return result
Important: Use await agent.acall() (not agent()) because MCP tool calls are async operations.
Mix MCP-discovered tools with locally-defined Python tools:
def calculate(expression: str) -> str:
"""Evaluate a math expression."""
return str(eval(expression)) # use a safe evaluator in production
async def build_hybrid_agent():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
mcp_tools = await session.list_tools()
dspy_tools = [
dspy.Tool.from_mcp_tool(session, tool)
for tool in mcp_tools.tools
]
# Combine MCP tools with local tools
all_tools = dspy_tools + [calculate]
agent = dspy.ReAct("question -> answer", tools=all_tools)
result = await agent.acall(question="How many lines in main.py divided by 3?")
return result
MCP connections can fail. Wrap the connection in proper error handling:
from mcp import McpError
async def safe_agent_call(question: str):
try:
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
mcp_tools = await session.list_tools()
dspy_tools = [
dspy.Tool.from_mcp_tool(session, tool)
for tool in mcp_tools.tools
]
agent = dspy.ReAct("question -> answer", tools=dspy_tools)
return await agent.acall(question=question)
except McpError as e:
print(f"MCP server error: {e}")
return None
except ConnectionError:
print("Could not connect to MCP server")
return None
acall() and uses synchronous agent(). MCP tools are async -- you must use await agent.acall() or you get runtime errors. DSPy cannot call async MCP tools from a sync context.async with block. The MCP session is only valid inside the context manager. If you build the tools inside and call the agent outside, the session is closed and tool calls fail.session.list_tools() to get the current tool set -- MCP servers can add/remove tools dynamically.StdioServerParameters launches the server process. If the command fails (e.g., npx not installed, package not found), you get a cryptic connection error. Test the server command manually first.stdio_client context and one ClientSession context. Do not add extra wrappers.Tool descriptions matter for agent performance. The GEPA paper (arxiv 2507.19457) includes an MCP adapter that can automatically optimize tool descriptions -- not just task instructions -- through the same reflective evolution process. If your agent struggles to pick the right tool or misuses tool parameters, consider optimizing tool descriptions with /dspy-gepa.
Install any skill:
npx skills add lebsral/DSPy-Programming-not-prompting-LMs-skills --skill <name>
/dspy-tools/dspy-react/dspy-codeact/ai-taking-actions/dspy-async/ai-do if you do not have it -- it routes any AI problem to the right skill and is the fastest way to work: npx skills add lebsral/DSPy-Programming-not-prompting-LMs-skills --skill ai-dotools
See what is happening during optimizer.compile() instead of waiting blind. Use when you want to watch optimization progress, see scores as they come in, know if your optimizer is working, check if optimization is stuck, understand why optimization is taking too long, get live progress during compile, monitor convergence, detect overfitting during optimization, interpret optimization results, or pick the right tool for watching optimization. Also used for optimizer progress bar, is my optimizer doing anything, optimization seems stuck, how long will optimization take, watch GEPA run, watch MIPROv2 run, live optimization dashboard, optimizer not improving, scores not going up, optimization taking forever, see what optimizer is doing, debug slow optimization, optimization visibility, optimizer metrics, track compile progress, optimization observability.
testing
Use when you want the highest-quality prompt optimization DSPy offers — jointly optimizes instructions and few-shot demos, with auto=light/medium/heavy presets. Common scenarios - you want the best possible accuracy from prompt optimization, jointly tuning instructions and few-shot demonstrations, using auto presets for different compute budgets, or when COPRO or BootstrapFewShot alone are not reaching your accuracy target. Related - ai-improving-accuracy, dspy-copro, dspy-bootstrap-few-shot. Also used for dspy.MIPROv2, best DSPy optimizer, highest quality optimization, auto=light medium heavy, joint instruction and demo optimization, most powerful prompt optimizer, MIPROv2 vs COPRO vs BootstrapFewShot, which optimizer should I use, state of the art prompt optimization, when to use MIPROv2, optimize both instructions and examples, heavy optimization for production, best optimizer for accuracy.
testing
Use LangWatch for DSPy auto-tracing and real-time optimizer progress. Use when you want to set up LangWatch, langwatch.dspy.init, auto-tracing DSPy, real-time optimization dashboard, optimizer progress tracking, app.langwatch.ai, or DSPy optimizer dashboard. Also used for langwatch setup, pip install langwatch, langwatch trace, optimizer progress, real-time optimization, watch optimizer run, LangWatch self-hosted, langwatch docker, langwatch vs langtrace, langwatch autotrack_dspy.
data-ai
Use when you want to optimize instructions without few-shot examples — a lightweight alternative to COPRO when you do not have or do not want to use demonstrations. Common scenarios - optimizing instructions when you do not have or do not want to use few-shot demonstrations, lightweight instruction search as a first step, tasks where examples in the prompt confuse the model, or when you want fast instruction optimization without the cost of COPRO. Related - ai-improving-accuracy, dspy-copro, dspy-miprov2. Also used for dspy.GEPA, instruction optimization without demos, lightweight prompt optimization, optimize instructions only, no few-shot examples needed, GEPA vs COPRO, quick instruction search, when demonstrations hurt performance, zero-shot optimization, instruction-only optimizer, simplest instruction tuner, fast prompt optimization, skip few-shot and just tune instructions, optimize Pydantic field descriptions, GEPA structured output, GEPA does not optimize field desc.