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
hanzo_mcp/cli_enhanced.py CHANGED
@@ -1,14 +1,16 @@
1
1
  """Enhanced command-line interface for the Hanzo AI server with full tool configuration."""
2
2
 
3
- import argparse
4
- import json
5
- import logging
6
3
  import os
7
- import sys
8
- from pathlib import Path
9
- from typing import Any, Dict, cast
10
-
11
- from hanzo_mcp.config import HanzoMCPSettings, load_settings, save_settings, TOOL_REGISTRY
4
+ import logging
5
+ import argparse
6
+ from typing import Any, Dict
7
+
8
+ from hanzo_mcp.config import (
9
+ TOOL_REGISTRY,
10
+ HanzoMCPSettings,
11
+ load_settings,
12
+ save_settings,
13
+ )
12
14
  from hanzo_mcp.server import HanzoMCPServer
13
15
 
14
16
 
@@ -35,7 +37,7 @@ Examples:
35
37
 
36
38
  # Save current configuration
37
39
  hanzo-mcp --save-config
38
- """
40
+ """,
39
41
  )
40
42
 
41
43
  # Basic server options
@@ -85,7 +87,7 @@ Examples:
85
87
  )
86
88
  path_group.add_argument(
87
89
  "--project",
88
- action="append",
90
+ action="append",
89
91
  dest="project_paths",
90
92
  help="Add a project path (can be specified multiple times)",
91
93
  )
@@ -96,12 +98,12 @@ Examples:
96
98
 
97
99
  # Individual tool configuration
98
100
  tool_group = parser.add_argument_group("Individual Tool Configuration")
99
-
101
+
100
102
  # Add CLI flags for each tool
101
103
  for tool_name, tool_config in TOOL_REGISTRY.items():
102
- flag_name = tool_config.cli_flag.lstrip('-')
104
+ flag_name = tool_config.cli_flag.lstrip("-")
103
105
  help_text = f"{tool_config.description}"
104
-
106
+
105
107
  if tool_config.enabled:
106
108
  # Tool is enabled by default, add disable flag
107
109
  tool_group.add_argument(
@@ -110,7 +112,7 @@ Examples:
110
112
  help=f"Disable {tool_name} tool: {help_text}",
111
113
  )
112
114
  else:
113
- # Tool is disabled by default, add enable flag
115
+ # Tool is disabled by default, add enable flag
114
116
  tool_group.add_argument(
115
117
  f"--enable-{tool_name.replace('_', '-')}",
116
118
  action="store_true",
@@ -125,7 +127,7 @@ Examples:
125
127
  help="Disable all write tools (write, edit, multi_edit, content_replace)",
126
128
  )
127
129
  category_group.add_argument(
128
- "--disable-search-tools",
130
+ "--disable-search-tools",
129
131
  action="store_true",
130
132
  help="Disable all search tools (grep, grep_ast)",
131
133
  )
@@ -141,7 +143,7 @@ Examples:
141
143
  )
142
144
  category_group.add_argument(
143
145
  "--disable-shell-tools",
144
- action="store_true",
146
+ action="store_true",
145
147
  help="Disable shell command execution tools",
146
148
  )
147
149
  category_group.add_argument(
@@ -212,7 +214,7 @@ Examples:
212
214
  )
213
215
  config_group.add_argument(
214
216
  "--save-project-config",
215
- action="store_true",
217
+ action="store_true",
216
218
  help="Save current configuration to project config file",
217
219
  )
218
220
  config_group.add_argument(
@@ -238,37 +240,37 @@ def apply_cli_overrides(args: argparse.Namespace) -> Dict[str, Any]:
238
240
 
239
241
  # Server configuration
240
242
  server_config = {}
241
- if hasattr(args, 'name') and args.name != "hanzo-mcp":
243
+ if hasattr(args, "name") and args.name != "hanzo-mcp":
242
244
  server_config["name"] = args.name
243
- if hasattr(args, 'host') and args.host != "127.0.0.1":
245
+ if hasattr(args, "host") and args.host != "127.0.0.1":
244
246
  server_config["host"] = args.host
245
- if hasattr(args, 'port') and args.port != 8888:
247
+ if hasattr(args, "port") and args.port != 8888:
246
248
  server_config["port"] = args.port
247
- if hasattr(args, 'transport') and args.transport != "stdio":
249
+ if hasattr(args, "transport") and args.transport != "stdio":
248
250
  server_config["transport"] = args.transport
249
- if hasattr(args, 'log_level') and args.log_level != "INFO":
251
+ if hasattr(args, "log_level") and args.log_level != "INFO":
250
252
  server_config["log_level"] = args.log_level
251
- if hasattr(args, 'command_timeout') and args.command_timeout != 120.0:
253
+ if hasattr(args, "command_timeout") and args.command_timeout != 120.0:
252
254
  server_config["command_timeout"] = args.command_timeout
253
-
255
+
254
256
  if server_config:
255
257
  overrides["server"] = server_config
256
258
 
257
259
  # Path configuration
258
- if hasattr(args, 'allowed_paths') and args.allowed_paths:
260
+ if hasattr(args, "allowed_paths") and args.allowed_paths:
259
261
  overrides["allowed_paths"] = args.allowed_paths
260
- if hasattr(args, 'project_paths') and args.project_paths:
261
- overrides["project_paths"] = args.project_paths
262
- if hasattr(args, 'project_dir') and args.project_dir:
262
+ if hasattr(args, "project_paths") and args.project_paths:
263
+ overrides["project_paths"] = args.project_paths
264
+ if hasattr(args, "project_dir") and args.project_dir:
263
265
  overrides["project_dir"] = args.project_dir
264
266
 
265
267
  # Tool configuration
266
268
  enabled_tools = {}
267
-
269
+
268
270
  # Handle individual tool flags
269
271
  for tool_name, tool_config in TOOL_REGISTRY.items():
270
- flag_name = tool_name.replace('_', '-')
271
-
272
+ flag_name = tool_name.replace("_", "-")
273
+
272
274
  if tool_config.enabled:
273
275
  # Check for disable flag
274
276
  disable_flag = f"disable_{tool_name}"
@@ -281,28 +283,36 @@ def apply_cli_overrides(args: argparse.Namespace) -> Dict[str, Any]:
281
283
  enabled_tools[tool_name] = True
282
284
 
283
285
  # Handle category-level disables
284
- if hasattr(args, 'disable_write_tools') and args.disable_write_tools:
286
+ if hasattr(args, "disable_write_tools") and args.disable_write_tools:
285
287
  for tool_name in ["write", "edit", "multi_edit", "content_replace"]:
286
288
  enabled_tools[tool_name] = False
287
-
288
- if hasattr(args, 'disable_search_tools') and args.disable_search_tools:
289
+
290
+ if hasattr(args, "disable_search_tools") and args.disable_search_tools:
289
291
  for tool_name in ["grep", "grep_ast"]:
290
292
  enabled_tools[tool_name] = False
291
-
292
- if hasattr(args, 'disable_filesystem_tools') and args.disable_filesystem_tools:
293
- filesystem_tools = ["read", "write", "edit", "multi_edit", "directory_tree",
294
- "grep", "grep_ast", "content_replace"]
293
+
294
+ if hasattr(args, "disable_filesystem_tools") and args.disable_filesystem_tools:
295
+ filesystem_tools = [
296
+ "read",
297
+ "write",
298
+ "edit",
299
+ "multi_edit",
300
+ "directory_tree",
301
+ "grep",
302
+ "grep_ast",
303
+ "content_replace",
304
+ ]
295
305
  for tool_name in filesystem_tools:
296
306
  enabled_tools[tool_name] = False
297
-
298
- if hasattr(args, 'disable_jupyter_tools') and args.disable_jupyter_tools:
307
+
308
+ if hasattr(args, "disable_jupyter_tools") and args.disable_jupyter_tools:
299
309
  for tool_name in ["notebook_read", "notebook_edit"]:
300
310
  enabled_tools[tool_name] = False
301
-
302
- if hasattr(args, 'disable_shell_tools') and args.disable_shell_tools:
311
+
312
+ if hasattr(args, "disable_shell_tools") and args.disable_shell_tools:
303
313
  enabled_tools["run_command"] = False
304
-
305
- if hasattr(args, 'disable_todo_tools') and args.disable_todo_tools:
314
+
315
+ if hasattr(args, "disable_todo_tools") and args.disable_todo_tools:
306
316
  for tool_name in ["todo_read", "todo_write"]:
307
317
  enabled_tools[tool_name] = False
308
318
 
@@ -311,32 +321,35 @@ def apply_cli_overrides(args: argparse.Namespace) -> Dict[str, Any]:
311
321
 
312
322
  # Agent configuration
313
323
  agent_config = {}
314
- if hasattr(args, 'agent_model') and args.agent_model:
324
+ if hasattr(args, "agent_model") and args.agent_model:
315
325
  agent_config["model"] = args.agent_model
316
326
  agent_config["enabled"] = True
317
- if hasattr(args, 'agent_api_key') and args.agent_api_key:
327
+ if hasattr(args, "agent_api_key") and args.agent_api_key:
318
328
  agent_config["api_key"] = args.agent_api_key
319
- if hasattr(args, 'agent_base_url') and args.agent_base_url:
329
+ if hasattr(args, "agent_base_url") and args.agent_base_url:
320
330
  agent_config["base_url"] = args.agent_base_url
321
- if hasattr(args, 'agent_max_tokens') and args.agent_max_tokens:
331
+ if hasattr(args, "agent_max_tokens") and args.agent_max_tokens:
322
332
  agent_config["max_tokens"] = args.agent_max_tokens
323
- if hasattr(args, 'agent_max_iterations') and args.agent_max_iterations != 10:
333
+ if hasattr(args, "agent_max_iterations") and args.agent_max_iterations != 10:
324
334
  agent_config["max_iterations"] = args.agent_max_iterations
325
- if hasattr(args, 'agent_max_tool_uses') and args.agent_max_tool_uses != 30:
335
+ if hasattr(args, "agent_max_tool_uses") and args.agent_max_tool_uses != 30:
326
336
  agent_config["max_tool_uses"] = args.agent_max_tool_uses
327
-
337
+
328
338
  if agent_config:
329
339
  overrides["agent"] = agent_config
330
340
 
331
341
  # Vector store configuration
332
342
  vector_config = {}
333
- if hasattr(args, 'enable_vector_store') and args.enable_vector_store:
343
+ if hasattr(args, "enable_vector_store") and args.enable_vector_store:
334
344
  vector_config["enabled"] = True
335
- if hasattr(args, 'vector_store_path') and args.vector_store_path:
345
+ if hasattr(args, "vector_store_path") and args.vector_store_path:
336
346
  vector_config["data_path"] = args.vector_store_path
337
- if hasattr(args, 'embedding_model') and args.embedding_model != "text-embedding-3-small":
347
+ if (
348
+ hasattr(args, "embedding_model")
349
+ and args.embedding_model != "text-embedding-3-small"
350
+ ):
338
351
  vector_config["embedding_model"] = args.embedding_model
339
-
352
+
340
353
  if vector_config:
341
354
  overrides["vector_store"] = vector_config
342
355
 
@@ -348,26 +361,28 @@ def list_tools(settings: HanzoMCPSettings) -> None:
348
361
  logger = logging.getLogger(__name__)
349
362
  logger.info("Hanzo AI Tools Status:")
350
363
  logger.info("=" * 50)
351
-
364
+
352
365
  categories = {}
353
366
  for tool_name, tool_config in TOOL_REGISTRY.items():
354
367
  category = tool_config.category.value
355
368
  if category not in categories:
356
369
  categories[category] = []
357
-
370
+
358
371
  enabled = settings.is_tool_enabled(tool_name)
359
372
  status = "✅ ENABLED " if enabled else "❌ DISABLED"
360
373
  categories[category].append((tool_name, status, tool_config.description))
361
-
374
+
362
375
  for category, tools in categories.items():
363
376
  logger.info(f"\n{category.upper()} TOOLS:")
364
377
  logger.info("-" * 30)
365
378
  for tool_name, status, description in tools:
366
379
  logger.info(f" {status} {tool_name:<15} - {description}")
367
-
380
+
368
381
  logger.info(f"\nTotal: {len(TOOL_REGISTRY)} tools")
369
382
  enabled_count = len(settings.get_enabled_tools())
370
- logger.info(f"Enabled: {enabled_count}, Disabled: {len(TOOL_REGISTRY) - enabled_count}")
383
+ logger.info(
384
+ f"Enabled: {enabled_count}, Disabled: {len(TOOL_REGISTRY) - enabled_count}"
385
+ )
371
386
 
372
387
 
373
388
  def main() -> None:
@@ -376,31 +391,32 @@ def main() -> None:
376
391
  args = parser.parse_args()
377
392
 
378
393
  # Handle list tools command
379
- if hasattr(args, 'list_tools') and args.list_tools:
394
+ if hasattr(args, "list_tools") and args.list_tools:
380
395
  settings = load_settings()
381
396
  list_tools(settings)
382
397
  return
383
398
 
384
399
  # Load configuration with CLI overrides
385
400
  config_overrides = apply_cli_overrides(args)
386
- project_dir = getattr(args, 'project_dir', None)
401
+ project_dir = getattr(args, "project_dir", None)
387
402
  settings = load_settings(project_dir=project_dir, config_overrides=config_overrides)
388
403
 
389
404
  # Handle configuration saving
390
405
  logger = logging.getLogger(__name__)
391
- if hasattr(args, 'save_config') and args.save_config:
406
+ if hasattr(args, "save_config") and args.save_config:
392
407
  saved_path = save_settings(settings, global_config=True)
393
408
  logger.info(f"Configuration saved to: {saved_path}")
394
409
  return
395
-
396
- if hasattr(args, 'save_project_config') and args.save_project_config:
410
+
411
+ if hasattr(args, "save_project_config") and args.save_project_config:
397
412
  saved_path = save_settings(settings, global_config=False)
398
413
  logger.info(f"Project configuration saved to: {saved_path}")
399
414
  return
400
415
 
401
416
  # Handle installation
402
- if hasattr(args, 'install') and args.install:
417
+ if hasattr(args, "install") and args.install:
403
418
  from hanzo_mcp.cli import install_claude_desktop_config
419
+
404
420
  install_claude_desktop_config(
405
421
  settings.server.name,
406
422
  settings.allowed_paths,
@@ -411,7 +427,7 @@ def main() -> None:
411
427
  allowed_paths = settings.allowed_paths[:]
412
428
  if settings.project_dir and settings.project_dir not in allowed_paths:
413
429
  allowed_paths.append(settings.project_dir)
414
-
430
+
415
431
  if not allowed_paths:
416
432
  allowed_paths = [os.getcwd()]
417
433
 
@@ -426,16 +442,22 @@ def main() -> None:
426
442
  agent_base_url=settings.agent.base_url,
427
443
  agent_max_iterations=settings.agent.max_iterations,
428
444
  agent_max_tool_uses=settings.agent.max_tool_uses,
429
- enable_agent_tool=settings.agent.enabled or settings.is_tool_enabled("dispatch_agent"),
430
- disable_write_tools=not any(settings.is_tool_enabled(t) for t in ["write", "edit", "multi_edit", "content_replace"]),
431
- disable_search_tools=not any(settings.is_tool_enabled(t) for t in ["grep", "grep_ast"]),
445
+ enable_agent_tool=settings.agent.enabled
446
+ or settings.is_tool_enabled("dispatch_agent"),
447
+ disable_write_tools=not any(
448
+ settings.is_tool_enabled(t)
449
+ for t in ["write", "edit", "multi_edit", "content_replace"]
450
+ ),
451
+ disable_search_tools=not any(
452
+ settings.is_tool_enabled(t) for t in ["grep", "grep_ast"]
453
+ ),
432
454
  host=settings.server.host,
433
455
  port=settings.server.port,
434
456
  enabled_tools=settings.enabled_tools, # Pass individual tool configuration
435
457
  )
436
-
458
+
437
459
  server.run(transport=settings.server.transport)
438
460
 
439
461
 
440
462
  if __name__ == "__main__":
441
- main()
463
+ main()
hanzo_mcp/cli_plugin.py CHANGED
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env python3
2
2
  """CLI for managing Hanzo MCP plugins."""
3
3
 
4
- import argparse
5
4
  import sys
5
+ import argparse
6
6
  from pathlib import Path
7
7
 
8
- from hanzo_mcp.tools.common.plugin_loader import create_plugin_template, list_plugin_tools
8
+ from hanzo_mcp.tools.common.plugin_loader import (
9
+ create_plugin_template,
10
+ )
9
11
 
10
12
 
11
13
  def main():
@@ -23,26 +25,27 @@ Examples:
23
25
 
24
26
  # Create plugin in specific directory
25
27
  hanzo-plugin create mytool --output /path/to/plugins
26
- """
28
+ """,
27
29
  )
28
-
30
+
29
31
  subparsers = parser.add_subparsers(dest="command", help="Command to run")
30
-
32
+
31
33
  # Create command
32
34
  create_parser = subparsers.add_parser("create", help="Create a new plugin template")
33
35
  create_parser.add_argument("name", help="Name of the tool (e.g., 'mytool')")
34
36
  create_parser.add_argument(
35
- "--output", "-o",
37
+ "--output",
38
+ "-o",
36
39
  type=Path,
37
40
  default=Path.home() / ".hanzo" / "plugins",
38
- help="Output directory for the plugin (default: ~/.hanzo/plugins)"
41
+ help="Output directory for the plugin (default: ~/.hanzo/plugins)",
39
42
  )
40
-
43
+
41
44
  # List command
42
45
  list_parser = subparsers.add_parser("list", help="List installed plugins")
43
-
46
+
44
47
  args = parser.parse_args()
45
-
48
+
46
49
  if args.command == "create":
47
50
  # Create plugin template
48
51
  output_dir = args.output / args.name
@@ -50,19 +53,22 @@ Examples:
50
53
  create_plugin_template(output_dir, args.name)
51
54
  print(f"\n✅ Plugin template created successfully!")
52
55
  print(f"\nTo use your plugin:")
53
- print(f"1. Edit the tool implementation in {output_dir / f'{args.name}_tool.py'}")
56
+ print(
57
+ f"1. Edit the tool implementation in {output_dir / f'{args.name}_tool.py'}"
58
+ )
54
59
  print(f"2. Restart Hanzo MCP to load the plugin")
55
60
  print(f"3. Add '{args.name}' to your mode's tool list")
56
61
  except Exception as e:
57
62
  print(f"❌ Error creating plugin: {e}", file=sys.stderr)
58
63
  sys.exit(1)
59
-
64
+
60
65
  elif args.command == "list":
61
66
  # List installed plugins
62
67
  try:
63
68
  from hanzo_mcp.tools.common.plugin_loader import load_user_plugins
69
+
64
70
  plugins = load_user_plugins()
65
-
71
+
66
72
  if not plugins:
67
73
  print("No plugins installed.")
68
74
  print("\nPlugin directories:")
@@ -75,17 +81,21 @@ Examples:
75
81
  print(f"\n {name}:")
76
82
  print(f" Source: {plugin.source_path}")
77
83
  if plugin.metadata:
78
- print(f" Version: {plugin.metadata.get('version', 'unknown')}")
84
+ print(
85
+ f" Version: {plugin.metadata.get('version', 'unknown')}"
86
+ )
79
87
  print(f" Author: {plugin.metadata.get('author', 'unknown')}")
80
- print(f" Description: {plugin.metadata.get('description', '')}")
88
+ print(
89
+ f" Description: {plugin.metadata.get('description', '')}"
90
+ )
81
91
  except Exception as e:
82
92
  print(f"❌ Error listing plugins: {e}", file=sys.stderr)
83
93
  sys.exit(1)
84
-
94
+
85
95
  else:
86
96
  parser.print_help()
87
97
  sys.exit(1)
88
98
 
89
99
 
90
100
  if __name__ == "__main__":
91
- main()
101
+ main()
@@ -12,8 +12,8 @@ from .tool_config import ToolConfig, ToolCategory
12
12
 
13
13
  __all__ = [
14
14
  "HanzoMCPSettings",
15
- "ToolConfig",
15
+ "ToolConfig",
16
16
  "ToolCategory",
17
17
  "load_settings",
18
18
  "save_settings",
19
- ]
19
+ ]