{"id":50535930,"url":"https://github.com/universal-tool-calling-protocol/zig-utcp","last_synced_at":"2026-06-03T16:30:47.586Z","repository":{"id":361688601,"uuid":"1255410380","full_name":"universal-tool-calling-protocol/zig-utcp","owner":"universal-tool-calling-protocol","description":"zig implementation of UTCP","archived":false,"fork":false,"pushed_at":"2026-05-31T20:16:17.000Z","size":41,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T21:22:55.745Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/universal-tool-calling-protocol.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-31T19:46:56.000Z","updated_at":"2026-05-31T20:16:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/universal-tool-calling-protocol/zig-utcp","commit_stats":null,"previous_names":["universal-tool-calling-protocol/zig-utcp"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/universal-tool-calling-protocol/zig-utcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-tool-calling-protocol%2Fzig-utcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-tool-calling-protocol%2Fzig-utcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-tool-calling-protocol%2Fzig-utcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-tool-calling-protocol%2Fzig-utcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/universal-tool-calling-protocol","download_url":"https://codeload.github.com/universal-tool-calling-protocol/zig-utcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-tool-calling-protocol%2Fzig-utcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33874679,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-03T16:30:47.518Z","updated_at":"2026-06-03T16:30:47.580Z","avatar_url":"https://github.com/universal-tool-calling-protocol.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zig-utcp\n\n`zig-utcp` is a Zig implementation of the Universal Tool Calling Protocol (UTCP)\nclient model, based on the package boundaries in\n[`universal-tool-calling-protocol/go-utcp`](https://github.com/universal-tool-calling-protocol/go-utcp).\n\nA UTCP client discovers tools from *providers* (described by JSON config),\nstores them in a repository, searches across them, and calls them — each\nprovider kind is handled by a matching *transport*.\n\nRequires Zig `0.16.0`.\n\n## Features\n\n- Provider models and working transports for every UTCP provider kind:\n  `text`, `cli`, `http`, `sse`, `http_stream`, `websocket`, `grpc`, `graphql`,\n  `tcp`, `udp`, `webrtc`, and `mcp`\n- UTCP manual parsing and an in-memory provider/tool repository\n- Tag + description tool search\n- `$VAR` / `${VAR}` substitution from inline variables, dotenv files, or an\n  optional `std.process.Environ`\n- Text template rendering with `{{.name}}` and `{{.Inputs.name}}`\n- Auth helpers: API key (header / query / cookie) and HTTP basic\n\n## Quick start\n\n```zig\nconst std = @import(\"std\");\nconst utcp = @import(\"zig_utcp\");\n\npub fn main() !void {\n    var client = try utcp.Client.init(std.heap.page_allocator, .{});\n    defer client.deinit();\n\n    // Register a provider; the matching transport discovers its tools.\n    try client.registerToolProvider(.{ .text = .{\n        .base = .{ .name = \"greetings\", .provider_type = .text },\n        .templates = \u0026.{.{ .name = \"hello\", .value = \"Hello, {{.name}}!\" }},\n    } });\n\n    // Tools are addressed as \"\u003cprovider\u003e.\u003ctool\u003e\".\n    const result = try client.callToolJson(\"greetings.hello\", \"{\\\"name\\\":\\\"Ada\\\"}\");\n    std.debug.print(\"{s}\\n\", .{result.string}); // Hello, Ada!\n}\n```\n\n`Client` owns its own arena, repository, and one instance of every transport.\n`callTool` takes a parsed `std.json.Value`; `callToolJson` parses a JSON string\nfor you. `searchTools(query, limit)` ranks the combined catalog by tag and\ndescription.\n\n## Using it as a dependency\n\n```sh\nzig fetch --save https://github.com/universal-tool-calling-protocol/zig-utcp/archive/refs/tags/v0.1.1.tar.gz\n```\n\n```zig\n// build.zig\nconst utcp = b.dependency(\"zig_utcp\", .{ .target = target, .optimize = optimize });\nexe.root_module.addImport(\"zig_utcp\", utcp.module(\"zig_utcp\"));\n```\n\n## Transports\n\nEach provider kind maps to a transport under `utcp.transport`. The client\ndispatches automatically, but a transport can also be driven directly\n(`registerToolProvider` to discover tools, `callTool` to invoke one) — see the\nper-transport examples.\n\n| `provider_type` | Transport | Key config fields |\n| --- | --- | --- |\n| `text` | `TextTransport` | `templates` (offline; renders locally) |\n| `cli` | `CliTransport` | `command_name`, `working_dir`, `env_vars` |\n| `http` | `HttpTransport` | `url`, `http_method`, `headers`, `auth`, `body_field` |\n| `sse` | `SseTransport` | `url`, `event_type`, `headers`, `auth` |\n| `http_stream` | `HttpStreamTransport` | `url`, `http_method`, `chunk_size`, `timeout` |\n| `websocket` | `WebSocketTransport` | `url` (`ws://`), `protocol`, `headers`, `auth` |\n| `grpc` | `GrpcTransport` | `host`, `port`, `service_name`, `method_name` |\n| `graphql` | `GraphQLTransport` | `url`, `operation_type`, `operation_name` |\n| `tcp` | `TcpTransport` | `host`, `port`, `timeout` (newline-delimited JSON) |\n| `udp` | `UdpTransport` | `host`, `port`, `timeout` |\n| `webrtc` | `WebRTCTransport` | `signaling_server`, `peer_id`, `data_channel_name` |\n| `mcp` | `McpTransport` | `command` + `args` (stdio) **or** `url` (HTTP) |\n\n`text` runs fully offline. The rest need a matching server reachable at the\nconfigured endpoint.\n\n## Providers from JSON\n\nInstead of building providers in code, load them from JSON — a single provider,\nan array, or a `{ \"providers\": [...] }` wrapper. `$VAR` / `${VAR}` references are\nsubstituted from `variables`, `dotenv_paths`, or `environ`.\n\n```jsonc\n// providers.json\n{\n  \"providers\": [\n    {\n      \"provider_type\": \"text\",\n      \"name\": \"greeter\",\n      \"templates\": { \"welcome\": \"$GREETING {{.name}}, welcome to zig-utcp\" }\n    }\n  ]\n}\n```\n\n```zig\nvar client = try utcp.Client.init(std.heap.page_allocator, .{\n    .providers_file_path = \"providers.json\",\n    .variables = \u0026.{.{ .name = \"GREETING\", .value = \"Hello\" }},\n});\ndefer client.deinit();\nconst result = try client.callToolJson(\"greeter.welcome\", \"{\\\"name\\\":\\\"Ada\\\"}\");\n```\n\n## Examples\n\nThe [`examples/`](examples/) directory has one program per transport plus client\ndemos. Build them all with `zig build examples`, or run one:\n\n```sh\n# High-level client API (offline, runnable as-is)\nzig build run-client        # register providers, search, call a tool\nzig build run-client-file   # load examples/providers.json with $VAR substitution\n\n# Each transport example loads its endpoint/config from examples/*_provider.json.\n# Server-backed examples start a tiny local fixture server before discovery.\nzig build run-text\nzig build run-cli\nzig build run-http\nzig build run-sse\nzig build run-http-stream\nzig build run-graphql\nzig build run-websocket\nzig build run-grpc\nzig build run-tcp\nzig build run-udp\nzig build run-webrtc\nzig build run-mcp\n\n# Parse every bundled provider config and print its transport kind\nzig build run-all\n```\n\n## Build and test\n\n```sh\nzig build test       # run the unit tests\nzig build examples   # compile every example\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiversal-tool-calling-protocol%2Fzig-utcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funiversal-tool-calling-protocol%2Fzig-utcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiversal-tool-calling-protocol%2Fzig-utcp/lists"}