hanzo-mcp 0.7.6__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of hanzo-mcp might be problematic. Click here for more details.
- hanzo_mcp/__init__.py +7 -1
- hanzo_mcp/__main__.py +1 -1
- hanzo_mcp/analytics/__init__.py +2 -2
- hanzo_mcp/analytics/posthog_analytics.py +76 -82
- hanzo_mcp/cli.py +31 -36
- hanzo_mcp/cli_enhanced.py +94 -72
- hanzo_mcp/cli_plugin.py +27 -17
- hanzo_mcp/config/__init__.py +2 -2
- hanzo_mcp/config/settings.py +112 -88
- hanzo_mcp/config/tool_config.py +32 -34
- hanzo_mcp/dev_server.py +66 -67
- hanzo_mcp/prompts/__init__.py +94 -12
- hanzo_mcp/prompts/enhanced_prompts.py +809 -0
- hanzo_mcp/prompts/example_custom_prompt.py +6 -5
- hanzo_mcp/prompts/project_todo_reminder.py +0 -1
- hanzo_mcp/prompts/tool_explorer.py +10 -7
- hanzo_mcp/server.py +17 -21
- hanzo_mcp/server_enhanced.py +15 -22
- hanzo_mcp/tools/__init__.py +56 -28
- hanzo_mcp/tools/agent/__init__.py +16 -19
- hanzo_mcp/tools/agent/agent.py +82 -65
- hanzo_mcp/tools/agent/agent_tool.py +152 -122
- hanzo_mcp/tools/agent/agent_tool_v1_deprecated.py +66 -62
- hanzo_mcp/tools/agent/clarification_protocol.py +55 -50
- hanzo_mcp/tools/agent/clarification_tool.py +11 -10
- hanzo_mcp/tools/agent/claude_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/claude_desktop_auth.py +130 -144
- hanzo_mcp/tools/agent/cli_agent_base.py +59 -53
- hanzo_mcp/tools/agent/code_auth.py +102 -107
- hanzo_mcp/tools/agent/code_auth_tool.py +28 -27
- hanzo_mcp/tools/agent/codex_cli_tool.py +20 -19
- hanzo_mcp/tools/agent/critic_tool.py +86 -73
- hanzo_mcp/tools/agent/gemini_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/grok_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/iching_tool.py +404 -139
- hanzo_mcp/tools/agent/network_tool.py +89 -73
- hanzo_mcp/tools/agent/prompt.py +2 -1
- hanzo_mcp/tools/agent/review_tool.py +101 -98
- hanzo_mcp/tools/agent/swarm_alias.py +87 -0
- hanzo_mcp/tools/agent/swarm_tool.py +246 -161
- hanzo_mcp/tools/agent/swarm_tool_v1_deprecated.py +134 -92
- hanzo_mcp/tools/agent/tool_adapter.py +21 -11
- hanzo_mcp/tools/common/__init__.py +1 -1
- hanzo_mcp/tools/common/base.py +3 -5
- hanzo_mcp/tools/common/batch_tool.py +46 -39
- hanzo_mcp/tools/common/config_tool.py +120 -84
- hanzo_mcp/tools/common/context.py +1 -5
- hanzo_mcp/tools/common/context_fix.py +5 -3
- hanzo_mcp/tools/common/critic_tool.py +4 -8
- hanzo_mcp/tools/common/decorators.py +58 -56
- hanzo_mcp/tools/common/enhanced_base.py +29 -32
- hanzo_mcp/tools/common/fastmcp_pagination.py +91 -94
- hanzo_mcp/tools/common/forgiving_edit.py +91 -87
- hanzo_mcp/tools/common/mode.py +15 -17
- hanzo_mcp/tools/common/mode_loader.py +27 -24
- hanzo_mcp/tools/common/paginated_base.py +61 -53
- hanzo_mcp/tools/common/paginated_response.py +72 -79
- hanzo_mcp/tools/common/pagination.py +50 -53
- hanzo_mcp/tools/common/permissions.py +4 -4
- hanzo_mcp/tools/common/personality.py +186 -138
- hanzo_mcp/tools/common/plugin_loader.py +54 -54
- hanzo_mcp/tools/common/stats.py +65 -47
- hanzo_mcp/tools/common/test_helpers.py +31 -0
- hanzo_mcp/tools/common/thinking_tool.py +4 -8
- hanzo_mcp/tools/common/tool_disable.py +17 -12
- hanzo_mcp/tools/common/tool_enable.py +13 -14
- hanzo_mcp/tools/common/tool_list.py +36 -28
- hanzo_mcp/tools/common/truncate.py +23 -23
- hanzo_mcp/tools/config/__init__.py +4 -4
- hanzo_mcp/tools/config/config_tool.py +42 -29
- hanzo_mcp/tools/config/index_config.py +37 -34
- hanzo_mcp/tools/config/mode_tool.py +175 -55
- hanzo_mcp/tools/database/__init__.py +15 -12
- hanzo_mcp/tools/database/database_manager.py +77 -75
- hanzo_mcp/tools/database/graph.py +137 -91
- hanzo_mcp/tools/database/graph_add.py +30 -18
- hanzo_mcp/tools/database/graph_query.py +178 -102
- hanzo_mcp/tools/database/graph_remove.py +33 -28
- hanzo_mcp/tools/database/graph_search.py +97 -75
- hanzo_mcp/tools/database/graph_stats.py +91 -59
- hanzo_mcp/tools/database/sql.py +107 -79
- hanzo_mcp/tools/database/sql_query.py +30 -24
- hanzo_mcp/tools/database/sql_search.py +29 -25
- hanzo_mcp/tools/database/sql_stats.py +47 -35
- hanzo_mcp/tools/editor/neovim_command.py +25 -28
- hanzo_mcp/tools/editor/neovim_edit.py +21 -23
- hanzo_mcp/tools/editor/neovim_session.py +60 -54
- hanzo_mcp/tools/filesystem/__init__.py +31 -30
- hanzo_mcp/tools/filesystem/ast_multi_edit.py +329 -249
- hanzo_mcp/tools/filesystem/ast_tool.py +4 -4
- hanzo_mcp/tools/filesystem/base.py +1 -1
- hanzo_mcp/tools/filesystem/batch_search.py +316 -224
- hanzo_mcp/tools/filesystem/content_replace.py +4 -4
- hanzo_mcp/tools/filesystem/diff.py +71 -59
- hanzo_mcp/tools/filesystem/directory_tree.py +7 -7
- hanzo_mcp/tools/filesystem/directory_tree_paginated.py +49 -37
- hanzo_mcp/tools/filesystem/edit.py +4 -4
- hanzo_mcp/tools/filesystem/find.py +173 -80
- hanzo_mcp/tools/filesystem/find_files.py +73 -52
- hanzo_mcp/tools/filesystem/git_search.py +157 -104
- hanzo_mcp/tools/filesystem/grep.py +8 -8
- hanzo_mcp/tools/filesystem/multi_edit.py +4 -8
- hanzo_mcp/tools/filesystem/read.py +12 -10
- hanzo_mcp/tools/filesystem/rules_tool.py +59 -43
- hanzo_mcp/tools/filesystem/search_tool.py +263 -207
- hanzo_mcp/tools/filesystem/symbols_tool.py +94 -54
- hanzo_mcp/tools/filesystem/tree.py +35 -33
- hanzo_mcp/tools/filesystem/unix_aliases.py +13 -18
- hanzo_mcp/tools/filesystem/watch.py +37 -36
- hanzo_mcp/tools/filesystem/write.py +4 -8
- hanzo_mcp/tools/jupyter/__init__.py +4 -4
- hanzo_mcp/tools/jupyter/base.py +4 -5
- hanzo_mcp/tools/jupyter/jupyter.py +67 -47
- hanzo_mcp/tools/jupyter/notebook_edit.py +4 -4
- hanzo_mcp/tools/jupyter/notebook_read.py +4 -7
- hanzo_mcp/tools/llm/__init__.py +5 -7
- hanzo_mcp/tools/llm/consensus_tool.py +72 -52
- hanzo_mcp/tools/llm/llm_manage.py +101 -60
- hanzo_mcp/tools/llm/llm_tool.py +226 -166
- hanzo_mcp/tools/llm/provider_tools.py +25 -26
- hanzo_mcp/tools/lsp/__init__.py +1 -1
- hanzo_mcp/tools/lsp/lsp_tool.py +228 -143
- hanzo_mcp/tools/mcp/__init__.py +2 -3
- hanzo_mcp/tools/mcp/mcp_add.py +27 -25
- hanzo_mcp/tools/mcp/mcp_remove.py +7 -8
- hanzo_mcp/tools/mcp/mcp_stats.py +23 -22
- hanzo_mcp/tools/mcp/mcp_tool.py +129 -98
- hanzo_mcp/tools/memory/__init__.py +39 -21
- hanzo_mcp/tools/memory/knowledge_tools.py +124 -99
- hanzo_mcp/tools/memory/memory_tools.py +90 -108
- hanzo_mcp/tools/search/__init__.py +7 -2
- hanzo_mcp/tools/search/find_tool.py +297 -212
- hanzo_mcp/tools/search/unified_search.py +366 -314
- hanzo_mcp/tools/shell/__init__.py +8 -7
- hanzo_mcp/tools/shell/auto_background.py +56 -49
- hanzo_mcp/tools/shell/base.py +1 -1
- hanzo_mcp/tools/shell/base_process.py +75 -75
- hanzo_mcp/tools/shell/bash_session.py +2 -2
- hanzo_mcp/tools/shell/bash_session_executor.py +4 -4
- hanzo_mcp/tools/shell/bash_tool.py +24 -31
- hanzo_mcp/tools/shell/command_executor.py +12 -12
- hanzo_mcp/tools/shell/logs.py +43 -33
- hanzo_mcp/tools/shell/npx.py +13 -13
- hanzo_mcp/tools/shell/npx_background.py +24 -21
- hanzo_mcp/tools/shell/npx_tool.py +18 -22
- hanzo_mcp/tools/shell/open.py +19 -21
- hanzo_mcp/tools/shell/pkill.py +31 -26
- hanzo_mcp/tools/shell/process_tool.py +32 -32
- hanzo_mcp/tools/shell/processes.py +57 -58
- hanzo_mcp/tools/shell/run_background.py +24 -25
- hanzo_mcp/tools/shell/run_command.py +5 -5
- hanzo_mcp/tools/shell/run_command_windows.py +5 -5
- hanzo_mcp/tools/shell/session_storage.py +3 -3
- hanzo_mcp/tools/shell/streaming_command.py +141 -126
- hanzo_mcp/tools/shell/uvx.py +24 -25
- hanzo_mcp/tools/shell/uvx_background.py +35 -33
- hanzo_mcp/tools/shell/uvx_tool.py +18 -22
- hanzo_mcp/tools/todo/__init__.py +6 -2
- hanzo_mcp/tools/todo/todo.py +50 -37
- hanzo_mcp/tools/todo/todo_read.py +5 -8
- hanzo_mcp/tools/todo/todo_write.py +5 -7
- hanzo_mcp/tools/vector/__init__.py +40 -28
- hanzo_mcp/tools/vector/ast_analyzer.py +176 -143
- hanzo_mcp/tools/vector/git_ingester.py +170 -179
- hanzo_mcp/tools/vector/index_tool.py +96 -44
- hanzo_mcp/tools/vector/infinity_store.py +283 -228
- hanzo_mcp/tools/vector/mock_infinity.py +39 -40
- hanzo_mcp/tools/vector/project_manager.py +88 -78
- hanzo_mcp/tools/vector/vector.py +59 -42
- hanzo_mcp/tools/vector/vector_index.py +30 -27
- hanzo_mcp/tools/vector/vector_search.py +64 -45
- hanzo_mcp/types.py +6 -4
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/METADATA +1 -1
- hanzo_mcp-0.8.0.dist-info/RECORD +185 -0
- hanzo_mcp-0.7.6.dist-info/RECORD +0 -182
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/WHEEL +0 -0
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/entry_points.txt +0 -0
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/top_level.txt +0 -0
|
@@ -14,19 +14,20 @@ Focus on:
|
|
|
14
14
|
|
|
15
15
|
Be constructive and specific in your feedback."""
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
# You can also create dynamic prompts that take parameters
|
|
18
19
|
def create_custom_analysis_prompt(file_path: str, analysis_type: str = "general"):
|
|
19
20
|
"""Create a dynamic analysis prompt for a specific file."""
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
analysis_types = {
|
|
22
23
|
"general": "Provide a general analysis including structure, purpose, and quality",
|
|
23
24
|
"security": "Focus on security vulnerabilities and best practices",
|
|
24
25
|
"performance": "Analyze performance bottlenecks and optimization opportunities",
|
|
25
|
-
"refactor": "Suggest refactoring opportunities to improve code maintainability"
|
|
26
|
+
"refactor": "Suggest refactoring opportunities to improve code maintainability",
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
|
|
28
29
|
analysis_instruction = analysis_types.get(analysis_type, analysis_types["general"])
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
return f"""Please analyze the file at {file_path}.
|
|
31
32
|
|
|
32
33
|
{analysis_instruction}
|
|
@@ -37,4 +38,4 @@ Your analysis should include:
|
|
|
37
38
|
3. Specific recommendations with code examples where applicable
|
|
38
39
|
4. Priority ranking of any issues found
|
|
39
40
|
|
|
40
|
-
Be thorough but concise in your analysis."""
|
|
41
|
+
Be thorough but concise in your analysis."""
|
|
@@ -3,7 +3,6 @@ from typing import Any
|
|
|
3
3
|
# Import TodoStorage to access todo data
|
|
4
4
|
from hanzo_mcp.tools.todo.base import TodoStorage
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
PROJECT_TODO_EMPTY_REMINDER = """<system-reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to me explicitly because i have already aware. If you are working on tasks that would benefit from a todo list please use the todo_write tool to create one. If not, please feel free to ignore.</system-reminder>"""
|
|
8
7
|
|
|
9
8
|
|
|
@@ -585,19 +585,22 @@ Tools NOT available in batch (require state/session):
|
|
|
585
585
|
- think
|
|
586
586
|
- todo_write"""
|
|
587
587
|
|
|
588
|
+
|
|
588
589
|
def create_tool_category_prompt(category: str, tools: list[str]):
|
|
589
590
|
"""Create a dynamic prompt for a specific tool category."""
|
|
590
|
-
|
|
591
|
+
|
|
591
592
|
tool_descriptions = {
|
|
592
593
|
"filesystem": FILESYSTEM_TOOLS_HELP,
|
|
593
594
|
"agent": AGENT_TOOLS_HELP,
|
|
594
595
|
"shell": SHELL_TOOLS_HELP,
|
|
595
|
-
"batch": BATCH_TOOL_EXAMPLES
|
|
596
|
+
"batch": BATCH_TOOL_EXAMPLES,
|
|
596
597
|
}
|
|
597
|
-
|
|
598
|
-
base_prompt = tool_descriptions.get(
|
|
599
|
-
|
|
598
|
+
|
|
599
|
+
base_prompt = tool_descriptions.get(
|
|
600
|
+
category, f"# {category.title()} Tools\n\nAvailable tools in this category:\n"
|
|
601
|
+
)
|
|
602
|
+
|
|
600
603
|
if category not in tool_descriptions:
|
|
601
604
|
base_prompt += "\n".join(f"- **{tool}**: [Tool description]" for tool in tools)
|
|
602
|
-
|
|
603
|
-
return base_prompt
|
|
605
|
+
|
|
606
|
+
return base_prompt
|
hanzo_mcp/server.py
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""MCP server implementing Hanzo capabilities."""
|
|
2
2
|
|
|
3
3
|
import atexit
|
|
4
|
-
import logging
|
|
5
4
|
import signal
|
|
5
|
+
import logging
|
|
6
6
|
import threading
|
|
7
|
-
import time
|
|
8
7
|
import warnings
|
|
9
8
|
from typing import Literal, cast, final
|
|
10
9
|
|
|
11
|
-
#
|
|
10
|
+
# Suppress litellm deprecation warnings about event loop
|
|
11
|
+
warnings.filterwarnings("ignore", message="There is no current event loop", category=DeprecationWarning)
|
|
12
12
|
|
|
13
13
|
try:
|
|
14
14
|
from fastmcp import FastMCP
|
|
@@ -17,11 +17,9 @@ except ImportError:
|
|
|
17
17
|
from mcp.server import FastMCP
|
|
18
18
|
|
|
19
19
|
# Import our enhanced server
|
|
20
|
-
from hanzo_mcp.server_enhanced import EnhancedFastMCP
|
|
21
|
-
|
|
22
|
-
from hanzo_mcp.prompts import register_all_prompts
|
|
23
20
|
from hanzo_mcp.tools import register_all_tools
|
|
24
|
-
|
|
21
|
+
from hanzo_mcp.prompts import register_all_prompts
|
|
22
|
+
from hanzo_mcp.server_enhanced import EnhancedFastMCP
|
|
25
23
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
26
24
|
from hanzo_mcp.tools.shell.session_storage import SessionStorage
|
|
27
25
|
|
|
@@ -126,7 +124,7 @@ class HanzoMCPServer:
|
|
|
126
124
|
final_enabled_tools = self.enabled_tools.copy()
|
|
127
125
|
for tool_name in self.disabled_tools:
|
|
128
126
|
final_enabled_tools[tool_name] = False
|
|
129
|
-
|
|
127
|
+
|
|
130
128
|
# Store the final processed tool configuration
|
|
131
129
|
self.enabled_tools = final_enabled_tools
|
|
132
130
|
|
|
@@ -159,8 +157,9 @@ class HanzoMCPServer:
|
|
|
159
157
|
# Register signal handlers for graceful shutdown
|
|
160
158
|
def signal_handler(signum, frame):
|
|
161
159
|
import sys
|
|
160
|
+
|
|
162
161
|
# Only log if not stdio transport
|
|
163
|
-
if hasattr(self,
|
|
162
|
+
if hasattr(self, "_transport") and self._transport != "stdio":
|
|
164
163
|
logger = logging.getLogger(__name__)
|
|
165
164
|
logger.info("\nShutting down gracefully...")
|
|
166
165
|
self._cleanup_sessions()
|
|
@@ -198,7 +197,7 @@ class HanzoMCPServer:
|
|
|
198
197
|
cleared_count = SessionStorage.clear_all_sessions()
|
|
199
198
|
if cleared_count > 0:
|
|
200
199
|
# Only log if not stdio transport
|
|
201
|
-
if hasattr(self,
|
|
200
|
+
if hasattr(self, "_transport") and self._transport != "stdio":
|
|
202
201
|
logger = logging.getLogger(__name__)
|
|
203
202
|
logger.info(f"Cleaned up {cleared_count} tmux sessions on shutdown")
|
|
204
203
|
except Exception:
|
|
@@ -214,7 +213,7 @@ class HanzoMCPServer:
|
|
|
214
213
|
"""
|
|
215
214
|
# Store transport for later use
|
|
216
215
|
self._transport = transport
|
|
217
|
-
|
|
216
|
+
|
|
218
217
|
# Add allowed paths if provided
|
|
219
218
|
allowed_paths_list = allowed_paths or []
|
|
220
219
|
for path in allowed_paths_list:
|
|
@@ -232,30 +231,27 @@ def create_server(
|
|
|
232
231
|
name: str = "hanzo-mcp",
|
|
233
232
|
allowed_paths: list[str] | None = None,
|
|
234
233
|
enable_all_tools: bool = False,
|
|
235
|
-
**kwargs
|
|
234
|
+
**kwargs,
|
|
236
235
|
) -> HanzoMCPServer:
|
|
237
236
|
"""Create a Hanzo MCP server instance.
|
|
238
|
-
|
|
237
|
+
|
|
239
238
|
Args:
|
|
240
239
|
name: Server name
|
|
241
240
|
allowed_paths: List of allowed file paths
|
|
242
241
|
enable_all_tools: Enable all tools including agent tools
|
|
243
242
|
**kwargs: Additional server configuration
|
|
244
|
-
|
|
243
|
+
|
|
245
244
|
Returns:
|
|
246
245
|
HanzoMCPServer instance
|
|
247
246
|
"""
|
|
248
247
|
if enable_all_tools:
|
|
249
|
-
kwargs[
|
|
250
|
-
|
|
251
|
-
return HanzoMCPServer(
|
|
252
|
-
name=name,
|
|
253
|
-
allowed_paths=allowed_paths,
|
|
254
|
-
**kwargs
|
|
255
|
-
)
|
|
248
|
+
kwargs["enable_agent_tool"] = True
|
|
249
|
+
|
|
250
|
+
return HanzoMCPServer(name=name, allowed_paths=allowed_paths, **kwargs)
|
|
256
251
|
|
|
257
252
|
|
|
258
253
|
def main():
|
|
259
254
|
"""Main entry point for the server."""
|
|
260
255
|
from hanzo_mcp.cli import main as cli_main
|
|
256
|
+
|
|
261
257
|
cli_main()
|
hanzo_mcp/server_enhanced.py
CHANGED
|
@@ -4,8 +4,7 @@ This module provides an enhanced FastMCP server that automatically
|
|
|
4
4
|
applies context normalization to all registered tools.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import
|
|
8
|
-
from functools import wraps
|
|
7
|
+
from typing import Callable
|
|
9
8
|
|
|
10
9
|
from mcp.server import FastMCP
|
|
11
10
|
|
|
@@ -14,56 +13,50 @@ from hanzo_mcp.tools.common.decorators import with_context_normalization
|
|
|
14
13
|
|
|
15
14
|
class EnhancedFastMCP(FastMCP):
|
|
16
15
|
"""Enhanced FastMCP server with automatic context normalization.
|
|
17
|
-
|
|
16
|
+
|
|
18
17
|
This server automatically wraps all tool registrations with context
|
|
19
18
|
normalization, ensuring that tools work properly when called externally
|
|
20
19
|
with serialized context parameters.
|
|
21
20
|
"""
|
|
22
|
-
|
|
23
|
-
def tool(
|
|
24
|
-
self,
|
|
25
|
-
name: str | None = None,
|
|
26
|
-
description: str | None = None
|
|
27
|
-
) -> Callable:
|
|
21
|
+
|
|
22
|
+
def tool(self, name: str | None = None, description: str | None = None) -> Callable:
|
|
28
23
|
"""Enhanced tool decorator that includes automatic context normalization.
|
|
29
|
-
|
|
24
|
+
|
|
30
25
|
Args:
|
|
31
26
|
name: Tool name (defaults to function name)
|
|
32
27
|
description: Tool description
|
|
33
|
-
|
|
28
|
+
|
|
34
29
|
Returns:
|
|
35
30
|
Decorator function that registers the tool with context normalization
|
|
36
31
|
"""
|
|
37
32
|
# Get the original decorator from parent class
|
|
38
|
-
original_decorator = super().tool(
|
|
39
|
-
|
|
40
|
-
description=description
|
|
41
|
-
)
|
|
42
|
-
|
|
33
|
+
original_decorator = super().tool(name=name, description=description)
|
|
34
|
+
|
|
43
35
|
# Create our enhanced decorator
|
|
44
36
|
def enhanced_decorator(func: Callable) -> Callable:
|
|
45
37
|
# Apply context normalization first
|
|
46
38
|
# Check if function has ctx parameter
|
|
47
39
|
import inspect
|
|
40
|
+
|
|
48
41
|
sig = inspect.signature(func)
|
|
49
|
-
if
|
|
42
|
+
if "ctx" in sig.parameters:
|
|
50
43
|
normalized_func = with_context_normalization(func)
|
|
51
44
|
else:
|
|
52
45
|
normalized_func = func
|
|
53
|
-
|
|
46
|
+
|
|
54
47
|
# Then apply the original decorator
|
|
55
48
|
return original_decorator(normalized_func)
|
|
56
|
-
|
|
49
|
+
|
|
57
50
|
return enhanced_decorator
|
|
58
51
|
|
|
59
52
|
|
|
60
53
|
def create_enhanced_server(name: str = "hanzo") -> EnhancedFastMCP:
|
|
61
54
|
"""Create an enhanced MCP server with automatic context normalization.
|
|
62
|
-
|
|
55
|
+
|
|
63
56
|
Args:
|
|
64
57
|
name: Server name
|
|
65
|
-
|
|
58
|
+
|
|
66
59
|
Returns:
|
|
67
60
|
Enhanced FastMCP server instance
|
|
68
61
|
"""
|
|
69
|
-
return EnhancedFastMCP(name)
|
|
62
|
+
return EnhancedFastMCP(name)
|
hanzo_mcp/tools/__init__.py
CHANGED
|
@@ -11,39 +11,50 @@ to delegate tasks to sub-agents for concurrent execution and specialized process
|
|
|
11
11
|
|
|
12
12
|
from mcp.server import FastMCP
|
|
13
13
|
|
|
14
|
+
from hanzo_mcp.tools.todo import register_todo_tools
|
|
14
15
|
from hanzo_mcp.tools.agent import register_agent_tools
|
|
15
|
-
from hanzo_mcp.tools.
|
|
16
|
+
from hanzo_mcp.tools.shell import register_shell_tools
|
|
17
|
+
from hanzo_mcp.tools.common import (
|
|
18
|
+
register_batch_tool,
|
|
19
|
+
register_critic_tool,
|
|
20
|
+
register_thinking_tool,
|
|
21
|
+
)
|
|
22
|
+
from hanzo_mcp.tools.vector import register_vector_tools
|
|
23
|
+
from hanzo_mcp.tools.jupyter import register_jupyter_tools
|
|
24
|
+
from hanzo_mcp.tools.database import DatabaseManager, register_database_tools
|
|
25
|
+
from hanzo_mcp.tools.filesystem import register_filesystem_tools
|
|
16
26
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
27
|
+
from hanzo_mcp.tools.common.stats import StatsTool
|
|
28
|
+
from hanzo_mcp.tools.common.tool_list import ToolListTool
|
|
17
29
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
18
30
|
from hanzo_mcp.tools.common.tool_enable import ToolEnableTool
|
|
19
31
|
from hanzo_mcp.tools.common.tool_disable import ToolDisableTool
|
|
20
|
-
from hanzo_mcp.tools.common.tool_list import ToolListTool
|
|
21
|
-
from hanzo_mcp.tools.common.stats import StatsTool
|
|
22
|
-
from hanzo_mcp.tools.filesystem import register_filesystem_tools
|
|
23
|
-
from hanzo_mcp.tools.jupyter import register_jupyter_tools
|
|
24
|
-
from hanzo_mcp.tools.shell import register_shell_tools
|
|
25
|
-
from hanzo_mcp.tools.todo import register_todo_tools
|
|
26
|
-
from hanzo_mcp.tools.vector import register_vector_tools
|
|
27
|
-
from hanzo_mcp.tools.database import register_database_tools, DatabaseManager
|
|
28
32
|
|
|
29
33
|
# Try to import memory tools, but don't fail if hanzo-memory is not installed
|
|
30
34
|
try:
|
|
31
35
|
from hanzo_mcp.tools.memory import register_memory_tools
|
|
36
|
+
|
|
32
37
|
MEMORY_TOOLS_AVAILABLE = True
|
|
33
38
|
except ImportError:
|
|
34
39
|
MEMORY_TOOLS_AVAILABLE = False
|
|
35
40
|
register_memory_tools = None
|
|
36
|
-
from hanzo_mcp.tools.
|
|
41
|
+
from hanzo_mcp.tools.llm import (
|
|
42
|
+
LLMTool,
|
|
43
|
+
ConsensusTool,
|
|
44
|
+
LLMManageTool,
|
|
45
|
+
create_provider_tools,
|
|
46
|
+
)
|
|
47
|
+
from hanzo_mcp.tools.mcp import MCPTool, McpAddTool, McpStatsTool, McpRemoveTool
|
|
37
48
|
from hanzo_mcp.tools.editor import NeovimEditTool, NeovimCommandTool, NeovimSessionTool
|
|
38
|
-
from hanzo_mcp.tools.
|
|
49
|
+
from hanzo_mcp.tools.common.mode import activate_mode_from_env
|
|
39
50
|
from hanzo_mcp.tools.config.mode_tool import mode_tool
|
|
40
51
|
from hanzo_mcp.tools.common.mode_loader import ModeLoader
|
|
41
|
-
from hanzo_mcp.tools.common.mode import activate_mode_from_env
|
|
42
52
|
from hanzo_mcp.tools.common.plugin_loader import load_user_plugins
|
|
43
53
|
|
|
44
54
|
# Try to import LSP tool
|
|
45
55
|
try:
|
|
46
56
|
from hanzo_mcp.tools.lsp import LSPTool, create_lsp_tool
|
|
57
|
+
|
|
47
58
|
LSP_TOOL_AVAILABLE = True
|
|
48
59
|
except ImportError:
|
|
49
60
|
LSP_TOOL_AVAILABLE = False
|
|
@@ -84,7 +95,7 @@ def register_all_tools(
|
|
|
84
95
|
vector_config: Vector store configuration (default: None)
|
|
85
96
|
use_mode: Whether to use mode system for tool configuration (default: True)
|
|
86
97
|
force_mode: Force a specific mode to be active (default: None)
|
|
87
|
-
|
|
98
|
+
|
|
88
99
|
Returns:
|
|
89
100
|
List of registered BaseTool instances
|
|
90
101
|
"""
|
|
@@ -95,11 +106,15 @@ def register_all_tools(
|
|
|
95
106
|
try:
|
|
96
107
|
plugins = load_user_plugins()
|
|
97
108
|
import logging
|
|
109
|
+
|
|
98
110
|
logger = logging.getLogger(__name__)
|
|
99
111
|
if plugins:
|
|
100
|
-
logger.info(
|
|
112
|
+
logger.info(
|
|
113
|
+
f"Loaded {len(plugins)} user plugin tools: {', '.join(plugins.keys())}"
|
|
114
|
+
)
|
|
101
115
|
except Exception as e:
|
|
102
116
|
import logging
|
|
117
|
+
|
|
103
118
|
logger = logging.getLogger(__name__)
|
|
104
119
|
logger.warning(f"Failed to load user plugins: {e}")
|
|
105
120
|
plugins = {}
|
|
@@ -110,8 +125,7 @@ def register_all_tools(
|
|
|
110
125
|
activate_mode_from_env()
|
|
111
126
|
|
|
112
127
|
tool_config = ModeLoader.get_enabled_tools_from_mode(
|
|
113
|
-
base_enabled_tools=enabled_tools,
|
|
114
|
-
force_mode=force_mode
|
|
128
|
+
base_enabled_tools=enabled_tools, force_mode=force_mode
|
|
115
129
|
)
|
|
116
130
|
# Apply mode environment variables
|
|
117
131
|
ModeLoader.apply_environment_from_mode()
|
|
@@ -146,18 +160,26 @@ def register_all_tools(
|
|
|
146
160
|
}
|
|
147
161
|
|
|
148
162
|
# Create project manager if vector tools, batch_search, or unified_search are enabled
|
|
149
|
-
if
|
|
163
|
+
if (
|
|
164
|
+
any(vector_enabled.values())
|
|
165
|
+
or filesystem_enabled.get("batch_search", False)
|
|
166
|
+
or filesystem_enabled.get("search", False)
|
|
167
|
+
):
|
|
150
168
|
if vector_config:
|
|
151
169
|
from hanzo_mcp.tools.vector.project_manager import ProjectVectorManager
|
|
170
|
+
|
|
152
171
|
search_paths = [str(path) for path in permission_manager.allowed_paths]
|
|
153
172
|
project_manager = ProjectVectorManager(
|
|
154
173
|
global_db_path=vector_config.get("data_path"),
|
|
155
|
-
embedding_model=vector_config.get(
|
|
174
|
+
embedding_model=vector_config.get(
|
|
175
|
+
"embedding_model", "text-embedding-3-small"
|
|
176
|
+
),
|
|
156
177
|
dimension=vector_config.get("dimension", 1536),
|
|
157
178
|
)
|
|
158
179
|
# Auto-detect projects from search paths
|
|
159
180
|
detected_projects = project_manager.detect_projects(search_paths)
|
|
160
181
|
import logging
|
|
182
|
+
|
|
161
183
|
logger = logging.getLogger(__name__)
|
|
162
184
|
logger.info(f"Detected {len(detected_projects)} projects with LLM.md files")
|
|
163
185
|
|
|
@@ -178,7 +200,9 @@ def register_all_tools(
|
|
|
178
200
|
}
|
|
179
201
|
|
|
180
202
|
if any(jupyter_enabled.values()):
|
|
181
|
-
jupyter_tools = register_jupyter_tools(
|
|
203
|
+
jupyter_tools = register_jupyter_tools(
|
|
204
|
+
mcp_server, permission_manager, enabled_tools=jupyter_enabled
|
|
205
|
+
)
|
|
182
206
|
for tool in jupyter_tools:
|
|
183
207
|
all_tools[tool.name] = tool
|
|
184
208
|
|
|
@@ -189,7 +213,11 @@ def register_all_tools(
|
|
|
189
213
|
all_tools[tool.name] = tool
|
|
190
214
|
|
|
191
215
|
# Register agent tools if enabled
|
|
192
|
-
agent_enabled =
|
|
216
|
+
agent_enabled = (
|
|
217
|
+
enable_agent_tool
|
|
218
|
+
or is_tool_enabled("agent", False)
|
|
219
|
+
or is_tool_enabled("dispatch_agent", False)
|
|
220
|
+
)
|
|
193
221
|
swarm_enabled = is_tool_enabled("swarm", False)
|
|
194
222
|
|
|
195
223
|
if agent_enabled or swarm_enabled:
|
|
@@ -205,9 +233,12 @@ def register_all_tools(
|
|
|
205
233
|
)
|
|
206
234
|
# Filter based on what's enabled
|
|
207
235
|
for tool in agent_tools:
|
|
208
|
-
if
|
|
209
|
-
|
|
210
|
-
|
|
236
|
+
if (
|
|
237
|
+
tool.name == "agent"
|
|
238
|
+
and agent_enabled
|
|
239
|
+
or tool.name == "swarm"
|
|
240
|
+
and swarm_enabled
|
|
241
|
+
):
|
|
211
242
|
all_tools[tool.name] = tool
|
|
212
243
|
elif tool.name in ["claude", "codex", "gemini", "grok", "code_auth"]:
|
|
213
244
|
# CLI tools and auth are always included when agent tools are enabled
|
|
@@ -415,10 +446,7 @@ def register_all_tools(
|
|
|
415
446
|
if any(memory_enabled.values()) and MEMORY_TOOLS_AVAILABLE:
|
|
416
447
|
try:
|
|
417
448
|
memory_tools = register_memory_tools(
|
|
418
|
-
mcp_server,
|
|
419
|
-
permission_manager,
|
|
420
|
-
user_id="default",
|
|
421
|
-
project_id="default"
|
|
449
|
+
mcp_server, permission_manager, user_id="default", project_id="default"
|
|
422
450
|
)
|
|
423
451
|
# Filter based on enabled state
|
|
424
452
|
for tool in memory_tools:
|
|
@@ -446,6 +474,6 @@ def register_all_tools(
|
|
|
446
474
|
logger.info(f"Registered plugin tool: {plugin_name}")
|
|
447
475
|
except Exception as e:
|
|
448
476
|
logger.error(f"Failed to register plugin tool {plugin_name}: {e}")
|
|
449
|
-
|
|
477
|
+
|
|
450
478
|
# Return all registered tools
|
|
451
479
|
return list(all_tools.values())
|
|
@@ -4,22 +4,20 @@ This module provides tools that allow Claude to delegate tasks to sub-agents,
|
|
|
4
4
|
enabling concurrent execution of multiple operations and specialized processing.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import os
|
|
8
7
|
from mcp.server import FastMCP
|
|
9
8
|
|
|
9
|
+
from hanzo_mcp.tools.common.base import BaseTool, ToolRegistry
|
|
10
|
+
|
|
10
11
|
# Import the main implementations (using hanzo-agents SDK)
|
|
11
12
|
from hanzo_mcp.tools.agent.agent_tool import AgentTool
|
|
12
13
|
from hanzo_mcp.tools.agent.swarm_tool import SwarmTool
|
|
13
|
-
|
|
14
|
-
from hanzo_mcp.tools.
|
|
15
|
-
from hanzo_mcp.tools.agent.codex_cli_tool import CodexCLITool
|
|
16
|
-
from hanzo_mcp.tools.agent.gemini_cli_tool import GeminiCLITool
|
|
14
|
+
from hanzo_mcp.tools.agent.network_tool import NetworkTool
|
|
15
|
+
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
17
16
|
from hanzo_mcp.tools.agent.grok_cli_tool import GrokCLITool
|
|
18
17
|
from hanzo_mcp.tools.agent.code_auth_tool import CodeAuthTool
|
|
19
|
-
from hanzo_mcp.tools.agent.
|
|
20
|
-
from hanzo_mcp.tools.
|
|
21
|
-
|
|
22
|
-
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
18
|
+
from hanzo_mcp.tools.agent.codex_cli_tool import CodexCLITool
|
|
19
|
+
from hanzo_mcp.tools.agent.claude_cli_tool import ClaudeCLITool
|
|
20
|
+
from hanzo_mcp.tools.agent.gemini_cli_tool import GeminiCLITool
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
def register_agent_tools(
|
|
@@ -58,7 +56,7 @@ def register_agent_tools(
|
|
|
58
56
|
max_iterations=agent_max_iterations,
|
|
59
57
|
max_tool_uses=agent_max_tool_uses,
|
|
60
58
|
)
|
|
61
|
-
|
|
59
|
+
|
|
62
60
|
# Create swarm tool
|
|
63
61
|
swarm_tool = SwarmTool(
|
|
64
62
|
permission_manager=permission_manager,
|
|
@@ -69,36 +67,35 @@ def register_agent_tools(
|
|
|
69
67
|
agent_max_iterations=agent_max_iterations,
|
|
70
68
|
agent_max_tool_uses=agent_max_tool_uses,
|
|
71
69
|
)
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
|
|
74
71
|
# Create CLI agent tools
|
|
75
72
|
claude_cli_tool = ClaudeCLITool(
|
|
76
73
|
permission_manager=permission_manager,
|
|
77
74
|
model=agent_model, # Can override default Sonnet
|
|
78
75
|
)
|
|
79
|
-
|
|
76
|
+
|
|
80
77
|
codex_cli_tool = CodexCLITool(
|
|
81
78
|
permission_manager=permission_manager,
|
|
82
79
|
model=agent_model if agent_model and "gpt" in agent_model else None,
|
|
83
80
|
)
|
|
84
|
-
|
|
81
|
+
|
|
85
82
|
gemini_cli_tool = GeminiCLITool(
|
|
86
83
|
permission_manager=permission_manager,
|
|
87
84
|
model=agent_model if agent_model and "gemini" in agent_model else None,
|
|
88
85
|
)
|
|
89
|
-
|
|
86
|
+
|
|
90
87
|
grok_cli_tool = GrokCLITool(
|
|
91
88
|
permission_manager=permission_manager,
|
|
92
89
|
model=agent_model if agent_model and "grok" in agent_model else None,
|
|
93
90
|
)
|
|
94
|
-
|
|
91
|
+
|
|
95
92
|
# Create auth management tool
|
|
96
93
|
code_auth_tool = CodeAuthTool()
|
|
97
|
-
|
|
94
|
+
|
|
98
95
|
# Create network tool
|
|
99
96
|
network_tool = NetworkTool(
|
|
100
97
|
permission_manager=permission_manager,
|
|
101
|
-
default_mode="hybrid" # Prefer local, fallback to cloud
|
|
98
|
+
default_mode="hybrid", # Prefer local, fallback to cloud
|
|
102
99
|
)
|
|
103
100
|
|
|
104
101
|
# Register tools
|
|
@@ -113,7 +110,7 @@ def register_agent_tools(
|
|
|
113
110
|
|
|
114
111
|
# Return list of registered tools
|
|
115
112
|
return [
|
|
116
|
-
agent_tool,
|
|
113
|
+
agent_tool,
|
|
117
114
|
swarm_tool,
|
|
118
115
|
network_tool,
|
|
119
116
|
claude_cli_tool,
|