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

# call_tool

> Execute one Toolshed tool by path. HTTP transport only.

## Overview

`call_tool` is the HTTP transport's primary execution verb. Where the stdio transport's [`run`](/mcp/run) tool composes multiple calls inside a TypeScript sandbox, `call_tool` invokes a single tool by path with structured arguments. One MCP call, one upstream call.

Available only on the remote MCP endpoint (`POST /api/mcp/:token`). The CLI's stdio surface uses `run` instead.

## Input

| Parameter   | Type     | Required | Description                                      |
| ----------- | -------- | -------- | ------------------------------------------------ |
| `path`      | `string` | Yes      | Tool path (e.g. `granola.personal.notes.list`)   |
| `arguments` | `object` | No       | Tool arguments matching the tool's `inputSchema` |

Use [`search_tools`](/mcp/search-tools) to find a path and [`read_tool`](/mcp/read-tool) to see what `arguments` should contain.

## Annotations

The MCP-level annotation on `call_tool` is non-destructive (it's a meta tool), but the underlying tool may itself be destructive. Hosts should rely on the `destructive` field returned by `read_tool` to decide whether to require user confirmation before invoking.

## Behavior

1. Look up the handler by `path`. Returns `Tool not found` if the tool isn't in the user's filtered catalog (either it doesn't exist or the user hasn't connected the provider).
2. Build a plugin context (`userId`, role, `auth.getToken` resolver, no-op elicitation, console logger).
3. Pass `arguments ?? {}` through the SDK's Zod input wrap — defaults from the tool's `inputSchema` are applied here, so omitted fields take their declared default rather than `undefined`.
4. Run the handler and stringify the result back as `text/plain` content.

## Examples

```jsonc theme={null}
// Search → read → call
{ "name": "search_tools", "arguments": { "query": "meeting notes" } }
// → returns granola.personal.notes.list (only if the user has the personal Granola key connected)

{ "name": "read_tool", "arguments": { "path": "granola.personal.notes.list" } }
// → returns inputSchema, outputSchema, destructive flag, authProvider

{ "name": "call_tool", "arguments": {
    "path": "granola.personal.notes.list",
    "arguments": { "limit": 5 }
} }
// → returns the user's 5 most recent meeting notes
```

## Errors

If the handler throws, `call_tool` returns `{ isError: true, content: [{ type: "text", text: "Error: <message>" }] }` so the agent gets a structured failure rather than a transport-level error. Common shapes:

* `Tool not found: <path>` — typo or unconnected provider
* `No credentials for "<provider>". Connect it in the Toolshed dashboard.` — `resolveToken()` exhausted all three sources
* Upstream API messages bubble through unchanged (e.g. `Granola API error 401: Unauthorized`)
