MCP Tools
Four tools over the hosted MCP transport, mirrored as HTTP endpoints. The local stdio server (zcouncil mcp) renames run_script → exec and routes it to a local Node runtime; everything else is identical.
Tools
run — hosted council, plain string in
Server wraps the input as return council.run(input), runs it in the cloud sandbox, and returns the orchestrator's synthesized answer plus per-member outputs.
ask — one member, no orchestration
Skips the orchestrator. Returns { memberId, name, text }.
members — discovery
Returns { members: [{ memberId, name, routedModel, bridgeModel? }] }.
run_script — raw JavaScript (hosted code mode)
The power-user escape hatch. Same Cloudflare WorkerLoader sandbox the orchestrator uses internally.
Available script globals are listed in code mode. The script's return value gets synthesized into the orchestrator's final answer for run_script callers; programmatic clients that want the raw return value should use the HTTP /v1/exec endpoint or the local stdio server's exec tool, both of which skip the synthesis pass.
The sandbox has no filesystem, secrets, outbound network, imports, eval, Function, or globalThis access. Real model calls, visible intermediate streaming, and final synthesis are owned by the worker host.
Local stdio server
zcouncil mcp (see CLI) exposes run / ask / members identically, but replaces run_script with exec:
exec runs in the user's Node process. Trust tier is "the user's own terminal" — fs, child_process, fetch, and user modules are available. orchestrator.checkpoint is unavailable here (it needs the trusted orchestrator that only exists cloud-side); use the hosted server for scripts that need it.
HTTP endpoints
Every MCP tool has an equivalent HTTP endpoint. Same auth header (Authorization: Bearer YOUR_TOKEN), same input shape, JSON response with { ok, data } or { ok: false, error }.
/v1/attachments takes raw file bytes in the body — set Content-Type to the file's actual media type (image/png, image/jpeg, application/pdf, etc.) and Content-Length to the size in bytes; the optional X-Filename header preserves the original name. The returned uploadId is what you pass as attachments[].uploadId to /v1/run, /v1/ask, or /v1/exec.
/v1/run also supports SSE streaming when the client sets Accept: text/event-stream. See the CLI source for the canonical consumer.
Errors
401— bad or missing token. Create a fresh API token.-32602— invalid arguments. The error'sdatafield shows the failing path.-32601— unknown tool name.429— usage gating exceeded for the token's tier.
Transport
Hosted MCP at https://api.zcouncil.com/mcp is stateless POST-only JSON-RPC 2.0 — no sessions, no batching, no SSE. GET /mcp and DELETE /mcp return 405.
Local stdio (zcouncil mcp) speaks newline-delimited JSON-RPC 2.0 on stdin/stdout (no LSP-style framing).
{ "name": "run", "arguments": { "input": "Review this architecture and recommend next steps." }}{ "name": "ask", "arguments": { "memberId": "anthropic_claude_opus_4_7", "input": "Deeply critique this migration plan..." }}{ "name": "members", "arguments": {} }{ "name": "run_script", "arguments": { "code": "const input = `Should we move this worker to a DO?`;\nconst [arch, rollout] = await Promise.all([\n council.ask('anthropic_claude_opus_4_7', input),\n council.ask('openai_gpt_5_4_mini', input)\n]);\nreturn { arch, rollout };" }}{ "name": "exec", "arguments": { "code": "..." } }