Direct Tool Calls
MCP-Use allows you to call MCP server tools directly without needing an LLM or agent. This is useful when you want to use MCP servers as a simple interface to various tools and APIs, or when you need programmatic control over tool execution.
Direct tool calls are appropriate when:
- You know exactly which tool to call and with what parameters
- You don’t need an LLM to make decisions about tool selection
- You want to integrate MCP tools into existing Python applications
- You need deterministic, programmatic control over tool execution
Direct tool calls will not work for tools that require sampling/completion, as
these need an LLM to generate responses.
Basic Example
Here’s how to call tools directly using the MCPClient:
import asyncio
from mcp_use import MCPClient
async def call_tool_example():
# Configure the MCP server
config = {
"mcpServers": {
"everything": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"],
}
}
}
# Create client from configuration
client = MCPClient(config)
try:
# Initialize all configured sessions
await client.create_all_sessions()
# Get the session for a specific server
session = client.get_session("everything")
# List available tools
tools = await session.list_tools()
tool_names = [t.name for t in tools]
print(f"Available tools: {tool_names}")
# Call a specific tool with arguments
result = await session.call_tool(
name="add",
arguments={"a": 1, "b": 2}
)
# Handle the result
if getattr(result, "isError", False):
print(f"Error: {result.content}")
else:
print(f"Tool result: {result.content}")
print(f"Text result: {result.content[0].text}")
finally:
# Clean up resources
await client.close_all_sessions()
if __name__ == "__main__":
asyncio.run(call_tool_example())
The call_tool method returns a CallToolResult object with the following attributes:
content: A list of ContentBlock objects containing the tool’s output
structuredContent: A dictionary with the structured result (for non-sampling tools)
isError: Boolean indicating if the tool call encountered an error
Accessing Results
# Call a tool
result = await session.call_tool(
name="get_weather",
arguments={"location": "San Francisco"}
)
# Check for errors
if result.isError:
print(f"Tool error: {result.content}")
else:
# Access text content
text_result = result.content[0].text
print(f"Weather: {text_result}")
# Access structured content if available
if hasattr(result, 'structuredContent'):
structured = result.structuredContent
print(f"Temperature: {structured.get('temperature')}")
Multiple Server Example
You can work with multiple MCP servers and call tools from each:
import asyncio
from mcp_use import MCPClient
async def multi_server_example():
config = {
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem"],
"env": {"FILE_PATH": "/tmp"}
},
"time": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-time"]
}
}
}
client = MCPClient(config)
try:
await client.create_all_sessions()
# Call tool from filesystem server
fs_session = client.get_session("filesystem")
files = await fs_session.call_tool(
name="list_files",
arguments={"path": "/tmp"}
)
print(f"Files: {files.content[0].text}")
# Call tool from time server
time_session = client.get_session("time")
current_time = await time_session.call_tool(
name="get_current_time",
arguments={}
)
print(f"Current time: {current_time.content[0].text}")
finally:
await client.close_all_sessions()
if __name__ == "__main__":
asyncio.run(multi_server_example())
Before calling tools, you may want to discover what’s available:
async def discover_tools():
client = MCPClient(config)
await client.create_all_sessions()
try:
session = client.get_session("my_server")
# Get all tools
tools = await session.list_tools()
for tool in tools:
print(f"Tool: {tool.name}")
print(f" Description: {tool.description}")
# Print input schema if available
if hasattr(tool, 'inputSchema'):
print(f" Parameters: {tool.inputSchema}")
print()
finally:
await client.close_all_sessions()
Error Handling
Always handle potential errors when making direct tool calls:
async def safe_tool_call():
try:
result = await session.call_tool(
name="some_tool",
arguments={"param": "value"}
)
if result.isError:
# Handle tool-specific errors
error_msg = result.content[0].text if result.content else "Unknown error"
print(f"Tool returned error: {error_msg}")
return None
return result.content[0].text
except Exception as e:
# Handle connection or other errors
print(f"Failed to call tool: {e}")
return None
Limitations
When using direct tool calls, be aware of these limitations:
- No Sampling Support: Tools that require sampling/completion (like text generation) won’t work without an LLM
- Manual Tool Selection: You need to know which tool to call - there’s no automatic selection
- No Context Management: Unlike agents, direct calls don’t maintain conversation context
- Parameter Validation: You’re responsible for providing correct parameters
Complete Example
View the complete working example in the repository:
examples/direct_tool_call.py
Next Steps