Tools
List the MCP tools this key can reach.
List the MCP tools this key can reach.
GET /v1/tools is the catalogue read: every tool the caller's org and project can reach, from every source, each flagged with whether it is activated. Assert the count is greater than zero and print three names.
This flow named mcp_rpc (POST /v1/mcp, the JSON-RPC door) until the document became the only authority on what exists. That door IS live — POST /v1/mcp answers 200 with the tool list while POST /v1/mcp-zzq9 answers 404, so the address is real and the control refutes nothing — but cloud's emission does not declare it, so it has no operationId and no generated method. An example may not reach for an address the document does not carry: that is a hand-rolled HTTP call inside a generated client, the exact drift these SDKs exist to prevent. POST /v1/mcp returns here the release cloud declares it (LLM.md, "Handed to hanzo-inc/cloud").
Note for whoever writes that declaration: JSON-RPC reports failure INSIDE a 200, so a client reads error before result and result.isError before result.content. The same door with method=tools/call runs one.
Lists every tool the caller's org and project can reach, from every source, each flagged with whether it is activated.
GET /v1/tools · reference →
Lists every tool the caller's org and project can reach, from every source, each flagged with whether it is activated. This is the discovery surface: one flat set of names spanning connector actions, user functions, zap-service routes, agents, skills and the org's own external MCP servers, deduplicated by name so the highest-precedence source wins a collision. It lists; it does not call — dispatch is POST /v1/tools/call.
| Parameter | In | Required | Description |
|---|---|---|---|
source | query | — | Source keeps only tools from one source — connector, function, zap-service, agent, skill or mcp. Empty keeps e |
activated | query | — | Activated keeps only the tools activated for the caller's org and project, and only when it is exactly the str |
hanzo tools getimport { Configuration, ToolsApi } from 'hanzoai';
const api = new ToolsApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getTools();from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import ToolsApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = ToolsApi(client).get_tools()cfg := cloud.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := cloud.NewAPIClient(cfg)
resp, _, err := client.ToolsAPI.GetTools(context.Background()).Execute()
if err != nil {
return err
}use hanzo_cloud::apis::{configuration::Configuration, tools_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = tools_api::get_tools(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.ToolsApi;
ApiClient client = new ApiClient();
client.setRequestInterceptor(b -> b.header("Authorization", "Bearer " + System.getenv("HANZO_API_KEY")));
var result = new ToolsApi(client).getTools();curl https://api.hanzo.ai/v1/tools \
-H "Authorization: Bearer $HANZO_API_KEY"The door reaches tools through the tools tool, which names its 19 operations with its own verbs — this one among them, under a name only the door declares. describe explains any of them:
curl -X POST https://api.hanzo.ai/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "describe",
"arguments": {
"op": "list_mcp_servers"
}
}
}'Every command, call and tool above is generated from the same OpenAPI document that generates the SDKs themselves — the four surfaces are projections of one doc comment, so they cannot disagree.
How is this guide?