Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
42ab7f8
MCP Resources
h3xxit Aug 29, 2025
51fe2da
update minimum python version
h3xxit Aug 29, 2025
75e3a22
Update test.yml
h3xxit Aug 29, 2025
2b51248
core[dev] install fix
AndreiGS Aug 30, 2025
1dc0a0f
Fix plugin logs not showing and mcp register tools
AndreiGS Aug 31, 2025
5c145a3
Add tool name
AndreiGS Aug 31, 2025
133c187
Performance optimisation
AndreiGS Aug 31, 2025
a27941e
Update plugins/communication_protocols/http/src/utcp_http/http_commun…
h3xxit Sep 2, 2025
68b06be
Update plugins/communication_protocols/http/src/utcp_http/sse_communi…
h3xxit Sep 2, 2025
33785d0
Update plugins/communication_protocols/gql/src/utcp_gql/gql_communica…
h3xxit Sep 2, 2025
677ec11
Update plugins/communication_protocols/mcp/src/utcp_mcp/mcp_communica…
h3xxit Sep 2, 2025
0887a00
Update plugins/communication_protocols/cli/src/utcp_cli/cli_communica…
h3xxit Sep 2, 2025
26ba8c3
Update plugins/communication_protocols/text/src/utcp_text/text_commun…
h3xxit Sep 2, 2025
e4627ab
Merge pull request #56 from universal-tool-calling-protocol/docs/readme
h3xxit Sep 2, 2025
c685a6e
Revert mcp specific config
AndreiGS Sep 4, 2025
7c8f0d2
Add server name to mcp tool
AndreiGS Sep 4, 2025
c23b594
Fix mcp tests
AndreiGS Sep 4, 2025
1320bf5
Replace handlers with hasHandlers()
AndreiGS Sep 4, 2025
fe3aad0
Merge pull request #57 from universal-tool-calling-protocol/hotfix/mc…
h3xxit Sep 5, 2025
8a0a449
Enhance documentation: Move docs to class docstrings and improve READ…
perrozzi Sep 7, 2025
aa6f7e3
Copy Readme to core
h3xxit Sep 7, 2025
d8464a0
default logging via basicConfig
h3xxit Sep 7, 2025
666eb1e
Update minor versions of all projects
h3xxit Sep 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13"]
python-version: ["3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4
Expand Down
97 changes: 63 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Universal Tool Calling Protocol (UTCP) 1.0.1
# Universal Tool Calling Protocol (UTCP)

[![Follow Org](https://img.shields.io/github/followers/universal-tool-calling-protocol?label=Follow%20Org&logo=github)](https://github.com/universal-tool-calling-protocol)
[![PyPI Downloads](https://static.pepy.tech/badge/utcp)](https://pepy.tech/projects/utcp)
Expand All @@ -19,47 +19,76 @@ In contrast to other protocols, UTCP places a strong emphasis on:

![MCP vs. UTCP](https://github.com/user-attachments/assets/3cadfc19-8eea-4467-b606-66e580b89444)

## New Architecture in 1.0.0
## Repository Structure

UTCP has been refactored into a core library and a set of optional plugins.
This repository contains the complete UTCP Python implementation:

- **[`core/`](core/)** - Core `utcp` package with foundational components ([README](core/README.md))
- **[`plugins/communication_protocols/`](plugins/communication_protocols/)** - Protocol-specific plugins:
- [`http/`](plugins/communication_protocols/http/) - HTTP/REST, SSE, streaming, OpenAPI ([README](plugins/communication_protocols/http/README.md))
- [`cli/`](plugins/communication_protocols/cli/) - Command-line tools ([README](plugins/communication_protocols/cli/README.md))
- [`mcp/`](plugins/communication_protocols/mcp/) - Model Context Protocol ([README](plugins/communication_protocols/mcp/README.md))
- [`text/`](plugins/communication_protocols/text/) - File-based tools ([README](plugins/communication_protocols/text/README.md))
- [`socket/`](plugins/communication_protocols/socket/) - TCP/UDP (🚧 In Progress)
- [`gql/`](plugins/communication_protocols/gql/) - GraphQL (🚧 In Progress)

## Architecture Overview

UTCP uses a modular architecture with a core library and protocol plugins:

### Core Package (`utcp`)

The `utcp` package provides the central components and interfaces:
* **Data Models**: Pydantic models for `Tool`, `CallTemplate`, `UtcpManual`, and `Auth`.
* **Pluggable Interfaces**:
* `CommunicationProtocol`: Defines the contract for protocol-specific communication (e.g., HTTP, CLI).
* `ConcurrentToolRepository`: An interface for storing and retrieving tools with thread-safe access.
* `ToolSearchStrategy`: An interface for implementing tool search algorithms.
* `VariableSubstitutor`: Handles variable substitution in configurations.
* `ToolPostProcessor`: Allows for modifying tool results before they are returned.
* **Default Implementations**:
* `UtcpClient`: The main client for interacting with the UTCP ecosystem.
* `InMemToolRepository`: An in-memory tool repository with asynchronous read-write locks.
* `TagAndDescriptionWordMatchStrategy`: An improved search strategy that matches on tags and description keywords.

### Protocol Plugins

Communication protocols are now separate, installable packages. This keeps the core lean and allows users to install only the protocols they need.
* `utcp-http`: Supports HTTP, SSE, and streamable HTTP, plus an OpenAPI converter.
* `utcp-cli`: For wrapping local command-line tools.
* `utcp-mcp`: For interoperability with the Model Context Protocol (MCP).
* `utcp-text`: For reading text files.
* `utcp-socket`: Scaffolding for TCP and UDP protocols. (Work in progress, requires update)
* `utcp-gql`: Scaffolding for GraphQL. (Work in progress, requires update)

## Installation

Install the core library and any required protocol plugins.
The [`core/`](core/) directory contains the foundational components:
- **Data Models**: Pydantic models for `Tool`, `CallTemplate`, `UtcpManual`, and `Auth`
- **Client Interface**: Main `UtcpClient` for 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:

```bash
# Install the core client and the HTTP plugin
# Install core + HTTP plugin (most common)
pip install utcp utcp-http

# Install the CLI plugin as well
pip install utcp-cli
# Install additional plugins as needed
pip install utcp-cli utcp-mcp utcp-text
```

### Basic Usage

```python
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`](plugins/communication_protocols/http/) | HTTP/REST APIs, SSE, streaming | ✅ Stable | [HTTP Plugin README](plugins/communication_protocols/http/README.md) |
| [`utcp-cli`](plugins/communication_protocols/cli/) | Command-line tools | ✅ Stable | [CLI Plugin README](plugins/communication_protocols/cli/README.md) |
| [`utcp-mcp`](plugins/communication_protocols/mcp/) | Model Context Protocol | ✅ Stable | [MCP Plugin README](plugins/communication_protocols/mcp/README.md) |
| [`utcp-text`](plugins/communication_protocols/text/) | Local file-based tools | ✅ Stable | [Text Plugin README](plugins/communication_protocols/text/README.md) |
| [`utcp-socket`](plugins/communication_protocols/socket/) | TCP/UDP protocols | 🚧 In Progress | [Socket Plugin README](plugins/communication_protocols/socket/README.md) |
| [`utcp-gql`](plugins/communication_protocols/gql/) | GraphQL APIs | 🚧 In Progress | [GraphQL Plugin README](plugins/communication_protocols/gql/README.md) |

For development, you can install the packages in editable mode from the cloned repository:

```bash
Expand All @@ -68,7 +97,7 @@ 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]
pip install -e "core[dev]"

# Install a specific protocol plugin in editable mode
pip install -e plugins/communication_protocols/http
Expand Down Expand Up @@ -269,7 +298,7 @@ app = FastAPI()
def utcp_discovery():
return {
"manual_version": "1.0.0",
"utcp_version": "1.0.1",
"utcp_version": "1.0.2",
"tools": [
{
"name": "get_weather",
Expand Down
109 changes: 69 additions & 40 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Universal Tool Calling Protocol (UTCP) 1.0.1
# Universal Tool Calling Protocol (UTCP)

[![Follow Org](https://img.shields.io/github/followers/universal-tool-calling-protocol?label=Follow%20Org&logo=github)](https://github.com/universal-tool-calling-protocol)
[![PyPI Downloads](https://static.pepy.tech/badge/utcp)](https://pepy.tech/projects/utcp)
Expand All @@ -7,7 +7,7 @@

## Introduction

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. UTCP 1.0.0 introduces a modular core with a plugin-based architecture, making it more extensible, testable, and easier to package.
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:

Expand All @@ -19,47 +19,76 @@ In contrast to other protocols, UTCP places a strong emphasis on:

![MCP vs. UTCP](https://github.com/user-attachments/assets/3cadfc19-8eea-4467-b606-66e580b89444)

## New Architecture in 1.0.0
## Repository Structure

UTCP has been refactored into a core library and a set of optional plugins.
This repository contains the complete UTCP Python implementation:

- **[`core/`](core/)** - Core `utcp` package with foundational components ([README](core/README.md))
- **[`plugins/communication_protocols/`](plugins/communication_protocols/)** - Protocol-specific plugins:
- [`http/`](plugins/communication_protocols/http/) - HTTP/REST, SSE, streaming, OpenAPI ([README](plugins/communication_protocols/http/README.md))
- [`cli/`](plugins/communication_protocols/cli/) - Command-line tools ([README](plugins/communication_protocols/cli/README.md))
- [`mcp/`](plugins/communication_protocols/mcp/) - Model Context Protocol ([README](plugins/communication_protocols/mcp/README.md))
- [`text/`](plugins/communication_protocols/text/) - File-based tools ([README](plugins/communication_protocols/text/README.md))
- [`socket/`](plugins/communication_protocols/socket/) - TCP/UDP (🚧 In Progress)
- [`gql/`](plugins/communication_protocols/gql/) - GraphQL (🚧 In Progress)

## Architecture Overview

UTCP uses a modular architecture with a core library and protocol plugins:

### Core Package (`utcp`)

The `utcp` package provides the central components and interfaces:
* **Data Models**: Pydantic models for `Tool`, `CallTemplate`, `UtcpManual`, and `Auth`.
* **Pluggable Interfaces**:
* `CommunicationProtocol`: Defines the contract for protocol-specific communication (e.g., HTTP, CLI).
* `ConcurrentToolRepository`: An interface for storing and retrieving tools with thread-safe access.
* `ToolSearchStrategy`: An interface for implementing tool search algorithms.
* `VariableSubstitutor`: Handles variable substitution in configurations.
* `ToolPostProcessor`: Allows for modifying tool results before they are returned.
* **Default Implementations**:
* `UtcpClient`: The main client for interacting with the UTCP ecosystem.
* `InMemToolRepository`: An in-memory tool repository with asynchronous read-write locks.
* `TagAndDescriptionWordMatchStrategy`: An improved search strategy that matches on tags and description keywords.

### Protocol Plugins

Communication protocols are now separate, installable packages. This keeps the core lean and allows users to install only the protocols they need.
* `utcp-http`: Supports HTTP, SSE, and streamable HTTP, plus an OpenAPI converter.
* `utcp-cli`: For wrapping local command-line tools.
* `utcp-mcp`: For interoperability with the Model Context Protocol (MCP).
* `utcp-text`: For reading text files.
* `utcp-socket`: Scaffolding for TCP and UDP protocols. (Work in progress, requires update)
* `utcp-gql`: Scaffolding for GraphQL. (Work in progress, requires update)

## Installation

Install the core library and any required protocol plugins.
The [`core/`](core/) directory contains the foundational components:
- **Data Models**: Pydantic models for `Tool`, `CallTemplate`, `UtcpManual`, and `Auth`
- **Client Interface**: Main `UtcpClient` for 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:

```bash
# Install the core client and the HTTP plugin
# Install core + HTTP plugin (most common)
pip install utcp utcp-http

# Install the CLI plugin as well
pip install utcp-cli
# Install additional plugins as needed
pip install utcp-cli utcp-mcp utcp-text
```

### Basic Usage

```python
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`](plugins/communication_protocols/http/) | HTTP/REST APIs, SSE, streaming | ✅ Stable | [HTTP Plugin README](plugins/communication_protocols/http/README.md) |
| [`utcp-cli`](plugins/communication_protocols/cli/) | Command-line tools | ✅ Stable | [CLI Plugin README](plugins/communication_protocols/cli/README.md) |
| [`utcp-mcp`](plugins/communication_protocols/mcp/) | Model Context Protocol | ✅ Stable | [MCP Plugin README](plugins/communication_protocols/mcp/README.md) |
| [`utcp-text`](plugins/communication_protocols/text/) | Local file-based tools | ✅ Stable | [Text Plugin README](plugins/communication_protocols/text/README.md) |
| [`utcp-socket`](plugins/communication_protocols/socket/) | TCP/UDP protocols | 🚧 In Progress | [Socket Plugin README](plugins/communication_protocols/socket/README.md) |
| [`utcp-gql`](plugins/communication_protocols/gql/) | GraphQL APIs | 🚧 In Progress | [GraphQL Plugin README](plugins/communication_protocols/gql/README.md) |

For development, you can install the packages in editable mode from the cloned repository:

```bash
Expand All @@ -68,7 +97,7 @@ 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]
pip install -e "core[dev]"

# Install a specific protocol plugin in editable mode
pip install -e plugins/communication_protocols/http
Expand All @@ -87,7 +116,7 @@ Version 1.0.0 introduces several breaking changes. Follow these steps to migrate
3. **Update Imports**: Change your imports to reflect the new modular structure. For example, `from utcp.client.transport_interfaces.http_transport import HttpProvider` becomes `from utcp_http.http_call_template import HttpCallTemplate`.
4. **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.
5. **Tool Naming**: Tool names are now namespaced as `manual_name.tool_name`. The client handles this automatically.
6 **Variable Substitution Namespacing**: Variables that are subsituted in different `call_templates`, are first namespaced with the name of the manual with the `_` duplicated. So a key in a tool call template called `API_KEY` from the manual `manual_1` would be converted to `manual__1_API_KEY`.
6. **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 called `API_KEY` from the manual `manual_1` would be converted to `manual__1_API_KEY`.

## Usage Examples

Expand Down Expand Up @@ -226,7 +255,7 @@ if __name__ == "__main__":

### 2. Providing a UTCP Manual

A `UTCPManual` describes the tools you offer. The key change is replacing `tool_provider` with `call_template`.
A `UTCPManual` describes the tools you offer. The key change is replacing `tool_provider` with `tool_call_template`.

**`server.py`**

Expand Down Expand Up @@ -269,7 +298,7 @@ app = FastAPI()
def utcp_discovery():
return {
"manual_version": "1.0.0",
"utcp_version": "1.0.1",
"utcp_version": "1.0.2",
"tools": [
{
"name": "get_weather",
Expand All @@ -288,7 +317,7 @@ def utcp_discovery():
"conditions": {"type": "string"}
}
},
"call_template": {
"tool_call_template": {
"call_template_type": "http",
"url": "https://example.com/api/weather",
"http_method": "GET"
Expand All @@ -311,7 +340,7 @@ You can find full examples in the [examples repository](https://github.com/unive

### `UtcpManual` and `Tool` Models

The `tool_provider` object inside a `Tool` has been replaced by `call_template`.
The `tool_provider` object inside a `Tool` has been replaced by `tool_call_template`.

```json
{
Expand All @@ -324,7 +353,7 @@ The `tool_provider` object inside a `Tool` has been replaced by `call_template`.
"inputs": { ... },
"outputs": { ... },
"tags": ["string"],
"call_template": {
"tool_call_template": {
"call_template_type": "http",
"url": "https://...",
"http_method": "GET"
Expand Down
2 changes: 1 addition & 1 deletion core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "utcp"
version = "1.0.1"
version = "1.0.2"
authors = [
{ name = "UTCP Contributors" },
]
Expand Down
11 changes: 4 additions & 7 deletions core/src/utcp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import logging
import sys

logger = logging.getLogger("utcp")

if not logger.handlers: # Only add default handler if user didn't configure logging
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d - %(message)s"))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d - %(message)s"
)
11 changes: 10 additions & 1 deletion core/src/utcp/exceptions/utcp_serializer_validation_error.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
class UtcpSerializerValidationError(Exception):
"""REQUIRED
Exception raised when a serializer validation fails."""
Exception raised when a serializer validation fails.

Thrown by serializers when they cannot validate or convert data structures
due to invalid format, missing required fields, or type mismatches.
Contains the original validation error details for debugging.

Usage:
Typically caught when loading configuration files or processing
external data that doesn't conform to UTCP specifications.
"""
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@
from utcp.utcp_client import UtcpClient

class FilterDictPostProcessor(ToolPostProcessor):
"""REQUIRED
Post-processor that filters dictionary keys from tool results.

Provides flexible filtering capabilities to include or exclude specific keys
from dictionary results, with support for nested dictionaries and lists.
Can be configured to apply filtering only to specific tools or manuals.

Attributes:
tool_post_processor_type: Always "filter_dict" for this processor.
exclude_keys: List of keys to remove from dictionary results.
only_include_keys: List of keys to keep in dictionary results (all others removed).
exclude_tools: List of tool names to skip processing for.
only_include_tools: List of tool names to process (all others skipped).
exclude_manuals: List of manual names to skip processing for.
only_include_manuals: List of manual names to process (all others skipped).
"""
tool_post_processor_type: Literal["filter_dict"] = "filter_dict"
exclude_keys: Optional[List[str]] = None
only_include_keys: Optional[List[str]] = None
Expand Down Expand Up @@ -89,6 +105,8 @@ def _filter_dict_only_include_keys(self, result: Any) -> Any:
return result

class FilterDictPostProcessorConfigSerializer(Serializer[FilterDictPostProcessor]):
"""REQUIRED
Serializer for FilterDictPostProcessor configuration."""
def to_dict(self, obj: FilterDictPostProcessor) -> dict:
return obj.model_dump()

Expand Down
Loading
Loading