utcp

package module
v1.6.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2025 License: MPL-2.0 Imports: 40 Imported by: 0

README

go-utcp

MCP vs. UTCP

Go Report Card PkgGoDev

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. It is designed to be easy to use, interoperable, and extensible, making it a powerful choice for building and consuming tool-based services.

In contrast to other protocols like MCP, UTCP places a strong emphasis on:

  • Scalability: UTCP is designed to handle a large number of tools and providers without compromising performance.
  • Interoperability: With support for a wide range of provider types (including HTTP, WebSockets, gRPC, and even CLI tools), UTCP can integrate with almost any existing service or infrastructure.
  • Ease of Use: The protocol is built on simple.

MCP vs. UTCP

Features
  • Built-in transports for HTTP, CLI, Server-Sent Events, streaming HTTP, GraphQL, MCP and UDP.
  • Variable substitution via environment variables or .env files using UtcpDotEnv.
  • In-memory repository for storing providers and tools discovered at runtime.
  • Utilities such as OpenApiConverter to convert OpenAPI definitions into UTCP manuals.
  • Example programs demonstrating the client in the examples directory.
Examples

Each subdirectory under examples/ is a standalone Go module demonstrating a client or transport. For an overview of available examples and usage instructions, see examples/README.md. When building or running an example from this repository, disable the workspace to ensure Go uses the module's own go.mod:

GOWORK=off go run ./examples/cli_transport

Getting Started

Add the library to your project with:

go get github.com/universal-tool-calling-protocol/go-utcp@latest

You can then construct a client and call tools using any of the built-in transports. The library ships transports for HTTP, Server-Sent Events, streaming HTTP, CLI, WebSocket, gRPC, GraphQL, TCP, UDP, WebRTC and MCP providers.

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	utcp "github.com/universal-tool-calling-protocol/go-utcp"
)

func main() {
	ctx := context.Background()

	cfg := &utcp.UtcpClientConfig{
		ProvidersFilePath: "providers.json",
	}

	fmt.Println("Creating UTCP client...")
	client, err := utcp.NewUTCPClient(ctx, cfg, nil, nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to create UTCP client: %v\n", err)
		os.Exit(1)
	}

	// Give the client time to fully initialize
	fmt.Println("Waiting for initialization...")
	time.Sleep(500 * time.Millisecond)

	fmt.Println("\n=== Tool Discovery ===")
	tools, err := client.SearchTools("", 10)
	if err != nil {
		fmt.Fprintf(os.Stderr, "search error: %v\n", err)
		os.Exit(1)
	}

	if len(tools) == 0 {
		fmt.Println("No tools found!")
		os.Exit(1)
	}

	tool := tools[0]
	fmt.Printf("Found tool: %s\n", tool.Name)
	fmt.Printf("Tool description: %s\n", tool.Description)

	// Test the tool call
	fmt.Println("\n=== Tool Call Test ===")
	input := map[string]interface{}{
		"name": "Kamil",
	}

	fmt.Printf("Calling tool '%s' with input: %v\n", tool.Name, input)
	result, err := client.CallTool(ctx, tool.Name, input)
	if err != nil {
		fmt.Printf("ERROR: %v\n", err)

		// Try to understand the error better
		fmt.Printf("Error type: %T\n", err)
		fmt.Printf("Error string: %s\n", err.Error())

		// Let's try a direct search for the provider
		fmt.Println("\n=== Searching for provider directly ===")
		providerTools, err2 := client.SearchTools("hello", 10)
		if err2 != nil {
			fmt.Printf("Provider search failed: %v\n", err2)
		} else {
			fmt.Printf("Provider search returned %d tools\n", len(providerTools))
			for i, t := range providerTools {
				fmt.Printf("  %d: %s\n", i, t.Name)
			}
		}

	} else {
		fmt.Printf("SUCCESS: %v\n", result)
	}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type UtcpClient

type UtcpClient struct {
	// contains filtered or unexported fields
}

UtcpClient holds all state and implements UtcpClientInterface.

func (*UtcpClient) CallTool

func (c *UtcpClient) CallTool(
	ctx context.Context,
	toolName string,
	args map[string]any,
) (any, error)

--- HOT PATH: CallTool with lock-free fast lookup ---

func (*UtcpClient) CallToolStream added in v1.5.8

func (c *UtcpClient) CallToolStream(
	ctx context.Context,
	toolName string,
	args map[string]any,
) (transports.StreamResult, error)

func (*UtcpClient) DeregisterToolProvider

func (c *UtcpClient) DeregisterToolProvider(ctx context.Context, providerName string) error

func (*UtcpClient) GetTransports added in v1.5.1

func (u *UtcpClient) GetTransports() map[string]ClientTransport

func (*UtcpClient) RegisterToolProvider

func (c *UtcpClient) RegisterToolProvider(
	ctx context.Context,
	prov Provider,
) ([]Tool, error)

RegisterToolProvider applies variable substitution, picks the right transport, and registers tools.

func (*UtcpClient) SearchTools

func (c *UtcpClient) SearchTools(query string, limit int) ([]Tool, error)

type UtcpClientConfig

type UtcpClientConfig struct {
	// Variables explicitly passed in (takes precedence)
	Variables map[string]string

	// Optional path to a providers‐definition file
	ProvidersFilePath string

	// A list of providers to load from (e.g. .env, AWS SSM, Vault, etc.)
	LoadVariablesFrom []UtcpVariablesConfig
}

UtcpClientConfig holds your resolved variables and provider settings.

func NewClientConfig

func NewClientConfig() *UtcpClientConfig

NewClientConfig constructs a config with sensible defaults.

type UtcpClientInterface

type UtcpClientInterface interface {
	RegisterToolProvider(ctx context.Context, prov Provider) ([]Tool, error)
	DeregisterToolProvider(ctx context.Context, providerName string) error
	CallTool(ctx context.Context, toolName string, args map[string]any) (any, error)
	SearchTools(query string, limit int) ([]Tool, error)
	GetTransports() map[string]ClientTransport
	CallToolStream(ctx context.Context, toolName string, args map[string]any) (transports.StreamResult, error)
}

UtcpClientInterface defines the public API.

func NewUTCPClient

func NewUTCPClient(
	ctx context.Context,
	cfg *UtcpClientConfig,
	repo ToolRepository,
	strat ToolSearchStrategy,
) (UtcpClientInterface, error)

NewUTCPClient constructs a new client, loading providers if configured.

type UtcpDotEnv

type UtcpDotEnv struct {
	EnvFilePath string
}

UtcpDotEnv implements UtcpVariablesConfig by loading a .env file.

func NewDotEnv

func NewDotEnv(path string) *UtcpDotEnv

func (*UtcpDotEnv) Get

func (u *UtcpDotEnv) Get(key string) (string, error)

Get loads the file and looks up a single key.

func (*UtcpDotEnv) Load

func (u *UtcpDotEnv) Load() (map[string]string, error)

Load reads the .env file and returns a map of key→value.

type UtcpVariableNotFound

type UtcpVariableNotFound struct {
	VariableName string
}

UtcpVariableNotFound is returned when a requested variable isn't present.

func (*UtcpVariableNotFound) Error

func (e *UtcpVariableNotFound) Error() string

type UtcpVariablesConfig

type UtcpVariablesConfig interface {
	// Load returns all variables available from this provider.
	Load() (map[string]string, error)
	// Get returns a single variable value or an error if not present.
	Get(key string) (string, error)
}

UtcpVariablesConfig is the interface for any variable‐loading strategy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL