Hanzo

Tools

Package tools is everything your org can call, in one list: connector actions, functions, agents, skills and your own MCP servers.

Package tools is everything your org can call, in one list: connector actions, functions, agents, skills and your own MCP servers.

Base URLhttps://api.hanzo.ai
Operations19
AuthAuthorization: Bearer $HANZO_API_KEY

Specification

HIP-1213 · Tools — The Tool Plane — Draft · read the specification →

/v1/tools is the one registry of everything an org can call: each entry is a Tool with a Source, a JSON-Schema, a per-(org, project) activation state and an optional price. Cloud's own typed operations are not here — they are code, projected onto the fleet's MCP door (HIP-0300); what lives here is rows (apps/tools/LLM.md:1-9). It is implemented in hanzoai/cloud at apps/tools, and this HIP states the surface under which its skills, plugins and external-MCP-server views answer.

Motivation

The plane's views grew their own roots — /v1/skills, /v1/plugins, /v1/mcp/servers — and the last of these left the /v1/mcp root answered by two apps, the host's agent door and this one's server collection. The store decides all three (HIP-0139 §7): every row behind those roots is tools' own, so each view folds home rather than splitting into an app that would share this one's store.

Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as in RFC 2119.

The surface

Every address is under /v1/tools: the registry reads and dispatch at the root, then three views that are the same rows narrowed. /v1/tools/skills is the registry narrowed to one source, not a second store (apps/tools/zipdoc_gen.go:70), and skill activation is a tools row. /v1/tools/plugins lists this deployment's mounted subsystems and the org's authored plugins, and POST /v1/tools/plugins/build builds one (apps/tools/tools.go:43); the build route is the plane's one untyped operation, declared with its bodies and its prose because its 422 carries diagnostics outside the declared success shape (apps/tools/tools.go:44-71). /v1/tools/mcp/servers is the org's registered external MCP servers — the one way an org gains a server, by url or by picked listing, both writing the same row (apps/tools/external_mcp.go). Every other operation is typed.

Today's router serves the three views at /v1/skills, /v1/plugins and /v1/mcp/servers (manifest/apps.go:429); each pair is a line in hanzoai/cloud openapi/misfiled.txt until the fold lands, and the last fold vacates /v1/mcp entirely to the host's agent door. The skills app keeps only /.well-known/agent-skills discovery and the plugins app only /v1/admin/plugins, both exempt by HIP-0139 §3.2.

The store

The capability owns the tools-* system SQLite set — catalog, activation, plugins, skills, mcp — each opened only by this package (apps/tools/catalog.go:171, activation.go:41, pluginstore.go:50, skillstore.go:57, external_mcp.go:87). Sources register their own Provider from their own Mount (apps/tools/registry.go:75), so this package never learns how another source lists or runs its tools; what it owns is the rows and the door.

Tenancy

Every write and dispatch resolves the caller's org from the validated principal; activation is keyed (org, project), and an authored plugin is stored under the authoring principal's org. External-server credentials live in KMS under the org's custody, never in the row.

Money

A tools-plane dispatch is metered per call: CLOUD_TOOLS_FEE_CENTS prices the unit per deployment, zero making it free, attributed under kind call (apps/tools/tools.go:83-84, plugin/tools/main.go:22). A marketplace-priced call is offered — free ones included, so the gate and the settlement read one table — to the x402 rail over the internal plane; what a call costs, who is paid and whether a signature verifies stay entirely on the rail's side (apps/tools/charge_peer.go:16-33).

Events and observability

It publishes no events on the tenant bus, so a customer's webhooks receive nothing from it. Beyond the request span, every dispatch appends an audit record — actor, resource, auth context, outcome — through the shared recorder (apps/tools/http.go:704-715).

Stage

ga. The manifest row carries no stage field, which is ga by HIP-0139 §8.

Upstreams

Two OSS libraries are embedded on the authored-plugin build path: evanw/esbuild (MIT) bundles the source to one CommonJS program and dop251/goja (MIT) is the runtime that compiles — and later executes — it (apps/tools/pluginbuild.go:24-26). The catalog mirrors the public MCP registry's listings (registry.modelcontextprotocol.io) as data, replaced wholesale on sync with local curation held in columns the sync cannot touch (apps/tools/LLM.md:11-32). Nothing else derives from an OSS upstream.

Rationale

The tempting resolution was a split: a skills app for /v1/skills, this one for the rest. But skill activation lives in tools-activation, so the split puts two apps on one store — the defect HIP-0139 §7.2 refuses — and buys a name for a view that is one WHERE clause. The store decides, and it decides fold, three times.

Security Considerations

A tool dispatch is credentialed execution on a caller's behalf, so the wrong implementation hands one org's credentials or activations to another. The guards: credentials are KMS refs read at run time, never fields of a plugin or a row; source that contains something shaped like a key is refused rather than scrubbed; and a plugin in the store is one this deployment has already compiled and loaded once — the build pipeline is the gate, so a model's claim that code is fine never substitutes for the runtime accepting it (apps/tools/tools.go:53-60). Deregistering a server destroys its credential material even though the KMS interface lacks delete: the ref is overwritten empty, which is the half that matters for rotation (apps/tools/LLM.md:48-58).

Four surfaces

SurfaceReaches this capability asCoverage
RESTtools at its own prefix19 operations
CLIhanzo tools …8 of 19 — the CLI pins the document on its own clock
SDKToolsApi in every published client8 of 19 — the clients are generated at their own release
MCPtool tools on https://api.hanzo.ai/v1/mcp19 operations, 2 under the document's own id — ask describe for the rest

Quickstart

export HANZO_API_KEY=sk-...   # console.hanzo.ai → API keys

Then the first call — a read that needs nothing but the key. GET /v1/tools, operation get_tools:

hanzo tools get

Answers 200 with object — ok.

Endpoints

EndpointWhat it does
GET /v1/tools/activationReports which tools are switched on for the caller's org and project.
PUT /v1/tools/activationSwitches tools on and off for the caller's org and project, and answers with the resulting activated set.
POST /v1/tools/callRuns one of the caller's activated tools and answers with its output.
GET /v1/tools/catalog/{id}Returns one catalog entry in full: the publisher's description, its repository and site, every package form with the runtime that launches it, and…
PATCH /v1/tools/catalog/{id}Sets what WE say about one catalog entry — hidden, featured, official, logo — and answers with the stored listing.
POST /v1/tools/catalog/syncPulls the public MCP registry into our canonical copy and reports what changed.
GET /v1/tools/catalogLists the MCP servers the public registries publish, as we hold them: our canonical copy of registry.modelcontextprotocol.io, plus what we decided…
DELETE /v1/tools/mcp/servers/{id}Deregisters one of the caller org's external MCP servers, so its tools leave the registry.
GET /v1/tools/mcp/serversLists the external MCP servers the caller's org has registered.
POST /v1/tools/mcp/serversGives the caller's org one more external MCP server, so its tools join the org's tool plane and the fleet's MCP door.
DELETE /v1/tools/plugins/authored/{id}Removes one of the caller org's built plugins, so the runtime can no longer load it.
GET /v1/tools/plugins/authoredLists the plugins the caller's org BUILT, newest first, each with the TypeScript as authored.
POST /v1/tools/plugins/buildBuilds and stores one plugin for the caller's org.
GET /v1/tools/pluginsReports what this deployment actually mounted: every subsystem the composition root declared and whether it is switched on.
DELETE /v1/tools/skills/{id}Removes one of the caller org's authored skills.
GET /v1/tools/skills/authoredLists the caller org's OWN skills with their SKILL.md bodies.
GET /v1/tools/skillsLists the skills the caller's org can reach — the brand's embedded catalogue plus the org's own authored ones — with each one's activation flag.
POST /v1/tools/skillsAdds or revises one of the caller org's own skills, and answers 201 with the stored record.
GET /v1/toolsLists every tool the caller's org and project can reach, from every source, each flagged with whether it is activated.

All Hanzo APIs · Interactive reference

How is this guide?

On this page