mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
Introduces hanzo-tools-* namespace packages for independent tool installation: Core packages: - hanzo-tools-core: BaseTool, ToolRegistry, PermissionManager - hanzo-tools-filesystem: read, write, edit, tree, find, search, ast (7 tools) - hanzo-tools-shell: dag, ps, zsh, shell, npx, uvx, open (7 tools) AI/Agent packages: - hanzo-tools-agent: critic, iching, review, network, CLI agents (12 tools) - hanzo-tools-memory: recall/create/update/delete memories, facts, KB (9 tools) - hanzo-tools-reasoning: think, critic (2 tools) Editor/Dev packages: - hanzo-tools-lsp: Language Server Protocol tool (1 tool) - hanzo-tools-refactor: rename, extract, inline, move, change_signature (1 tool) - hanzo-tools-database: SQL + graph database tools (8 tools) - hanzo-tools-editor: neovim integration (3 tools) - hanzo-tools-jupyter: notebook read/edit (1 tool) - hanzo-tools-browser: Playwright browser automation (1 tool) - hanzo-tools-todo: unified todo management (1 tool) Key improvements: - All subprocess.run calls have timeout protection - All tool .call() methods are async - Namespace package pattern for mix-and-match installation - Entry point discovery via hanzo.tools - No blocking imports (all < 2s) Also updates hanzo-mcp: - Browser tool integration - Tool install/registry for dynamic tool management - Auto-background timeout reduced to 60s
91 lines
2.4 KiB
Python
91 lines
2.4 KiB
Python
"""UVX tool for both sync and background execution."""
|
|
|
|
from typing import Optional, override
|
|
from pathlib import Path
|
|
|
|
from mcp.server import FastMCP
|
|
from mcp.server.fastmcp import Context as MCPContext
|
|
|
|
from hanzo_tools.core import auto_timeout
|
|
from hanzo_tools.shell.base_process import BaseBinaryTool
|
|
|
|
|
|
class UvxTool(BaseBinaryTool):
|
|
"""Tool for running uvx commands."""
|
|
|
|
name = "uvx"
|
|
|
|
@property
|
|
@override
|
|
def description(self) -> str:
|
|
"""Get the tool description."""
|
|
return """Run Python packages with uvx with automatic backgrounding for long-running processes.
|
|
|
|
Commands that run for more than 2 minutes will automatically continue in the background.
|
|
|
|
Usage:
|
|
uvx ruff check .
|
|
uvx mkdocs serve # Auto-backgrounds after 2 minutes
|
|
uvx black --check src/
|
|
uvx jupyter lab --port 8888 # Auto-backgrounds if needed"""
|
|
|
|
@override
|
|
def get_binary_name(self) -> str:
|
|
"""Get the binary name."""
|
|
return "uvx"
|
|
|
|
@override
|
|
async def run(
|
|
self,
|
|
ctx: MCPContext,
|
|
package: str,
|
|
args: str = "",
|
|
cwd: Optional[str] = None,
|
|
python: Optional[str] = None,
|
|
) -> str:
|
|
"""Run a uvx command with auto-backgrounding."""
|
|
work_dir = Path(cwd).resolve() if cwd else Path.cwd()
|
|
|
|
flags = []
|
|
if python:
|
|
flags.extend(["--python", python])
|
|
|
|
full_args = args.split() if args else []
|
|
|
|
return await self.execute_sync(
|
|
package,
|
|
cwd=work_dir,
|
|
flags=flags,
|
|
args=full_args,
|
|
timeout=None,
|
|
)
|
|
|
|
def register(self, server: FastMCP) -> None:
|
|
"""Register the tool with the MCP server."""
|
|
tool_self = self
|
|
|
|
@server.tool(name=self.name, description=self.description)
|
|
async def uvx(
|
|
ctx: MCPContext,
|
|
package: str,
|
|
args: str = "",
|
|
cwd: Optional[str] = None,
|
|
python: Optional[str] = None,
|
|
) -> str:
|
|
return await tool_self.run(ctx, package=package, args=args, cwd=cwd, python=python)
|
|
|
|
@auto_timeout("uvx")
|
|
async def call(self, ctx: MCPContext, **params) -> str:
|
|
"""Call the tool with arguments."""
|
|
return await self.run(
|
|
ctx,
|
|
package=params["package"],
|
|
args=params.get("args", ""),
|
|
cwd=params.get("cwd"),
|
|
python=params.get("python"),
|
|
)
|
|
|
|
|
|
# Create tool instance
|
|
uvx_tool = UvxTool()
|