python-utcp
Official python implementation of UTCP. UTCP is an open standard that lets AI agents call any API directly, without extra middleware.
Install / Use
claude mcp add universal-tool-calling-protocol -- npx -y github:universal-tool-calling-protocol/python-utcpIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
AI & Machine LearningSupported Platforms
Skill content
View source on GitHubUniversal Tool Calling Protocol (UTCP)
Introduction
The Universal Tool Calling Protocol (UTCP) is a secure, scalable standard for defining and interacting with tools across a wide variety of communication protocols. UTCP 1.0.0 introduces a modular core with a plugin-based architecture, making it more extensible, testable, and easier to package.
In contrast to other protocols, UTCP places a strong emphasis on:
- Scalability: UTCP is designed to handle a large number of tools and providers without compromising performance.
- Extensibility: A pluggable architecture allows developers to easily add new communication protocols, tool storage mechanisms, and search strategies without modifying the core library.
- Interoperability: With a growing ecosystem of protocol plugins (including HTTP, SSE, CLI, and more), UTCP can integrate with almost any existing service or infrastructure.
- Ease of Use: The protocol is built on simple, well-defined Pydantic models, making it easy for developers to implement and use.
Repository Structure
This repository contains the complete UTCP Python implementation:
core/- Coreutcppackage with foundational components (README)plugins/communication_protocols/- Protocol-specific plugins:
Architecture Overview
UTCP uses a modular architecture with a core library and protocol plugins:
Core Package (utcp)
The core/ directory contains the foundational components:
- Data Models: Pydantic models for
Tool,CallTemplate,UtcpManual, andAuth - Client Interface: Main
UtcpClientfor tool interaction - Plugin System: Extensible interfaces for protocols, repositories, and search
- Default Implementations: Built-in tool storage and search strategies
Quick Start
Installation
Install the core library and any required protocol plugins:
# Install core + HTTP plugin (most common)
pip install utcp utcp-http
# Install additional plugins as needed
pip install utcp-cli utcp-mcp utcp-text
Basic Usage
from utcp.utcp_client import UtcpClient
# Create client with HTTP API
client = await UtcpClient.create(config={
"manual_call_templates": [{
"name": "my_api",
"call_template_type": "http",
"url": "https://api.example.com/utcp"
}]
})
# Call a tool
result = await client.call_tool("my_api.get_data", {"id": "123"})
Protocol Plugins
UTCP supports multiple communication protocols through dedicated plugins:
| Plugin | Description | Status | Documentation |
|--------|-------------|--------|---------------|
| utcp-http | HTTP/REST APIs, SSE, streaming | ✅ Stable | HTTP Plugin README |
| utcp-cli | Command-line tools | ✅ Stable | CLI Plugin README |
| utcp-mcp | Model Context Protocol | ✅ Stable | MCP Plugin README |
| utcp-text | Local file-based tools | ✅ Stable | Text Plugin README |
| utcp-websocket | WebSocket real-time bidirectional communication | ✅ Stable | WebSocket Plugin README |
| utcp-socket | TCP/UDP protocols | 🚧 In Progress | Socket Plugin README |
| utcp-gql | GraphQL APIs | 🚧 In Progress | GraphQL Plugin README |
For development, you can install the packages in editable mode from the cloned repository:
# Clone the repository
git clone https://github.com/universal-tool-calling-protocol/python-utcp.git
cd python-utcp
# Install the core package in editable mode with dev dependencies
pip install -e "core[dev]"
# Install a specific protocol plugin in editable mode
pip install -e plugins/communication_protocols/http
Migration Guide from 0.x to 1.0.0
Version 1.0.0 introduces several breaking changes. Follow these steps to migrate your project.
- Update Dependencies: Install the new
utcpcore package and the specific protocol plugins you use (e.g.,utcp-http,utcp-cli). - Configuration:
- Configuration Object:
UtcpClientis initialized with aUtcpClientConfigobject, dict or a path to a JSON file containing the configuration. - Manual Call Templates: The
providers_file_pathoption is removed. Instead of a file path, you now provide a list ofmanual_call_templatesdirectly within theUtcpClientConfig. - Terminology: The term
providerhas been replaced withcall_template, andprovider_typeis nowcall_template_type. - Streamable HTTP: The
call_template_typehttp_streamhas been renamed tostreamable_http.
- Configuration Object:
- Update Imports: Change your imports to reflect the new modular structure. For example,
from utcp.client.transport_interfaces.http_transport import HttpProviderbecomesfrom utcp_http.http_call_template import HttpCallTemplate. - Tool Search: If you were using the default search, the new strategy is
TagAndDescriptionWordMatchStrategy. This is the new default and requires no changes unless you were implementing a custom strategy. - Tool Naming: Tool names are now namespaced as
manual_name.tool_name. The client handles this automatically. - Variable Substitution Namespacing: Variables that are substituted in different
call_templates, are first namespaced with the name of the manual with the_duplicated. So a key in a tool call template calledAPI_KEYfrom the manualmanual_1would be converted tomanual__1_API_KEY.
Usage Examples
1. Using the UTCP Client
config.json (Optional)
You can define a comprehensive client configuration in a JSON file. All of these fields are optional.
{
"variables": {
"openlibrary_URL": "https://openlibrary.org/static/openapi.json"
},
"load_variables_from": [
{
"variable_loader_type": "dotenv",
"env_file_path": ".env"
}
],
"tool_repository": {
"tool_repository_type": "in_memory"
},
"tool_search_strategy": {
"tool_search_strategy_type": "tag_and_description_word_match"
},
"manual_call_templates": [
{
"name": "openlibrary",
"call_template_type": "http",
"http_method": "GET",
"url": "${URL}",
"content_type": "application/json"
},
],
"post_processing": [
{
"tool_post_processor_type": "filter_dict",
"only_include_keys": ["name", "key"],
"only_include_tools": ["openlibrary.read_search_authors_json_search_authors_json_get"]
}
]
}
client.py
import asyncio
from utcp.utcp_client import UtcpClient
from utcp.data.utcp_client_config import UtcpClientConfig
async def main():
# The UtcpClient can be created with a config file path, a dict, or a UtcpClientConfig object.
# Option 1: Initialize from a config file path
# client_from_file = await UtcpClient.create(config="./config.json")
# Option 2: Initialize from a dictionary
client_from_dict = await UtcpClient.create(config={
"variables": {
"openlibrary_URL": "https://openlibrary.org/static/openapi.json"
},
"load_variables_from": [
{
"variable_loader_type": "dotenv",
"env_file_path": ".env"
}
],
"tool_repository": {
"tool_repository_type": "in_memory"
},
"tool_search_strategy": {
"tool_search_strategy_type": "tag_and_description_word_match"
},
"manual_call_templates": [
{
"name": "openlibrary",
"call_template_type": "http",
"http_method": "GET",
"url": "${URL}",
"content_type": "application/json"
}
],
"post_processing": [
{
"tool_post_processor_type": "filter_dict",
"only_include_keys": ["name", "key"],
"only_include_tools": ["openlibrary.read_search_authors_json_search_authors_json_get"]
}
]
})
# Option 3: Initialize with a full-featured UtcpClientConfig object
from utcp_http.http_call_template import HttpCallTemplate
from utcp.data.variable_loader import VariableLoaderSerializer
from utcp.interfaces.tool_post_processor import ToolPostProcessorConfigSerializer
config_obj = UtcpClientConfig(
variables={"openlibrary_URL": "https://openlibrary.org/static/openapi.json"},
load_variables_from=[
VariableLoaderSerializer().validate_dict({
"variable_loader_type": "dotenv", "env_file_path": ".env"
})
],
manual_call_templates=[
HttpCallTemplate(
name="openlibrary",
call_template_type="http",
http_method="GET",
url="${URL}",
content_type="application/json"
)
],
post_processing=[
ToolPostProcessorConfigSerializer().validate_dict({
"tool_post_processor_type": "filter_dict",
"only_include_keys": ["name", "key"],
"only_include_tools": ["openlibrary.read_search_authors_json_search_authors_json_get"]
})
]
)
client = await UtcpClient.create(config=config_obj)
# Call a tool. The name is namespaced: `manual_name.tool_name`
result = await client.call_tool(
tool_name="openlibrary.read_search_authors_json_search_authors_json_get",
tool_args={"q": "J. K. Rowling"}
)
print(result)
if __name__ == "__main__":
asyncio.run(main())
2. Providing a UTCP Manual
A UTCPManual describes the tools you offer. The key change is replacing tool_provider with tool_call_template.
server.py
UTCP decorator version:
from fastapi import FastAPI
from utcp_http.http_call_template import HttpCallTemplate
from utcp.data.utcp_manual import UtcpManual
from utcp.python_specific_tooling.tool_decorator import utcp_tool
app = FastAPI()
# The discovery endpoint returns the tool manual
@app.get("/utcp
Truncated for display — read the full file on GitHub.
Related Skills
caveman
107.1k🪨 why use many token when few token do trick. Viral skill + proxy for coding agents that cuts 65% of tokens by talking like a caveman.
claude-mem
94.4kPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode + More
Agent-Reach
84.2kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
Understand-Anything
83.5kGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.
