Introduction to UTCP

Version: v0.1

The Universal Tool Calling Protocol (UTCP) is a modern, flexible, and scalable standard for defining and interacting with tools across a wide variety of communication protocols.

Core Components

UTCP consists of three main components:

The “Manual” Approach

UTCP’s fundamental philosophy is to act as a descriptive manual rather than a prescriptive middleman:

A UTCP Manual tells an agent: “Here is a tool. Here is its native endpoint (HTTP, WebSocket, CLI, etc.), and here is how to call it directly.”

This approach eliminates the need for wrapper servers and allows direct communication between agents and tools.

Minimal Example

Let’s see how easy it is to use UTCP with a minimal example.

1. Defining a Tool (Tool Provider)

Create a simple HTTP endpoint that serves a UTCP Manual (JSON):

# app.py
from fastapi import FastAPI

app = FastAPI()

@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",
                            "description": "City name"
                        }
                    },
                    "required": ["location"]
                },
                "outputs": {
                    "type": "object",
                    "properties": {
                        "temperature": {"type": "number"},
                        "conditions": {"type": "string"}
                    }
                },
                "tool_provider": {
                    "provider_type": "http",
                    "url": "https://example.com/api/weather",
                    "http_method": "GET"
                }
            }
        ]
    }

# Implement the actual weather API endpoint
@app.get("/api/weather")
def get_weather(location: str):
    # In a real app, you'd fetch actual weather data
    return {"temperature": 22.5, "conditions": "Sunny"}

Run the server:

uvicorn app:app --reload

2. Using the Tool (Client)

# client.py
import asyncio
from utcp.client import UtcpClient
from utcp.shared.provider import HttpProvider

async def main():
    # Create a UTCP client
    client = await UtcpClient.create()

    # Define the manual provider (points to the discovery endpoint)
    manual_provider = HttpProvider(
        name="weather_service",
        provider_type="http",
        http_method="GET",
        url="http://localhost:8000/utcp"
    )

    # Register tools from the manual provider
    tools = await client.register_manual_provider(manual_provider)
    print(f"Registered {len(tools)} tools from {manual_provider.name}")

    # Call a tool by its namespaced name: {provider_name}.{tool_name}
    result = await client.call_tool(
        "weather_service.get_weather", 
        arguments={"location": "San Francisco"}
    )
    print(f"Weather: {result['temperature']}°C, {result['conditions']}")

if __name__ == "__main__":
    asyncio.run(main())

Run the client:

python client.py

Benefits of the UTCP Approach

In the following sections, we’ll explore the details of UTCP’s components and how to implement them in your applications.