mirror of
https://github.com/mcp-use/mcp-use.git
synced 2026-09-14 18:06:01 +08:00
244 lines
6.8 KiB
Plaintext
244 lines
6.8 KiB
Plaintext
---
|
|
title: Direct Tool Calls
|
|
description: Learn how to call MCP tools directly without using an LLM
|
|
icon: "phone-outgoing"
|
|
---
|
|
|
|
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.
|
|
|
|
## When to Use Direct Tool Calls
|
|
|
|
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
|
|
|
|
<Note>
|
|
Direct tool calls will not work for tools that require sampling/completion, as
|
|
these need an LLM to generate responses.
|
|
</Note>
|
|
|
|
## Basic Example
|
|
|
|
Here's how to call tools directly using the MCPClient:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
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())
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Working with Tool Results
|
|
|
|
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
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# 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')}")
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Multiple Server Example
|
|
|
|
You can work with multiple MCP servers and call tools from each:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
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())
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Discovering Available Tools
|
|
|
|
Before calling tools, you may want to discover what's available:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
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()
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Error Handling
|
|
|
|
Always handle potential errors when making direct tool calls:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
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
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Limitations
|
|
|
|
When using direct tool calls, be aware of these limitations:
|
|
|
|
1. **No Sampling Support**: Tools that require sampling/completion (like text generation) won't work without an LLM
|
|
2. **Manual Tool Selection**: You need to know which tool to call - there's no automatic selection
|
|
3. **No Context Management**: Unlike agents, direct calls don't maintain conversation context
|
|
4. **Parameter Validation**: You're responsible for providing correct parameters
|
|
|
|
## Complete Example
|
|
|
|
View the complete working example in the repository:
|
|
|
|
[examples/direct_tool_call.py](https://github.com/pietrozullo/mcp-use/blob/main/examples/direct_tool_call.py)
|
|
|
|
## Next Steps
|
|
|
|
- Learn about [tool discovery](/python/client/tools) to explore available tools
|
|
- Understand [connection types](/python/client/connection-types) for different server configurations
|
|
- Explore [building custom agents](/python/agent/building-custom-agents) for more complex use cases
|