docs/api-reference/client-api/tool-invocation.mdx
2024-11-20 12:24:08 -05:00

329 lines
No EOL
7.8 KiB
Text

---
title: "Tool invocation"
description: "Learn how to invoke tools through the MCP client API"
---
MCP allows clients to invoke tools exposed by servers. Tools are discrete operations that servers can perform on behalf of clients, similar to function calls.
## Getting available tools
Before invoking tools, you'll need to get a list of available tools from the server.
<CodeGroup>
```typescript TypeScript
import { Client } from "@modelcontextprotocol/sdk/client";
import { ListToolsResultSchema } from "@modelcontextprotocol/sdk/types";
// Assuming client is already connected
const result = await client.request(
{
method: "tools/list"
},
ListToolsResultSchema
);
// Tools are now available in result.tools
for (const tool of result.tools) {
console.log(`Found tool: ${tool.name}`);
console.log(`Description: ${tool.description}`);
}
```
```python Python
from mcp.client import Client
from mcp.types import ListToolsRequest
# Assuming client is already connected
result = await client.request(
ListToolsRequest(method="tools/list"),
ListToolsResultSchema
)
# Tools are now available in result.tools
for tool in result.tools:
print(f"Found tool: {tool.name}")
print(f"Description: {tool.description}")
```
</CodeGroup>
## Tool invocation
To invoke a tool, you'll use the `tools/call` method with the tool name and any required arguments.
<CodeGroup>
```typescript TypeScript
import { CallToolRequest, CallToolResultSchema } from "@modelcontextprotocol/sdk/types";
const result = await client.request(
{
method: "tools/call",
params: {
name: "example_tool",
arguments: {
param1: "value1",
param2: 42
}
}
},
CallToolResultSchema
);
// Tool result is available in result.toolResult
console.log("Tool result:", result.toolResult);
```
```python Python
from mcp.types import CallToolRequest, CallToolResult
result = await client.request(
CallToolRequest(
method="tools/call",
params={
"name": "example_tool",
"arguments": {
"param1": "value1",
"param2": 42
}
}
),
CallToolResult
)
# Tool result is available in result.tool_result
print("Tool result:", result.tool_result)
```
</CodeGroup>
## Progress tracking
For long-running tools, you can track progress using progress notifications.
<CodeGroup>
```typescript TypeScript
const result = await client.request(
{
method: "tools/call",
params: {
name: "long_running_tool",
arguments: {
duration: 10
}
}
},
CallToolResultSchema,
(progress) => {
console.log(`Progress: ${progress.progress}/${progress.total ?? '?'}`);
}
);
```
```python Python
def progress_callback(progress):
print(f"Progress: {progress.progress}/{progress.total or '?'}")
result = await client.request(
CallToolRequest(
method="tools/call",
params={
"name": "long_running_tool",
"arguments": {
"duration": 10
}
}
),
CallToolResult,
on_progress=progress_callback
)
```
</CodeGroup>
## Error handling
Tool invocations may fail for various reasons. Always handle potential errors appropriately.
<CodeGroup>
```typescript TypeScript
try {
const result = await client.request(
{
method: "tools/call",
params: {
name: "risky_tool",
arguments: {
important_param: "value"
}
}
},
CallToolResultSchema
);
} catch (error) {
if (error instanceof McpError) {
console.error(`Tool error (${error.code}): ${error.message}`);
if (error.data) {
console.error("Additional error data:", error.data);
}
} else {
console.error("Unexpected error:", error);
}
}
```
```python Python
from mcp.errors import McpError
try:
result = await client.request(
CallToolRequest(
method="tools/call",
params={
"name": "risky_tool",
"arguments": {
"important_param": "value"
}
}
),
CallToolResult
)
except McpError as e:
print(f"Tool error ({e.code}): {e.message}")
if e.data:
print("Additional error data:", e.data)
except Exception as e:
print("Unexpected error:", e)
```
</CodeGroup>
## Complete example
Here's a complete example showing how to discover and use tools with proper error handling.
<CodeGroup>
```typescript TypeScript
import { Client } from "@modelcontextprotocol/sdk/client";
import {
ListToolsResultSchema,
CallToolResultSchema,
McpError
} from "@modelcontextprotocol/sdk/types";
async function invokeTools(client: Client) {
try {
// Get available tools
const toolsList = await client.request(
{ method: "tools/list" },
ListToolsResultSchema
);
// Find a specific tool
const tool = toolsList.tools.find(t => t.name === "example_tool");
if (!tool) {
console.error("Tool not found");
return;
}
// Invoke the tool with progress tracking
const result = await client.request(
{
method: "tools/call",
params: {
name: tool.name,
arguments: {
// Tool-specific arguments
param1: "value1"
}
}
},
CallToolResultSchema,
(progress) => {
console.log(
`Progress: ${progress.progress}/${progress.total ?? '?'}`
);
}
);
console.log("Tool result:", result.toolResult);
} catch (error) {
if (error instanceof McpError) {
console.error(`Tool error (${error.code}): ${error.message}`);
} else {
console.error("Unexpected error:", error);
}
}
}
```
```python Python
from mcp.client import Client
from mcp.types import ListToolsRequest, CallToolRequest
from mcp.errors import McpError
async def invoke_tools(client: Client):
try:
# Get available tools
tools_list = await client.request(
ListToolsRequest(method="tools/list"),
ListToolsResultSchema
)
# Find a specific tool
tool = next(
(t for t in tools_list.tools if t.name == "example_tool"),
None
)
if not tool:
print("Tool not found")
return
# Invoke the tool with progress tracking
result = await client.request(
CallToolRequest(
method="tools/call",
params={
"name": tool.name,
"arguments": {
# Tool-specific arguments
"param1": "value1"
}
}
),
CallToolResult,
on_progress=lambda p: print(
f"Progress: {p.progress}/{p.total or '?'}"
)
)
print("Tool result:", result.tool_result)
except McpError as e:
print(f"Tool error ({e.code}): {e.message}")
except Exception as e:
print("Unexpected error:", e)
```
</CodeGroup>
## Best practices
When working with tools:
<CardGroup cols={2}>
<Card title="Validation" icon="check-circle">
Always check tool availability before invoking
</Card>
<Card title="Error handling" icon="shield-check">
Implement comprehensive error handling
</Card>
<Card title="Progress" icon="bars-progress">
Use progress callbacks for long-running operations
</Card>
<Card title="Arguments" icon="input-text">
Validate arguments against the tool's input schema
</Card>
</CardGroup>
## Common errors
| Error Code | Description | Resolution |
|------------|-------------|------------|
| -32601 | Method not found | Verify the tool name exists |
| -32602 | Invalid params | Check the tool's input schema |
| -32603 | Internal error | Server-side error, check server logs |
| -1 | Connection closed | Check connection status |