mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-27 04:20:09 +00:00
Nine per-service packages registered a hanzo.tools entry point and sat in hanzo-mcp's default dependencies, so installing it put them in a model's tool list beside the unified tool and without its filter. hanzo-tools-kms offered inject, which lists a path and reads every secret at it. hanzo-tools-iam offered create_user, delete_user and the token and session reads. cloud withholds all of them from an agent; these were a second way to the same API, so the rule held on one path and not the other. The auto-registration is withdrawn, not the packages: they stay importable for a human at a CLI, which is where reading a secret is a legitimate act. An agent reaches all eight through the unified tool, verified against the live document. mpc keeps its registration because the fleet has no equivalent, and auth keeps its because it reads the caller's own claims rather than another identity's.
263 lines
7.6 KiB
TOML
263 lines
7.6 KiB
TOML
[build-system]
|
|
requires = ["setuptools>=61.0.0", "wheel"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "hanzo-mcp"
|
|
version = "0.15.16"
|
|
description = "The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others."
|
|
readme = "README.md"
|
|
requires-python = ">=3.12"
|
|
license = { text = "MIT" }
|
|
authors = [{ name = "Hanzo Industries Inc", email = "[email protected]" }]
|
|
classifiers = [
|
|
"Programming Language :: Python :: 3",
|
|
"License :: OSI Approved :: MIT License",
|
|
"Operating System :: OS Independent",
|
|
]
|
|
keywords = ["mcp", "claude", "hanzo", "code", "agent"]
|
|
dependencies = [
|
|
# Hanzo AI core SDK (canonical types, config, session, MCP client)
|
|
# 2.2.1 is the first release shipping hanzoai.protocols (permissions.py imports it)
|
|
"hanzoai>=2.2.1",
|
|
# Core MCP dependencies
|
|
"mcp>=1.25.0",
|
|
"fastmcp>=2.14.4",
|
|
"pydantic>=2.12.5",
|
|
"pydantic-settings>=2.12.0",
|
|
"typing-extensions>=4.13.0",
|
|
# Unified async I/O (aiofiles + uvloop auto-installed on Linux/macOS, graceful fallback)
|
|
"hanzo-async>=0.1.3",
|
|
"uvloop>=0.22.1; sys_platform != 'win32'",
|
|
# Hanzo tool infrastructure (all tools)
|
|
"hanzo-tools>=0.3.6", # 0.3.6 carries capture(): downscaled inline, full-res on disk
|
|
"hanzo-tools-fs>=0.3.4", # 0.3.4 returns image files as native MCP ImageContent
|
|
"hanzo-tools-shell>=0.6.5", # 0.6.5 pairs with hanzo-tools>=0.3.0 (ToolError)
|
|
"hanzo-tools-core>=0.3.1", # 0.3.1 is the EMPTY shim — no longer shadows canonical hanzo-tools.core
|
|
"hanzo-tools-browser[playwright]>=0.5.11", # 0.5.11 screenshots downscale before they reach the wire
|
|
"hanzo-tools-memory>=0.2.0",
|
|
"hanzo-tools-todo>=0.1.0",
|
|
"hanzo-tools-reasoning>=0.1.0",
|
|
"hanzo-tools-lsp>=0.1.0",
|
|
"hanzo-tools-computer>=0.5.5", # 0.5.5 screenshots downscale before they reach the wire
|
|
# 0.2.1 fixes ConfigTool passing permission_manager positionally into BaseTool.__init__
|
|
"hanzo-tools-config>=0.2.1",
|
|
"hanzo-tools-refactor>=0.1.0",
|
|
"hanzo-tools-llm>=0.1.0",
|
|
"hanzo-tools-code>=0.1.0",
|
|
"hanzo-tools-vcs>=0.1.0",
|
|
"hanzo-tools-net>=0.1.0",
|
|
"hanzo-tools-agent>=0.3.1",
|
|
"hanzo-tools-api>=0.3.2", # 0.3.2 is the unified `hanzo` tool projected from cloud's OpenAPI registry
|
|
# The fleet is reached through the unified `hanzo` tool (hanzo-tools-api),
|
|
# which offers what cloud offers an AGENT — it withholds an operation whose
|
|
# name discloses a bearer secret, or whose mutating verb acts on identity or
|
|
# authority. The per-service packages that used to be installed here carried
|
|
# no such filter: hanzo-tools-kms handed a model `inject`, which reads every
|
|
# secret at a path, and hanzo-tools-iam handed it create_user/delete_user and
|
|
# the token and session reads. They remain installable for a human at a CLI.
|
|
"hanzo-tools-auth>=0.1.0",
|
|
"hanzo-tools-mpc>=0.1.0",
|
|
"hanzo-tools-ui>=0.1.0",
|
|
"hanzo-persona>=1.0.0",
|
|
]
|
|
|
|
# For local development, install hanzo-tools-* packages from pkg/
|
|
# pip install -e ../hanzo-tools ../hanzo-tools-fs etc.
|
|
# Or when published, add them back as dependencies
|
|
|
|
[project.urls]
|
|
"Homepage" = "https://github.com/hanzoai/mcp"
|
|
"Bug Tracker" = "https://github.com/hanzoai/mcp/issues"
|
|
"Documentation" = "https://mcp.hanzo.ai"
|
|
|
|
[project.optional-dependencies]
|
|
# NOTE: hanzo-tools-* packages are installed separately from pkg/
|
|
# Use: pip install -e ../hanzo-tools -e ../hanzo-tools-fs etc.
|
|
# When published to PyPI, these extras will work:
|
|
# filesystem = ["hanzo-tools-fs>=0.1.0"]
|
|
# shell = ["hanzo-tools-shell>=0.1.0"]
|
|
# etc.
|
|
|
|
# Memory tools with full backend support
|
|
memory = [
|
|
"hanzo-tools-memory[full]>=0.2.2",
|
|
"sqlite-vec>=0.1.0",
|
|
"fastembed>=0.4.0",
|
|
]
|
|
|
|
# Interactive REPL with multi-language Jupyter kernels
|
|
repl = [
|
|
"hanzo-tools-repl>=0.1.0",
|
|
"jupyter-client>=8.6.0",
|
|
"ipykernel>=6.29.0",
|
|
]
|
|
|
|
# IDE integration (VS Code, Cursor, JetBrains)
|
|
ide = [
|
|
"hanzo-tools-ide>=0.1.0",
|
|
]
|
|
|
|
# Full interactive suite (REPL + IDE + Browser)
|
|
interactive = [
|
|
"hanzo-mcp[repl,ide]",
|
|
"hanzo-tools-browser>=0.2.1",
|
|
]
|
|
|
|
# Development
|
|
dev = [
|
|
"watchdog>=3.0.0",
|
|
"pytest>=7.0.0",
|
|
"pytest-cov>=4.1.0",
|
|
"ruff>=0.14.0",
|
|
"black>=23.3.0",
|
|
"mypy>=1.10.0",
|
|
"types-aiofiles>=23.2.0",
|
|
"types-psutil>=5.9.5",
|
|
"types-setuptools>=69.5.0",
|
|
]
|
|
docs = ["sphinx>=8.0.0", "sphinx-rtd-theme>=3.0.0", "myst-parser>=4.0.0", "sphinx-copybutton>=0.5.0"]
|
|
test = [
|
|
"pytest>=7.0.0",
|
|
"pytest-cov>=4.1.0",
|
|
"pytest-mock>=3.10.0",
|
|
"pytest-asyncio>=0.26.0,<1.0.0",
|
|
]
|
|
performance = [
|
|
"ujson>=5.7.0",
|
|
"orjson>=3.9.0",
|
|
]
|
|
publish = ["twine>=4.0.2", "build>=1.0.3"]
|
|
|
|
[project.scripts]
|
|
hanzo-mcp = "hanzo_mcp.cli:main"
|
|
hanzo-mcp-dev = "hanzo_mcp.dev_server:run_dev_server"
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["."]
|
|
include = ["hanzo_mcp*"]
|
|
|
|
[tool.setuptools.package-data]
|
|
hanzo_mcp = ["py.typed"]
|
|
|
|
[tool.basedpyright]
|
|
include = ["hanzo_mcp"]
|
|
|
|
[tool.pytest.ini_options]
|
|
# Configuration for pytest
|
|
addopts = "--no-header --no-summary -p asyncio"
|
|
asyncio_mode = "auto"
|
|
asyncio_default_fixture_loop_scope = "function"
|
|
# Note: --cov-fail-under=96.3 will be added after achieving target coverage
|
|
markers = [
|
|
"asyncio: mark test as using asyncio",
|
|
"requires_hanzo_agents: mark test as requiring hanzo-agents SDK",
|
|
"requires_memory_tools: mark test as requiring hanzo-memory package",
|
|
"slow: mark test as slow running",
|
|
"integration: mark test as integration test",
|
|
]
|
|
testpaths = ["tests"]
|
|
python_files = ["test_*.py", "*_test.py"]
|
|
python_classes = ["Test*"]
|
|
python_functions = ["test_*"]
|
|
|
|
[tool.pytest_asyncio]
|
|
mode = "auto"
|
|
default_loop_scope = "function"
|
|
|
|
[tool.mypy]
|
|
python_version = "3.12"
|
|
strict = true
|
|
warn_return_any = true
|
|
warn_unused_configs = true
|
|
disallow_untyped_defs = true
|
|
disallow_any_generics = true
|
|
check_untyped_defs = true
|
|
no_implicit_optional = true
|
|
warn_redundant_casts = true
|
|
warn_unused_ignores = true
|
|
warn_no_return = true
|
|
warn_unreachable = true
|
|
strict_equality = true
|
|
show_error_codes = true
|
|
show_column_numbers = true
|
|
pretty = true
|
|
|
|
# Per-module options
|
|
[[tool.mypy.overrides]]
|
|
module = [
|
|
"bashlex.*",
|
|
"grep_ast.*",
|
|
"libtmux.*",
|
|
"llm.*",
|
|
"nbformat.*",
|
|
"ffind.*",
|
|
"fastmcp.*",
|
|
"mcp.*",
|
|
"hanzo_agents.*",
|
|
"hanzo_memory.*",
|
|
"personalities.*",
|
|
]
|
|
ignore_missing_imports = true
|
|
|
|
[tool.coverage.run]
|
|
source = ["hanzo_mcp"]
|
|
omit = [
|
|
"*/tests/*",
|
|
"*/__pycache__/*",
|
|
"*/site-packages/*",
|
|
"*/venv/*",
|
|
"*/migrations/*",
|
|
]
|
|
|
|
[tool.coverage.report]
|
|
precision = 2
|
|
show_missing = true
|
|
skip_covered = false
|
|
fail_under = 96.3
|
|
exclude_lines = [
|
|
"pragma: no cover",
|
|
"def __repr__",
|
|
"if self.debug:",
|
|
"if __name__ == .__main__.:",
|
|
"raise AssertionError",
|
|
"raise NotImplementedError",
|
|
"if TYPE_CHECKING:",
|
|
"@abstractmethod",
|
|
]
|
|
|
|
[tool.coverage.html]
|
|
directory = "htmlcov"
|
|
|
|
[tool.ruff]
|
|
exclude = [
|
|
".git",
|
|
".venv",
|
|
"venv",
|
|
"__pycache__",
|
|
"build",
|
|
"dist",
|
|
"*.egg-info",
|
|
"node_modules",
|
|
"vscode-extension",
|
|
]
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I", "B"]
|
|
ignore = [
|
|
"E501", # Line too long
|
|
"B017", # Blind exception test
|
|
"B023", # Function definition loop variable
|
|
"B904", # Raise without from in except
|
|
"E741", # Ambiguous variable name
|
|
"E402", # Module level import not at top
|
|
"F401", # Unused imports (handled by tests themselves)
|
|
"F821", # Undefined name (tests may have conditional imports)
|
|
"F841", # Local variable assigned but never used
|
|
"B007", # Loop control variable not used
|
|
]
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
"tests/*" = ["F401", "F821", "F841", "B007"] # Relax rules for test files
|
|
"*/__init__.py" = ["F401"] # Allow unused imports in __init__.py
|