/api/tools*) are the UI-facing half of the broker’s dual surface: list the builtin tools with their availability verdict, read the pending tool-approval queue, resolve an approval, and read the forensic audit log. The MCP routes (/api/mcp/*) are the in-process Streamable-HTTP transport for Clawboo’s four MCP servers (tasks, memory, tools, teamchat), the same SQLite-backed servers an external runtime attaches to, plus a per-runtime attach-config snippet endpoint.
The MCP routes are not request/response in the usual sense. They speak the Model Context Protocol over Streamable HTTP: a per-session JSON-RPC channel keyed by the
mcp-session-id header. They are documented below with the transport mechanics + status codes, not a JSON response shape. The tools and their input schemas served over these channels are in MCP tools reference.express.json({ limit: '2mb' }). Error responses on the /api/tools* routes are masked at the rendering boundary by redactValue / redactJsonString (defense-in-depth over the write-time secret scrub).
Routes
GET /api/tools
Lists every builtin tool with a server-evaluated availability verdict. The availability is computed against the current process env (defaultAvailabilityContext()), so a tool that requires an unconfigured provider reads available: false with a diagnostics list explaining why; the UI greys it out and the model’s tools/list omits it. The four builtins are echo and note (safe), web_search (external, hidden until a search provider is configured), and delete_path (destructive).
- Path/query params: none.
- Request body: none.
Responses
200 OK: the tool list with availability:
500 Internal Server Error: any failure building the registry or evaluating availability:
Example
GET /api/tools/approvals
Returns the pending tool-approval queue, the tool_call_approvals rows with status = 'pending' that have not passed their expiresAt, newest first. Each row’s argsSummary (scrubbed JSON written by the broker) is masked again at this boundary via redactJsonString. This is the queue the Approvals panel and the Governance dashboard render through the shared tool-approval queue UI; the broker (in either the Express process or an MCP stdio bin) polls the same rows for resolution.
- Path/query params: none.
- Request body: none.
Responses
200 OK: the pending approvals:
500 Internal Server Error:
Example
POST /api/tools/approvals/:id/resolve
Resolves a still-pending approval. The decision is validated by a Zod schema; an unknown decision returns 400. The UPDATE is guarded status = 'pending', so resolving an already-resolved (or expired-but-still-present) row is a no-op UPDATE; but the handler still returns 200 with the existing row unchanged, because resolveApproval returns getApproval(db, id), which has no status or expiry filter and is truthy for any row that exists. The 404 (approval not found) fires only when no row with that id exists at all. A blocking broker waiter sees the new status on its next poll.
- Path params:
id(approval id). - Request body: validated by
resolveApprovalBody:
Responses
400 Bad Request: the body fails Zod validation (missing/invalid decision):
404 Not Found: no row with that id exists at all (getApproval returns nothing):
200 OK: the approval was resolved; the updated row is returned:
The response
approval.argsSummary here is the stored (scrubbed-at-write) value; unlike GET /api/tools/approvals, the resolve response is not re-masked at the boundary.500 Internal Server Error:
Example
GET /api/tools/audit
Returns the append-only tool-call audit log (before + after phases), newest first. Both argsSummary and resultSummary are masked at this boundary with redactJsonString. The default page size is 100 rows.
- Query params:
- Request body: none.
Responses
200 OK: the audit rows:
500 Internal Server Error:
Example
MCP transport: /api/mcp/{tasks,memory,tools,teamchat}
These four route groups are the in-process Streamable HTTP transport for Clawboo’s MCP servers. The API server hosts and supervises the servers in-process; HTTP-capable runtimes (and the live smoke) attach over these paths. They are NOT a Clawboo-defined request/response API; they speak MCP’s JSON-RPC over Streamable HTTP, with a stateful session per connection keyed by the mcp-session-id header.
Each server name maps to a (POST, GET, DELETE) trio:
The session lifecycle is enforced by the transport, not by Clawboo handlers:
- A
POSTwith no session id that is not aninitializerequest → JSON-RPC error, HTTP 400 ("No valid session; send an initialize request first."). - A
POSTwith a session id that has no live transport → same 400. - A
GET/DELETEwith a missing or unknown session id → JSON-RPC error, HTTP 400 ("Invalid or missing MCP session id."). - A handler-level throw before headers are sent → HTTP 500
{ error: "<message>" }.
initialize request) and reused for that session’s subsequent requests; closing the transport drops it from the session map.
Per-server session binding (scoping query params)
Thememory and teamchat POST handlers read authoritative binding from the attach URL’s query string at session-initialize time. This is how Clawboo binds a run’s MCP session to its team/agent; the model can neither widen its visibility nor spoof its identity through tool arguments, because the URL is Clawboo-written config. The other two servers (tasks, tools) take no scoping params.
Memory: visibility scope (parseBoundScope):
When none are present the memory session is unbound (legacy model-arg behavior, used by the raw stdio bin / external attach).
TeamChat: room + author identity (anti-spoof) (
parseTeamChatBinding):
Both
roomTeamId and postAuthorAgentId are required for a bound TeamChat session; if either is missing the session is unbound and identity falls back to tool args. A bound TeamChat server also emits a team_chat_post orchestration event into the observability log on every post.
Event stream
The MCP servers’ SSE channel (theGET route) carries Model Context Protocol JSON-RPC notifications and streamed tool results, not Clawboo-shaped events. The tools each server exposes: list_tasks / create_task / claim_task / add_comment (tasks), memory_save / memory_search / memory_browse (memory), the brokered tool set (tools), and team_chat_post / team_chat_subscribe (teamchat), and their Zod input shapes are catalogued in the MCP tools reference.
Example (raw initialize handshake)
GET /api/mcp/config to get the attach snippet for your runtime.
GET /api/mcp/config
Emits a copy-pasteable attach snippet so the consuming runtime can register one of Clawboo’s MCP servers. Clawboo “hosts” the connection setup; the snippet differs per runtime and transport. The HTTP base URL is built from the server’s own bound loopback port (loopbackMcpBaseUrl(req), reading req.app.locals.apiPort set at boot), never the client Host header, since a forged Host could otherwise redirect a runtime’s MCP traffic. It falls back to http://127.0.0.1:<CLAWBOO_API_PORT or 18790>. For the stdio transport the bin path uses CLAWBOO_MCP_BIN_DIR.
- Query params:
- Request body: none.
Responses
400 Bad Request: server is not one of the four known MCP server names:
200 OK: the attach config for the requested runtime/server/transport:
snippet/structured shape branches on runtime and transport; for example claude-code + http yields claude mcp add --transport http clawboo-<server> <url>, while codex + stdio yields a [mcp_servers.clawboo-<server>] TOML block. For openclaw, the snippet targets the top-level mcp.servers key with transport: "streamable-http".
500 Internal Server Error:
Example
Error envelope
Every error response on these routes is the standard envelope{ error: string }. On the /api/tools* routes the error string (and, where present, the response body’s JSON-string summaries) is masked through redactValue / redactJsonString so credential-shaped values never leak into a response. The MCP transport’s protocol-level errors (bad/missing session) are JSON-RPC error objects ({ jsonrpc: "2.0", error: { code: -32000, message } }) at HTTP 400; a handler throw before headers are sent is the plain { error } envelope at 500.
See also
- MCP tools reference, the 4 servers, their tools, and Zod input shapes
- Operating: MCP servers as teammates, attach config, transports, scoping in practice
- Memory API, the UI-facing memory REST surface over the same store
- Governance API, budgets, delegation-approval, and the shared approval queue
- Capabilities API, the unified capability inventory that surfaces broker tools
- Runtimes API, a
:id/runattaches to these/api/mcp/*endpoints - REST API overview