Each hanzo-mcp now hosts a ZAP server directly on the lowest free port from [9999..9995], using a POSIX flock for cross-MCP arbitration. The browser extension discovers and connects to this server without any node-side bridge in the critical path. - New hanzo_tools/browser/zap_server.py: wire format, server, lifecycle, client registry, leases, cluster-visibility config registry. - _extension_command tries ZAP first (sub-1ms median round-trip on loopback), falls back to legacy HTTP bridge on :9224 only when no ZAP-connected client matches. Pinnable via BROWSER_TRANSPORT. - New tool actions: list_mcp_instances, claim_browser, release_browser for sub-agent coordination across multiple parallel MCPs. - Legacy CDP HTTP bridge no longer auto-starts (opt in with HANZO_CDP_BRIDGE_ENABLED=1). It remains available for non-ZAP MCP clients. Tests: 30 new unit tests cover wire format, port arbitration, multi-MCP coexistence, lease semantics, and cluster registry. Bench shows 0.35ms median round-trip on local loopback. Total tests: 4 baseline -> 35 passing (30 zap_server + 1 bench + 4 imports).
5.7 KiB
LLM.md - Hanzo Python SDK
Quick Start
uv sync --all-packages
uv run python -c "from hanzoai import __version__; print(__version__)"
Packages
Core (Workspace Members)
| Package | Import | Description |
|---|---|---|
| hanzoai | import hanzoai |
Official Hanzo API client |
| hanzo-mcp | import hanzo_mcp |
MCP server with 39 tools |
| hanzo-memory | import hanzo_memory |
Memory service with SQLite/vector |
| hanzo-repl | import hanzo_repl |
Interactive REPL |
| hanzo-agent | import hanzo_agent |
Agent framework |
Tool Packages (Entry Points)
All tools discovered via [project.entry-points."hanzo.tools"]:
hanzo-tools-shell- zsh, ps, open, npx, uvxhanzo-tools-browser- Playwright automationhanzo-tools-fs- read, write, edit, tree, find, search, asthanzo-tools-memory- Unified memory toolhanzo-tools-reasoning- think, critichanzo-tools-agent- CLI agent runner, iching, reviewhanzo-tools-api- Generic REST API via OpenAPIhanzo-tools-lsp- Language server protocolhanzo-tools-refactor- AST-based refactoringhanzo-tools-llm- LLM calls, consensus
Architecture
hanzo-mcp (thin wrapper)
└── discovers tools via entry points from hanzo-tools-* packages
hanzo-tools-*
└── each exports TOOLS list via entry point
Entry Point Pattern:
[project.entry-points."hanzo.tools"]
shell = "hanzo_tools.shell:TOOLS"
Key Patterns
Tool Registration
class MyTool(BaseTool):
name = "my_tool"
@property
def description(self) -> str:
return "Tool description"
async def call(self, ctx, **params) -> str:
pass
Async (Non-blocking)
# Use asyncio subprocess
proc = await asyncio.create_subprocess_exec(*cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=30)
# Use aiofiles for file I/O
async with aiofiles.open(path) as f:
content = await f.read()
Auto-backgrounding
Commands auto-background after 45s. Use ps tool to monitor.
Memory System
SQLite-based with optional vector search (sqlite-vec).
~/.hanzo/
├── memory/ # Global markdown files
└── db/
└── global.db # SQLite with FTS5
/project/.hanzo/
├── memory/ # Project memories
└── db/
└── memory.db # Project database
Backends: local (default), sqlite, lancedb (optional), kuzudb (optional)
Browser Tool (hanzo-tools-browser)
Two-process architecture (since 0.5.0): hanzo-tools-browser hosts the
ZAP server directly inside the MCP process. Browser extensions discover
it on the lowest free port from [9999, 9998, 9997, 9996, 9995] (POSIX
flock ensures multi-MCP coexistence under one ext).
from hanzo_tools.browser import (
BrowserTool, # the MCP tool
ZapServer, # raw server (for advanced use)
get_or_start_server, # bootstrap + return singleton
get_server, # return current singleton or None
)
Key files:
hanzo_tools/browser/zap_server.py— wire format, server, leases, cluster registry (~/.hanzo/extension/config.json:mcp_instances).hanzo_tools/browser/browser_tool.py—_extension_commandtries ZAP first, falls back to legacy HTTP bridge on:9224. New actionslist_mcp_instances,claim_browser,release_browser.hanzo_tools/browser/cdp_bridge_server.py— legacy node-bridge replacement (kept for non-ZAP callers).
Env vars:
BROWSER_TRANSPORT=zap|http|auto— pin transport (default auto).HANZO_ZAP_DISABLED=1— don't auto-start the ZAP server.HANZO_ZAP_PORTS=9999,9998— override the candidate port list.HANZO_AGENT_LABEL=...— attach to the cluster registry entry.HANZO_CDP_BRIDGE_ENABLED=1— opt back into the legacy HTTP bridge.
Tests live in pkg/hanzo-tools-browser/tests/test_zap_server.py (30
cases: wire format, lifecycle, RPC, leases, multi-MCP). Latency bench
in test_zap_bench.py. The full suite runs with:
cd pkg/hanzo-tools-browser
uv venv .venv --python 3.12
.venv/bin/python -m pip install -e .
.venv/bin/python -m pytest tests/ -v
API Tool
Generic REST API tool with OpenAPI specs.
api(action="list") # List providers
api(action="config", provider="github", api_key="x") # Configure
api(action="call", provider="github", operation="listRepos")
Auto-detects: GITHUB_TOKEN, CLOUDFLARE_API_TOKEN, OPENAI_API_KEY, etc.
Hanzo API Providers
All Hanzo services have unified OpenAPI specs at /Users/z/work/hanzo/openapi/:
| Provider | Service | Base URL | Spec |
|---|---|---|---|
hanzo |
Unified API | api.hanzo.ai | hanzo.yaml |
hanzo-iam |
Identity/Auth | iam.hanzo.ai | iam/openapi.yaml |
hanzo-gateway |
LLM Gateway | gateway.hanzo.ai | gateway/openapi.yaml |
hanzo-commerce |
E-commerce | api.hanzo.ai/v1 | commerce/openapi.yaml |
hanzo-vector |
Vector DB | vector.hanzo.ai | vector/openapi.yaml |
hanzo-cloud |
AI Platform | cloud.hanzo.ai | cloud/openapi.yaml |
hanzo-nexus |
RAG/Knowledge | nexus.hanzo.ai | nexus/openapi.yaml |
# Example: Call IAM API
api(action="spec", provider="hanzo-iam")
api(action="ops", provider="hanzo-iam", search="user")
api(action="call", provider="hanzo-iam", operation="getUser", params='{"id": "admin/user1"}')
Testing
uv run pytest tests/ -v
uv run python -c "from hanzoai import __version__; print(__version__)"
Common Issues
Import error: Run uv sync --all-packages
Missing tool: Check entry point in package's pyproject.toml
Backend not available: Install optional deps (lancedb, kuzu, sqlite-vec)