For Tool Providers
This guide helps you expose your tools through UTCP so they can be discovered and used by AI agents and other applications.
Creating a UTCP Manual
A UTCP Manual is the standardized description of your tools. To create one, you need to define:
- Your tools and their capabilities
- The provider information for calling those tools
The UTCPManual
Structure
Your discovery endpoint should return a UTCPManual
object with the following structure:
{
"version": "1.0",
"tools": [
{
"name": "tool_name",
"description": "tool_description",
"inputs": { ... },
"outputs": { ... },
"tags": ["tag"],
"tool_provider": { ... }
}
]
}
Fields
Field | Description |
---|---|
version | The version of the UTCP protocol being used |
tools | A list of Tool objects representing available tools |
Tool discovery endpoints should be accessible at a consistent path, preferably /utcp
for HTTP-based providers.
Tool Definition
Each tool in your manual should be defined by a Tool
object:
{
"name": "tool_name",
"description": "tool_description",
"inputs": {
"type": "object",
"properties": { ... },
"required": ["string"],
"description": "parameters_description",
"title": "parameters"
},
"outputs": { ... },
"tags": ["string"],
"average_response_size": 200,
"provider": { ... }
}
Fields
Field | Description |
---|---|
name | The name of the tool (should be unique within your provider) |
description | A clear, concise description of what the tool does |
inputs | A schema defining the input parameters (follows simplified JSON Schema) |
outputs | A schema defining the output format (follows simplified JSON Schema) |
tags | Optional list of tags for categorization and search |
average_response_size | Optional integer indicating the estimated average number of tokens returned by this tool |
tool_provider | A Provider object that describes how to connect to and use the tool |
Input and Output Schemas
Both inputs
and outputs
use a simplified JSON Schema format:
{
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "Description of parameter 1"
},
"param2": {
"type": "integer",
"description": "Description of parameter 2"
}
},
"required": ["param1"],
"description": "Overall description of the input/output",
"title": "Optional title"
}
Best Practices for Tool Definitions
- Clear Descriptions: Provide clear, concise descriptions for both tools and parameters
- Precise Types: Use the most specific schema types to help clients validate inputs
- Required Fields: Explicitly list all required parameters
- Complete Output Schemas: Define output schemas thoroughly to help clients parse responses
- Meaningful Names: Use descriptive, action-oriented names for tools (e.g.,
get_weather
,translate_text
) - Logical Tags: Use tags to group related tools and aid in discovery
Generating Tools from an OpenAPI Specification
If you already have an OpenAPI (formerly Swagger) specification for your API, you can automatically generate a UTCPManual
using the OpenApiConverter
utility. This saves you from having to manually define each tool.
Using the Converter
The converter takes an OpenAPI specification in JSON format and produces a UTCPManual
object. Here's how you can use it in your discovery endpoint:
import json
from fastapi import FastAPI
from utcp.client.openapi_converter import OpenApiConverter
app = FastAPI()
# Load your OpenAPI specification from a file
with open("openapi.json", "r") as f:
openapi_spec = json.load(f)
@app.get("/utcp")
def utcp_discovery():
# Convert the OpenAPI spec to a UTCP manual
converter = OpenApiConverter(openapi_spec)
utcp_manual = converter.convert()
return utcp_manual
How it Works
The OpenApiConverter
maps OpenAPI concepts to UTCP tool definitions:
- Paths and Methods: Each combination of a path (e.g.,
/users/{id}
) and an HTTP method (GET
,POST
, etc.) becomes a separate tool. - Operation ID: The
operationId
from the OpenAPI operation is used as the tool's name. - Summary and Description: The
summary
anddescription
fields are used for the tool's description. - Parameters: Request parameters (path, query, header, cookie) are mapped to the tool's
inputs
schema. - Request Body: The
requestBody
is also mapped to the tool'sinputs
schema. - Responses: The successful response (typically
200
or201
) is mapped to the tool'soutputs
schema. - Security Schemes: The converter automatically detects security schemes (API Key, Basic Auth, OAuth2) and includes the appropriate
auth
configuration in the provider definition. It will even generate placeholder variables for secrets (e.g.,$PROVIDER_API_KEY
).
By using the converter, you can quickly expose your existing API as a set of UTCP tools with minimal effort.
Provider Types: Manual vs. Tool
It's important to understand the distinction between two types of providers in UTCP:
-
Manual Provider: This is the provider that a
UtcpClient
connects to for tool discovery. Its responsibility is to return aUTCPManual
object (or an OpenAPI specification that can be converted into one). It defines an endpoint for discovery but doesn't execute the tools themselves. -
Tool Provider: This provider is defined inside each
Tool
object within theUTCPManual
. Its purpose is to provide the specific connection and configuration details needed to execute that one tool. Thetool_provider
field contains all the information a client needs to make a call, such as the URL, HTTP method, or command-line arguments.
In simple cases, a single service might act as both a manual provider (at its discovery endpoint) and a tool provider (for the tools it offers). In more complex scenarios, a manual provider could return a manual listing tools from many different tool providers.
Tool Provider Configuration
The provider object tells clients how to call your tool:
{
"name": "provider_name",
"provider_type": "http",
... (protocol-specific attributes)
}
Variable Substitution
You can use variables in your provider configuration by prefixing values with $
or enclosing them in ${...}
. These variables will be replaced with values from the client's configuration or environment variables when the tool is called.
{
"auth": {
"auth_type": "api_key",
"api_key": "$API_KEY",
"var_name": "X-API-Key"
}
}
You can also use the ${VAR}
syntax for more complex strings:
{
"url": "https://${DOMAIN}/api/v1/endpoint"
}
Make sure your tool definitions are accurate and complete.
Make sure to document which variables users need to set in their environment or configuration.
For details on provider-specific configuration, see the dedicated pages for each type:
- HTTP Provider
- HTTP Stream Provider
- Server-Sent Events (SSE) Provider
- WebSocket Provider
- gRPC Provider
- GraphQL Provider
- Command-Line (CLI) Provider
- Model Context Protocol (MCP) Provider
- Text File Provider
- TCP Provider
- UDP Provider
- WebRTC Provider
Implementing a Discovery Endpoint
For HTTP-based providers, implement a discovery endpoint at /utcp
that returns your UTCP Manual:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List, Dict, Any
app = FastAPI()
class UTCPManual(BaseModel):
version: str
tools: List[Dict[str, Any]]
@app.get("/utcp")
def utcp_discovery():
return UTCPManual(
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"}
}
},
"provider": {
"name": "weather_api",
"provider_type": "http",
"url": "https://api.example.com/api/weather",
"http_method": "GET"
},
"tags": ["weather", "current"],
"average_response_size": 150
}
]
)
Testing Your UTCP Manual
To ensure your UTCP Manual is valid and functional:
- Validate the JSON against the UTCP schema
- Test with the
utcp
command-line tool:utcp test --url https://your-api.com/utcp
- Try registering with a UTCP client and calling your tools
For more detailed implementation guidance, see the Implementation page.