The Universal Tool Calling Protocol (UTCP) establishes a standardized framework for communication between disparate tools. It operates across multiple transport layers, including HTTP, WebSocket, gRPC, and CLI. By utilizing a streamlined Pydantic core, the protocol ensures robust interoperability without unnecessary overhead. UTCP includes native support for common authentication methods (API Key, Basic Auth, OAuth2), automatic OpenAPI v3 conversion, and a design optimized for Large Language Models (LLMs). This allows LLMs to discover tools dynamically, identify the most relevant functions, and execute multi-turn, context-aware interactions.
Compared to MCP and other similar protocols, UTCP distinguishes itself through three primary advantages:
The following snippets demonstrate the basic implementation. For comprehensive, end-to-end code, refer to the examples/ directory in the repository.
The client is initialized by referencing a providers.json file, which automates the orchestration of different tools.
The providers.json file specifies where the client should fetch one or more UTCP manuals—the endpoints that define available tools.
[
{
"name": "cool_public_apis",
"provider_type": "http",
"url": "http://utcp.io/public-apis-manual",
"http_method": "GET"
}
]
The client.py script initializes the client and invokes a specific tool from a provider.
import asyncio
from utcp.client import UtcpClient
async def main():
# Initialize the client by loading providers from the specified config file.
client = await UtcpClient.create(
config={"providers_file_path": "./providers.json"}
)
# Invoke a tool. Tool names follow the "provider_name.tool_name" convention.
result = await client.call_tool(
tool_name="cool_public_apis.example_tool",
arguments={}
)
print(result)
if __name__ == "__main__":
asyncio.run(main())
Any service can function as a UTCP tool by exposing a UTCPManual. This manual can be served directly by the tool or managed by a third-party registry—a powerful approach for wrapping existing APIs that do not natively support the UTCP specification.
Below is a minimal FastAPI implementation:
server.py
from fastapi import FastAPI
app = FastAPI()
# The discovery endpoint provides the tool manual.
@app.get("/utcp")
def utcp_discovery():
return {
"version": "1.0",
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a location",
"inputs": {
"type": "object",
"properties": {
"location": {"type": "string"}
}
},
"outputs": {
"type": "object",
"properties": {
"temperature": {"type": "number"}
}
},
"tool_provider": {
"provider_type": "http",
"url": "https://example.com/api/weather",
"http_method": "GET"
}
}
]
}
# The functional tool endpoint
@app.get("/api/weather")
def get_weather(location: str):
return {"temperature": 22.5, "conditions": "sunny"}
For a full demonstration connecting UTCP to OpenAI, see example/src/full_llm_example/openai_utcp_example.py.
That implementation demonstrates:
providers.json rather than using hardcoded names.utcp_client.search_tools() identifies the most appropriate tool.utcp_client.call_tool(), and returns the result to the model to generate a natural language answer.Running the Example:
cd example/src/full_llm_example/example.env to .env and insert your OpenAI API key.python openai_utcp_example.pyUTCP is defined by several core data models: tools, providers, and authentication mechanisms.
Clients require a UtcpManual object, which lists every tool offered by a provider. Depending on the provider type, this manual is either fetched from an HTTP discovery endpoint or read from a local file (common for CLI tools).
UtcpManual model:
{
"version": "string",
"tools": [
{
"name": "string",
"description": "string",
"inputs": { ... },
"outputs": { ... },
"tags": ["string"],
"tool_provider": { ... }
}
]
}
version: The current UTCP protocol version.tools: An array of Tool objects.Every tool is defined using the Tool model.
Tool model:
{
"name": "string",
"description": "string",
"inputs": {
"type": "object",
"properties": { ... },
"required": ["string"],
"description": "string",
"title": "string"
},
"outputs": { ... },
"tags": ["string"],
"tool_provider": { ... }
}
name: A unique identifier for the tool.description: A clear summary of the tool's function.inputs: A JSON Schema defining required input parameters.outputs: A JSON Schema defining the tool’s output format.tags: Used for categorization and search filtering.tool_provider: A ToolProvider object specifying the connection and invocation details.UTCP supports various authentication protocols. The auth object within a provider configuration determines the method used.
ApiKeyAuth): A static key, usually passed in the header.{
"auth_type": "api_key",
"api_key": "YOUR_SECRET_API_KEY",
"var_name": "X-API-Key"
}
BasicAuth): Standard username and password credentials.{
"auth_type": "basic",
"username": "your_username",
"password": "your_password"
}
OAuth2Auth): Client credentials flow. The UTCP client automatically retrieves a bearer token from the specified token_url.{
"auth_type": "oauth2",
"token_url": "https://auth.example.com/token",
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"scope": "read write"
}
Providers give UTCP its flexibility by defining the communication protocol for specific tools.
Supported Provider Types:
http: RESTful HTTP/HTTPS APIssse: Server-Sent Eventshttp_stream: HTTP chunked transfer encodingcli: Command-line interfaceswebsocket: WebSocket (in development)grpc: gRPC (in development)graphql: GraphQL (in development)tcp: Raw TCP sockets (in development)udp: UDP (in development)webrtc: WebRTC (in development)mcp: Model Context Protocol (for interoperability)text: Local text filesEach provider type requires specific configuration. For example, an HttpProvider requires a url and http_method. By default, the discovery endpoint is located at /utcp.
Provider Configuration Examples
{
"name": "my_rest_api",
"provider_type": "http",
"url": "https://api.example.com/utcp",
"http_method": "POST",
"content_type": "application/json",
"auth": {
"auth_type": "oauth2",
"token_url": "https://api.example.com/oauth/token",
"client_id": "your_client_id",
"client_secret": "your_client_secret"
}
}
UtcpManual, an HTTP provider can link to an OpenAPI v3 specification. The OpenApiConverter automatically maps these to UTCP, providing immediate access to thousands of existing APIs.{
"name": "open_library_api",
"provider_type": "http",
"url": "https://openlibrary.org/dev/docs/api/openapi.json"
}
{
"name": "live_updates_service",
"provider_type": "sse",
"url": "https://api.example.com/utcp",
"event_type": "message"
}
{
"name": "streaming_data_source",
"provider_type": "http_stream",
"url": "https://api.example.com/utcp",
"http_method": "GET"
}
{
"name": "my_cli_tool",
"provider_type": "cli",
"command_name": "my-command -utcp"
}
stdio or http){
"name": "my_mcp_service",
"provider_type": "mcp",
"config": {
"mcpServers": {
"my-server": {
"transport": "http",
"url": "http://localhost:8000/mcp"
}
}
},
"auth": {
"auth_type": "oauth2",
"token_url": "http://localhost:8000/token",
"client_id": "test-client",
"client_secret": "test-secret"
}
}
{
"name": "my_local_tools",
"provider_type": "text",
"file_path": "/path/to/my/tools.json"
}
The Python-based UTCP client serves as a modular framework for managing and invoking tools. It relies on several integrated components.
UtcpClient: The primary entry point. It manages provider registration, tool execution, and search functionality.UtcpClientConfig: A Pydantic model that defines the providers_file_path and manages variable loading (e.g., from .env files).ClientTransportInterface: An abstract base class for all transports (such as HttpClientTransport or CliTransport). Each transport implements the specifics of its respective protocol.ToolRepository: An interface for tool and provider storage. The default implementation is InMemToolRepository.ToolSearchStrategy: An interface for search logic. The default TagSearchStrategy ranks tools based on tag matches and description keywords.The UtcpClient is instantiated via the asynchronous UtcpClient.create() method.
import asyncio
from utcp.client import UtcpClient
async def main():
client = await UtcpClient.create(
config={
"providers_file_path": "/path/to/your/providers.json",
"load_variables_from": [{
"type": "dotenv",
"env_file_path": ".env"
}]
}
)
# The client is now ready for use.
asyncio.run(main())
During initialization, the client parses providers.json, resolves variables (such as ${API_KEY}), and registers each defined provider.
register_tool_provider method uses the relevant transport to fetch definitions and populate the repository.call_tool method identifies the tool, retrieves its provider, and executes it with the provided arguments. Tools are namespaced by their provider (e.g., my_api.get_weather).The search_tools method locates tools via query strings.
tools = client.search_tools(query="current weather in London")
for tool in tools:
print(tool.name, tool.description)
conda create --name utcp python=3.10
conda activate utcppip install -r requirements.txtpython -m pip install --upgrade pippython -m buildpip install dist/utcp-<version>.tar.gz (e.g., pip install dist/utcp-1.0.0.tar.gz)
HiChunk Review: Smarter Chunking for RAG Pipelines
Sora 2 AI Watermark Remover: Remove Sora Watermarks Cleanly
MiMo-Audio: 100M-Hour Pretrained Model for Few-Shot Speech Tasks
withoutbg: Free Local & API-Based AI Background Removal Tool
AhaSpeed VPN Review: High-Speed Performance, No Ads, and Unlimited Bandwidth
Eigent: Multi-Agent Workflow Desktop App with CAMEL and MCP
ZeroGraph TS: A 300-Line TypeScript Framework for AI Agent Coding
Chatterbox TTS API: Open Source Text-to-Speech for Developers
Gmail AutoAuth MCP Server: Control Gmail via Claude Desktop
AI Peer Review Tool for Neuroscience: LLM-Driven Meta-Review Framework
Magentic-UI: Multi-Agent Web Automation You Can Watch and Control
AG-UI Protocol: The Open Standard for Connecting AI Agents to Frontends