mirror of
https://github.com/hanzoai/mcp.git
synced 2026-10-29 02:55:49 +00:00
🎨 **Tool Palette System** - Created palette system for organizing development tools by ecosystem - Pre-defined palettes: Python (Guido), Ruby (Matz), JavaScript, Go, Rust, DevOps, Full Stack, Minimal - `palette` tool to list, activate, and manage tool sets - Environment variables applied from active palette - Keeps MCP interface clean while supporting specialized workflows 🔧 **Unified Process Tools with OO Design** - Refactored all process execution to use clean base class hierarchy - `BaseProcessTool`, `BaseBinaryTool`, `BaseScriptTool` for consistent interface - Unified `bash`, `npx`, `uvx` tools with action-based approach (run/background) - `process` tool for managing background processes - All tools use same execution pipeline internally 🐚 **Smart Shell Detection** - Shell tool now detects user's preferred shell from $SHELL environment - Automatically uses zsh if .zshrc exists (perfect for your setup\!) - Falls back to bash if no special configuration found - All zsh aliases, functions, and configurations now available in MCP 🚀 **Development Mode with Hot Reload** - Added `--dev` flag to hanzo-mcp CLI for development mode - File watching with automatic reload detection using watchdog - `hanzo-mcp-dev` command for dedicated dev server - Watches Python files and config changes - Debounced reloading to prevent spam 🛠️ **New Tools Added** - `open`: Opens files/URLs in default application (platform-aware) - `watch`: Monitors files/directories for changes with pattern matching - `diff`: Compares files with unified/context diff formats - `config`: Git-style configuration management 📚 **Documentation & Infrastructure** - Comprehensive Sphinx documentation with black theme - Automated deployment to mcp.hanzo.ai via Cloudflare Pages - GitHub Actions workflow for docs deployment - 25+ documentation pages organized by category ⚙️ **Configuration Improvements** - Tool enable/disable system with palette override - Per-project vs global indexing configuration - Environment variable management through palettes - Clean separation of concerns in tool registration This release provides a much cleaner, more extensible architecture while maintaining backward compatibility. The palette system makes it easy to switch between development environments, and the unified process tools eliminate code duplication while providing consistent behavior. Co-authored-by: Hanzo Dev <[email protected]>
122 lines
3.7 KiB
Python
122 lines
3.7 KiB
Python
"""Base functionality for filesystem tools.
|
|
|
|
This module provides common functionality for filesystem tools including path handling,
|
|
error formatting, and shared utilities for file operations.
|
|
"""
|
|
|
|
from abc import ABC
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from mcp.server.fastmcp import Context as MCPContext
|
|
|
|
from hanzo_mcp.tools.common.base import FileSystemTool
|
|
from hanzo_mcp.tools.common.context import ToolContext, create_tool_context
|
|
|
|
|
|
class FilesystemBaseTool(FileSystemTool, ABC):
|
|
"""Enhanced base class for all filesystem tools.
|
|
|
|
Provides additional utilities specific to filesystem operations beyond
|
|
the base functionality in FileSystemTool.
|
|
"""
|
|
|
|
async def check_path_allowed(
|
|
self, path: str, tool_ctx: Any, error_prefix: str = "Error"
|
|
) -> tuple[bool, str]:
|
|
"""Check if a path is allowed and log an error if not.
|
|
|
|
Args:
|
|
path: Path to check
|
|
tool_ctx: Tool context for logging
|
|
error_prefix: Prefix for error messages
|
|
|
|
Returns:
|
|
tuple of (is_allowed, error_message)
|
|
"""
|
|
if not self.is_path_allowed(path):
|
|
message = f"Access denied - path outside allowed directories: {path}"
|
|
await tool_ctx.error(message)
|
|
return False, f"{error_prefix}: {message}"
|
|
return True, ""
|
|
|
|
async def check_path_exists(
|
|
self, path: str, tool_ctx: Any, error_prefix: str = "Error"
|
|
) -> tuple[bool, str]:
|
|
"""Check if a path exists and log an error if not.
|
|
|
|
Args:
|
|
path: Path to check
|
|
tool_ctx: Tool context for logging
|
|
error_prefix: Prefix for error messages
|
|
|
|
Returns:
|
|
tuple of (exists, error_message)
|
|
"""
|
|
file_path = Path(path)
|
|
if not file_path.exists():
|
|
message = f"Path does not exist: {path}"
|
|
await tool_ctx.error(message)
|
|
return False, f"{error_prefix}: {message}"
|
|
return True, ""
|
|
|
|
async def check_is_file(
|
|
self, path: str, tool_ctx: Any, error_prefix: str = "Error"
|
|
) -> tuple[bool, str]:
|
|
"""Check if a path is a file and log an error if not.
|
|
|
|
Args:
|
|
path: Path to check
|
|
tool_ctx: Tool context for logging
|
|
error_prefix: Prefix for error messages
|
|
|
|
Returns:
|
|
tuple of (is_file, error_message)
|
|
"""
|
|
file_path = Path(path)
|
|
if not file_path.is_file():
|
|
message = f"Path is not a file: {path}"
|
|
await tool_ctx.error(message)
|
|
return False, f"{error_prefix}: {message}"
|
|
return True, ""
|
|
|
|
async def check_is_directory(
|
|
self, path: str, tool_ctx: Any, error_prefix: str = "Error"
|
|
) -> tuple[bool, str]:
|
|
"""Check if a path is a directory and log an error if not.
|
|
|
|
Args:
|
|
path: Path to check
|
|
tool_ctx: Tool context for logging
|
|
error_prefix: Prefix for error messages
|
|
|
|
Returns:
|
|
tuple of (is_directory, error_message)
|
|
"""
|
|
dir_path = Path(path)
|
|
if not dir_path.is_dir():
|
|
message = f"Path is not a directory: {path}"
|
|
await tool_ctx.error(message)
|
|
return False, f"{error_prefix}: {message}"
|
|
return True, ""
|
|
|
|
def create_tool_context(self, ctx: MCPContext) -> ToolContext:
|
|
"""Create a tool context with the tool name.
|
|
|
|
Args:
|
|
ctx: MCP context
|
|
|
|
Returns:
|
|
Tool context
|
|
"""
|
|
tool_ctx = create_tool_context(ctx)
|
|
return tool_ctx
|
|
|
|
def set_tool_context_info(self, tool_ctx: ToolContext) -> None:
|
|
"""Set the tool info on the context.
|
|
|
|
Args:
|
|
tool_ctx: Tool context
|
|
"""
|
|
tool_ctx.set_tool_info(self.name)
|