# Typescript Utcp

> Official typescript implementation of UTCP. UTCP is an open standard that lets AI agents call any API directly, without extra middleware.

- **Type:** MCP server
- **Install:** `agentstack add mcp-universal-tool-calling-protocol-typescript-utcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [universal-tool-calling-protocol](https://agentstack.voostack.com/s/universal-tool-calling-protocol)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MPL-2.0
- **Upstream author:** [universal-tool-calling-protocol](https://github.com/universal-tool-calling-protocol)
- **Source:** https://github.com/universal-tool-calling-protocol/typescript-utcp
- **Website:** https://www.utcp.io

## Install

```sh
agentstack add mcp-universal-tool-calling-protocol-typescript-utcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Universal Tool Calling Protocol (UTCP) for TypeScript

[](https://github.com/universal-tool-calling-protocol)
[](https://www.npmjs.com/package/@utcp/sdk)
[](https://github.com/universal-tool-calling-protocol/typescript-utcp/blob/main/LICENSE)
[](https://cdtm.com/)

**The Universal Tool Calling Protocol (UTCP) is a secure and scalable standard for defining and interacting with tools across a wide variety of communication protocols. This repository contains the official TypeScript implementation, structured as a monorepo with a lean core and pluggable communication protocols.**

UTCP offers a unified framework for integrating disparate tools and services, making them accessible through a consistent and well-defined interface. This TypeScript SDK provides a comprehensive toolkit for developers to leverage the full power of the UTCP standard in their applications.

## Key Features

*   **Automatic Plugin Registration**: The official plugins are automatically discovered and registered when you import the core client—no manual setup required. For other plugins, you will need to register them manually.
*   **Scalability**: 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, MCP, Text, File, and CLI—UTCP can integrate with almost any existing service or infrastructure.
*   **Code Execution Mode**: Execute TypeScript code with hierarchical access to tools, complete console output capture, and runtime interface introspection for powerful AI agent workflows.
*   **Type Safety**: Built on well-defined TypeScript interfaces and runtime validation powered by Zod, making it robust and developer-friendly.
*   **Secure Variable Management**: Namespace-isolated variables prevent leakage between manuals, with support for environment variables and .env files.

## Getting Started

### Installation

Install UTCP packages from npm:

```bash
# Install core SDK and desired protocol plugins
npm install @utcp/sdk @utcp/http @utcp/mcp @utcp/text @utcp/file

# Optional: Add dotenv variable loader for Node.js
npm install @utcp/dotenv-loader

# Or using bun
bun add @utcp/sdk @utcp/http @utcp/mcp @utcp/text @utcp/file
```

### For Development

To set up the monorepo for development:

```bash
# Clone the repository
git clone https://github.com/universal-tool-calling-protocol/typescript-utcp.git
cd typescript-utcp

# Install dependencies (requires bun)
bun install

# Build all packages
bun run build
```

## Quick Start

### Basic Usage

Plugins are **automatically registered** when you import the UtcpClient—no manual registration needed!

```typescript
import { UtcpClient } from '@utcp/sdk';
import { HttpCallTemplateSerializer } from '@utcp/http';

async function main() {
  // Create client - plugins auto-register
  const serializer = new HttpCallTemplateSerializer();
  const githubTemplate = serializer.validateDict({
    name: 'github_api',
    call_template_type: 'http',
    http_method: 'GET',
    url: 'https://api.github.com/users/${username}',
  });

  const client = await UtcpClient.create(process.cwd(), {
    manual_call_templates: [githubTemplate],
    variables: {
      // Namespace format: manual_name_VARIABLE
      github__api_username: 'octocat'
    }
  });

  // Search for tools
  const tools = await client.searchTools('github user');
  console.log('Found tools:', tools.map(t => t.name));

  // Call a tool
  const result = await client.callTool('github_api.get_user', {});
  console.log('Result:', result);

  await client.close();
}

main().catch(console.error);
```

### Working with Multiple Protocols

```typescript
import { UtcpClient } from '@utcp/sdk';
import { HttpCallTemplateSerializer } from '@utcp/http';
import { McpCallTemplateSerializer } from '@utcp/mcp';
import { FileCallTemplateSerializer } from '@utcp/file';

async function main() {
  // Create serializers for each protocol
  const httpSerializer = new HttpCallTemplateSerializer();
  const mcpSerializer = new McpCallTemplateSerializer();
  const fileSerializer = new FileCallTemplateSerializer();

  // Validate and create call templates
  const httpTemplate = httpSerializer.validateDict({
    name: 'api_manual',
    call_template_type: 'http',
    http_method: 'GET',
    url: 'https://api.example.com/data',
    headers: {
      'Authorization': 'Bearer ${API_KEY}'
    }
  });

  const mcpTemplate = mcpSerializer.validateDict({
    name: 'mcp_tools',
    call_template_type: 'mcp',
    config: {
      mcpServers: {
        my_mcp_server: {
          transport: 'stdio',
          command: 'node',
          args: ['./mcp-server.js'],
          cwd: './servers'
        }
      }
    }
  });

  const fileTemplate = fileSerializer.validateDict({
    name: 'local_tools',
    call_template_type: 'file',
    file_path: './config/tools.json'
  });

  const client = await UtcpClient.create(process.cwd(), {
    variables: {
      // Namespaced variables for security
      api__manual_API_KEY: process.env.API_KEY || 'default-key',
    },
    load_variables_from: [
      {
        variable_loader_type: 'dotenv',
        env_file_path: './.env'
      }
    ],
    manual_call_templates: [
      httpTemplate,  // HTTP API
      mcpTemplate,   // MCP Server
      fileTemplate   // Local file-based tools
    ]
  });

  // Tools are namespaced: manual_name.tool_name
  // For MCP: manual_name.server_name.tool_name
  const allTools = await client.getTools();
  console.log('Registered tools:', allTools.map(t => t.name));
  
  // Examples:
  // - 'api_manual.get_data'
  // - 'mcp_tools.my_mcp_server.echo'
  // - 'local_tools.my_function'

  await client.close();
}
```

## API Reference

### UtcpClient.create()

```typescript
static async create(
  root_dir: string,
  config: Partial
): Promise
```

**Parameters:**
- `root_dir`: Base directory for resolving relative paths (usually `process.cwd()`)
- `config`: Client configuration object

**Configuration Options:**

```typescript
interface UtcpClientConfig {
  // Direct variable definitions (highest priority)
  variables?: Record;
  
  // External variable loaders (e.g., .env files)
  load_variables_from?: Array;
  
  // Manual call templates to register at startup
  manual_call_templates?: CallTemplate[];
  
  // Tool repository configuration (defaults to in-memory)
  tool_repository?: ConcurrentToolRepository;
  
  // Search strategy configuration (defaults to tag_and_description_word_match)
  tool_search_strategy?: ToolSearchStrategy;
  
  // Post-processing configurations
  post_processing?: ToolPostProcessor[];
}
```

### Core Methods

#### Search Tools
```typescript
async searchTools(
  query: string,
  limit?: number,
  anyOfTagsRequired?: string[]
): Promise
```

Searches for tools matching the query. The search considers:
- **Tool names** (highest priority)
- **Tool tags**
- **Tool descriptions**

#### Call Tool
```typescript
async callTool(
  toolName: string,
  args: Record
): Promise
```

Executes a tool with the given arguments. Tool names follow these formats:
- HTTP/Text/CLI: `manual_name.tool_name`
- MCP: `manual_name.server_name.tool_name`

#### Get Tools
```typescript
async getTools(): Promise
async getTool(toolName: string): Promise
```

Retrieve all registered tools or get a specific tool by name.

#### Register/Deregister Manuals
```typescript
async registerManual(callTemplate: CallTemplate): Promise
async deregisterManual(manualName: string): Promise
```

Dynamically add or remove tool manuals at runtime.

## Variable Management

### Variable Namespacing (Security Feature)

Variables are **namespace-isolated** by manual name to prevent variable leakage between manuals:

```typescript
// For a manual named "github_api", variables are accessed as:
// ${VARIABLE} -> resolved from "github__api_VARIABLE"

import { HttpCallTemplateSerializer } from '@utcp/http';

const serializer = new HttpCallTemplateSerializer();
const githubTemplate = serializer.validateDict({
  name: 'github_api',
  call_template_type: 'http',
  http_method: 'GET',
  url: 'https://api.github.com/users',
  headers: {
    // Resolves to 'github__api_TOKEN' only
    'Authorization': 'Bearer ${TOKEN}'
  }
});

const client = await UtcpClient.create(process.cwd(), {
  variables: {
    'github__api_TOKEN': 'github-token-123',
    'slack__api_TOKEN': 'slack-token-456',
  },
  manual_call_templates: [githubTemplate]
});
```

**Namespace transformation**: Manual name underscores become double underscores:
- `github_api` → `github__api_`
- `my-service` → `my_service_` (hyphens to underscores)

### Variable Resolution Order

1. **Client config variables** (highest priority)
2. **Variable loaders** (e.g., .env files, in order)
3. **Environment variables** (lowest priority)

All lookups use the namespaced key: `{namespace}_VARIABLE_NAME`.

### Loading from .env Files

```typescript
const client = await UtcpClient.create(process.cwd(), {
  load_variables_from: [
    {
      variable_loader_type: 'dotenv',
      env_file_path: './.env'
    }
  ]
});
```

## Communication Protocols

### HTTP Protocol

Supports RESTful APIs with automatic OpenAPI specification conversion:

```typescript
import { HttpCallTemplateSerializer } from '@utcp/http';

const serializer = new HttpCallTemplateSerializer();
const weatherTemplate = serializer.validateDict({
  name: 'weather_api',
  call_template_type: 'http',
  http_method: 'GET',
  url: 'https://api.weather.com/v1/forecast',
  headers: {
    'X-API-Key': '${API_KEY}'
  },
  // Optional: Basic, API Key, or OAuth2 authentication
  auth: {
    auth_type: 'api_key',
    var_name: 'X-API-Key',
    api_key_value: '${API_KEY}',
    in: 'header'
  }
});
```

**Features:**
- Path parameter substitution
- Header and body templates
- Multiple authentication methods
- Automatic OpenAPI to UTCP conversion

### MCP Protocol

Connect to Model Context Protocol servers:

```typescript
import { McpCallTemplateSerializer } from '@utcp/mcp';

const serializer = new McpCallTemplateSerializer();
const mcpTemplate = serializer.validateDict({
  name: 'mcp_manual',
  call_template_type: 'mcp',
  config: {
    mcpServers: {
      server_name: {
        transport: 'stdio', // or 'http'
        command: 'bun',
        args: ['run', './mcp-server.ts'],
        cwd: './servers',
        env: { DEBUG: 'true' }
      }
    }
  }
});
```

**Tool Naming:** `manual_name.server_name.tool_name`

**Features:**
- Stdio and HTTP transports
- Persistent session management
- Automatic retry on connection errors
- Multiple servers per manual

### Text Protocol

Handle direct text/string content (browser-compatible):

```typescript
import { TextCallTemplateSerializer } from '@utcp/text';

const serializer = new TextCallTemplateSerializer();
const textTemplate = serializer.validateDict({
  name: 'inline_tools',
  call_template_type: 'text',
  content: JSON.stringify({
    tools: [
      // UTCP manual or OpenAPI spec as string
    ]
  })
});
```

### File Protocol

Load tools from local JSON/YAML files or OpenAPI specs (Node.js only):

```typescript
import { FileCallTemplateSerializer } from '@utcp/file';

const serializer = new FileCallTemplateSerializer();
const fileTemplate = serializer.validateDict({
  name: 'local_tools',
  call_template_type: 'file',
  file_path: './config/tools.json'
  // Supports: .json, .yaml, .yml, OpenAPI specs
});
```

### CLI Protocol

Execute command-line tools:

```typescript
import { CliCallTemplateSerializer } from '@utcp/cli';

const serializer = new CliCallTemplateSerializer();
const cliTemplate = serializer.validateDict({
  name: 'system_commands',
  call_template_type: 'cli',
  commands: [
    {
      command: 'git status'
    }
  ],
  working_dir: './my-repo'
});
```

## Code Execution Mode 

Implementation moved to https://github.com/universal-tool-calling-protocol/code-mode/tree/main/typescript-library

The `@utcp/code-mode` package provides a powerful extension that allows executing TypeScript code with direct access to registered tools, perfect for AI agents and complex workflows:

```typescript
import { CodeModeUtcpClient } from '@utcp/code-mode';

async function main() {
  const client = await CodeModeUtcpClient.create();
  
  // Register your tools (same as regular UTCP)
  await client.registerManual({
    name: 'math_tools',
    call_template_type: 'text',
    content: '...' // Your tool definitions
  });

  // Execute TypeScript code with hierarchical tool access
  const { result, logs } = await client.callToolChain(`
    console.log('Starting calculation...');
    
    // Tools are organized by namespace: manual.tool
    const sum = await math_tools.add({ a: 10, b: 20 });
    console.log('Sum result:', sum.result);
    
    // Access TypeScript interfaces at runtime for introspection
    const addInterface = __getToolInterface('math_tools.add');
    console.log('Tool interface:', addInterface);
    
    // Chain multiple tool calls
    const result = await math_tools.multiply({ 
      a: sum.result, 
      b: 2 
    });
    
    return result;
  `);
  
  console.log('Execution result:', result);
  console.log('Console output:', logs);
  // logs: ['Starting calculation...', 'Sum result: 30', 'Tool interface: ...']
  
  await client.close();
}
```

### Code Mode Features

- **Hierarchical Tool Access**: Tools organized by manual namespace (`manual.tool()`) preventing naming conflicts
- **Console Output Capture**: All console output automatically captured and returned
- **Runtime Interface Introspection**: Access TypeScript interface definitions during execution
- **Type Safety**: Generated TypeScript interfaces for all tools with hierarchical namespaces
- **Secure Execution**: VM-based sandboxed execution with timeout protection
- **AI Agent Ready**: Built-in prompt template to guide AI agents on proper usage

### Perfect for AI Agents

The `CodeModeUtcpClient.AGENT_PROMPT_TEMPLATE` provides comprehensive guidance for AI agents:

```typescript
// Add to your AI system prompt
const systemPrompt = `
${CodeModeUtcpClient.AGENT_PROMPT_TEMPLATE}

Your additional instructions...
`;
```

The template includes:
- Tool discovery workflow
- Interface introspection patterns
- Best practices for hierarchical tool access
- Error handling guidelines
- Runtime context documentation

## Monorepo Structure

```
typescript-utcp/
├── packages/
│   ├── core/          # Core SDK with UtcpClient and interfaces
│   ├── http/          # HTTP protocol plugin
│   ├── mcp/           # MCP protocol plugin
│   ├── text/          # Text/string content protocol plugin (browser-compatible)
│   ├── file/          # File system protocol plugin (Node.js only)
│   ├── dotenv-loader/ # DotEnv variable loader plugin (Node.js only)
│   ├── direct-call/   # Direct call protocol plugin
│   └── cli/           # CLI protocol plugin
├── tests/             # End-to-end integration tests
└── README.md
```

Each package is independently published to npm:
- `@utcp/sdk` - Core SDK library (required)
- `@utcp/http` - HTTP protocol support
- `@utcp/mcp` - MCP protocol support
- `@utcp/text` - Direct text/string content (browser-compatible)
- `@utcp/file` - File system operations (Node.js only)
- `@utcp/dotenv-loader` - DotEnv variable loader (Node.js only)
- `@utcp/direct-call` - Direct function call protocol
- `@utcp/cli` - Command-line tools

## Development & Testing

### Build

```bash
# Build all packages
bun run build

# Clean and rebuild
bun run rebuild
```

### Testing

```bash
# Run all tests
bun test

# Run specific test file
bun test tests/utcp_client.test.ts
```

### Publishing

```bash
# Publish all packages
bun run publish:all

# Or publish individually
bun run publish:core
bun run publish:http
bun run publish:mcp
```

## Advanced Features

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [universal-tool-calling-protocol](https://github.com/universal-tool-calling-protocol)
- **Source:** [universal-tool-calling-protocol/typescript-utcp](https://github.com/universal-tool-calling-protocol/typescript-utcp)
- **License:** MPL-2.0
- **Homepage:** https://www.utcp.io

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-universal-tool-calling-protocol-typescript-utcp
- Seller: https://agentstack.voostack.com/s/universal-tool-calling-protocol
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
