hanzo-mcp 0.9.0__py3-none-any.whl → 0.9.2__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 +1 -1
- hanzo_mcp/analytics/posthog_analytics.py +14 -1
- hanzo_mcp/cli.py +108 -4
- hanzo_mcp/server.py +11 -0
- hanzo_mcp/tools/__init__.py +3 -16
- hanzo_mcp/tools/agent/__init__.py +5 -0
- hanzo_mcp/tools/agent/agent.py +5 -0
- hanzo_mcp/tools/agent/agent_tool.py +3 -17
- hanzo_mcp/tools/agent/agent_tool_v1_deprecated.py +623 -0
- hanzo_mcp/tools/agent/clarification_tool.py +7 -1
- hanzo_mcp/tools/agent/claude_desktop_auth.py +16 -6
- hanzo_mcp/tools/agent/cli_agent_base.py +5 -0
- hanzo_mcp/tools/agent/cli_tools.py +26 -0
- hanzo_mcp/tools/agent/code_auth_tool.py +5 -0
- hanzo_mcp/tools/agent/critic_tool.py +7 -1
- hanzo_mcp/tools/agent/iching_tool.py +5 -0
- hanzo_mcp/tools/agent/network_tool.py +5 -0
- hanzo_mcp/tools/agent/review_tool.py +7 -1
- hanzo_mcp/tools/agent/swarm_alias.py +5 -0
- hanzo_mcp/tools/agent/swarm_tool.py +701 -0
- hanzo_mcp/tools/agent/swarm_tool_v1_deprecated.py +554 -0
- hanzo_mcp/tools/agent/unified_cli_tools.py +5 -0
- hanzo_mcp/tools/common/auto_timeout.py +254 -0
- hanzo_mcp/tools/common/base.py +4 -0
- hanzo_mcp/tools/common/batch_tool.py +5 -0
- hanzo_mcp/tools/common/config_tool.py +5 -0
- hanzo_mcp/tools/common/critic_tool.py +5 -0
- hanzo_mcp/tools/common/paginated_base.py +4 -0
- hanzo_mcp/tools/common/permissions.py +38 -12
- hanzo_mcp/tools/common/personality.py +673 -980
- hanzo_mcp/tools/common/stats.py +5 -0
- hanzo_mcp/tools/common/thinking_tool.py +5 -0
- hanzo_mcp/tools/common/timeout_parser.py +103 -0
- hanzo_mcp/tools/common/tool_disable.py +5 -0
- hanzo_mcp/tools/common/tool_enable.py +5 -0
- hanzo_mcp/tools/common/tool_list.py +5 -0
- hanzo_mcp/tools/config/config_tool.py +5 -0
- hanzo_mcp/tools/config/mode_tool.py +5 -0
- hanzo_mcp/tools/database/graph.py +5 -0
- hanzo_mcp/tools/database/graph_add.py +5 -0
- hanzo_mcp/tools/database/graph_query.py +5 -0
- hanzo_mcp/tools/database/graph_remove.py +5 -0
- hanzo_mcp/tools/database/graph_search.py +5 -0
- hanzo_mcp/tools/database/graph_stats.py +5 -0
- hanzo_mcp/tools/database/sql.py +5 -0
- hanzo_mcp/tools/database/sql_query.py +2 -0
- hanzo_mcp/tools/database/sql_search.py +5 -0
- hanzo_mcp/tools/database/sql_stats.py +5 -0
- hanzo_mcp/tools/editor/neovim_command.py +5 -0
- hanzo_mcp/tools/editor/neovim_edit.py +7 -2
- hanzo_mcp/tools/editor/neovim_session.py +5 -0
- hanzo_mcp/tools/filesystem/__init__.py +23 -26
- hanzo_mcp/tools/filesystem/ast_tool.py +3 -4
- hanzo_mcp/tools/filesystem/base.py +2 -18
- hanzo_mcp/tools/filesystem/batch_search.py +825 -0
- hanzo_mcp/tools/filesystem/content_replace.py +5 -3
- hanzo_mcp/tools/filesystem/diff.py +5 -0
- hanzo_mcp/tools/filesystem/directory_tree.py +34 -281
- hanzo_mcp/tools/filesystem/directory_tree_paginated.py +345 -0
- hanzo_mcp/tools/filesystem/edit.py +6 -5
- hanzo_mcp/tools/filesystem/find.py +177 -311
- hanzo_mcp/tools/filesystem/find_files.py +370 -0
- hanzo_mcp/tools/filesystem/git_search.py +5 -3
- hanzo_mcp/tools/filesystem/grep.py +454 -0
- hanzo_mcp/tools/filesystem/multi_edit.py +6 -5
- hanzo_mcp/tools/filesystem/read.py +10 -9
- hanzo_mcp/tools/filesystem/rules_tool.py +6 -4
- hanzo_mcp/tools/filesystem/search_tool.py +728 -0
- hanzo_mcp/tools/filesystem/symbols_tool.py +510 -0
- hanzo_mcp/tools/filesystem/tree.py +273 -0
- hanzo_mcp/tools/filesystem/watch.py +6 -1
- hanzo_mcp/tools/filesystem/write.py +13 -7
- hanzo_mcp/tools/jupyter/jupyter.py +30 -2
- hanzo_mcp/tools/jupyter/notebook_edit.py +298 -0
- hanzo_mcp/tools/jupyter/notebook_read.py +148 -0
- hanzo_mcp/tools/llm/consensus_tool.py +8 -6
- hanzo_mcp/tools/llm/llm_manage.py +5 -0
- hanzo_mcp/tools/llm/llm_tool.py +2 -0
- hanzo_mcp/tools/llm/llm_unified.py +5 -0
- hanzo_mcp/tools/llm/provider_tools.py +5 -0
- hanzo_mcp/tools/lsp/lsp_tool.py +475 -622
- hanzo_mcp/tools/mcp/mcp_add.py +7 -2
- hanzo_mcp/tools/mcp/mcp_remove.py +15 -2
- hanzo_mcp/tools/mcp/mcp_stats.py +5 -0
- hanzo_mcp/tools/mcp/mcp_tool.py +5 -0
- hanzo_mcp/tools/memory/knowledge_tools.py +14 -0
- hanzo_mcp/tools/memory/memory_tools.py +17 -0
- hanzo_mcp/tools/search/find_tool.py +5 -3
- hanzo_mcp/tools/search/unified_search.py +3 -1
- hanzo_mcp/tools/shell/__init__.py +2 -14
- hanzo_mcp/tools/shell/base_process.py +4 -2
- hanzo_mcp/tools/shell/bash_tool.py +2 -0
- hanzo_mcp/tools/shell/command_executor.py +7 -7
- hanzo_mcp/tools/shell/logs.py +5 -0
- hanzo_mcp/tools/shell/npx.py +5 -0
- hanzo_mcp/tools/shell/npx_background.py +5 -0
- hanzo_mcp/tools/shell/npx_tool.py +5 -0
- hanzo_mcp/tools/shell/open.py +5 -0
- hanzo_mcp/tools/shell/pkill.py +5 -0
- hanzo_mcp/tools/shell/process_tool.py +5 -0
- hanzo_mcp/tools/shell/processes.py +5 -0
- hanzo_mcp/tools/shell/run_background.py +5 -0
- hanzo_mcp/tools/shell/run_command.py +2 -0
- hanzo_mcp/tools/shell/run_command_windows.py +5 -0
- hanzo_mcp/tools/shell/streaming_command.py +5 -0
- hanzo_mcp/tools/shell/uvx.py +5 -0
- hanzo_mcp/tools/shell/uvx_background.py +5 -0
- hanzo_mcp/tools/shell/uvx_tool.py +5 -0
- hanzo_mcp/tools/shell/zsh_tool.py +3 -0
- hanzo_mcp/tools/todo/todo.py +5 -0
- hanzo_mcp/tools/todo/todo_read.py +142 -0
- hanzo_mcp/tools/todo/todo_write.py +367 -0
- hanzo_mcp/tools/vector/__init__.py +42 -95
- hanzo_mcp/tools/vector/index_tool.py +5 -0
- hanzo_mcp/tools/vector/vector.py +5 -0
- hanzo_mcp/tools/vector/vector_index.py +5 -0
- hanzo_mcp/tools/vector/vector_search.py +5 -0
- {hanzo_mcp-0.9.0.dist-info → hanzo_mcp-0.9.2.dist-info}/METADATA +1 -1
- hanzo_mcp-0.9.2.dist-info/RECORD +195 -0
- hanzo_mcp/tools/common/path_utils.py +0 -34
- hanzo_mcp/tools/compiler/__init__.py +0 -8
- hanzo_mcp/tools/compiler/sandboxed_compiler.py +0 -681
- hanzo_mcp/tools/environment/__init__.py +0 -8
- hanzo_mcp/tools/environment/environment_detector.py +0 -594
- hanzo_mcp/tools/filesystem/search.py +0 -1160
- hanzo_mcp/tools/framework/__init__.py +0 -8
- hanzo_mcp/tools/framework/framework_modes.py +0 -714
- hanzo_mcp/tools/memory/conversation_memory.py +0 -636
- hanzo_mcp/tools/shell/run_tool.py +0 -56
- hanzo_mcp/tools/vector/node_tool.py +0 -538
- hanzo_mcp/tools/vector/unified_vector.py +0 -384
- hanzo_mcp-0.9.0.dist-info/RECORD +0 -191
- {hanzo_mcp-0.9.0.dist-info → hanzo_mcp-0.9.2.dist-info}/WHEEL +0 -0
- {hanzo_mcp-0.9.0.dist-info → hanzo_mcp-0.9.2.dist-info}/entry_points.txt +0 -0
- {hanzo_mcp-0.9.0.dist-info → hanzo_mcp-0.9.2.dist-info}/top_level.txt +0 -0
hanzo_mcp/tools/common/stats.py
CHANGED
|
@@ -7,6 +7,8 @@ from datetime import datetime
|
|
|
7
7
|
import psutil
|
|
8
8
|
from mcp.server.fastmcp import Context as MCPContext
|
|
9
9
|
|
|
10
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
11
|
+
|
|
10
12
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
11
13
|
from hanzo_mcp.tools.mcp.mcp_add import McpAddTool
|
|
12
14
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
@@ -57,6 +59,9 @@ Example:
|
|
|
57
59
|
"""
|
|
58
60
|
|
|
59
61
|
@override
|
|
62
|
+
@auto_timeout("stats")
|
|
63
|
+
|
|
64
|
+
|
|
60
65
|
async def call(
|
|
61
66
|
self,
|
|
62
67
|
ctx: MCPContext,
|
|
@@ -7,6 +7,8 @@ from typing import Unpack, Annotated, TypedDict, final, override
|
|
|
7
7
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
from mcp.server import FastMCP
|
|
10
|
+
|
|
11
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
10
12
|
from mcp.server.fastmcp import Context as MCPContext
|
|
11
13
|
|
|
12
14
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
@@ -93,6 +95,9 @@ Feature Implementation Planning
|
|
|
93
95
|
pass
|
|
94
96
|
|
|
95
97
|
@override
|
|
98
|
+
@auto_timeout("thinking")
|
|
99
|
+
|
|
100
|
+
|
|
96
101
|
async def call(
|
|
97
102
|
self,
|
|
98
103
|
ctx: MCPContext,
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Human-readable timeout parsing utilities."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Union
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def parse_timeout(timeout_str: Union[str, int, float]) -> float:
|
|
8
|
+
"""Parse timeout from human-readable string or numeric value.
|
|
9
|
+
|
|
10
|
+
Supports formats like:
|
|
11
|
+
- "2min", "5m", "120s", "30sec", "1.5h", "0.5hr"
|
|
12
|
+
- 120 (seconds as number)
|
|
13
|
+
- "120" (seconds as string)
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
timeout_str: Timeout value as string or number
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
Timeout in seconds as float
|
|
20
|
+
|
|
21
|
+
Raises:
|
|
22
|
+
ValueError: If format is not recognized
|
|
23
|
+
"""
|
|
24
|
+
if isinstance(timeout_str, (int, float)):
|
|
25
|
+
return float(timeout_str)
|
|
26
|
+
|
|
27
|
+
if isinstance(timeout_str, str):
|
|
28
|
+
# Handle pure numeric strings
|
|
29
|
+
try:
|
|
30
|
+
return float(timeout_str)
|
|
31
|
+
except ValueError:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
# Handle human-readable formats
|
|
35
|
+
timeout_str = timeout_str.lower().strip()
|
|
36
|
+
|
|
37
|
+
# Regex patterns for different time units
|
|
38
|
+
patterns = [
|
|
39
|
+
# Hours: 1h, 1.5hr, 2hour, 3hours
|
|
40
|
+
(r'^(\d*\.?\d+)\s*h(?:r|our|ours)?$', 3600),
|
|
41
|
+
# Minutes: 2m, 5min, 10mins, 1.5minute
|
|
42
|
+
(r'^(\d*\.?\d+)\s*m(?:in|ins|inute|inutes)?$', 60),
|
|
43
|
+
# Seconds: 30s, 120sec, 45secs, 60second, 90seconds
|
|
44
|
+
(r'^(\d*\.?\d+)\s*s(?:ec|ecs|econd|econds)?$', 1),
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
for pattern, multiplier in patterns:
|
|
48
|
+
match = re.match(pattern, timeout_str)
|
|
49
|
+
if match:
|
|
50
|
+
value = float(match.group(1))
|
|
51
|
+
return value * multiplier
|
|
52
|
+
|
|
53
|
+
# If no pattern matches, raise error
|
|
54
|
+
raise ValueError(
|
|
55
|
+
f"Invalid timeout format: '{timeout_str}'. "
|
|
56
|
+
f"Supported formats: 2min, 5m, 120s, 30sec, 1.5h, 0.5hr, or numeric seconds."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
raise ValueError(f"Unsupported timeout type: {type(timeout_str)}")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def format_timeout(seconds: float) -> str:
|
|
63
|
+
"""Format timeout seconds into human-readable string.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
seconds: Timeout in seconds
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Human-readable string like "2m", "90s", "1.5h"
|
|
70
|
+
"""
|
|
71
|
+
if seconds >= 3600: # >= 1 hour
|
|
72
|
+
hours = seconds / 3600
|
|
73
|
+
if hours.is_integer():
|
|
74
|
+
return f"{int(hours)}h"
|
|
75
|
+
else:
|
|
76
|
+
return f"{hours:.1f}h"
|
|
77
|
+
elif seconds >= 60: # >= 1 minute
|
|
78
|
+
minutes = seconds / 60
|
|
79
|
+
if minutes.is_integer():
|
|
80
|
+
return f"{int(minutes)}m"
|
|
81
|
+
else:
|
|
82
|
+
return f"{minutes:.1f}m"
|
|
83
|
+
else: # < 1 minute
|
|
84
|
+
if seconds.is_integer():
|
|
85
|
+
return f"{int(seconds)}s"
|
|
86
|
+
else:
|
|
87
|
+
return f"{seconds:.1f}s"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# Test the parser
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
test_cases = [
|
|
93
|
+
"2min", "5m", "120s", "30sec", "1.5h", "0.5hr",
|
|
94
|
+
"90", 120, 3600.0, "1hour", "2hours", "30seconds"
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
for case in test_cases:
|
|
98
|
+
try:
|
|
99
|
+
result = parse_timeout(case)
|
|
100
|
+
formatted = format_timeout(result)
|
|
101
|
+
print(f"{case} -> {result}s ({formatted})")
|
|
102
|
+
except ValueError as e:
|
|
103
|
+
print(f"{case} -> ERROR: {e}")
|
|
@@ -5,6 +5,8 @@ from typing import Unpack, Annotated, TypedDict, final, override
|
|
|
5
5
|
from pydantic import Field
|
|
6
6
|
from mcp.server.fastmcp import Context as MCPContext
|
|
7
7
|
|
|
8
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
9
|
+
|
|
8
10
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
9
11
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
10
12
|
from hanzo_mcp.tools.common.tool_enable import ToolEnableTool
|
|
@@ -72,6 +74,9 @@ Use 'tool_enable' to re-enable disabled tools.
|
|
|
72
74
|
"""
|
|
73
75
|
|
|
74
76
|
@override
|
|
77
|
+
@auto_timeout("tool_disable")
|
|
78
|
+
|
|
79
|
+
|
|
75
80
|
async def call(
|
|
76
81
|
self,
|
|
77
82
|
ctx: MCPContext,
|
|
@@ -7,6 +7,8 @@ from pathlib import Path
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
from mcp.server.fastmcp import Context as MCPContext
|
|
9
9
|
|
|
10
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
11
|
+
|
|
10
12
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
11
13
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
12
14
|
|
|
@@ -119,6 +121,9 @@ Use 'tool_list' to see all available tools and their status.
|
|
|
119
121
|
"""
|
|
120
122
|
|
|
121
123
|
@override
|
|
124
|
+
@auto_timeout("tool_enable")
|
|
125
|
+
|
|
126
|
+
|
|
122
127
|
async def call(
|
|
123
128
|
self,
|
|
124
129
|
ctx: MCPContext,
|
|
@@ -5,6 +5,8 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
5
5
|
from pydantic import Field
|
|
6
6
|
from mcp.server.fastmcp import Context as MCPContext
|
|
7
7
|
|
|
8
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
9
|
+
|
|
8
10
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
9
11
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
10
12
|
from hanzo_mcp.tools.common.tool_enable import ToolEnableTool
|
|
@@ -158,6 +160,9 @@ Use 'tool_enable' and 'tool_disable' to change tool status.
|
|
|
158
160
|
"""
|
|
159
161
|
|
|
160
162
|
@override
|
|
163
|
+
@auto_timeout("tool_list")
|
|
164
|
+
|
|
165
|
+
|
|
161
166
|
async def call(
|
|
162
167
|
self,
|
|
163
168
|
ctx: MCPContext,
|
|
@@ -9,6 +9,8 @@ from pathlib import Path
|
|
|
9
9
|
from pydantic import Field
|
|
10
10
|
from mcp.server.fastmcp import Context as MCPContext
|
|
11
11
|
|
|
12
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
13
|
+
|
|
12
14
|
from hanzo_mcp.config import load_settings, save_settings
|
|
13
15
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
14
16
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -104,6 +106,9 @@ config --action list
|
|
|
104
106
|
config --action toggle index.scope --path ./project"""
|
|
105
107
|
|
|
106
108
|
@override
|
|
109
|
+
@auto_timeout("config")
|
|
110
|
+
|
|
111
|
+
|
|
107
112
|
async def call(
|
|
108
113
|
self,
|
|
109
114
|
ctx: MCPContext,
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
from typing import Optional, override
|
|
4
4
|
|
|
5
5
|
from mcp.server import FastMCP
|
|
6
|
+
|
|
7
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
6
8
|
from mcp.server.fastmcp import Context as MCPContext
|
|
7
9
|
|
|
8
10
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
@@ -310,6 +312,9 @@ mode --action current"""
|
|
|
310
312
|
"""Handle mode tool calls."""
|
|
311
313
|
return await tool_self.run(ctx, action=action, name=name)
|
|
312
314
|
|
|
315
|
+
@auto_timeout("mode")
|
|
316
|
+
|
|
317
|
+
|
|
313
318
|
async def call(self, ctx: MCPContext, **params) -> str:
|
|
314
319
|
"""Call the tool with arguments."""
|
|
315
320
|
return await self.run(ctx, action=params.get("action", "list"), name=params.get("name"))
|
|
@@ -15,6 +15,8 @@ from typing import (
|
|
|
15
15
|
from pydantic import Field
|
|
16
16
|
from mcp.server.fastmcp import Context as MCPContext
|
|
17
17
|
|
|
18
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
19
|
+
|
|
18
20
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
19
21
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
20
22
|
from hanzo_mcp.tools.database.database_manager import DatabaseManager
|
|
@@ -146,6 +148,9 @@ graph --action search --pattern "John" --node-type User
|
|
|
146
148
|
"""
|
|
147
149
|
|
|
148
150
|
@override
|
|
151
|
+
@auto_timeout("graph")
|
|
152
|
+
|
|
153
|
+
|
|
149
154
|
async def call(
|
|
150
155
|
self,
|
|
151
156
|
ctx: MCPContext,
|
|
@@ -6,6 +6,8 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from mcp.server.fastmcp import Context as MCPContext
|
|
8
8
|
|
|
9
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
10
|
+
|
|
9
11
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
10
12
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
11
13
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -137,6 +139,9 @@ Examples:
|
|
|
137
139
|
"""
|
|
138
140
|
|
|
139
141
|
@override
|
|
142
|
+
@auto_timeout("graph_add")
|
|
143
|
+
|
|
144
|
+
|
|
140
145
|
async def call(
|
|
141
146
|
self,
|
|
142
147
|
ctx: MCPContext,
|
|
@@ -15,6 +15,8 @@ from collections import deque
|
|
|
15
15
|
from pydantic import Field
|
|
16
16
|
from mcp.server.fastmcp import Context as MCPContext
|
|
17
17
|
|
|
18
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
19
|
+
|
|
18
20
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
19
21
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
20
22
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -147,6 +149,9 @@ Examples:
|
|
|
147
149
|
"""
|
|
148
150
|
|
|
149
151
|
@override
|
|
152
|
+
@auto_timeout("graph_query")
|
|
153
|
+
|
|
154
|
+
|
|
150
155
|
async def call(
|
|
151
156
|
self,
|
|
152
157
|
ctx: MCPContext,
|
|
@@ -5,6 +5,8 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
5
5
|
from pydantic import Field
|
|
6
6
|
from mcp.server.fastmcp import Context as MCPContext
|
|
7
7
|
|
|
8
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
9
|
+
|
|
8
10
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
9
11
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
10
12
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -116,6 +118,9 @@ Examples:
|
|
|
116
118
|
"""
|
|
117
119
|
|
|
118
120
|
@override
|
|
121
|
+
@auto_timeout("graph_remove")
|
|
122
|
+
|
|
123
|
+
|
|
119
124
|
async def call(
|
|
120
125
|
self,
|
|
121
126
|
ctx: MCPContext,
|
|
@@ -7,6 +7,8 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
from mcp.server.fastmcp import Context as MCPContext
|
|
9
9
|
|
|
10
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
11
|
+
|
|
10
12
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
11
13
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
12
14
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -117,6 +119,9 @@ Examples:
|
|
|
117
119
|
"""
|
|
118
120
|
|
|
119
121
|
@override
|
|
122
|
+
@auto_timeout("graph_search")
|
|
123
|
+
|
|
124
|
+
|
|
120
125
|
async def call(
|
|
121
126
|
self,
|
|
122
127
|
ctx: MCPContext,
|
|
@@ -7,6 +7,8 @@ from collections import defaultdict
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
from mcp.server.fastmcp import Context as MCPContext
|
|
9
9
|
|
|
10
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
11
|
+
|
|
10
12
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
11
13
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
12
14
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -97,6 +99,9 @@ Examples:
|
|
|
97
99
|
"""
|
|
98
100
|
|
|
99
101
|
@override
|
|
102
|
+
@auto_timeout("graph_stats")
|
|
103
|
+
|
|
104
|
+
|
|
100
105
|
async def call(
|
|
101
106
|
self,
|
|
102
107
|
ctx: MCPContext,
|
hanzo_mcp/tools/database/sql.py
CHANGED
|
@@ -15,6 +15,8 @@ from typing import (
|
|
|
15
15
|
from pydantic import Field
|
|
16
16
|
from mcp.server.fastmcp import Context as MCPContext
|
|
17
17
|
|
|
18
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
19
|
+
|
|
18
20
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
19
21
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
20
22
|
from hanzo_mcp.tools.database.database_manager import DatabaseManager
|
|
@@ -100,6 +102,9 @@ sql --action stats --table users
|
|
|
100
102
|
"""
|
|
101
103
|
|
|
102
104
|
@override
|
|
105
|
+
@auto_timeout("sql")
|
|
106
|
+
|
|
107
|
+
|
|
103
108
|
async def call(
|
|
104
109
|
self,
|
|
105
110
|
ctx: MCPContext,
|
|
@@ -6,6 +6,7 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from mcp.server.fastmcp import Context as MCPContext
|
|
8
8
|
|
|
9
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
9
10
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
10
11
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
11
12
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -89,6 +90,7 @@ Examples:
|
|
|
89
90
|
Note: Use sql_search for text search operations."""
|
|
90
91
|
|
|
91
92
|
@override
|
|
93
|
+
@auto_timeout("sql_query")
|
|
92
94
|
async def call(
|
|
93
95
|
self,
|
|
94
96
|
ctx: MCPContext,
|
|
@@ -6,6 +6,8 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from mcp.server.fastmcp import Context as MCPContext
|
|
8
8
|
|
|
9
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
10
|
+
|
|
9
11
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
10
12
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
11
13
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -107,6 +109,9 @@ Examples:
|
|
|
107
109
|
Use sql_query for complex queries with joins, conditions, etc."""
|
|
108
110
|
|
|
109
111
|
@override
|
|
112
|
+
@auto_timeout("sql_search")
|
|
113
|
+
|
|
114
|
+
|
|
110
115
|
async def call(
|
|
111
116
|
self,
|
|
112
117
|
ctx: MCPContext,
|
|
@@ -6,6 +6,8 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from mcp.server.fastmcp import Context as MCPContext
|
|
8
8
|
|
|
9
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
10
|
+
|
|
9
11
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
10
12
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
11
13
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -75,6 +77,9 @@ Examples:
|
|
|
75
77
|
"""
|
|
76
78
|
|
|
77
79
|
@override
|
|
80
|
+
@auto_timeout("sql_stats")
|
|
81
|
+
|
|
82
|
+
|
|
78
83
|
async def call(
|
|
79
84
|
self,
|
|
80
85
|
ctx: MCPContext,
|
|
@@ -9,6 +9,8 @@ from typing import List, Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
9
9
|
from pydantic import Field
|
|
10
10
|
from mcp.server.fastmcp import Context as MCPContext
|
|
11
11
|
|
|
12
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
13
|
+
|
|
12
14
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
13
15
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
14
16
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -128,6 +130,9 @@ Note: Requires Neovim to be installed.
|
|
|
128
130
|
"""
|
|
129
131
|
|
|
130
132
|
@override
|
|
133
|
+
@auto_timeout("neovim_command")
|
|
134
|
+
|
|
135
|
+
|
|
131
136
|
async def call(
|
|
132
137
|
self,
|
|
133
138
|
ctx: MCPContext,
|
|
@@ -8,6 +8,8 @@ from typing import Unpack, Optional, Annotated, TypedDict, final, override
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
from mcp.server.fastmcp import Context as MCPContext
|
|
10
10
|
|
|
11
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
12
|
+
|
|
11
13
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
12
14
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
13
15
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
@@ -125,6 +127,9 @@ Note: Requires Neovim to be installed and available in PATH.
|
|
|
125
127
|
"""
|
|
126
128
|
|
|
127
129
|
@override
|
|
130
|
+
@auto_timeout("neovim_edit")
|
|
131
|
+
|
|
132
|
+
|
|
128
133
|
async def call(
|
|
129
134
|
self,
|
|
130
135
|
ctx: MCPContext,
|
|
@@ -252,7 +257,7 @@ Or visit: https://neovim.io/"""
|
|
|
252
257
|
end if
|
|
253
258
|
end tell"""
|
|
254
259
|
|
|
255
|
-
subprocess.run(["osascript", "-e", applescript])
|
|
260
|
+
subprocess.run(["osascript", "-e", applescript], timeout=10)
|
|
256
261
|
return f"Opened {file_path} in Neovim (new terminal window)"
|
|
257
262
|
|
|
258
263
|
elif shutil.which("gnome-terminal"):
|
|
@@ -272,7 +277,7 @@ Or visit: https://neovim.io/"""
|
|
|
272
277
|
|
|
273
278
|
else:
|
|
274
279
|
# Run and wait for completion
|
|
275
|
-
result = subprocess.run(cmd)
|
|
280
|
+
result = subprocess.run(cmd, timeout=120)
|
|
276
281
|
|
|
277
282
|
if result.returncode == 0:
|
|
278
283
|
return f"Successfully edited {file_path} in Neovim"
|
|
@@ -11,6 +11,8 @@ from datetime import datetime
|
|
|
11
11
|
from pydantic import Field
|
|
12
12
|
from mcp.server.fastmcp import Context as MCPContext
|
|
13
13
|
|
|
14
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
15
|
+
|
|
14
16
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
15
17
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
16
18
|
|
|
@@ -114,6 +116,9 @@ Note: Requires Neovim to be installed.
|
|
|
114
116
|
"""
|
|
115
117
|
|
|
116
118
|
@override
|
|
119
|
+
@auto_timeout("neovim_session")
|
|
120
|
+
|
|
121
|
+
|
|
117
122
|
async def call(
|
|
118
123
|
self,
|
|
119
124
|
ctx: MCPContext,
|
|
@@ -9,30 +9,25 @@ from mcp.server import FastMCP
|
|
|
9
9
|
from hanzo_mcp.tools.common.base import BaseTool, ToolRegistry
|
|
10
10
|
from hanzo_mcp.tools.filesystem.diff import create_diff_tool
|
|
11
11
|
from hanzo_mcp.tools.filesystem.edit import Edit
|
|
12
|
+
from hanzo_mcp.tools.filesystem.grep import Grep
|
|
12
13
|
from hanzo_mcp.tools.filesystem.read import ReadTool
|
|
13
14
|
from hanzo_mcp.tools.filesystem.watch import watch_tool
|
|
14
15
|
from hanzo_mcp.tools.filesystem.write import Write
|
|
15
16
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
16
17
|
from hanzo_mcp.tools.filesystem.ast_tool import ASTTool
|
|
17
|
-
from hanzo_mcp.tools.filesystem.
|
|
18
|
+
from hanzo_mcp.tools.filesystem.find_files import FindFilesTool
|
|
18
19
|
from hanzo_mcp.tools.filesystem.git_search import GitSearchTool
|
|
19
20
|
from hanzo_mcp.tools.filesystem.multi_edit import MultiEdit
|
|
20
21
|
from hanzo_mcp.tools.filesystem.rules_tool import RulesTool
|
|
22
|
+
from hanzo_mcp.tools.filesystem.search_tool import SearchTool
|
|
23
|
+
from hanzo_mcp.tools.filesystem.batch_search import BatchSearchTool
|
|
21
24
|
from hanzo_mcp.tools.filesystem.directory_tree import DirectoryTreeTool
|
|
22
25
|
from hanzo_mcp.tools.filesystem.content_replace import ContentReplaceTool
|
|
23
26
|
|
|
24
|
-
# Import unified search tool (which includes legacy Grep as alias)
|
|
25
|
-
from hanzo_mcp.tools.filesystem.search import (
|
|
26
|
-
UnifiedSearchTool,
|
|
27
|
-
Grep, # Legacy alias for backward compatibility
|
|
28
|
-
create_unified_search_tool,
|
|
29
|
-
create_grep_tool,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
27
|
# Import new search tools
|
|
33
28
|
try:
|
|
34
29
|
from hanzo_mcp.tools.search import (
|
|
35
|
-
FindTool
|
|
30
|
+
FindTool,
|
|
36
31
|
UnifiedSearch,
|
|
37
32
|
create_find_tool,
|
|
38
33
|
create_unified_search_tool,
|
|
@@ -49,15 +44,14 @@ __all__ = [
|
|
|
49
44
|
"Edit",
|
|
50
45
|
"MultiEdit",
|
|
51
46
|
"DirectoryTreeTool",
|
|
52
|
-
"Grep",
|
|
53
|
-
"UnifiedSearchTool", # New unified search tool
|
|
47
|
+
"Grep",
|
|
54
48
|
"ContentReplaceTool",
|
|
55
49
|
"ASTTool",
|
|
56
50
|
"GitSearchTool",
|
|
57
|
-
"
|
|
51
|
+
"BatchSearchTool",
|
|
52
|
+
"FindFilesTool",
|
|
58
53
|
"RulesTool",
|
|
59
|
-
"
|
|
60
|
-
"create_grep_tool",
|
|
54
|
+
"SearchTool",
|
|
61
55
|
"get_filesystem_tools",
|
|
62
56
|
"register_filesystem_tools",
|
|
63
57
|
]
|
|
@@ -82,14 +76,15 @@ def get_read_only_filesystem_tools(
|
|
|
82
76
|
Grep(permission_manager),
|
|
83
77
|
ASTTool(permission_manager),
|
|
84
78
|
GitSearchTool(permission_manager),
|
|
85
|
-
|
|
79
|
+
FindFilesTool(permission_manager),
|
|
86
80
|
RulesTool(permission_manager),
|
|
87
81
|
watch_tool,
|
|
88
82
|
create_diff_tool(permission_manager),
|
|
89
83
|
]
|
|
90
84
|
|
|
91
|
-
# Add
|
|
92
|
-
|
|
85
|
+
# Add search if project manager is available
|
|
86
|
+
if project_manager:
|
|
87
|
+
tools.append(SearchTool(permission_manager, project_manager))
|
|
93
88
|
|
|
94
89
|
# Add new search tools if available
|
|
95
90
|
if UNIFIED_SEARCH_AVAILABLE:
|
|
@@ -118,14 +113,15 @@ def get_filesystem_tools(permission_manager: PermissionManager, project_manager=
|
|
|
118
113
|
ContentReplaceTool(permission_manager),
|
|
119
114
|
ASTTool(permission_manager),
|
|
120
115
|
GitSearchTool(permission_manager),
|
|
121
|
-
|
|
116
|
+
FindFilesTool(permission_manager),
|
|
122
117
|
RulesTool(permission_manager),
|
|
123
118
|
watch_tool,
|
|
124
119
|
create_diff_tool(permission_manager),
|
|
125
120
|
]
|
|
126
121
|
|
|
127
|
-
# Add
|
|
128
|
-
|
|
122
|
+
# Add search if project manager is available
|
|
123
|
+
if project_manager:
|
|
124
|
+
tools.append(SearchTool(permission_manager, project_manager))
|
|
129
125
|
|
|
130
126
|
# Add new search tools if available
|
|
131
127
|
if UNIFIED_SEARCH_AVAILABLE:
|
|
@@ -162,13 +158,14 @@ def register_filesystem_tools(
|
|
|
162
158
|
"edit": Edit,
|
|
163
159
|
"multi_edit": MultiEdit,
|
|
164
160
|
"directory_tree": DirectoryTreeTool,
|
|
165
|
-
"grep": Grep,
|
|
166
|
-
"search": UnifiedSearchTool, # New unified search tool (replaces SearchTool and BatchSearchTool)
|
|
161
|
+
"grep": Grep,
|
|
167
162
|
"ast": ASTTool, # AST-based code structure search with tree-sitter
|
|
168
163
|
"git_search": GitSearchTool,
|
|
169
164
|
"content_replace": ContentReplaceTool,
|
|
170
|
-
"
|
|
165
|
+
"batch_search": BatchSearchTool,
|
|
166
|
+
"find_files": FindFilesTool,
|
|
171
167
|
"rules": RulesTool,
|
|
168
|
+
"search": SearchTool,
|
|
172
169
|
"watch": lambda pm: watch_tool, # Singleton instance
|
|
173
170
|
"diff": create_diff_tool,
|
|
174
171
|
}
|
|
@@ -185,8 +182,8 @@ def register_filesystem_tools(
|
|
|
185
182
|
for tool_name, enabled in enabled_tools.items():
|
|
186
183
|
if enabled and tool_name in tool_classes:
|
|
187
184
|
tool_class = tool_classes[tool_name]
|
|
188
|
-
if tool_name
|
|
189
|
-
#
|
|
185
|
+
if tool_name in ["batch_search", "search"]:
|
|
186
|
+
# Batch search and search require project_manager
|
|
190
187
|
tools.append(tool_class(permission_manager, project_manager))
|
|
191
188
|
elif tool_name == "watch":
|
|
192
189
|
# Watch tool is a singleton
|
|
@@ -15,6 +15,7 @@ from grep_ast.grep_ast import TreeContext
|
|
|
15
15
|
from mcp.server.fastmcp import Context as MCPContext
|
|
16
16
|
|
|
17
17
|
from hanzo_mcp.tools.filesystem.base import FilesystemBaseTool
|
|
18
|
+
from hanzo_mcp.tools.common.auto_timeout import auto_timeout
|
|
18
19
|
|
|
19
20
|
Pattern = Annotated[
|
|
20
21
|
str,
|
|
@@ -97,6 +98,7 @@ ast "def test_" ./tests
|
|
|
97
98
|
Searches code structure intelligently, understanding syntax and providing semantic context."""
|
|
98
99
|
|
|
99
100
|
@override
|
|
101
|
+
@auto_timeout("ast")
|
|
100
102
|
async def call(
|
|
101
103
|
self,
|
|
102
104
|
ctx: MCPContext,
|
|
@@ -112,14 +114,11 @@ Searches code structure intelligently, understanding syntax and providing semant
|
|
|
112
114
|
Tool result
|
|
113
115
|
"""
|
|
114
116
|
tool_ctx = self.create_tool_context(ctx)
|
|
115
|
-
self.set_tool_context_info(tool_ctx)
|
|
117
|
+
await self.set_tool_context_info(tool_ctx)
|
|
116
118
|
|
|
117
119
|
# Extract parameters
|
|
118
120
|
pattern: Pattern = params["pattern"]
|
|
119
121
|
path: SearchPath = params["path"]
|
|
120
|
-
|
|
121
|
-
# Expand path (handles ~, $HOME, etc.)
|
|
122
|
-
path = self.expand_path(path)
|
|
123
122
|
ignore_case = params.get("ignore_case", False)
|
|
124
123
|
line_number = params.get("line_number", False)
|
|
125
124
|
|