hanzo-mcp 0.7.7__py3-none-any.whl → 0.8.1__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.

Files changed (178) hide show
  1. hanzo_mcp/__init__.py +6 -0
  2. hanzo_mcp/__main__.py +1 -1
  3. hanzo_mcp/analytics/__init__.py +2 -2
  4. hanzo_mcp/analytics/posthog_analytics.py +76 -82
  5. hanzo_mcp/cli.py +31 -36
  6. hanzo_mcp/cli_enhanced.py +94 -72
  7. hanzo_mcp/cli_plugin.py +27 -17
  8. hanzo_mcp/config/__init__.py +2 -2
  9. hanzo_mcp/config/settings.py +112 -88
  10. hanzo_mcp/config/tool_config.py +32 -34
  11. hanzo_mcp/dev_server.py +66 -67
  12. hanzo_mcp/prompts/__init__.py +94 -12
  13. hanzo_mcp/prompts/enhanced_prompts.py +809 -0
  14. hanzo_mcp/prompts/example_custom_prompt.py +6 -5
  15. hanzo_mcp/prompts/project_todo_reminder.py +0 -1
  16. hanzo_mcp/prompts/tool_explorer.py +10 -7
  17. hanzo_mcp/server.py +17 -21
  18. hanzo_mcp/server_enhanced.py +15 -22
  19. hanzo_mcp/tools/__init__.py +56 -28
  20. hanzo_mcp/tools/agent/__init__.py +16 -19
  21. hanzo_mcp/tools/agent/agent.py +82 -65
  22. hanzo_mcp/tools/agent/agent_tool.py +152 -122
  23. hanzo_mcp/tools/agent/agent_tool_v1_deprecated.py +66 -62
  24. hanzo_mcp/tools/agent/clarification_protocol.py +55 -50
  25. hanzo_mcp/tools/agent/clarification_tool.py +11 -10
  26. hanzo_mcp/tools/agent/claude_cli_tool.py +21 -20
  27. hanzo_mcp/tools/agent/claude_desktop_auth.py +130 -144
  28. hanzo_mcp/tools/agent/cli_agent_base.py +59 -53
  29. hanzo_mcp/tools/agent/code_auth.py +102 -107
  30. hanzo_mcp/tools/agent/code_auth_tool.py +28 -27
  31. hanzo_mcp/tools/agent/codex_cli_tool.py +20 -19
  32. hanzo_mcp/tools/agent/critic_tool.py +86 -73
  33. hanzo_mcp/tools/agent/gemini_cli_tool.py +21 -20
  34. hanzo_mcp/tools/agent/grok_cli_tool.py +21 -20
  35. hanzo_mcp/tools/agent/iching_tool.py +404 -139
  36. hanzo_mcp/tools/agent/network_tool.py +89 -73
  37. hanzo_mcp/tools/agent/prompt.py +2 -1
  38. hanzo_mcp/tools/agent/review_tool.py +101 -98
  39. hanzo_mcp/tools/agent/swarm_alias.py +87 -0
  40. hanzo_mcp/tools/agent/swarm_tool.py +246 -161
  41. hanzo_mcp/tools/agent/swarm_tool_v1_deprecated.py +134 -92
  42. hanzo_mcp/tools/agent/tool_adapter.py +21 -11
  43. hanzo_mcp/tools/common/__init__.py +1 -1
  44. hanzo_mcp/tools/common/base.py +3 -5
  45. hanzo_mcp/tools/common/batch_tool.py +46 -39
  46. hanzo_mcp/tools/common/config_tool.py +120 -84
  47. hanzo_mcp/tools/common/context.py +1 -5
  48. hanzo_mcp/tools/common/context_fix.py +5 -3
  49. hanzo_mcp/tools/common/critic_tool.py +4 -8
  50. hanzo_mcp/tools/common/decorators.py +58 -56
  51. hanzo_mcp/tools/common/enhanced_base.py +29 -32
  52. hanzo_mcp/tools/common/fastmcp_pagination.py +91 -94
  53. hanzo_mcp/tools/common/forgiving_edit.py +91 -87
  54. hanzo_mcp/tools/common/mode.py +15 -17
  55. hanzo_mcp/tools/common/mode_loader.py +27 -24
  56. hanzo_mcp/tools/common/paginated_base.py +61 -53
  57. hanzo_mcp/tools/common/paginated_response.py +72 -79
  58. hanzo_mcp/tools/common/pagination.py +50 -53
  59. hanzo_mcp/tools/common/permissions.py +4 -4
  60. hanzo_mcp/tools/common/personality.py +186 -138
  61. hanzo_mcp/tools/common/plugin_loader.py +54 -54
  62. hanzo_mcp/tools/common/stats.py +65 -47
  63. hanzo_mcp/tools/common/test_helpers.py +31 -0
  64. hanzo_mcp/tools/common/thinking_tool.py +4 -8
  65. hanzo_mcp/tools/common/tool_disable.py +17 -12
  66. hanzo_mcp/tools/common/tool_enable.py +13 -14
  67. hanzo_mcp/tools/common/tool_list.py +36 -28
  68. hanzo_mcp/tools/common/truncate.py +23 -23
  69. hanzo_mcp/tools/config/__init__.py +4 -4
  70. hanzo_mcp/tools/config/config_tool.py +42 -29
  71. hanzo_mcp/tools/config/index_config.py +37 -34
  72. hanzo_mcp/tools/config/mode_tool.py +175 -55
  73. hanzo_mcp/tools/database/__init__.py +15 -12
  74. hanzo_mcp/tools/database/database_manager.py +77 -75
  75. hanzo_mcp/tools/database/graph.py +137 -91
  76. hanzo_mcp/tools/database/graph_add.py +30 -18
  77. hanzo_mcp/tools/database/graph_query.py +178 -102
  78. hanzo_mcp/tools/database/graph_remove.py +33 -28
  79. hanzo_mcp/tools/database/graph_search.py +97 -75
  80. hanzo_mcp/tools/database/graph_stats.py +91 -59
  81. hanzo_mcp/tools/database/sql.py +107 -79
  82. hanzo_mcp/tools/database/sql_query.py +30 -24
  83. hanzo_mcp/tools/database/sql_search.py +29 -25
  84. hanzo_mcp/tools/database/sql_stats.py +47 -35
  85. hanzo_mcp/tools/editor/neovim_command.py +25 -28
  86. hanzo_mcp/tools/editor/neovim_edit.py +21 -23
  87. hanzo_mcp/tools/editor/neovim_session.py +60 -54
  88. hanzo_mcp/tools/filesystem/__init__.py +31 -30
  89. hanzo_mcp/tools/filesystem/ast_multi_edit.py +329 -249
  90. hanzo_mcp/tools/filesystem/ast_tool.py +4 -4
  91. hanzo_mcp/tools/filesystem/base.py +1 -1
  92. hanzo_mcp/tools/filesystem/batch_search.py +316 -224
  93. hanzo_mcp/tools/filesystem/content_replace.py +4 -4
  94. hanzo_mcp/tools/filesystem/diff.py +71 -59
  95. hanzo_mcp/tools/filesystem/directory_tree.py +7 -7
  96. hanzo_mcp/tools/filesystem/directory_tree_paginated.py +49 -37
  97. hanzo_mcp/tools/filesystem/edit.py +4 -4
  98. hanzo_mcp/tools/filesystem/find.py +173 -80
  99. hanzo_mcp/tools/filesystem/find_files.py +73 -52
  100. hanzo_mcp/tools/filesystem/git_search.py +157 -104
  101. hanzo_mcp/tools/filesystem/grep.py +8 -8
  102. hanzo_mcp/tools/filesystem/multi_edit.py +4 -8
  103. hanzo_mcp/tools/filesystem/read.py +12 -10
  104. hanzo_mcp/tools/filesystem/rules_tool.py +59 -43
  105. hanzo_mcp/tools/filesystem/search_tool.py +263 -207
  106. hanzo_mcp/tools/filesystem/symbols_tool.py +94 -54
  107. hanzo_mcp/tools/filesystem/tree.py +35 -33
  108. hanzo_mcp/tools/filesystem/unix_aliases.py +13 -18
  109. hanzo_mcp/tools/filesystem/watch.py +37 -36
  110. hanzo_mcp/tools/filesystem/write.py +4 -8
  111. hanzo_mcp/tools/jupyter/__init__.py +4 -4
  112. hanzo_mcp/tools/jupyter/base.py +4 -5
  113. hanzo_mcp/tools/jupyter/jupyter.py +67 -47
  114. hanzo_mcp/tools/jupyter/notebook_edit.py +4 -4
  115. hanzo_mcp/tools/jupyter/notebook_read.py +4 -7
  116. hanzo_mcp/tools/llm/__init__.py +5 -7
  117. hanzo_mcp/tools/llm/consensus_tool.py +72 -52
  118. hanzo_mcp/tools/llm/llm_manage.py +101 -60
  119. hanzo_mcp/tools/llm/llm_tool.py +226 -166
  120. hanzo_mcp/tools/llm/provider_tools.py +25 -26
  121. hanzo_mcp/tools/lsp/__init__.py +1 -1
  122. hanzo_mcp/tools/lsp/lsp_tool.py +228 -143
  123. hanzo_mcp/tools/mcp/__init__.py +2 -3
  124. hanzo_mcp/tools/mcp/mcp_add.py +27 -25
  125. hanzo_mcp/tools/mcp/mcp_remove.py +7 -8
  126. hanzo_mcp/tools/mcp/mcp_stats.py +23 -22
  127. hanzo_mcp/tools/mcp/mcp_tool.py +129 -98
  128. hanzo_mcp/tools/memory/__init__.py +39 -21
  129. hanzo_mcp/tools/memory/knowledge_tools.py +124 -99
  130. hanzo_mcp/tools/memory/memory_tools.py +90 -108
  131. hanzo_mcp/tools/search/__init__.py +7 -2
  132. hanzo_mcp/tools/search/find_tool.py +297 -212
  133. hanzo_mcp/tools/search/unified_search.py +366 -314
  134. hanzo_mcp/tools/shell/__init__.py +8 -7
  135. hanzo_mcp/tools/shell/auto_background.py +56 -49
  136. hanzo_mcp/tools/shell/base.py +1 -1
  137. hanzo_mcp/tools/shell/base_process.py +75 -75
  138. hanzo_mcp/tools/shell/bash_session.py +2 -2
  139. hanzo_mcp/tools/shell/bash_session_executor.py +4 -4
  140. hanzo_mcp/tools/shell/bash_tool.py +24 -31
  141. hanzo_mcp/tools/shell/command_executor.py +12 -12
  142. hanzo_mcp/tools/shell/logs.py +43 -33
  143. hanzo_mcp/tools/shell/npx.py +13 -13
  144. hanzo_mcp/tools/shell/npx_background.py +24 -21
  145. hanzo_mcp/tools/shell/npx_tool.py +18 -22
  146. hanzo_mcp/tools/shell/open.py +19 -21
  147. hanzo_mcp/tools/shell/pkill.py +31 -26
  148. hanzo_mcp/tools/shell/process_tool.py +32 -32
  149. hanzo_mcp/tools/shell/processes.py +57 -58
  150. hanzo_mcp/tools/shell/run_background.py +24 -25
  151. hanzo_mcp/tools/shell/run_command.py +5 -5
  152. hanzo_mcp/tools/shell/run_command_windows.py +5 -5
  153. hanzo_mcp/tools/shell/session_storage.py +3 -3
  154. hanzo_mcp/tools/shell/streaming_command.py +141 -126
  155. hanzo_mcp/tools/shell/uvx.py +24 -25
  156. hanzo_mcp/tools/shell/uvx_background.py +35 -33
  157. hanzo_mcp/tools/shell/uvx_tool.py +18 -22
  158. hanzo_mcp/tools/todo/__init__.py +6 -2
  159. hanzo_mcp/tools/todo/todo.py +50 -37
  160. hanzo_mcp/tools/todo/todo_read.py +5 -8
  161. hanzo_mcp/tools/todo/todo_write.py +5 -7
  162. hanzo_mcp/tools/vector/__init__.py +40 -28
  163. hanzo_mcp/tools/vector/ast_analyzer.py +176 -143
  164. hanzo_mcp/tools/vector/git_ingester.py +170 -179
  165. hanzo_mcp/tools/vector/index_tool.py +96 -44
  166. hanzo_mcp/tools/vector/infinity_store.py +283 -228
  167. hanzo_mcp/tools/vector/mock_infinity.py +39 -40
  168. hanzo_mcp/tools/vector/project_manager.py +88 -78
  169. hanzo_mcp/tools/vector/vector.py +59 -42
  170. hanzo_mcp/tools/vector/vector_index.py +30 -27
  171. hanzo_mcp/tools/vector/vector_search.py +64 -45
  172. hanzo_mcp/types.py +6 -4
  173. {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/METADATA +1 -1
  174. hanzo_mcp-0.8.1.dist-info/RECORD +185 -0
  175. hanzo_mcp-0.7.7.dist-info/RECORD +0 -182
  176. {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/WHEEL +0 -0
  177. {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/entry_points.txt +0 -0
  178. {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/top_level.txt +0 -0
@@ -5,15 +5,16 @@ This package provides tools for executing shell commands and scripts.
5
5
 
6
6
  from mcp.server import FastMCP
7
7
 
8
+ from hanzo_mcp.tools.shell.open import open_tool
8
9
  from hanzo_mcp.tools.common.base import BaseTool, ToolRegistry
9
- from hanzo_mcp.tools.common.permissions import PermissionManager
10
+ from hanzo_mcp.tools.shell.npx_tool import npx_tool
11
+ from hanzo_mcp.tools.shell.uvx_tool import uvx_tool
10
12
 
11
13
  # Import tools
12
14
  from hanzo_mcp.tools.shell.bash_tool import bash_tool
13
- from hanzo_mcp.tools.shell.npx_tool import npx_tool
14
- from hanzo_mcp.tools.shell.uvx_tool import uvx_tool
15
+ from hanzo_mcp.tools.common.permissions import PermissionManager
15
16
  from hanzo_mcp.tools.shell.process_tool import process_tool
16
- from hanzo_mcp.tools.shell.open import open_tool
17
+
17
18
  # from hanzo_mcp.tools.shell.streaming_command import StreamingCommandTool
18
19
 
19
20
  # Export all tool classes
@@ -38,10 +39,10 @@ def get_shell_tools(
38
39
  bash_tool.permission_manager = permission_manager
39
40
  npx_tool.permission_manager = permission_manager
40
41
  uvx_tool.permission_manager = permission_manager
41
-
42
+
42
43
  # Note: StreamingCommandTool is abstract and shouldn't be instantiated directly
43
44
  # It's used as a base class for other streaming tools
44
-
45
+
45
46
  return [
46
47
  bash_tool,
47
48
  npx_tool,
@@ -67,4 +68,4 @@ def register_shell_tools(
67
68
  """
68
69
  tools = get_shell_tools(permission_manager)
69
70
  ToolRegistry.register_tools(mcp_server, tools)
70
- return tools
71
+ return tools
@@ -4,32 +4,33 @@ This module provides automatic backgrounding of long-running processes.
4
4
  Commands that take more than 2 minutes automatically continue in background.
5
5
  """
6
6
 
7
- import asyncio
8
- import os
9
7
  import time
10
8
  import uuid
9
+ import asyncio
10
+ from typing import Tuple, Optional
11
11
  from pathlib import Path
12
- from typing import Any, Optional, Tuple
13
12
 
14
13
  from hanzo_mcp.tools.shell.base_process import ProcessManager
15
14
 
16
15
 
17
16
  class AutoBackgroundExecutor:
18
17
  """Executor that automatically backgrounds long-running processes."""
19
-
18
+
20
19
  # Default timeout before auto-backgrounding (2 minutes)
21
20
  DEFAULT_TIMEOUT = 120.0
22
-
23
- def __init__(self, process_manager: ProcessManager, timeout: float = DEFAULT_TIMEOUT):
21
+
22
+ def __init__(
23
+ self, process_manager: ProcessManager, timeout: float = DEFAULT_TIMEOUT
24
+ ):
24
25
  """Initialize the auto-background executor.
25
-
26
+
26
27
  Args:
27
28
  process_manager: Process manager for tracking background processes
28
29
  timeout: Timeout in seconds before auto-backgrounding (default: 120s)
29
30
  """
30
31
  self.process_manager = process_manager
31
32
  self.timeout = timeout
32
-
33
+
33
34
  async def execute_with_auto_background(
34
35
  self,
35
36
  cmd_args: list[str],
@@ -38,22 +39,22 @@ class AutoBackgroundExecutor:
38
39
  env: Optional[dict[str, str]] = None,
39
40
  ) -> Tuple[str, bool, Optional[str]]:
40
41
  """Execute a command with automatic backgrounding if it takes too long.
41
-
42
+
42
43
  Args:
43
44
  cmd_args: Command arguments list
44
45
  tool_name: Name of the tool (for process ID generation)
45
46
  cwd: Working directory
46
47
  env: Environment variables
47
-
48
+
48
49
  Returns:
49
50
  Tuple of (output/status, was_backgrounded, process_id)
50
51
  """
51
52
  # Generate process ID
52
53
  process_id = f"{tool_name}_{uuid.uuid4().hex[:8]}"
53
-
54
+
54
55
  # Create log file
55
56
  log_file = self.process_manager.create_log_file(process_id)
56
-
57
+
57
58
  # Start the process
58
59
  process = await asyncio.create_subprocess_exec(
59
60
  *cmd_args,
@@ -62,69 +63,75 @@ class AutoBackgroundExecutor:
62
63
  cwd=cwd,
63
64
  env=env,
64
65
  )
65
-
66
+
66
67
  # Track in process manager
67
68
  self.process_manager.add_process(process_id, process, str(log_file))
68
-
69
+
69
70
  # Try to wait for completion with timeout
70
71
  start_time = time.time()
71
72
  output_lines = []
72
-
73
+
73
74
  try:
74
75
  # Create tasks for reading output and waiting for process
75
76
  async def read_output():
76
77
  """Read output from process."""
77
78
  if process.stdout:
78
79
  async for line in process.stdout:
79
- line_str = line.decode('utf-8', errors='replace')
80
+ line_str = line.decode("utf-8", errors="replace")
80
81
  output_lines.append(line_str)
81
82
  # Also write to log file
82
- with open(log_file, 'a') as f:
83
+ with open(log_file, "a") as f:
83
84
  f.write(line_str)
84
-
85
+
85
86
  async def wait_for_process():
86
87
  """Wait for process to complete."""
87
88
  return await process.wait()
88
-
89
+
89
90
  # Run both tasks with timeout
90
91
  read_task = asyncio.create_task(read_output())
91
92
  wait_task = asyncio.create_task(wait_for_process())
92
-
93
+
93
94
  # Wait for either timeout or completion
94
95
  done, pending = await asyncio.wait(
95
96
  [read_task, wait_task],
96
97
  timeout=self.timeout,
97
- return_when=asyncio.FIRST_COMPLETED
98
+ return_when=asyncio.FIRST_COMPLETED,
98
99
  )
99
-
100
+
100
101
  # Check if process completed
101
102
  if wait_task in done:
102
103
  # Process completed within timeout
103
104
  return_code = await wait_task
104
105
  await read_task # Ensure all output is read
105
-
106
+
106
107
  # Mark process as completed
107
108
  self.process_manager.mark_completed(process_id, return_code)
108
-
109
- output = ''.join(output_lines)
109
+
110
+ output = "".join(output_lines)
110
111
  if return_code != 0:
111
- return f"Command failed with exit code {return_code}:\n{output}", False, None
112
+ return (
113
+ f"Command failed with exit code {return_code}:\n{output}",
114
+ False,
115
+ None,
116
+ )
112
117
  else:
113
118
  return output, False, None
114
-
119
+
115
120
  else:
116
121
  # Timeout reached - background the process
117
122
  # Cancel the tasks we were waiting on
118
123
  for task in pending:
119
124
  task.cancel()
120
-
125
+
121
126
  # Continue reading output in background
122
- asyncio.create_task(self._background_reader(process, process_id, log_file))
123
-
127
+ asyncio.create_task(
128
+ self._background_reader(process, process_id, log_file)
129
+ )
130
+
124
131
  # Return status message
125
132
  elapsed = time.time() - start_time
126
- partial_output = ''.join(output_lines[-50:]) # Last 50 lines
127
-
133
+ partial_output = "".join(output_lines[-50:]) # Last 50 lines
134
+
128
135
  return (
129
136
  f"Process automatically backgrounded after {elapsed:.1f}s\n"
130
137
  f"Process ID: {process_id}\n"
@@ -133,17 +140,17 @@ class AutoBackgroundExecutor:
133
140
  f"Use 'process --action kill --id {process_id}' to stop the process\n\n"
134
141
  f"=== Last output ===\n{partial_output}",
135
142
  True,
136
- process_id
143
+ process_id,
137
144
  )
138
-
145
+
139
146
  except Exception as e:
140
147
  # Handle errors
141
148
  self.process_manager.mark_completed(process_id, -1)
142
149
  return f"Error executing command: {str(e)}", False, None
143
-
150
+
144
151
  async def _background_reader(self, process, process_id: str, log_file: Path):
145
152
  """Continue reading output from a backgrounded process.
146
-
153
+
147
154
  Args:
148
155
  process: The subprocess
149
156
  process_id: Process identifier
@@ -153,24 +160,24 @@ class AutoBackgroundExecutor:
153
160
  # Continue reading output
154
161
  if process.stdout:
155
162
  async for line in process.stdout:
156
- with open(log_file, 'a') as f:
157
- f.write(line.decode('utf-8', errors='replace'))
158
-
163
+ with open(log_file, "a") as f:
164
+ f.write(line.decode("utf-8", errors="replace"))
165
+
159
166
  # Wait for process to complete
160
167
  return_code = await process.wait()
161
-
168
+
162
169
  # Mark as completed
163
170
  self.process_manager.mark_completed(process_id, return_code)
164
-
171
+
165
172
  # Add completion marker to log
166
- with open(log_file, 'a') as f:
173
+ with open(log_file, "a") as f:
167
174
  f.write(f"\n\n=== Process completed with exit code {return_code} ===\n")
168
-
175
+
169
176
  except Exception as e:
170
177
  # Log error
171
- with open(log_file, 'a') as f:
178
+ with open(log_file, "a") as f:
172
179
  f.write(f"\n\n=== Background reader error: {str(e)} ===\n")
173
-
180
+
174
181
  self.process_manager.mark_completed(process_id, -1)
175
182
 
176
183
 
@@ -181,13 +188,13 @@ def format_auto_background_message(
181
188
  partial_output: str = "",
182
189
  ) -> str:
183
190
  """Format a user-friendly message for auto-backgrounded processes.
184
-
191
+
185
192
  Args:
186
193
  process_id: Process identifier
187
194
  elapsed_time: Time elapsed before backgrounding
188
195
  log_file: Path to log file
189
196
  partial_output: Partial output to show
190
-
197
+
191
198
  Returns:
192
199
  Formatted message
193
200
  """
@@ -199,5 +206,5 @@ def format_auto_background_message(
199
206
  f" • View logs: process --action logs --id {process_id}\n"
200
207
  f" • Check status: process\n"
201
208
  f" • Stop process: process --action kill --id {process_id}\n"
202
- f"{f'\\n=== Recent output ===\\n{partial_output}' if partial_output else ''}"
203
- )
209
+ f"{chr(10) + '=== Recent output ===' + chr(10) + partial_output if partial_output else ''}"
210
+ )
@@ -6,7 +6,7 @@ including command execution, script running, and process management.
6
6
 
7
7
  from abc import ABC, abstractmethod
8
8
  from enum import Enum
9
- from typing import Any, Self, final
9
+ from typing import Any, final
10
10
 
11
11
  from mcp.server.fastmcp import Context as MCPContext
12
12