{"_id":"@aprovan/utcp-http","name":"@aprovan/utcp-http","dist-tags":{"latest":"1.1.1"},"versions":{"1.1.1":{"name":"@aprovan/utcp-http","version":"1.1.1","description":"HTTP utilities for UTCP","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","type":"module","license":"MPL-2.0","author":{"name":"UTCP Contributors"},"repository":{"type":"git","url":"git+https://github.com/JacobSampson/typescript-utcp.git","directory":"packages/http"},"keywords":["utcp","universal-tool-calling-protocol","tools","api","typescript","tool calling","http","agent","ai","llm"],"publishConfig":{"access":"public"},"scripts":{"build":"tsup"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs","default":"./dist/index.js"}},"dependencies":{"@utcp/sdk":"^1.1.0","axios":"^1.11.0","js-yaml":"^4.1.0"},"devDependencies":{"bun-types":"latest","typescript":"^5.0.0","@types/bun":"latest"},"_id":"@aprovan/utcp-http@1.1.1","gitHead":"5e37442943b06302f7d3e3aa7fea35b503b09d34","bugs":{"url":"https://github.com/JacobSampson/typescript-utcp/issues"},"homepage":"https://github.com/JacobSampson/typescript-utcp#readme","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-mCrld0jTA9wZH5+dRUDX3LiwIWq3J3xl9XtgvW7aO/jhzP1xi5MV2a9kg93Pb2N9vaqgPVVnsShQv5MzSrQqJg==","shasum":"b6b4e57caa9058b87dbbebde50395dba4999027f","tarball":"https://registry.npmjs.org/@aprovan/utcp-http/-/utcp-http-1.1.1.tgz","fileCount":8,"unpackedSize":1072723,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aprovan%2futcp-http@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIH7rXVMAAQssTWEXuvFAYKGpf8zxu6RCuzcyhFs5F6JuAiEA/QlJ9a2Rrav7z3Z5B957fg3DBgmDr27uZJkJaqYLVlk="}]},"_npmUser":{"name":"jacobsampson","email":"jacob.samps@gmail.com"},"directories":{},"maintainers":[{"name":"jacobsampson","email":"jacob.samps@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/utcp-http_1.1.1_1769881509750_0.35884015984757367"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-31T17:45:09.665Z","1.1.1":"2026-01-31T17:45:09.943Z","modified":"2026-01-31T17:45:10.357Z"},"maintainers":[{"name":"jacobsampson","email":"jacob.samps@gmail.com"}],"description":"HTTP utilities for UTCP","homepage":"https://github.com/JacobSampson/typescript-utcp#readme","keywords":["utcp","universal-tool-calling-protocol","tools","api","typescript","tool calling","http","agent","ai","llm"],"repository":{"type":"git","url":"git+https://github.com/JacobSampson/typescript-utcp.git","directory":"packages/http"},"author":{"name":"UTCP Contributors"},"bugs":{"url":"https://github.com/JacobSampson/typescript-utcp/issues"},"license":"MPL-2.0","readme":"# @utcp/http\n\nHTTP-Based Communication Protocols for UTCP\n\n## Overview\n\nThe `@utcp/http` package provides comprehensive HTTP-based protocol support for the Universal Tool Calling Protocol (UTCP). It includes **three distinct protocols**:\n\n1. **HTTP** - Standard RESTful HTTP/HTTPS requests\n2. **Streamable HTTP** - HTTP with chunked transfer encoding for streaming large responses\n3. **SSE** - Server-Sent Events for real-time event streaming\n\nAll protocols support multiple authentication methods, URL path parameters, custom headers, and automatic OpenAPI specification conversion.\n\n## Features\n\n### 1. HTTP CallTemplate\n\nStandard HTTP requests for RESTful APIs:\n\n```typescript\ninterface HttpCallTemplate {\n  name: string;\n  call_template_type: 'http';\n  http_method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n  url: string;\n  headers?: Record<string, string>;\n  body_field?: string;\n  content_type?: string;\n  timeout?: number;\n  auth?: ApiKeyAuth | BasicAuth | OAuth2Auth;\n}\n```\n\n### 2. Streamable HTTP CallTemplate\n\nHTTP streaming with chunked transfer encoding for large responses:\n\n```typescript\ninterface StreamableHttpCallTemplate {\n  name: string;\n  call_template_type: 'streamable_http';\n  url: string;\n  http_method: 'GET' | 'POST';\n  content_type?: string;\n  chunk_size?: number;        // Default: 4096 bytes\n  timeout?: number;           // Default: 60000ms\n  headers?: Record<string, string>;\n  body_field?: string;\n  header_fields?: string[];\n  auth?: ApiKeyAuth | BasicAuth | OAuth2Auth;\n}\n```\n\n### 3. SSE CallTemplate\n\nServer-Sent Events for real-time streaming:\n\n```typescript\ninterface SseCallTemplate {\n  name: string;\n  call_template_type: 'sse';\n  url: string;\n  event_type?: string;        // Filter specific event types\n  reconnect?: boolean;        // Auto-reconnect on disconnect\n  retry_timeout?: number;     // Reconnection timeout (ms)\n  headers?: Record<string, string>;\n  body_field?: string;\n  header_fields?: string[];\n  auth?: ApiKeyAuth | BasicAuth | OAuth2Auth;\n}\n```\n\n### HTTP Communication Protocol\n\n*   **Tool Discovery**: Automatically registers tools from:\n    *   Remote UTCP Manuals\n    *   OpenAPI 2.0 (Swagger) specifications\n    *   OpenAPI 3.x specifications\n    *   Both JSON and YAML formats\n\n*   **Tool Execution**:\n    *   All HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS\n    *   URL path parameter substitution: `${param_name}` or `{param_name}`\n    *   Query parameter handling\n    *   Request body mapping via `body_field`\n    *   Custom headers with variable substitution\n\n*   **Authentication Support**:\n    *   **API Key**: Header, query parameter, or cookie-based\n    *   **Basic Auth**: Username/password authentication\n    *   **OAuth2**: Client credentials flow with automatic token caching and refresh\n\n*   **Security**:\n    *   Enforces HTTPS or localhost connections\n    *   Prevents Man-in-the-Middle (MITM) attacks\n    *   OAuth2 token caching to minimize token requests\n\n### OpenAPI Converter\n\nAutomatically converts OpenAPI specifications to UTCP tools:\n*   Parses OpenAPI 2.0 and 3.x specifications\n*   Generates tool definitions with proper schemas\n*   Extracts authentication requirements\n*   Creates placeholder variables for API keys\n\n## Protocol Comparison\n\n### When to Use Each Protocol\n\n| Protocol | Use Case | Response Type | Best For |\n|----------|----------|---------------|----------|\n| **HTTP** | Standard RESTful APIs | Complete response | Most APIs, CRUD operations, single requests |\n| **Streamable HTTP** | Large data downloads | Chunked streaming | Large files, datasets, progressive data |\n| **SSE** | Real-time updates | Event stream | Live updates, notifications, real-time feeds |\n\n### Key Differences\n\n**HTTP**\n- ✅ Simple request-response model\n- ✅ Complete data in single response\n- ✅ All HTTP methods supported\n- ❌ Not suitable for large responses\n- ❌ No real-time updates\n\n**Streamable HTTP**\n- ✅ Efficient for large responses\n- ✅ Progressive data processing\n- ✅ Reduced memory usage\n- ⚠️ Only GET/POST methods\n- ❌ No bidirectional communication\n\n**SSE**\n- ✅ Real-time event streaming\n- ✅ Automatic reconnection\n- ✅ Event type filtering\n- ✅ Server push updates\n- ❌ Unidirectional (server → client only)\n\n## Installation\n\n```bash\nnpm install @utcp/http @utcp/sdk\n\n# Or with bun\nbun add @utcp/http @utcp/sdk\n```\n\n**Dependencies:**\n- `@utcp/sdk` - Core UTCP SDK (peer dependency)\n- `axios` - HTTP client\n- `js-yaml` - YAML parsing for OpenAPI specs\n\n## Quick Start\n\n### Automatic Registration\n\nAll three HTTP-based protocols (`http`, `streamable_http`, `sse`) are **automatically registered** when you import the UtcpClient. No manual setup required!\n\n### Basic HTTP Usage\n\n```typescript\nimport { UtcpClient } from '@utcp/sdk';\nimport { HttpCallTemplateSerializer } from '@utcp/http';\n\nasync function main() {\n  const serializer = new HttpCallTemplateSerializer();\n  const weatherTemplate = serializer.validateDict({\n    name: 'weather_api',\n    call_template_type: 'http',\n    http_method: 'GET',\n    url: 'https://api.weatherapi.com/v1/current.json',\n    headers: {\n      'X-API-Key': '${API_KEY}'\n    }\n  });\n\n  const client = await UtcpClient.create(process.cwd(), {\n    variables: {\n      // Namespaced variables for security\n      'weather__api_API_KEY': process.env.WEATHER_API_KEY || ''\n    },\n    manual_call_templates: [weatherTemplate]\n  });\n\n  // Call the API\n  const weather = await client.callTool('weather_api.get_current', {\n    q: 'London'\n  });\n  \n  console.log('Weather:', weather);\n  await client.close();\n}\n```\n\n### With OpenAPI Specification\n\nAutomatically discover tools from an OpenAPI spec:\n\n```typescript\nimport { UtcpClient } from '@utcp/sdk';\nimport { HttpCallTemplateSerializer } from '@utcp/http';\n\nconst serializer = new HttpCallTemplateSerializer();\nconst petstoreTemplate = serializer.validateDict({\n  name: 'petstore_api',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://petstore.swagger.io/v2/swagger.json',\n  // Tools will be auto-discovered from the OpenAPI spec\n});\n\nconst client = await UtcpClient.create(process.cwd(), {\n  manual_call_templates: [petstoreTemplate]\n});\n\n// Search for discovered tools\nconst tools = await client.searchTools('pet');\nconsole.log('Available tools:', tools.map(t => t.name));\n\n// Call a discovered tool\nconst pets = await client.callTool('petstore_api.findPetsByStatus', {\n  status: 'available'\n});\n```\n\n### Streamable HTTP Usage\n\nStream large responses using chunked transfer encoding:\n\n```typescript\nimport { UtcpClient } from '@utcp/sdk';\nimport { StreamableHttpCallTemplateSerializer } from '@utcp/http';\n\nconst serializer = new StreamableHttpCallTemplateSerializer();\nconst streamTemplate = serializer.validateDict({\n  name: 'large_data_api',\n  call_template_type: 'streamable_http',\n  http_method: 'GET',\n  url: 'https://api.example.com/large-dataset',\n  chunk_size: 8192,  // 8KB chunks\n  timeout: 120000,   // 2 minutes\n  headers: {\n    'Accept': 'application/octet-stream'\n  }\n});\n\nconst client = await UtcpClient.create(process.cwd(), {\n  manual_call_templates: [streamTemplate]\n});\n\n// Stream the response\nconst stream = await client.callToolStreaming('large_data_api.get_dataset', {\n  filter: 'recent'\n});\n\nfor await (const chunk of stream) {\n  console.log('Received chunk:', chunk.length, 'bytes');\n  // Process chunk...\n}\n```\n\n### SSE (Server-Sent Events) Usage\n\nReal-time event streaming from servers:\n\n```typescript\nimport { UtcpClient } from '@utcp/sdk';\nimport { SseCallTemplateSerializer } from '@utcp/http';\n\nconst serializer = new SseCallTemplateSerializer();\nconst sseTemplate = serializer.validateDict({\n  name: 'events_api',\n  call_template_type: 'sse',\n  url: 'https://api.example.com/events',\n  event_type: 'notification',  // Filter to specific event type\n  reconnect: true,              // Auto-reconnect on disconnect\n  retry_timeout: 5000,          // Retry after 5 seconds\n  headers: {\n    'Authorization': 'Bearer ${API_KEY}'\n  }\n});\n\nconst client = await UtcpClient.create(process.cwd(), {\n  variables: {\n    'events__api_API_KEY': process.env.SSE_API_KEY || ''\n  },\n  manual_call_templates: [sseTemplate]\n});\n\n// Stream real-time events\nconst eventStream = await client.callToolStreaming('events_api.stream_events', {\n  channel: 'updates'\n});\n\nfor await (const event of eventStream) {\n  console.log('Event received:', event);\n  // Handle event...\n}\n```\n\n### Authentication Examples\n\n#### API Key Authentication\n\n```typescript\nimport { HttpCallTemplateSerializer } from '@utcp/http';\n\nconst serializer = new HttpCallTemplateSerializer();\nconst callTemplate = serializer.validateDict({\n  name: 'api_with_key',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://api.example.com/data',\n  auth: {\n    auth_type: 'api_key',\n    var_name: 'X-API-Key',\n    api_key_value: '${API_KEY}',\n    in: 'header' // or 'query' or 'cookie'\n  }\n});\n```\n\n#### Basic Authentication\n\n```typescript\nconst serializer = new HttpCallTemplateSerializer();\nconst callTemplate = serializer.validateDict({\n  name: 'api_with_basic',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://api.example.com/data',\n  auth: {\n    auth_type: 'basic',\n    username: '${USERNAME}',\n    password: '${PASSWORD}'\n  }\n});\n```\n\n#### OAuth2 Client Credentials\n\n```typescript\nconst serializer = new HttpCallTemplateSerializer();\nconst callTemplate = serializer.validateDict({\n  name: 'api_with_oauth',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://api.example.com/data',\n  auth: {\n    auth_type: 'oauth2',\n    token_url: 'https://auth.example.com/oauth/token',\n    client_id: '${CLIENT_ID}',\n    client_secret: '${CLIENT_SECRET}',\n    scope: 'read write'\n  }\n});\n```\n\n### Path Parameters\n\nUse `${param}` or `{param}` syntax for path parameters:\n\n```typescript\nconst serializer = new HttpCallTemplateSerializer();\nconst callTemplate = serializer.validateDict({\n  name: 'github_api',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://api.github.com/users/${username}',\n});\n\n// Call with arguments\nawait client.callTool('github_api.get_user', {\n  username: 'octocat'\n});\n// Resolves to: https://api.github.com/users/octocat\n```\n\n### Request Body\n\nFor POST/PUT/PATCH requests, use `body_field`:\n\n```typescript\nconst serializer = new HttpCallTemplateSerializer();\nconst callTemplate = serializer.validateDict({\n  name: 'create_resource',\n  call_template_type: 'http',\n  http_method: 'POST',\n  url: 'https://api.example.com/resources',\n  body_field: 'data',\n  content_type: 'application/json',\n  headers: {\n    'Content-Type': 'application/json'\n  }\n});\n\n// Call with body\nawait client.callTool('create_resource.post', {\n  data: {\n    name: 'My Resource',\n    value: 42\n  }\n});\n```\n\n## Use Case Examples\n\n### HTTP: GitHub API Integration\n\n```typescript\nconst serializer = new HttpCallTemplateSerializer();\nconst githubTemplate = serializer.validateDict({\n  name: 'github_api',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://api.github.com/repos/${owner}/${repo}/issues',\n  headers: { 'Authorization': 'Bearer ${TOKEN}' }\n});\n\nconst client = await UtcpClient.create(process.cwd(), {\n  variables: { 'github__api_TOKEN': process.env.GITHUB_TOKEN || '' },\n  manual_call_templates: [githubTemplate]\n});\n\nconst issues = await client.callTool('github_api.get_issues', {\n  owner: 'utcp', repo: 'typescript-utcp'\n});\n```\n\n### Streamable HTTP: Large File Download\n\n```typescript\nconst serializer = new StreamableHttpCallTemplateSerializer();\nconst cdnTemplate = serializer.validateDict({\n  name: 'cdn',\n  call_template_type: 'streamable_http',\n  http_method: 'GET',\n  url: 'https://cdn.example.com/large-file.zip',\n  chunk_size: 16384\n});\n\nconst client = await UtcpClient.create(process.cwd(), {\n  manual_call_templates: [cdnTemplate]\n});\n\nconst stream = await client.callToolStreaming('cdn.download', {});\nfor await (const chunk of stream) {\n  // Write chunk to file or process incrementally\n  fs.appendFileSync('output.zip', chunk);\n}\n```\n\n### SSE: Stock Price Updates\n\n```typescript\nconst serializer = new SseCallTemplateSerializer();\nconst stockTemplate = serializer.validateDict({\n  name: 'stock_api',\n  call_template_type: 'sse',\n  url: 'https://api.stocks.com/stream',\n  event_type: 'price_update',\n  reconnect: true\n});\n\nconst client = await UtcpClient.create(process.cwd(), {\n  manual_call_templates: [stockTemplate]\n});\n\nconst priceStream = await client.callToolStreaming('stock_api.watch', {\n  symbol: 'AAPL'\n});\n\nfor await (const update of priceStream) {\n  console.log('Price update:', update.price, 'at', update.timestamp);\n}\n```\n\n## Advanced Features\n\n### Custom Headers with Variables\n\n```typescript\nconst serializer = new HttpCallTemplateSerializer();\nconst callTemplate = serializer.validateDict({\n  name: 'custom_api',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://api.example.com/data',\n  headers: {\n    'Authorization': 'Bearer ${TOKEN}',\n    'X-Request-ID': '${REQUEST_ID}',\n    'User-Agent': 'UTCP-Client/1.0'\n  }\n});\n```\n\n### Timeout Configuration\n\n```typescript\nconst serializer = new HttpCallTemplateSerializer();\nconst callTemplate = serializer.validateDict({\n  name: 'slow_api',\n  call_template_type: 'http',\n  http_method: 'GET',\n  url: 'https://api.example.com/slow-endpoint',\n  timeout: 60000 // 60 seconds\n});\n```\n\n### Variable Namespacing\n\nAll variables are automatically namespaced by manual name for security:\n\n```typescript\nconst client = await UtcpClient.create(process.cwd(), {\n  variables: {\n    // For manual \"github_api\", variables must be prefixed\n    'github__api_TOKEN': 'github-token-123',\n    'gitlab__api_TOKEN': 'gitlab-token-456'\n  },\n  manual_call_templates: [\n    {\n      name: 'github_api',\n      // ...\n      headers: {\n        // Resolves to \"github__api_TOKEN\"\n        'Authorization': 'Bearer ${TOKEN}'\n      }\n    }\n  ]\n});\n```\n\n## OpenAPI Conversion\n\nThe `OpenApiConverter` automatically:\n\n1. **Parses OpenAPI specs** (2.0 and 3.x)\n2. **Extracts endpoints** as individual tools\n3. **Generates schemas** for inputs and outputs\n4. **Detects authentication** requirements\n5. **Creates placeholder variables** for API keys\n\n```typescript\nimport { OpenApiConverter } from '@utcp/http';\n\nconst converter = new OpenApiConverter('https://api.example.com/openapi.json');\nconst manual = await converter.convert();\n\nconsole.log('Discovered tools:', manual.tools.length);\n```\n\n## Security Features\n\n### HTTPS Enforcement\n\nThe HTTP protocol enforces HTTPS or localhost connections by default to prevent MITM attacks:\n\n```typescript\n// ✅ Allowed\n'https://api.example.com'\n'http://localhost:8080'\n'http://127.0.0.1:3000'\n\n// ❌ Rejected\n'http://api.example.com'  // Non-localhost HTTP\n```\n\n### OAuth2 Token Caching\n\nOAuth2 tokens are automatically cached by `client_id` to minimize token requests:\n\n- Tokens are cached until expiration\n- Automatic refresh when expired\n- Tries both body and auth header methods\n\n## Error Handling\n\n```typescript\ntry {\n  const result = await client.callTool('api_manual.endpoint', args);\n} catch (error) {\n  if (error.message.includes('401')) {\n    console.error('Authentication failed');\n  } else if (error.message.includes('404')) {\n    console.error('Endpoint not found');\n  } else {\n    console.error('Request failed:', error);\n  }\n}\n```\n\n## TypeScript Support\n\nFull TypeScript support with exported types for all three protocols:\n\n```typescript\nimport {\n  // HTTP Protocol\n  HttpCallTemplate,\n  HttpCommunicationProtocol,\n  \n  // Streamable HTTP Protocol\n  StreamableHttpCallTemplate,\n  StreamableHttpCommunicationProtocol,\n  \n  // SSE Protocol\n  SseCallTemplate,\n  SseCommunicationProtocol,\n  \n  // OpenAPI Converter\n  OpenApiConverter,\n  \n  // Authentication Types\n  ApiKeyAuth,\n  BasicAuth,\n  OAuth2Auth\n} from '@utcp/http';\n```\n\n## Testing\n\n```bash\n# Run HTTP protocol tests\nbun test packages/http/tests/\n```\n\n## Related Packages\n\n- `@utcp/sdk` - Core UTCP SDK\n- `@utcp/mcp` - MCP protocol support\n- `@utcp/text` - File-based tools\n- `@utcp/cli` - Command-line tools\n\n## Contributing\n\nSee the root repository for contribution guidelines.\n\n## License\n\nMozilla Public License Version 2.0","readmeFilename":"README.md","_rev":"1-42b277ece0aa98971698bf4760f00383"}