---
title: "UTCP"
url: "https://docs.unified.to/utcp"
description: "Unified.to documentation"
---
Table of Contents

# UTCP

Unified.to publishes its tools as a [UTCP](https://www.utcp.io) (Universal Tool Calling Protocol) manual at `/utcp`. A UTCP client reads the manual and then calls the Unified API directly over HTTP. The tools, permissions and billing are the same as on the [MCP server](https://docs.unified.to/mcp/overview), but UTCP is a separate protocol: there is no MCP connection involved.

> **For agents:** this page is also available as Markdown at <https://docs.unified.to/utcp.md>.

## [What is UTCP](https://docs.unified.to/utcp.md#what-is-utcp)

The **Universal Tool Calling Protocol** (UTCP) is an open standard for describing tools so that an agent can call them over their own protocol: HTTP, a CLI, WebSocket and others. There is no protocol server in between.

A UTCP server publishes a **manual**: a JSON document that lists each tool's name, description, input and output JSON schemas, and a **call template**. The call template says how to make the call, for example "POST to this URL, send this argument as the JSON body, put the API key in the `Authorization` header". The client fetches the manual once, then calls each tool itself.

|                      | MCP                                                   | UTCP                                                     |
| -------------------- | ----------------------------------------------------- | -------------------------------------------------------- |
| How a tool is called | JSON-RPC tools/call to an MCP server                  | A plain HTTP request built from the tool's call template |
| Discovery            | tools/list on a live connection                       | One GET of the manual                                    |
| Sessions             | Stateful (up to 2025-11-25) or stateless (2026-07-28) | None                                                     |
| Extras               | Events, Agent Skills, OAuth discovery                 | None of these: tools only                                |

Use UTCP when your agent framework already speaks UTCP, or when you want tool definitions that a client calls with ordinary HTTP. Use the [MCP server](https://docs.unified.to/mcp/installation) for MCP clients (Claude, ChatGPT, Cursor, VS Code, …) and when you need [MCP Events](https://docs.unified.to/mcp/overview#events-webhooks-for-agents) or [Agent Skills](https://docs.unified.to/mcp/core#agent-skills).

## [Who supports UTCP](https://docs.unified.to/utcp.md#who-supports-utcp)

UTCP is younger than MCP and none of the major LLM providers support it natively yet. You use it through a client library or an adapter. As of November 2026:

| Kind                  | Project                                                                                                                                                                                                  |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Python                | [utcp](https://pypi.org/project/utcp/) with the [utcp-http](https://pypi.org/project/utcp-http/) plugin ([python-utcp](https://github.com/universal-tool-calling-protocol/python-utcp))                  |
| TypeScript / Node.js  | [@utcp/sdk](https://www.npmjs.com/package/@utcp/sdk) with [@utcp/http](https://www.npmjs.com/package/@utcp/http) ([typescript-utcp](https://github.com/universal-tool-calling-protocol/typescript-utcp)) |
| Go                    | [go-utcp](https://github.com/universal-tool-calling-protocol/go-utcp)                                                                                                                                    |
| Rust                  | [rs-utcp](https://crates.io/crates/rs-utcp) (pre-1.0)                                                                                                                                                    |
| MCP clients           | [UTCP-MCP bridge](https://github.com/universal-tool-calling-protocol/utcp-mcp) (@utcp/mcp-bridge): exposes UTCP manuals to any MCP client, eg. Claude Desktop or Claude Code                             |
| Code execution        | [Code Mode](https://github.com/universal-tool-calling-protocol/code-mode) (@utcp/code-mode): the agent writes code that calls UTCP and MCP tools                                                         |
| LangChain / LangGraph | [langchain-utcp-adapters](https://pypi.org/project/langchain-utcp-adapters/) (early release)                                                                                                             |
| Pydantic AI           | [pydantic-ai-utcp](https://github.com/universal-tool-calling-protocol/pydantic-ai-utcp) (early release)                                                                                                  |
| Strands Agents        | [strands-utcp](https://strandsagents.com/docs/community/tools/utcp/) (community contribution)                                                                                                            |

There are also community libraries for Ruby, Elixir and Lua. See the [UTCP GitHub organization](https://github.com/universal-tool-calling-protocol) for the current list.

## [Manual URLs](https://docs.unified.to/utcp.md#manual-urls)

| Region | Manual URL                     |
| ------ | ------------------------------ |
| US     | https://api.unified.to/utcp    |
| EU     | https://api-eu.unified.to/utcp |
| AU     | https://api-au.unified.to/utcp |

Use the host for the region your workspace lives in: a credential only works on its own region's host, and every call URL in the manual points back to the host you fetched it from.

What the manual lists depends on the credential:

| Credential                                                        | Tools in the manual                                                                                                    |
| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| A connection-scoped token, or a workspace API key with connection | That connection's integration tools                                                                                    |
| A workspace API key without connection                            | The [Core Unified API](https://docs.unified.to/mcp/core) tools: connections, integrations, webhooks, docs search, …    |
| None                                                              | A preview of the Core tools, or with ?integration\_type=<type> that integration's tools. Calls still need a credential |

Authenticate with a workspace API key or a connection-scoped token, usually as `Authorization: Bearer <key>`. These are the same credentials the MCP server accepts; see [Authentication](https://docs.unified.to/mcp/authentication) for how to create a connection-scoped token.

The manual never contains your credential. Every tool's call template uses `Authorization: Bearer ${UNIFIED_API_KEY}`, and your UTCP client fills in the variable when it calls the tool.

### [Variable names](https://docs.unified.to/utcp.md#variable-names)

UTCP clients add the manual's name as a prefix to each variable: underscores in the name are doubled, then `_` is added. If you register the manual as `unified`, the client looks up `unified_UNIFIED_API_KEY`. If you name it `unified_crm`, the client looks up `unified__crm_UNIFIED_API_KEY`. Clients take the value from their config's `variables` first, then from configured loaders such as a `.env` file, then from the environment.

### [URL parameters](https://docs.unified.to/utcp.md#url-parameters)

Add these to the manual URL. They narrow the tool list, and are copied into every call URL so the calls run against the same tools.

|                          |                                                                                                                                                                              |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| connection               | The connection ID, when you authenticate with a workspace API key                                                                                                            |
| permissions              | A comma-delimited list of permissions from [Unified.to](https://docs.unified.to/guides/how%5Fto%5Fconfigure%5Fwebhooks%5Fin%5Fhubspot#select-permission-scopes-on-unifiedto) |
| tools                    | A comma-delimited list of tool IDs. Supports the wildcards \* and ?, eg. list\_\*,\*invoice\*                                                                                |
| include\_external\_tools | Include an integration's tools from all of its API and not just the default supported unified API                                                                            |
| hide\_sensitive          | Hides sensitive (ie. PII) data from results                                                                                                                                  |
| aliases                  | Additional words for tool descriptions, in the format word1:alias1,alias2;word2:alias1,alias2                                                                                |
| integration\_type        | Without a credential, preview that integration's tools                                                                                                                       |
|                          |                                                                                                                                                                              |

These are the same options the MCP server takes; [Server Options](https://docs.unified.to/mcp/server-options) describes each one in more detail. Most LLMs handle a few dozen tools at most, so limit the list with `permissions` or `tools`.

## [Python](https://docs.unified.to/utcp.md#python)

```
pip install utcp utcp-http

```

```
import asyncio
import os

from utcp.utcp_client import UtcpClient

async def main():
    key = os.environ['UNIFIED_API_KEY']  # a workspace API key or a connection-scoped token
    client = await UtcpClient.create(config={
        # The manual is named "unified", so the variable is unified_UNIFIED_API_KEY
        'variables': {'unified_UNIFIED_API_KEY': key},
        'manual_call_templates': [{
            'name': 'unified',
            'call_template_type': 'http',
            'http_method': 'GET',
            'url': 'https://api.unified.to/utcp?connection=<CONNECTION_ID>&permissions=crm_contact_read',
            'auth': {
                'auth_type': 'api_key',
                'api_key': 'Bearer ${UNIFIED_API_KEY}',
                'var_name': 'Authorization',
                'location': 'header',
            },
        }],
    })

    tools = await client.search_tools('list contacts', limit=5)
    print([t.name for t in tools])

    # Tool names are prefixed with the manual name. Arguments go under "arguments".
    result = await client.call_tool('unified.list_crm_contacts', {'arguments': {'limit': 10}})
    print(result)

asyncio.run(main())

```

The `auth` on the manual template authenticates the request for the manual itself. The tools in the manual carry their own auth.

## [TypeScript](https://docs.unified.to/utcp.md#typescript)

```
npm install @utcp/sdk @utcp/http

```

```
import { UtcpClient } from '@utcp/sdk';
import { HttpCallTemplateSerializer } from '@utcp/http';

const manual = new HttpCallTemplateSerializer().validateDict({
    name: 'unified',
    call_template_type: 'http',
    http_method: 'GET',
    url: 'https://api.unified.to/utcp?connection=<CONNECTION_ID>&permissions=crm_contact_read',
    auth: {
        auth_type: 'api_key',
        api_key: 'Bearer ${UNIFIED_API_KEY}',
        var_name: 'Authorization',
        location: 'header',
    },
});

const client = await UtcpClient.create(process.cwd(), {
    manual_call_templates: [manual],
    // The manual is named "unified", so the variable is unified_UNIFIED_API_KEY
    variables: { unified_UNIFIED_API_KEY: process.env.UNIFIED_API_KEY! },
});

const tools = await client.searchTools('list contacts', 5);
console.log(tools.map((t) => t.name));

const result = await client.callTool('unified.list_crm_contacts', { arguments: { limit: 10 } });
console.log(result);

await client.close();

```

## [MCP clients](https://docs.unified.to/utcp.md#mcp-clients)

An MCP client can already use Unified directly through the [MCP server](https://docs.unified.to/mcp/installation), which also gives it MCP Events and Agent Skills. Use the UTCP-MCP bridge only if you already manage your tools through UTCP. Add the manual template above to the bridge's `.utcp_config.json`, then add the bridge to your MCP client:

```
{
    "mcpServers": {
        "utcp": {
            "command": "npx",
            "args": ["@utcp/mcp-bridge"],
            "env": { "UTCP_CONFIG_FILE": "/path/to/.utcp_config.json" }
        }
    }
}

```

## [Reference](https://docs.unified.to/utcp.md#reference)

### [GET /utcp](https://docs.unified.to/utcp.md#get-utcp)

Returns a UTCP manual:

```
{
    utcp_version: string;
    manual_version: string;
    tools: {
        name: string;                  // the tool ID, eg. list_crm_contacts
        description: string;
        inputs: JSON-schema;           // { arguments: { ...the tool's parameters } }
        outputs?: JSON-schema;         // the shape of a successful result
        tags: string[];                // category, object, operation, read-only / destructive
        tool_call_template: {
            call_template_type: 'http';
            http_method: 'POST';
            url: string;               // <host>/tools/<name>/call?<your URL parameters>&format=utcp
            content_type: 'application/json';
            body_field: 'arguments';
            auth: { auth_type: 'api_key'; api_key: 'Bearer ${UNIFIED_API_KEY}'; var_name: 'Authorization'; location: 'header' };
        };
    }[];
}

```

| Status | When                                                         |
| ------ | ------------------------------------------------------------ |
| 401    | A credential was presented but is not valid                  |
| 403    | The request's IP address is not on the workspace's allowlist |
| 404    | integration\_type names an unknown integration               |

### [Tool calls](https://docs.unified.to/utcp.md#tool-calls)

Each tool is called with `POST /tools/{id}/call?…&format=utcp`, the [Call Tool](https://docs.unified.to/mcp/additional-api-endpoints#post-toolsidcall) endpoint.

* **Arguments are nested under `arguments`.** UTCP sends one input as the request body (the template's `body_field`) and every other input as a query parameter, so the tool's parameters are grouped into that one input. Pass `{ arguments: { … } }`, not the parameters at the top level.
* **A successful call returns the result itself**, described by the tool's `outputs`. A list result is wrapped as `{ results: [...] }`. With `format=utcp` there is no `{ content, structuredContent }` envelope.
* **A failed call returns an error status** (`400`, `401`, `403`, `404`, `429`, or the integration API's own status) with an `isError` body. UTCP clients raise these as errors.

Each tool call counts as 1 API request on your plan.

* [What is UTCP](https://docs.unified.to/utcp.md#what-is-utcp)
* [Who supports UTCP](https://docs.unified.to/utcp.md#who-supports-utcp)
* [Manual URLs](https://docs.unified.to/utcp.md#manual-urls)
* [Python](https://docs.unified.to/utcp.md#python)
* [TypeScript](https://docs.unified.to/utcp.md#typescript)
* [MCP clients](https://docs.unified.to/utcp.md#mcp-clients)
* [Reference](https://docs.unified.to/utcp.md#reference)
