---
title: "Call a tool"
method: POST
path: "/v1/projects/{project_id}/tools/{tool_id}/call"
tags: ["Tools"]
---

# Call a tool

`POST /v1/projects/{project_id}/tools/{tool_id}/call`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/tools/{tool_id}/call`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.naturali.ai/authorize`, token URL `https://api.naturali.ai/token`, scopes: `mcp:access`)

Directly invokes a tool and returns its output. Supported for `http`, `mcp`, and `pipeline` tools. `client` tools cannot be invoked server-side and will return 422. A `pipeline` tool runs its declared steps in order and returns the mapped `output` (or the last step's output); `action` is ignored and `input` is the pipeline input.
For `mcp` tools the `action` field is required and identifies which tool name to invoke. For `http` tools `action` is ignored. When an `mcp` tool declares an `actions` allowlist, an action outside it is rejected with `400 VALIDATION_FAILED` ("not available on this tool") before any outbound request is made.
`preset_parameters` stored on the tool are pinned over the caller-supplied `input` before execution: a key the tool presets keeps its preset value even when `input` sets it. Keys the presets do not name are taken from `input` as sent.
Guardrails attached to the tool or to its project adjudicate the call before dispatch, composing project + tool scope. A call this route cannot await a decision on — class C (human sign-off), class D, or a class-B tripwire — is refused with `422 TOOL_DISPATCH_FAILED`, whose `meta` carries the `tool_id` and the `outcome`. A `pipeline` tool is adjudicated before its first step runs, and every step is adjudicated as the call of that tool it is.

A credential scoped to a project the tool is shared with, through an accepted share, calls it in that project: the calling project's guardrails adjudicate it, it is metered there with `publisher_project_id`, and the tool receives the calling project as the `calling_project_id` tool context key.

## Path parameters

- `tool_id` string, required

## Request body

- CallToolRequest
  - `action` string: For `mcp` tools: the MCP tool name to invoke (must be in the tool's `actions` allowlist when one is set, and must not be in its `denied_actions` denylist). Ignored for `http` tools.
  - `input` object: Input parameters for the tool call. These are merged with the tool's `preset_parameters` before execution; a preset value wins over the same key sent here.
  - `tool_context` object: Key/value context for this call, forwarded to the tool as `X-Naturali-Context-<key>` request headers and resolving any `{{context:<key>}}` token in the tool's `execute.headers`, `mcp.headers` or `preset_parameters`. Narrowed by the tool's `context_keys` allowlist when it sets one. This route has no session, so it stamps no server-derived identity: the reserved keys `session_id`, `actor_id` and `actor_external_id` are dropped from this bag (in any casing) rather than forwarded, so a downstream tool can still trust that a context header naming one is server-derived. Every other key becomes an HTTP header name and must match that grammar, or the call fails with `INVALID_TOOL_CONTEXT_KEY`.

## Response `200`

Tool output

- unknown

## Other responses

- `400`: Bad Request — invalid input or unknown action
- `401`: Unauthorized
- `403`: Forbidden — the caller lacks permission, or the tool's target is blocked by the deployment's egress policy (TOOL_EGRESS_BLOCKED). An `http`/`mcp` tool may only reach publicly routable addresses unless the destination is listed in the server's TOOL_EGRESS_ALLOWED_HOSTS; the check runs against the resolved address and on every redirect hop, so `meta.tool_address` names the address that was refused.
- `404`: Tool not found
- `422`: Unprocessable — tool type cannot be invoked server-side
- `429`: `SHARE_CAP_EXCEEDED`: the tool is another project's, reached through a share whose `cap` is spent for the window. Carries a `Retry-After` header and `error.meta.retry_after`.
- `502`: Upstream tool target error (TOOL_HTTP_ERROR). Returned when an `http`-type tool's target responds with a non-2xx status. The error `meta` carries the real upstream `tool_status_code`, `tool_response_body`, `tool_url`, and `tool_method`. A target that never answers (`http` or `mcp`) is `TOOL_UNREACHABLE`, its message naming the network failure and its `meta` the `tool_url` and `tool_method`.

---

[API](https://skmtc.dev/naturali/apis/naturali-ai-api.md) · [All operations](https://skmtc.dev/naturali/apis/naturali-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/naturali/apis/naturali-ai-api/revisions/e4905b78f422?raw)
