Files
zeekay 7374804405 hanzo-mcp 0.15.21: the active mode is the whole manifest, and a flood of output has a ceiling
The default surface was 34 tools, 61 KB, ~15,300 tokens of schema in every
prompt of every agent. The mode system already names what a session should
carry, but only the tools register_all_tools enumerates obeyed it: zsh,
curl, playwright and the helpers (ps, npx, uvx, jq, wget, cdp, open) stayed
on in every mode. A mode now decides every discovered tool, the `hanzo`
mode lists what a coding agent calls every few steps (18 tools, 32 KB,
~8,000 tokens), and the rest is a name away: HANZO_MCP_ENABLED_TOOLS=a,b
or =all, `tool enable`, or `mode`.

hanzo-tools-shell 0.6.6: run_shell kept every byte a foreground command
wrote until the command ended. `yes` for thirty seconds is gigabytes. It
keeps the first 16 MiB per stream and drains the rest.

The tests' session-wide patch of asyncio.create_subprocess_exec handed
every shell command a stream that never reached EOF; the first test to run
one read it in a loop until the machine was out of memory (22 GB, killed).
The patch is now opt-in and its process has exited.

bench/latency.py measures the cold start, the tools/list bill and the common
calls through a real MCP client over stdio. Interleaved rounds, wall and CPU
seconds, p50 over 6 cold starts:

                         cold wall  cold CPU  tools  bytes   ~tokens
  installed 0.15.18      9.34 s     10.46 s   30     52,601  13,150
  main 0.15.20           1.52 s      1.13 s   34     61,287  15,321
  this                   0.96 s      1.06 s   18     32,222   8,055

The installed environment's 9 s is its hanzoai 8.5.156, whose package init
imports the whole generated cloud client; hanzo-mcp >= 0.15.20 requires
hanzoai >= 8.5.624, which loads it lazily. Per-call latency is spawn-bound
(zsh 17.6 ms, git status 33 ms, fs.read 2.5 ms at p50) and moves with the
machine's load; no call path changed.
2026-10-12 08:47:57 -07:00

130 lines
4.0 KiB
Python

"""Tool mode loader for dynamic tool configuration."""
import os
from typing import Dict, Optional, Set
from hanzo_mcp.tools.common.mode import (
ModeRegistry,
activate_mode_from_env,
register_default_modes,
)
# Essential system tools that are ALWAYS enabled regardless of mode
# These are core infrastructure tools that should never be disabled
# NOTE: llm and consensus are NOT essential (heavy llm dependency)
ESSENTIAL_SYSTEM_TOOLS: Set[str] = {
"mode", # Mode switching: the way to a wider surface
"tool", # Unified tool management (install, enable, disable, list)
"version", # Version info
"stats", # Statistics
}
# Heavy tools that are disabled by default (opt-in)
# These require large dependencies like llm
HEAVY_TOOLS: Set[str] = {
"consensus", # Requires llm
}
class ModeLoader:
"""Loads and manages tool modes for dynamic configuration."""
@staticmethod
def initialize_modes() -> None:
"""Initialize the mode system with defaults."""
# Initialize modes
register_default_modes()
# Check for mode from environment
activate_mode_from_env()
# If no mode set, use default
if not ModeRegistry.get_active():
default_mode = os.environ.get("HANZO_DEFAULT_MODE", "hanzo")
if ModeRegistry.get(default_mode):
ModeRegistry.set_active(default_mode)
@staticmethod
def get_enabled_tools_from_mode(
base_enabled_tools: Optional[Dict[str, bool]] = None,
force_mode: Optional[str] = None,
) -> Dict[str, bool]:
"""Get enabled tools configuration from active mode.
Args:
base_enabled_tools: Base configuration to merge with
force_mode: Force a specific mode (overrides active)
Returns:
Dictionary of tool enable states
"""
# Initialize if needed
if not ModeRegistry.list():
ModeLoader.initialize_modes()
# Get mode to use
tools_list = None
if force_mode:
# Set and get mode
if ModeRegistry.get(force_mode):
ModeRegistry.set_active(force_mode)
mode = ModeRegistry.get_active()
tools_list = mode.tools if mode else None
else:
# Check active mode
mode = ModeRegistry.get_active()
if mode:
tools_list = mode.tools
if not tools_list:
# No active mode, return base config
return base_enabled_tools or {}
# Start with base configuration
result = base_enabled_tools.copy() if base_enabled_tools else {}
# Get all possible tools from registry
from hanzo_mcp.config.tool_config import TOOL_REGISTRY
all_possible_tools = set(TOOL_REGISTRY.keys())
# Disable all tools first (clean slate for mode)
# EXCEPT essential system tools which are always enabled
for tool in all_possible_tools:
if tool in ESSENTIAL_SYSTEM_TOOLS:
result[tool] = True # Essential tools always enabled
else:
result[tool] = False
# Enable tools from mode
for tool in tools_list:
result[tool] = True
# Ensure all essential system tools are enabled (in case mode tried to disable them)
for tool in ESSENTIAL_SYSTEM_TOOLS:
result[tool] = True
return result
@staticmethod
def get_environment_from_mode() -> Dict[str, str]:
"""Get environment variables from active mode.
Returns:
Dictionary of environment variables
"""
# Check mode
mode = ModeRegistry.get_active()
if mode and mode.environment:
return mode.environment.copy()
return {}
@staticmethod
def apply_environment_from_mode() -> None:
"""Apply environment variables from active mode."""
env_vars = ModeLoader.get_environment_from_mode()
for key, value in env_vars.items():
os.environ[key] = value