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,11 +1,10 @@
1
1
  """Find files using ffind library."""
2
2
 
3
3
  import os
4
- from typing import Annotated, Optional, TypedDict, Unpack, final, override
5
- from pathlib import Path
4
+ from typing import Unpack, Optional, Annotated, TypedDict, final, override
6
5
 
7
- from mcp.server.fastmcp import Context as MCPContext
8
6
  from pydantic import Field
7
+ from mcp.server.fastmcp import Context as MCPContext
9
8
 
10
9
  from hanzo_mcp.tools.common.base import BaseTool
11
10
  from hanzo_mcp.tools.common.context import create_tool_context
@@ -13,6 +12,7 @@ from hanzo_mcp.tools.common.permissions import PermissionManager
13
12
 
14
13
  try:
15
14
  import ffind
15
+
16
16
  FFIND_AVAILABLE = True
17
17
  except ImportError:
18
18
  FFIND_AVAILABLE = False
@@ -181,109 +181,126 @@ For database search, use 'sql_search' or 'vector_search'.
181
181
  # If ffind is not available, fall back to basic implementation
182
182
  if not FFIND_AVAILABLE:
183
183
  return await self._find_files_fallback(
184
- pattern, search_path, recursive, ignore_case,
185
- hidden, dirs_only, files_only, max_results
184
+ pattern,
185
+ search_path,
186
+ recursive,
187
+ ignore_case,
188
+ hidden,
189
+ dirs_only,
190
+ files_only,
191
+ max_results,
186
192
  )
187
193
 
188
194
  try:
189
195
  # Use ffind for efficient searching
190
196
  results = []
191
197
  count = 0
192
-
198
+
193
199
  # Configure ffind options
194
200
  options = {
195
- 'pattern': pattern,
196
- 'path': search_path,
197
- 'recursive': recursive,
198
- 'ignore_case': ignore_case,
199
- 'hidden': hidden,
201
+ "pattern": pattern,
202
+ "path": search_path,
203
+ "recursive": recursive,
204
+ "ignore_case": ignore_case,
205
+ "hidden": hidden,
200
206
  }
201
-
207
+
202
208
  # Search with ffind
203
209
  for filepath in ffind.find(**options):
204
210
  # Check if it matches our criteria
205
211
  is_dir = os.path.isdir(filepath)
206
-
212
+
207
213
  if dirs_only and not is_dir:
208
214
  continue
209
215
  if files_only and is_dir:
210
216
  continue
211
-
217
+
212
218
  # Make path relative for cleaner output
213
219
  try:
214
220
  rel_path = os.path.relpath(filepath, search_path)
215
221
  except ValueError:
216
222
  rel_path = filepath
217
-
223
+
218
224
  results.append(rel_path)
219
225
  count += 1
220
-
226
+
221
227
  if count >= max_results:
222
228
  break
223
-
229
+
224
230
  if not results:
225
231
  return f"No files found matching '{pattern}'"
226
-
232
+
227
233
  # Format output
228
234
  output = [f"Found {len(results)} file(s) matching '{pattern}':"]
229
235
  output.append("")
230
-
236
+
231
237
  for filepath in sorted(results):
232
238
  output.append(filepath)
233
-
239
+
234
240
  if count >= max_results:
235
241
  output.append(f"\n... (showing first {max_results} results)")
236
-
242
+
237
243
  return "\n".join(output)
238
244
 
239
245
  except Exception as e:
240
246
  await tool_ctx.error(f"Error during search: {str(e)}")
241
247
  # Fall back to basic implementation
242
248
  return await self._find_files_fallback(
243
- pattern, search_path, recursive, ignore_case,
244
- hidden, dirs_only, files_only, max_results
249
+ pattern,
250
+ search_path,
251
+ recursive,
252
+ ignore_case,
253
+ hidden,
254
+ dirs_only,
255
+ files_only,
256
+ max_results,
245
257
  )
246
258
 
247
259
  async def _find_files_fallback(
248
- self, pattern: str, search_path: str, recursive: bool,
249
- ignore_case: bool, hidden: bool, dirs_only: bool,
250
- files_only: bool, max_results: int
260
+ self,
261
+ pattern: str,
262
+ search_path: str,
263
+ recursive: bool,
264
+ ignore_case: bool,
265
+ hidden: bool,
266
+ dirs_only: bool,
267
+ files_only: bool,
268
+ max_results: int,
251
269
  ) -> str:
252
270
  """Fallback implementation when ffind is not available."""
253
- import fnmatch
254
-
271
+
255
272
  results = []
256
273
  count = 0
257
-
274
+
258
275
  # Convert pattern for case-insensitive matching
259
276
  if ignore_case:
260
277
  pattern = pattern.lower()
261
-
278
+
262
279
  try:
263
280
  if recursive:
264
281
  # Walk directory tree
265
282
  for root, dirs, files in os.walk(search_path):
266
283
  # Skip hidden directories if not requested
267
284
  if not hidden:
268
- dirs[:] = [d for d in dirs if not d.startswith('.')]
269
-
285
+ dirs[:] = [d for d in dirs if not d.startswith(".")]
286
+
270
287
  # Check directories
271
288
  if not files_only:
272
289
  for dirname in dirs:
273
290
  if self._match_pattern(dirname, pattern, ignore_case):
274
291
  filepath = os.path.join(root, dirname)
275
292
  rel_path = os.path.relpath(filepath, search_path)
276
- results.append(rel_path + '/')
293
+ results.append(rel_path + "/")
277
294
  count += 1
278
295
  if count >= max_results:
279
296
  break
280
-
297
+
281
298
  # Check files
282
299
  if not dirs_only:
283
300
  for filename in files:
284
- if not hidden and filename.startswith('.'):
301
+ if not hidden and filename.startswith("."):
285
302
  continue
286
-
303
+
287
304
  if self._match_pattern(filename, pattern, ignore_case):
288
305
  filepath = os.path.join(root, filename)
289
306
  rel_path = os.path.relpath(filepath, search_path)
@@ -291,53 +308,57 @@ For database search, use 'sql_search' or 'vector_search'.
291
308
  count += 1
292
309
  if count >= max_results:
293
310
  break
294
-
311
+
295
312
  if count >= max_results:
296
313
  break
297
314
  else:
298
315
  # Only search in the specified directory
299
316
  for entry in os.listdir(search_path):
300
- if not hidden and entry.startswith('.'):
317
+ if not hidden and entry.startswith("."):
301
318
  continue
302
-
319
+
303
320
  filepath = os.path.join(search_path, entry)
304
321
  is_dir = os.path.isdir(filepath)
305
-
322
+
306
323
  if dirs_only and not is_dir:
307
324
  continue
308
325
  if files_only and is_dir:
309
326
  continue
310
-
327
+
311
328
  if self._match_pattern(entry, pattern, ignore_case):
312
- results.append(entry + '/' if is_dir else entry)
329
+ results.append(entry + "/" if is_dir else entry)
313
330
  count += 1
314
331
  if count >= max_results:
315
332
  break
316
-
333
+
317
334
  if not results:
318
335
  return f"No files found matching '{pattern}' (using fallback search)"
319
-
336
+
320
337
  # Format output
321
- output = [f"Found {len(results)} file(s) matching '{pattern}' (using fallback search):"]
338
+ output = [
339
+ f"Found {len(results)} file(s) matching '{pattern}' (using fallback search):"
340
+ ]
322
341
  output.append("")
323
-
342
+
324
343
  for filepath in sorted(results):
325
344
  output.append(filepath)
326
-
345
+
327
346
  if count >= max_results:
328
347
  output.append(f"\n... (showing first {max_results} results)")
329
-
330
- output.append("\nNote: Install 'ffind' for faster searching: pip install ffind")
331
-
348
+
349
+ output.append(
350
+ "\nNote: Install 'ffind' for faster searching: pip install ffind"
351
+ )
352
+
332
353
  return "\n".join(output)
333
-
354
+
334
355
  except Exception as e:
335
356
  return f"Error searching for files: {str(e)}"
336
357
 
337
358
  def _match_pattern(self, filename: str, pattern: str, ignore_case: bool) -> bool:
338
359
  """Check if filename matches pattern."""
339
360
  import fnmatch
340
-
361
+
341
362
  if ignore_case:
342
363
  return fnmatch.fnmatch(filename.lower(), pattern)
343
364
  else: