> ## Documentation Index
> Fetch the complete documentation index at: https://mcp-use.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://mcp-use.com/docs/feedback

```json
{
  "path": "/python/client/direct-tool-calls",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Direct Tool Calls

> Learn how to call MCP tools directly without using an LLM

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 theme={null}
  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 theme={null}
  # 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 theme={null}
  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 theme={null}
  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 theme={null}
  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
