utcp

package module
v1.4.5 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2025 License: MPL-2.0 Imports: 24 Imported by: 10

README

go-utcp

Go Report Card

Universal Tool Calling Protocol (UTCP) reference implementation in Go.

UTCP standardises how a client can discover and call "tools" (APIs) regardless of the underlying transport. Each provider describes a transport (HTTP, CLI, GraphQL and others) and lists the tools it exposes. This repository ships a lightweight Go client which can load provider definitions, register them at runtime and then invoke the discovered tools.

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. 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)
	}
}

The library is primarily intended for experimentation and interoperability testing. The API may change without notice.

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 NewUTCPClient

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

NewUtcpClient constructs a new client, loading providers if configured.

func (*UtcpClient) CallTool

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

func (*UtcpClient) DeregisterToolProvider

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

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(ctx context.Context, query string, limit int) ([]Tool, error)
}

UtcpClientInterface defines the public API.

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