zeekay ca6c1b8f65 kai_command_guard: allow only known workspace work, ask for the rest
The guard allowed anything its few patterns missed whenever Kai's choice said
allow, and kai-1.2 reads command risk near chance: on hermes-jev-skills' 118
gate fixtures (MIT) it allowed 12 of the 65 commands that must be denied or
asked (rm -rf ~/Documents, chmod -R 777 ~, base64 -d | sh) and asked or
denied 33 of the 53 ordinary ones.

Now deny and ask are classes matched on the whole line (wipe, pipe_shell,
exfiltrate, secret_read, permissions, clobber, disk, metadata, drop_data,
claimed_approval; git_remote, git_discard, publish, deploy, service,
message, privilege, global_install, sync_delete, persistence, environment,
parent_path), and allow needs every part of the line to be inspection, a
build or test, local git, or a file change under a relative path or /tmp.
Anything else asks. The caller's policy is a floor. No Kai request: its
risk questions changed no outcome on the fixtures but one more ask.

Frozen and read once on the fixtures: 1 of 65 allowed, 18 of 53 asked.
Two classes were fixed after that read and are not held out: the
metadata-endpoint fetch (the one allowed command) and a bare `rm -rf /`,
which asked where it must deny. With them: 0 of 65 allowed.
2026-10-14 18:30:09 -07:00
2026-09-08 23:53:37 -07:00
2026-09-01 09:42:54 -07:00
2026-02-14 05:26:48 -08:00
2026-09-01 09:42:54 -07:00

Hanzo MCP

@hanzo/mcp

An MCP server for coding agents: files, shell, code, git, HTTP, project context and UI components, plus tools that call the Hanzo API. It speaks MCP over stdio, or over streamable HTTP with --transport http.

npm

Register it with an agent

The package declares Node 18 or newer. For Claude Code:

claude mcp add hanzo -- npx -y @hanzo/mcp serve

npx -y @hanzo/mcp install --claude-code runs that command with --scope user, which registers the server for every project.

claude mcp list then reports hanzo: npx -y @hanzo/mcp serve - ✔ Connected. With --scope project the entry goes into the project's .mcp.json instead, and Claude Code asks before it starts a server from that file. Other MCP clients take the same command in their server config:

{
  "mcpServers": {
    "hanzo": {
      "command": "npx",
      "args": ["-y", "@hanzo/mcp", "serve"]
    }
  }
}

The first start downloads the package; with an empty npm cache that took 80 to 100 seconds.

Tools

serve with no flags offers these, in the groups src/tools/unified/index.ts defines:

group tools
core fs, exec, code, git, fetch, workspace, ui
optional think, memory, hanzo, plan, tasks, mode, gimp
code intelligence code_search, code_context, code_ask, code_index
tracker tracker_boards, tracker_issues, tracker_create, tracker_update
kai kai_decide, kai_choice, kai_score, kai_noul, kai_tool_select, kai_next_action, kai_command_guard, kai_injection_screen, kai_extract, kai_log_triage, kai_recover, kai_agent_step

The core and optional tools take an action argument that picks the operation; ui takes method. The code intelligence, tracker and kai tools call https://api.hanzo.ai with the key in HANZO_API_KEY, or a local Kai instance via LOCAL_KAI_URL (e.g. http://127.0.0.1:18977).

The kai tools ask Kai, Hanzo's decision model, typed questions about a case (POST /v1/decisions) and answer with calibrated probabilities: kai_choice picks a label, kai_score an ordinal level, kai_noul the probability that a statement holds, and kai_decide asks up to 100 of them in one call.

Beside the general decision primitives, 8 purpose-built native MCP tools provide fast-path zero-inference execution and targeted decision capabilities:

  • kai_tool_select: Shortlist tools from registered schemas and resolve client naming differences (e.g. bash → Bash).
  • kai_next_action: Recommend an executable next Action (type, target, payload) or calibrately abstain.
  • kai_command_guard: Shell command safety policy enforcement on monotonic lattice allow < ask < deny.
  • kai_injection_screen: Screen untrusted inputs or PR comments for prompt-injection / instruction overrides.
  • kai_log_triage: Classify compiler and test failures and pinpoint exact error spans.
  • kai_recover: Loop breaker and strategy recovery engine from failure fingerprints.
  • kai_extract: Typed discrete entity extraction across structured dimensions.
  • kai_decide: Joint multi-question evaluation in a single model forward pass.

See the Kai Cookbook for 15 runnable recipes and benchmarks across Claude Code, Cursor, Codex, and Hanzo Dev. instructions is optional on every question and recommended. A kai_choice call:

{ "state": "I was charged twice for my March invoice. Please refund the duplicate.",
  "instructions": "Which team should handle this ticket?",
  "criteria": { "billing": "charges, invoices and refunds", "product": "how to use the product" } }

hanzo reaches every Hanzo Cloud subsystem: resource names one, action one of its operations, args that operation's arguments. With no action it lists the resource's operations, and resource: "describe" with args: {subsystem, op} says what one takes. The list is generated from cloud's catalog.

{ "resource": "graph", "action": "graphResolve",
  "args": { "entity": "acme/svc/api", "relation": "owner", "as_of": "2026-09-01T00:00:00Z" } }

Flags on serve change the set:

flag effect
--disable-tools plan,tasks removes the named tools
--core-only only the core group
--enable-ui adds the ui_* component tools
--enable-desktop adds hanzo_desktop and playwright_control
--enable-autogui, --enable-orchestration, --enable-ui-registry, --enable-github-ui, --enable-community-cryptuon add those tool sets
--full-surface adds the UI, AutoGUI, orchestration, UI registry and GitHub UI sets together

npx -y @hanzo/mcp serve --help lists every flag. This prints the tool names a server offers; put any flags after serve:

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| npx -y @hanzo/mcp serve 2>/dev/null \
| node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{for(const l of s.split("\n"))if(l.includes("\"id\":2"))console.log(JSON.parse(l).result.tools.map(t=>t.name).join(" "))})'

Over HTTP

npx -y @hanzo/mcp serve --transport http --port 3000

The endpoint is the root path, http://127.0.0.1:3000/. POST JSON-RPC to it with Accept: application/json, text/event-stream; answers come back as server-sent events.

When a client shows no tools

Start the server by hand. A working one answers initialize with its name and version:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
  | npx -y @hanzo/mcp serve

With HANZO_MCP_DEBUG=1 in the server's environment, stderr also shows its working directory, the resolved binary, its arguments and the start of PATH.

Python

hanzo-mcp on PyPI is a separate server, built from hanzoai/python-sdk.

Development

pnpm install
pnpm build
pnpm smoke    # runs dist/cli.js over stdio: initialize, tools/call, resources

License

MIT

S
Description
Model Context Protocol server with 260+ tools for AI agents
Readme MIT
435 MiB
Languages
Rust 57.4%
TypeScript 37.7%
JavaScript 2.8%
Python 0.9%
Go 0.9%