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.

Files changed (178) hide show
  1. hanzo_mcp/__init__.py +7 -1
  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.6.dist-info → hanzo_mcp-0.8.0.dist-info}/METADATA +1 -1
  174. hanzo_mcp-0.8.0.dist-info/RECORD +185 -0
  175. hanzo_mcp-0.7.6.dist-info/RECORD +0 -182
  176. {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/WHEEL +0 -0
  177. {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/entry_points.txt +0 -0
  178. {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,19 @@
1
1
  """Manage Neovim sessions."""
2
2
 
3
3
  import os
4
- import subprocess
5
- import shutil
6
4
  import json
7
- from typing import Annotated, Optional, TypedDict, Unpack, final, override, List
5
+ import shutil
6
+ import subprocess
7
+ from typing import Unpack, Optional, Annotated, TypedDict, final, override
8
8
  from pathlib import Path
9
9
  from datetime import datetime
10
10
 
11
- from mcp.server.fastmcp import Context as MCPContext
12
11
  from pydantic import Field
12
+ from mcp.server.fastmcp import Context as MCPContext
13
13
 
14
14
  from hanzo_mcp.tools.common.base import BaseTool
15
15
  from hanzo_mcp.tools.common.context import create_tool_context
16
16
 
17
-
18
17
  Action = Annotated[
19
18
  str,
20
19
  Field(
@@ -161,8 +160,12 @@ Note: Requires Neovim to be installed.
161
160
  # Handle different actions
162
161
  if action == "save":
163
162
  return await self._save_session(
164
- tool_ctx, session_name, project_session_dir,
165
- auto_name, overwrite, project_path
163
+ tool_ctx,
164
+ session_name,
165
+ project_session_dir,
166
+ auto_name,
167
+ overwrite,
168
+ project_path,
166
169
  )
167
170
  elif action == "restore":
168
171
  return await self._restore_session(
@@ -174,59 +177,61 @@ Note: Requires Neovim to be installed.
174
177
  return self._delete_session(session_name, project_session_dir)
175
178
 
176
179
  async def _save_session(
177
- self, tool_ctx, session_name: Optional[str],
178
- project_dir: Path, auto_name: bool, overwrite: bool,
179
- project_path: str
180
+ self,
181
+ tool_ctx,
182
+ session_name: Optional[str],
183
+ project_dir: Path,
184
+ auto_name: bool,
185
+ overwrite: bool,
186
+ project_path: str,
180
187
  ) -> str:
181
188
  """Save Neovim session."""
182
189
  # Generate session name if needed
183
190
  if auto_name or not session_name:
184
191
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
185
192
  session_name = f"session_{timestamp}"
186
-
193
+
187
194
  # Sanitize session name
188
195
  session_name = session_name.replace("/", "_").replace(" ", "_")
189
-
196
+
190
197
  session_file = project_dir / f"{session_name}.vim"
191
198
  metadata_file = project_dir / f"{session_name}.json"
192
-
199
+
193
200
  # Check if exists
194
201
  if session_file.exists() and not overwrite:
195
202
  return f"Error: Session '{session_name}' already exists. Use --overwrite to replace."
196
-
203
+
197
204
  await tool_ctx.info(f"Saving Neovim session: {session_name}")
198
-
205
+
199
206
  # Create temporary vim script to save session
200
- vim_script = f'''
207
+ vim_script = f"""
201
208
  :mksession! {session_file}
202
209
  :echo "Session saved to {session_file}"
203
210
  :qa
204
- '''
205
-
211
+ """
212
+
206
213
  try:
207
214
  # Run Neovim to save session
208
215
  # First, check if Neovim is already running
209
216
  # For now, we'll create a new instance
210
217
  result = subprocess.run(
211
- ["nvim", "-c", vim_script.strip()],
212
- capture_output=True,
213
- text=True
218
+ ["nvim", "-c", vim_script.strip()], capture_output=True, text=True
214
219
  )
215
-
220
+
216
221
  if result.returncode != 0 and result.stderr:
217
222
  return f"Error saving session: {result.stderr}"
218
-
223
+
219
224
  # Save metadata
220
225
  metadata = {
221
226
  "name": session_name,
222
227
  "created_at": datetime.now().isoformat(),
223
228
  "project_path": project_path,
224
- "description": f"Neovim session for {project_path}"
229
+ "description": f"Neovim session for {project_path}",
225
230
  }
226
-
227
- with open(metadata_file, 'w') as f:
231
+
232
+ with open(metadata_file, "w") as f:
228
233
  json.dump(metadata, f, indent=2)
229
-
234
+
230
235
  return f"""Successfully saved Neovim session '{session_name}'
231
236
 
232
237
  Session file: {session_file}
@@ -237,13 +242,12 @@ neovim_session --action restore --session-name "{session_name}"
237
242
 
238
243
  Or manually in Neovim:
239
244
  :source {session_file}"""
240
-
245
+
241
246
  except Exception as e:
242
247
  return f"Error saving session: {str(e)}"
243
248
 
244
249
  async def _restore_session(
245
- self, tool_ctx, session_name: Optional[str],
246
- project_dir: Path
250
+ self, tool_ctx, session_name: Optional[str], project_dir: Path
247
251
  ) -> str:
248
252
  """Restore Neovim session."""
249
253
  if not session_name:
@@ -251,7 +255,7 @@ Or manually in Neovim:
251
255
  sessions = list(project_dir.glob("*.vim"))
252
256
  if not sessions:
253
257
  return "Error: No sessions found for this project. Use 'neovim_session --action list' to see all sessions."
254
-
258
+
255
259
  # Use most recent
256
260
  sessions.sort(key=lambda x: x.stat().st_mtime, reverse=True)
257
261
  session_file = sessions[0]
@@ -260,15 +264,15 @@ Or manually in Neovim:
260
264
  session_file = project_dir / f"{session_name}.vim"
261
265
  if not session_file.exists():
262
266
  return f"Error: Session '{session_name}' not found. Use 'neovim_session --action list' to see available sessions."
263
-
267
+
264
268
  await tool_ctx.info(f"Restoring Neovim session: {session_name}")
265
-
269
+
266
270
  try:
267
271
  # Open Neovim with the session
268
272
  subprocess.run(["nvim", "-S", str(session_file)])
269
-
273
+
270
274
  return f"Restored Neovim session '{session_name}'"
271
-
275
+
272
276
  except Exception as e:
273
277
  return f"Error restoring session: {str(e)}"
274
278
 
@@ -276,78 +280,80 @@ Or manually in Neovim:
276
280
  """List available sessions."""
277
281
  output = ["=== Neovim Sessions ==="]
278
282
  output.append(f"Project: {project_path}\n")
279
-
283
+
280
284
  # List project-specific sessions
281
285
  sessions = list(project_dir.glob("*.vim"))
282
-
286
+
283
287
  if sessions:
284
288
  output.append("Project Sessions:")
285
289
  sessions.sort(key=lambda x: x.stat().st_mtime, reverse=True)
286
-
290
+
287
291
  for session_file in sessions:
288
292
  session_name = session_file.stem
289
293
  metadata_file = project_dir / f"{session_name}.json"
290
-
294
+
291
295
  # Get metadata if available
292
296
  created_at = "Unknown"
293
297
  if metadata_file.exists():
294
298
  try:
295
- with open(metadata_file, 'r') as f:
299
+ with open(metadata_file, "r") as f:
296
300
  metadata = json.load(f)
297
301
  created_at = metadata.get("created_at", "Unknown")
298
302
  if created_at != "Unknown":
299
303
  # Format date
300
304
  dt = datetime.fromisoformat(created_at)
301
305
  created_at = dt.strftime("%Y-%m-%d %H:%M:%S")
302
- except:
306
+ except Exception:
303
307
  pass
304
-
308
+
305
309
  # Get file size
306
310
  size = session_file.stat().st_size
307
311
  size_kb = size / 1024
308
-
312
+
309
313
  output.append(f" - {session_name}")
310
314
  output.append(f" Created: {created_at}")
311
315
  output.append(f" Size: {size_kb:.1f} KB")
312
316
  else:
313
317
  output.append("No sessions found for this project.")
314
-
318
+
315
319
  # Also list all sessions
316
320
  all_sessions = list(self.session_dir.rglob("*.vim"))
317
321
  other_sessions = [s for s in all_sessions if s.parent != project_dir]
318
-
322
+
319
323
  if other_sessions:
320
324
  output.append("\nOther Projects' Sessions:")
321
325
  for session_file in other_sessions[:10]: # Show max 10
322
326
  project_name = session_file.parent.name
323
327
  session_name = session_file.stem
324
328
  output.append(f" - {project_name}/{session_name}")
325
-
329
+
326
330
  if len(other_sessions) > 10:
327
331
  output.append(f" ... and {len(other_sessions) - 10} more")
328
-
329
- output.append("\nUse 'neovim_session --action restore --session-name <name>' to restore a session.")
330
-
332
+
333
+ output.append(
334
+ "\nUse 'neovim_session --action restore --session-name <name>' to restore a session."
335
+ )
336
+
331
337
  return "\n".join(output)
332
338
 
333
339
  def _delete_session(self, session_name: Optional[str], project_dir: Path) -> str:
334
340
  """Delete a session."""
335
341
  if not session_name:
336
342
  return "Error: session_name is required for delete action"
337
-
343
+
338
344
  session_file = project_dir / f"{session_name}.vim"
339
345
  metadata_file = project_dir / f"{session_name}.json"
340
-
346
+
341
347
  if not session_file.exists():
342
348
  return f"Error: Session '{session_name}' not found"
343
-
349
+
344
350
  try:
345
351
  session_file.unlink()
346
352
  if metadata_file.exists():
347
353
  metadata_file.unlink()
348
-
354
+
349
355
  return f"Successfully deleted session '{session_name}'"
350
-
356
+
351
357
  except Exception as e:
352
358
  return f"Error deleting session: {str(e)}"
353
359
 
@@ -7,27 +7,32 @@ and editing files, directory navigation, and content searching.
7
7
  from mcp.server import FastMCP
8
8
 
9
9
  from hanzo_mcp.tools.common.base import BaseTool, ToolRegistry
10
-
11
- from hanzo_mcp.tools.common.permissions import PermissionManager
12
- from hanzo_mcp.tools.filesystem.content_replace import ContentReplaceTool
13
- from hanzo_mcp.tools.filesystem.directory_tree import DirectoryTreeTool
10
+ from hanzo_mcp.tools.filesystem.diff import create_diff_tool
14
11
  from hanzo_mcp.tools.filesystem.edit import Edit
15
12
  from hanzo_mcp.tools.filesystem.grep import Grep
16
- from hanzo_mcp.tools.filesystem.ast_tool import ASTTool
17
- from hanzo_mcp.tools.filesystem.git_search import GitSearchTool
18
- from hanzo_mcp.tools.filesystem.multi_edit import MultiEdit
19
13
  from hanzo_mcp.tools.filesystem.read import ReadTool
14
+ from hanzo_mcp.tools.filesystem.watch import watch_tool
20
15
  from hanzo_mcp.tools.filesystem.write import Write
21
- from hanzo_mcp.tools.filesystem.batch_search import BatchSearchTool
16
+ from hanzo_mcp.tools.common.permissions import PermissionManager
17
+ from hanzo_mcp.tools.filesystem.ast_tool import ASTTool
22
18
  from hanzo_mcp.tools.filesystem.find_files import FindFilesTool
19
+ from hanzo_mcp.tools.filesystem.git_search import GitSearchTool
20
+ from hanzo_mcp.tools.filesystem.multi_edit import MultiEdit
23
21
  from hanzo_mcp.tools.filesystem.rules_tool import RulesTool
24
22
  from hanzo_mcp.tools.filesystem.search_tool import SearchTool
25
- from hanzo_mcp.tools.filesystem.watch import watch_tool
26
- from hanzo_mcp.tools.filesystem.diff import create_diff_tool
23
+ from hanzo_mcp.tools.filesystem.batch_search import BatchSearchTool
24
+ from hanzo_mcp.tools.filesystem.directory_tree import DirectoryTreeTool
25
+ from hanzo_mcp.tools.filesystem.content_replace import ContentReplaceTool
27
26
 
28
27
  # Import new search tools
29
28
  try:
30
- from hanzo_mcp.tools.search import UnifiedSearch, create_unified_search_tool, FindTool, create_find_tool
29
+ from hanzo_mcp.tools.search import (
30
+ FindTool,
31
+ UnifiedSearch,
32
+ create_find_tool,
33
+ create_unified_search_tool,
34
+ )
35
+
31
36
  UNIFIED_SEARCH_AVAILABLE = True
32
37
  except ImportError:
33
38
  UNIFIED_SEARCH_AVAILABLE = False
@@ -76,22 +81,21 @@ def get_read_only_filesystem_tools(
76
81
  watch_tool,
77
82
  create_diff_tool(permission_manager),
78
83
  ]
79
-
84
+
80
85
  # Add search if project manager is available
81
86
  if project_manager:
82
87
  tools.append(SearchTool(permission_manager, project_manager))
83
-
88
+
84
89
  # Add new search tools if available
85
90
  if UNIFIED_SEARCH_AVAILABLE:
86
- tools.extend([
87
- create_unified_search_tool(),
88
- create_find_tool()
89
- ])
90
-
91
+ tools.extend([create_unified_search_tool(), create_find_tool()])
92
+
91
93
  return tools
92
94
 
93
95
 
94
- def get_filesystem_tools(permission_manager: PermissionManager, project_manager=None) -> list[BaseTool]:
96
+ def get_filesystem_tools(
97
+ permission_manager: PermissionManager, project_manager=None
98
+ ) -> list[BaseTool]:
95
99
  """Create instances of all filesystem tools.
96
100
 
97
101
  Args:
@@ -116,18 +120,15 @@ def get_filesystem_tools(permission_manager: PermissionManager, project_manager=
116
120
  watch_tool,
117
121
  create_diff_tool(permission_manager),
118
122
  ]
119
-
123
+
120
124
  # Add search if project manager is available
121
125
  if project_manager:
122
126
  tools.append(SearchTool(permission_manager, project_manager))
123
-
127
+
124
128
  # Add new search tools if available
125
129
  if UNIFIED_SEARCH_AVAILABLE:
126
- tools.extend([
127
- create_unified_search_tool(),
128
- create_find_tool()
129
- ])
130
-
130
+ tools.extend([create_unified_search_tool(), create_find_tool()])
131
+
131
132
  return tools
132
133
 
133
134
 
@@ -170,14 +171,14 @@ def register_filesystem_tools(
170
171
  "watch": lambda pm: watch_tool, # Singleton instance
171
172
  "diff": create_diff_tool,
172
173
  }
173
-
174
+
174
175
  # Add new search tools if available
175
176
  if UNIFIED_SEARCH_AVAILABLE:
176
177
  tool_classes["unified_search"] = lambda pm: create_unified_search_tool()
177
178
  tool_classes["find"] = lambda pm: create_find_tool()
178
-
179
+
179
180
  tools = []
180
-
181
+
181
182
  if enabled_tools:
182
183
  # Use individual tool configuration
183
184
  for tool_name, enabled in enabled_tools.items():
@@ -218,6 +219,6 @@ def register_filesystem_tools(
218
219
  else:
219
220
  # All tools
220
221
  tools = get_filesystem_tools(permission_manager, project_manager)
221
-
222
+
222
223
  ToolRegistry.register_tools(mcp_server, tools)
223
224
  return tools