모듈형 플러그인 기반 표준을 통해 AI agent가 다양한 통신 프로토콜을 사용하여 모든 API를 직접 호출할 수 있도록 지원합니다.
다른 이름 universal-tool-calling-protocol/python-utcp
- 스타
- 671
- Tools
- 1
- 다운로드, 30일
- —
- 최신 버전
- —
- 마지막 커밋
- 2026년 10월 25일
- 라이선스
- MPL-2.0
python-utcp MCP란?
python-utcp은(는) MCP server입니다. 모듈형 플러그인 기반 표준을 통해 AI agent가 다양한 통신 프로토콜을 사용하여 모든 API를 직접 호출할 수 있도록 지원합니다. 1개 도구를 제공합니다. 예: allowed_communication_protocols.
프로젝트 README에서 생성된 요약
python-utcp MCP server 정보
python-utcp의 주요 목표는 AI agent가 통일된 표준을 통해 다양한 서비스와 상호작용할 수 있도록 하는 것입니다. 이 라이브러리는 개발자가 단일 클라이언트 인터페이스를 사용하여 다양한 통신 프로토콜에 걸쳐 도구를 정의하고 호출할 수 있는 모듈형 프레임워크를 제공합니다. 플러그인 기반 아키텍처를 활용하여 서로 다른 인프라 간의 격차를 해소하며, 웹 서비스, CLI 또는 로컬 파일의 도구를 AI 워크플로우에 더 쉽게 통합할 수 있도록 돕습니다.
개발자는 UtcpClient를 사용하여 수동 호출 템플릿을 구성하고 도구 상호작용을 관리합니다. 이 시스템은 REST 및 SSE를 위한 utcp-http, 명령줄 도구를 위한 utcp-cli, Model Context Protocol을 위한 utcp-mcp, 로컬 파일 기반 도구를 위한 utcp-text 등 여러 특화된 플러그인을 지원합니다. 또한 WebSocket을 지원하며 GraphQL 및 TCP/UDP 소켓 기능을 개발 중입니다. 구현에는 Pydantic 모델을 사용하여 데이터 일관성을 보장하며, 공유 자격 증명 캐시나 클라이언트별 격리된 연결과 같이 상태를 관리하는 유연한 방법을 제공합니다.
프로젝트의 README를 바탕으로 작성되었습니다. 모든 활용 사례는 해당 내용의 인용문과 대조하여 확인합니다.
python-utcp MCP 도구 1
README에서 감지됨allowed_communication_protocols
| allowed_communication_protocols | — |
구성
API_KEYGIT_AUTHOR_NAME
| 이름 | 설명 | 유형 |
|---|---|---|
| API_KEY | — | |
| GIT_AUTHOR_NAME | — |
자동 검사
2026년 11월 13일에 실행됨전체 보고서 →자동 검사를 통과했습니다. 이는 보안 감사가 아닙니다. 코드를 직접 읽고 서버에 필요한 최소한의 권한만 부여하십시오. 검사 방식
- 소스 저장소 연결 및 접근 가능통과
- 오픈 소스 라이선스 (OSI)통과
- 최근 1년 내 커밋 또는 릴리스통과
- 패키지 이름이 인기 패키지와 유사하지 않음검사되지 않음
- 원격 엔드포인트가 HTTPS 사용검사되지 않음
- 파괴적인 도구에 라벨 표시됨통과
- 모델에 대한 숨겨진 지침 없음통과
- 패키지와 의존성에 심각한 보안 권고 없음검사되지 않음
README
GitHub에서 보기Universal 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"})
# Release the connections this client opened
await client.close()
Protocol Lifetime: Shared vs. Per-Client Instances
A protocol plugin registers itself in one of two registries, and the choice decides who its state belongs to.
An instance registered with register_communication_protocol is shared by every UtcpClient in the process, and so is any state it keeps. That is right for state that is meant to be shared — a credential cache, a registry a decorator writes into — and wrong for state that belongs to one client. A shared instance lives as long as the process; no client closes it.
A protocol whose state must not be shared between clients registers a factory instead: live sessions or connections keyed per manual, child processes — anything one client's use or close() would take away from another. Each UtcpClient calls the factory once — at creation, or on first use if it was registered later — so each client gets its own instance, its own connections, and its own teardown on close():
from utcp.plugins.discovery import register_communication_protocol_factory
register_communication_protocol_factory("custom_type", CustomCommunicationProtocol)
This is what makes "a client per tenant / per user / per pooled connection" actually isolate them, rather than every client reaching into one shared instance. A type registered as a factory wins over the same type registered as an instance, so a plugin migrates by moving its registration from one call to the other and callers change nothing.
utcp-mcp and utcp-websocket register this way — MCP sessions (and, for stdio, child processes) and per-manual WebSocket connections belong to the client that opened them. utcp-http (HTTP, SSE, streamable HTTP) and utcp-gql stay shared instances: the only state they keep is an OAuth token cache, which is meant to be reused across clients; every request opens its own session.
client.close() closes the instances the client created — every one of them, even if one fails, after which the failures are raised together as UtcpProtocolCloseError. If UtcpClient.create fails after creating them, they are closed the same way before the error is re-raised.
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")
def utcp_discovery():
return UtcpManual.create_from_decorators(manual_version="1.0.0")
# The actual tool endpoint
@utcp_tool(tool_call_template=HttpCallTemplate(
name="get_weather",
url=f"https://example.com/api/weather",
http_method="GET"
), tags=["weather"])
@app.get("/api/weather")
def get_weather(location: str):
return {"temperature": 22.5, "conditions": "Sunny"}
No UTCP dependencies server version:
from fastapi import FastAPI
app = FastAPI()
# The discovery endpoint returns the tool manual
@app.get("/utcp")
def utcp_discovery():
return {
"manual_version": "1.0.0",
"utcp_version": "1.0.2",
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a location",
"tags": ["weather"],
"inputs": {
"type": "object",
"properties": {
"location": {"type": "string"}
}
},
"outputs": {
"type": "object",
"properties": {
"temperature": {"type": "number"},
"conditions": {"type": "string"}
}
},
"tool_call_template": {
"call_template_type": "http",
"url": "https://example.com/api/weather",
"http_method": "GET"
}
}
]
}
# The actual tool endpoint
@app.get("/api/weather")
def get_weather(location: str):
return {"temperature": 22.5, "conditions": "Sunny"}
3. Full examples
You can find full examples in the examples repository.
Protocol Specification
UtcpManual and Tool Models
The tool_provider object inside a Tool has been replaced by tool_call_template.
{
"manual_version": "string",
"utcp_version": "string",
"tools": [
{
"name": "string",
"description": "string",
"inputs": { ... },
"outputs": { ... },
"tags": ["string"],
"tool_call_template": {
"call_template_type": "http",
"url": "https://...",
"http_method": "GET"
}
}
]
}
Call Template Configuration Examples
Configuration examples for each protocol. Remember to replace provider_type with call_template_type.
HTTP Call Template
{
"name": "my_rest_api",
"call_template_type": "http", // Required
"url": "https://api.example.com/users/{user_id}", // Required
"http_method": "POST", // Required, default: "GET"
"content_type": "application/json", // Optional, default: "application/json"
"allowed_communication_protocols": ["http"], // Optional, defaults to [call_template_type]. Restricts which protocols tools can use.
"auth": { // Optional, authentication for the HTTP request (example using ApiKeyAuth for Bearer token)
"auth_type": "api_key",
"api_key": "Bearer $API_KEY", // Required
"var_name": "Authorization", // Optional, default: "X-Api-Key"
"location": "header" // Optional, default: "header"
},
"auth_tools": { // Optional, authentication for converted tools, if this call template points to an openapi spec that should be automatically converted to a utcp manual (applied only to endpoints requiring auth per OpenAPI spec)
"auth_type": "api_key",
"api_key": "Bearer $TOOL_API_KEY", // Required
"var_name": "Authorization", // Optional, default: "X-Api-Key"
"location": "header" // Optional, default: "header"
},
"headers": { // Optional
"X-Custom-Header": "value"
},
"body_field": "body", // Optional, default: "body"
"header_fields": ["user_id"] // Optional
}
SSE (Server-Sent Events) Call Template
{
"name": "my_sse_stream",
"call_template_type": "sse", // Required
"url": "https://api.example.com/events", // Required
"event_type": "message", // Optional
"reconnect": true, // Optional, default: true
"retry_timeout": 30000, // Optional, default: 30000 (ms)
"auth": { // Optional, example using BasicAuth
"auth_type": "basic",
"username": "${USERNAME}", // Required
"password": "${PASSWORD}" // Required
},
"headers": { // Optional
"X-Client-ID": "12345"
},
"body_field": null, // Optional
"header_fields": [] // Optional
}
Streamable HTTP Call Template
Note the name change from http_stream to streamable_http.
{
"name": "streaming_data_source",
"call_template_type": "streamable_http", // Required
"url": "https://api.example.com/stream", // Required
"http_method": "POST", // Optional, default: "GET"
"content_type": "application/octet-stream", // Optional, default: "application/octet-stream"
"chunk_size": 4096, // Optional, default: 4096
"timeout": 60000, // Optional, default: 60000 (ms)
"auth": null, // Optional
"headers": {}, // Optional
"body_field": "data", // Optional
"header_fields": [] // Optional
}
CLI Call Template
{
"name": "multi_step_cli_tool",
"call_template_type": "cli", // Required
"commands": [ // Required - sequential command execution
{
"command": "git clone UTCP_ARG_repo_url_UTCP_END temp_repo",
"append_to_final_output": false
},
{
"command": "cd temp_repo && find . -name '*.py' | wc -l"
// Last command output returned by default
}
],
"env_vars": { // Optional
"GIT_AUTHOR_NAME": "UTCP Bot",
"API_KEY": "${MY_API_KEY}"
},
"working_dir": "/tmp", // Optional
"auth": null // Optional (always null for CLI)
}
CLI Protocol Features:
- Multi-command execution: Commands run sequentially in single subprocess
- Cross-platform: PowerShell on Windows, Bash on Unix/Linux/macOS
- State preservation: Directory changes (
cd) persist between commands - Argument placeholders:
UTCP_ARG_argname_UTCP_ENDformat - Output referencing: Access previous outputs with
$CMD_0_OUTPUT,$CMD_1_OUTPUT - Flexible output control: Choose which command outputs to include in final result
Text Call Template
{
"name": "my_text_manual",
"call_template_type": "text", // Required
"file_path": "./manuals/my_manual.json", // Required
"auth": null, // Optional (always null for Text)
"auth_tools": { // Optional, authentication for generated tools from OpenAPI specs
"auth_type": "api_key",
"api_key": "Bearer ${API_TOKEN}",
"var_name": "Authorization",
"location": "header"
}
}
MCP (Model Context Protocol) Call Template
{
"name": "my_mcp_server",
"call_template_type": "mcp", // Required
"config": { // Required
"mcpServers": {
"server_name": {
"transport": "stdio",
"command": ["python", "-m", "my_mcp_server"]
}
}
},
"auth": { // Optional, example using OAuth2
"auth_type": "oauth2",
"token_url": "https://auth.example.com/token", // Required
"client_id": "${CLIENT_ID}", // Required
"client_secret": "${CLIENT_SECRET}", // Required
"scope": "read:tools" // Optional
}
}
Security: Protocol Restrictions
UTCP provides fine-grained control over which communication protocols each manual can use through the allowed_communication_protocols field. This prevents potentially dangerous protocol escalation (e.g., an HTTP-based manual accidentally calling CLI tools).
Default Behavior (Secure by Default)
When allowed_communication_protocols is not set or is empty, a manual can only register and call tools that use the same protocol type as the manual itself:
from utcp_http.http_call_template import HttpCallTemplate
# This manual can ONLY register/call HTTP tools (default restriction)
http_manual = HttpCallTemplate(
name="my_api",
call_template_type="http",
url="https://api.example.com/utcp"
# allowed_communication_protocols not set → defaults to ["http"]
)
Allowing Multiple Protocols
To allow a manual to work with tools from multiple protocols, explicitly set allowed_communication_protocols:
from utcp_http.http_call_template import HttpCallTemplate
# This manual can register/call both HTTP and CLI tools
multi_protocol_manual = HttpCallTemplate(
name="flexible_manual",
call_template_type="http",
url="https://api.example.com/utcp",
allowed_communication_protocols=["http", "cli"] # Explicitly allow both
)
JSON Configuration
{
"name": "my_api",
"call_template_type": "http",
"url": "https://api.example.com/utcp",
"allowed_communication_protocols": ["http", "cli", "mcp"]
}
Behavior Summary
allowed_communication_protocols |
Manual Type | Allowed Tool Protocols |
|---|---|---|
Not set / null |
"http" |
Only "http" |
[] (empty) |
"http" |
Only "http" |
["http", "cli"] |
"http" |
"http" and "cli" |
["http", "cli", "mcp"] |
"cli" |
"http", "cli", and "mcp" |
Registration Filtering
During register_manual(), tools that don't match the allowed protocols are automatically filtered out with a warning:
WARNING - Tool 'dangerous_tool' uses communication protocol 'cli' which is not in
allowed protocols ['http'] for manual 'my_api'. Tool will not be registered.
Call-Time Validation
Even if a tool somehow exists in the repository, calling it will fail if its protocol is not allowed:
# Raises ValueError: Tool 'my_api.some_cli_tool' uses communication protocol 'cli'
python-utcp MCP 질문
python-utcp MCP는 어떤 도구를 제공하나요?
1개 도구를 제공합니다. 예: allowed_communication_protocols.
UTCP란 무엇인가요?
Universal Tool Calling Protocol (UTCP)은 다양한 통신 프로토콜 전반에서 도구를 정의하고 상호작용하기 위한 안전하고 확장 가능한 표준입니다.
UTCP는 어떤 통신 프로토콜을 지원하나요?
UTCP는 플러그인을 통해 HTTP/REST, SSE, CLI, MCP, 텍스트 기반 파일, WebSockets를 지원하며, TCP/UDP 및 GraphQL은 현재 개발 중입니다.
코어 라이브러리와 HTTP 플러그인을 어떻게 설치하나요?
다음 명령어를 사용하여 코어 라이브러리와 가장 일반적인 HTTP 플러그인을 설치할 수 있습니다: pip install utcp utcp-http.