hanzo-mcp 0.7.7__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 +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.0.dist-info}/METADATA +1 -1
  174. hanzo_mcp-0.8.0.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.0.dist-info}/WHEEL +0 -0
  177. {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.0.dist-info}/entry_points.txt +0 -0
  178. {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.0.dist-info}/top_level.txt +0 -0
@@ -4,36 +4,37 @@ This module manages indexing configuration for different scopes.
4
4
  """
5
5
 
6
6
  import json
7
- from pathlib import Path
8
- from typing import Dict, Any, Optional
9
7
  from enum import Enum
8
+ from typing import Any, Dict, Optional
9
+ from pathlib import Path
10
10
 
11
11
 
12
12
  class IndexScope(Enum):
13
13
  """Indexing scope options."""
14
+
14
15
  PROJECT = "project" # Per-project indexing
15
- GLOBAL = "global" # Global indexing
16
- AUTO = "auto" # Auto-detect based on git root
16
+ GLOBAL = "global" # Global indexing
17
+ AUTO = "auto" # Auto-detect based on git root
17
18
 
18
19
 
19
20
  class IndexConfig:
20
21
  """Manages indexing configuration."""
21
-
22
+
22
23
  def __init__(self, config_dir: Optional[Path] = None):
23
24
  """Initialize index configuration."""
24
25
  self.config_dir = config_dir or Path.home() / ".hanzo" / "mcp"
25
26
  self.config_file = self.config_dir / "index_config.json"
26
27
  self._config = self._load_config()
27
-
28
+
28
29
  def _load_config(self) -> Dict[str, Any]:
29
30
  """Load configuration from disk."""
30
31
  if self.config_file.exists():
31
32
  try:
32
33
  with open(self.config_file, "r") as f:
33
34
  return json.load(f)
34
- except:
35
+ except Exception:
35
36
  pass
36
-
37
+
37
38
  # Default configuration
38
39
  return {
39
40
  "default_scope": IndexScope.AUTO.value,
@@ -56,40 +57,40 @@ class IndexConfig:
56
57
  "graph": {
57
58
  "enabled": True,
58
59
  "per_project": True,
59
- }
60
- }
60
+ },
61
+ },
61
62
  }
62
-
63
+
63
64
  def save_config(self) -> None:
64
65
  """Save configuration to disk."""
65
66
  self.config_dir.mkdir(parents=True, exist_ok=True)
66
67
  with open(self.config_file, "w") as f:
67
68
  json.dump(self._config, f, indent=2)
68
-
69
+
69
70
  def get_scope(self, path: Optional[str] = None) -> IndexScope:
70
71
  """Get indexing scope for a path."""
71
72
  if not path:
72
73
  return IndexScope(self._config["default_scope"])
73
-
74
+
74
75
  # Check project-specific config
75
76
  project_root = self._find_project_root(path)
76
77
  if project_root:
77
78
  project_config = self._config["project_configs"].get(str(project_root))
78
79
  if project_config and "scope" in project_config:
79
80
  return IndexScope(project_config["scope"])
80
-
81
+
81
82
  # Use default
82
83
  scope = IndexScope(self._config["default_scope"])
83
-
84
+
84
85
  # Handle auto mode
85
86
  if scope == IndexScope.AUTO:
86
87
  if project_root:
87
88
  return IndexScope.PROJECT
88
89
  else:
89
90
  return IndexScope.GLOBAL
90
-
91
+
91
92
  return scope
92
-
93
+
93
94
  def set_scope(self, scope: IndexScope, path: Optional[str] = None) -> None:
94
95
  """Set indexing scope."""
95
96
  if path:
@@ -98,40 +99,42 @@ class IndexConfig:
98
99
  if project_root:
99
100
  if str(project_root) not in self._config["project_configs"]:
100
101
  self._config["project_configs"][str(project_root)] = {}
101
- self._config["project_configs"][str(project_root)]["scope"] = scope.value
102
+ self._config["project_configs"][str(project_root)][
103
+ "scope"
104
+ ] = scope.value
102
105
  else:
103
106
  # Set global default
104
107
  self._config["default_scope"] = scope.value
105
-
108
+
106
109
  self.save_config()
107
-
110
+
108
111
  def get_index_path(self, tool: str, path: Optional[str] = None) -> Path:
109
112
  """Get index path for a tool and location."""
110
113
  scope = self.get_scope(path)
111
-
114
+
112
115
  if scope == IndexScope.PROJECT and path:
113
116
  project_root = self._find_project_root(path)
114
117
  if project_root:
115
118
  return Path(project_root) / ".hanzo" / "index" / tool
116
-
119
+
117
120
  # Global index
118
121
  return self.config_dir / "index" / tool
119
-
122
+
120
123
  def is_indexing_enabled(self, tool: str) -> bool:
121
124
  """Check if indexing is enabled for a tool."""
122
125
  return self._config["index_settings"].get(tool, {}).get("enabled", True)
123
-
126
+
124
127
  def set_indexing_enabled(self, tool: str, enabled: bool) -> None:
125
128
  """Enable/disable indexing for a tool."""
126
129
  if tool not in self._config["index_settings"]:
127
130
  self._config["index_settings"][tool] = {}
128
131
  self._config["index_settings"][tool]["enabled"] = enabled
129
132
  self.save_config()
130
-
133
+
131
134
  def toggle_scope(self, path: Optional[str] = None) -> IndexScope:
132
135
  """Toggle between project and global scope."""
133
136
  current = self.get_scope(path)
134
-
137
+
135
138
  if current == IndexScope.PROJECT:
136
139
  new_scope = IndexScope.GLOBAL
137
140
  elif current == IndexScope.GLOBAL:
@@ -142,25 +145,25 @@ class IndexConfig:
142
145
  new_scope = IndexScope.GLOBAL
143
146
  else:
144
147
  new_scope = IndexScope.PROJECT
145
-
148
+
146
149
  self.set_scope(new_scope, path)
147
150
  return new_scope
148
-
151
+
149
152
  def _find_project_root(self, path: str) -> Optional[Path]:
150
153
  """Find project root (git root or similar)."""
151
154
  current = Path(path).resolve()
152
-
155
+
153
156
  # Walk up looking for markers
154
157
  markers = [".git", ".hg", "pyproject.toml", "package.json", "Cargo.toml"]
155
-
158
+
156
159
  while current != current.parent:
157
160
  for marker in markers:
158
161
  if (current / marker).exists():
159
162
  return current
160
163
  current = current.parent
161
-
164
+
162
165
  return None
163
-
166
+
164
167
  def get_status(self) -> Dict[str, Any]:
165
168
  """Get current configuration status."""
166
169
  return {
@@ -172,5 +175,5 @@ class IndexConfig:
172
175
  "per_project": settings.get("per_project", True),
173
176
  }
174
177
  for tool, settings in self._config["index_settings"].items()
175
- }
176
- }
178
+ },
179
+ }
@@ -2,24 +2,24 @@
2
2
 
3
3
  from typing import Optional, override
4
4
 
5
+ from mcp.server import FastMCP
5
6
  from mcp.server.fastmcp import Context as MCPContext
6
7
 
7
8
  from hanzo_mcp.tools.common.base import BaseTool
8
9
  from hanzo_mcp.tools.common.mode import ModeRegistry, register_default_modes
9
- from mcp.server import FastMCP
10
10
 
11
11
 
12
12
  class ModeTool(BaseTool):
13
13
  """Tool for managing development modes."""
14
-
14
+
15
15
  name = "mode"
16
-
16
+
17
17
  def __init__(self):
18
18
  """Initialize the mode tool."""
19
19
  super().__init__()
20
20
  # Register default modes on initialization
21
21
  register_default_modes()
22
-
22
+
23
23
  @property
24
24
  @override
25
25
  def description(self) -> str:
@@ -32,7 +32,7 @@ mode --action list
32
32
  mode --action activate guido
33
33
  mode --action show linus
34
34
  mode --action current"""
35
-
35
+
36
36
  @override
37
37
  async def run(
38
38
  self,
@@ -41,12 +41,12 @@ mode --action current"""
41
41
  name: Optional[str] = None,
42
42
  ) -> str:
43
43
  """Manage development modes.
44
-
44
+
45
45
  Args:
46
46
  ctx: MCP context
47
47
  action: Action to perform (list, activate, show, current)
48
48
  name: Mode name (for activate/show actions)
49
-
49
+
50
50
  Returns:
51
51
  Action result
52
52
  """
@@ -54,60 +54,182 @@ mode --action current"""
54
54
  modes = ModeRegistry.list()
55
55
  if not modes:
56
56
  return "No modes registered"
57
-
57
+
58
58
  output = ["Available development modes (100 programmer personalities):"]
59
59
  active = ModeRegistry.get_active()
60
-
60
+
61
61
  # Group modes by category
62
62
  categories = {
63
- "Language Creators": ["guido", "matz", "brendan", "dennis", "bjarne", "james", "anders", "larry", "rasmus", "rich"],
64
- "Systems & Infrastructure": ["linus", "rob", "ken", "bill", "richard", "brian", "donald", "graydon", "ryan", "mitchell"],
65
- "Web & Frontend": ["tim", "douglas", "john", "evan", "jordan", "jeremy", "david", "taylor", "adrian", "matt"],
66
- "Database & Data": ["michael_s", "michael_w", "salvatore", "dwight", "edgar", "jim_gray", "jeff_dean", "sanjay", "mike", "matei"],
67
- "AI & Machine Learning": ["yann", "geoffrey", "yoshua", "andrew", "demis", "ilya", "andrej", "chris", "francois", "jeremy_howard"],
68
- "Security & Cryptography": ["bruce", "phil", "whitfield", "ralph", "daniel_b", "moxie", "theo", "dan_kaminsky", "katie", "matt_blaze"],
69
- "Gaming & Graphics": ["john_carmack", "sid", "shigeru", "gabe", "markus", "jonathan", "casey", "tim_sweeney", "hideo", "will"],
70
- "Open Source Leaders": ["miguel", "nat", "patrick", "ian", "mark_shuttleworth", "lennart", "bram", "daniel_r", "judd", "fabrice"],
71
- "Modern Innovators": ["vitalik", "satoshi", "chris_lattner", "joe", "jose", "sebastian", "palmer", "dylan", "guillermo", "tom"],
72
- "Special Configurations": ["fullstack", "minimal", "data_scientist", "devops", "security", "academic", "startup", "enterprise", "creative", "hanzo"],
63
+ "Language Creators": [
64
+ "guido",
65
+ "matz",
66
+ "brendan",
67
+ "dennis",
68
+ "bjarne",
69
+ "james",
70
+ "anders",
71
+ "larry",
72
+ "rasmus",
73
+ "rich",
74
+ ],
75
+ "Systems & Infrastructure": [
76
+ "linus",
77
+ "rob",
78
+ "ken",
79
+ "bill",
80
+ "richard",
81
+ "brian",
82
+ "donald",
83
+ "graydon",
84
+ "ryan",
85
+ "mitchell",
86
+ ],
87
+ "Web & Frontend": [
88
+ "tim",
89
+ "douglas",
90
+ "john",
91
+ "evan",
92
+ "jordan",
93
+ "jeremy",
94
+ "david",
95
+ "taylor",
96
+ "adrian",
97
+ "matt",
98
+ ],
99
+ "Database & Data": [
100
+ "michael_s",
101
+ "michael_w",
102
+ "salvatore",
103
+ "dwight",
104
+ "edgar",
105
+ "jim_gray",
106
+ "jeff_dean",
107
+ "sanjay",
108
+ "mike",
109
+ "matei",
110
+ ],
111
+ "AI & Machine Learning": [
112
+ "yann",
113
+ "geoffrey",
114
+ "yoshua",
115
+ "andrew",
116
+ "demis",
117
+ "ilya",
118
+ "andrej",
119
+ "chris",
120
+ "francois",
121
+ "jeremy_howard",
122
+ ],
123
+ "Security & Cryptography": [
124
+ "bruce",
125
+ "phil",
126
+ "whitfield",
127
+ "ralph",
128
+ "daniel_b",
129
+ "moxie",
130
+ "theo",
131
+ "dan_kaminsky",
132
+ "katie",
133
+ "matt_blaze",
134
+ ],
135
+ "Gaming & Graphics": [
136
+ "john_carmack",
137
+ "sid",
138
+ "shigeru",
139
+ "gabe",
140
+ "markus",
141
+ "jonathan",
142
+ "casey",
143
+ "tim_sweeney",
144
+ "hideo",
145
+ "will",
146
+ ],
147
+ "Open Source Leaders": [
148
+ "miguel",
149
+ "nat",
150
+ "patrick",
151
+ "ian",
152
+ "mark_shuttleworth",
153
+ "lennart",
154
+ "bram",
155
+ "daniel_r",
156
+ "judd",
157
+ "fabrice",
158
+ ],
159
+ "Modern Innovators": [
160
+ "vitalik",
161
+ "satoshi",
162
+ "chris_lattner",
163
+ "joe",
164
+ "jose",
165
+ "sebastian",
166
+ "palmer",
167
+ "dylan",
168
+ "guillermo",
169
+ "tom",
170
+ ],
171
+ "Special Configurations": [
172
+ "fullstack",
173
+ "minimal",
174
+ "data_scientist",
175
+ "devops",
176
+ "security",
177
+ "academic",
178
+ "startup",
179
+ "enterprise",
180
+ "creative",
181
+ "hanzo",
182
+ ],
73
183
  }
74
-
184
+
75
185
  for category, mode_names in categories.items():
76
186
  output.append(f"\n{category}:")
77
187
  for mode_name in mode_names:
78
188
  mode = next((m for m in modes if m.name == mode_name), None)
79
189
  if mode:
80
- marker = " (active)" if active and active.name == mode.name else ""
81
- output.append(f" {mode.name}{marker}: {mode.programmer} - {mode.description}")
82
-
190
+ marker = (
191
+ " (active)" if active and active.name == mode.name else ""
192
+ )
193
+ output.append(
194
+ f" {mode.name}{marker}: {mode.programmer} - {mode.description}"
195
+ )
196
+
83
197
  output.append("\nUse 'mode --action activate <name>' to activate a mode")
84
-
198
+
85
199
  return "\n".join(output)
86
-
200
+
87
201
  elif action == "activate":
88
202
  if not name:
89
203
  return "Error: Mode name required for activate action"
90
-
204
+
91
205
  try:
92
206
  ModeRegistry.set_active(name)
93
207
  mode = ModeRegistry.get(name)
94
-
208
+
95
209
  output = [f"Activated mode: {mode.name}"]
96
210
  output.append(f"Programmer: {mode.programmer}")
97
211
  output.append(f"Description: {mode.description}")
98
212
  if mode.philosophy:
99
213
  output.append(f"Philosophy: {mode.philosophy}")
100
214
  output.append(f"\nEnabled tools ({len(mode.tools)}):")
101
-
215
+
102
216
  # Group tools by category
103
217
  core_tools = []
104
218
  package_tools = []
105
219
  ai_tools = []
106
220
  search_tools = []
107
221
  other_tools = []
108
-
222
+
109
223
  for tool in sorted(mode.tools):
110
- if tool in ["read", "write", "edit", "multi_edit", "bash", "tree", "grep"]:
224
+ if tool in [
225
+ "read",
226
+ "write",
227
+ "edit",
228
+ "multi_edit",
229
+ "bash",
230
+ "tree",
231
+ "grep",
232
+ ]:
111
233
  core_tools.append(tool)
112
234
  elif tool in ["npx", "uvx", "pip", "cargo", "gem"]:
113
235
  package_tools.append(tool)
@@ -117,7 +239,7 @@ mode --action current"""
117
239
  search_tools.append(tool)
118
240
  else:
119
241
  other_tools.append(tool)
120
-
242
+
121
243
  if core_tools:
122
244
  output.append(f" Core: {', '.join(core_tools)}")
123
245
  if package_tools:
@@ -128,82 +250,80 @@ mode --action current"""
128
250
  output.append(f" Search: {', '.join(search_tools)}")
129
251
  if other_tools:
130
252
  output.append(f" Specialized: {', '.join(other_tools)}")
131
-
253
+
132
254
  if mode.environment:
133
255
  output.append("\nEnvironment variables:")
134
256
  for key, value in mode.environment.items():
135
257
  output.append(f" {key}={value}")
136
-
137
- output.append("\nNote: Restart MCP session for changes to take full effect")
138
-
258
+
259
+ output.append(
260
+ "\nNote: Restart MCP session for changes to take full effect"
261
+ )
262
+
139
263
  return "\n".join(output)
140
-
264
+
141
265
  except ValueError as e:
142
266
  return str(e)
143
-
267
+
144
268
  elif action == "show":
145
269
  if not name:
146
270
  return "Error: Mode name required for show action"
147
-
271
+
148
272
  mode = ModeRegistry.get(name)
149
273
  if not mode:
150
274
  return f"Mode '{name}' not found"
151
-
275
+
152
276
  output = [f"Mode: {mode.name}"]
153
277
  output.append(f"Programmer: {mode.programmer}")
154
278
  output.append(f"Description: {mode.description}")
155
279
  if mode.philosophy:
156
280
  output.append(f"Philosophy: {mode.philosophy}")
157
281
  output.append(f"\nTools ({len(mode.tools)}):")
158
-
282
+
159
283
  for tool in sorted(mode.tools):
160
284
  output.append(f" - {tool}")
161
-
285
+
162
286
  if mode.environment:
163
287
  output.append("\nEnvironment:")
164
288
  for key, value in mode.environment.items():
165
289
  output.append(f" {key}={value}")
166
-
290
+
167
291
  return "\n".join(output)
168
-
292
+
169
293
  elif action == "current":
170
294
  active = ModeRegistry.get_active()
171
295
  if not active:
172
296
  return "No mode currently active\nUse 'mode --action activate <name>' to activate one"
173
-
297
+
174
298
  output = [f"Current mode: {active.name}"]
175
299
  output.append(f"Programmer: {active.programmer}")
176
300
  output.append(f"Description: {active.description}")
177
301
  if active.philosophy:
178
302
  output.append(f"Philosophy: {active.philosophy}")
179
303
  output.append(f"Enabled tools: {len(active.tools)}")
180
-
304
+
181
305
  return "\n".join(output)
182
-
306
+
183
307
  else:
184
308
  return f"Unknown action: {action}. Use 'list', 'activate', 'show', or 'current'"
185
309
 
186
310
  def register(self, server: FastMCP) -> None:
187
311
  """Register the tool with the MCP server."""
188
312
  tool_self = self
189
-
313
+
190
314
  @server.tool(name=self.name, description=self.description)
191
315
  async def mode_handler(
192
- ctx: MCPContext,
193
- action: str = "list",
194
- name: Optional[str] = None
316
+ ctx: MCPContext, action: str = "list", name: Optional[str] = None
195
317
  ) -> str:
196
318
  """Handle mode tool calls."""
197
319
  return await tool_self.run(ctx, action=action, name=name)
198
-
320
+
199
321
  async def call(self, ctx: MCPContext, **params) -> str:
200
322
  """Call the tool with arguments."""
201
323
  return await self.run(
202
- ctx,
203
- action=params.get("action", "list"),
204
- name=params.get("name")
324
+ ctx, action=params.get("action", "list"), name=params.get("name")
205
325
  )
206
326
 
207
327
 
208
328
  # Create tool instance
209
- mode_tool = ModeTool()
329
+ mode_tool = ModeTool()
@@ -4,26 +4,28 @@ This package provides tools for working with embedded SQLite databases
4
4
  and graph databases in projects.
5
5
  """
6
6
 
7
+ from mcp.server import FastMCP
8
+
7
9
  from hanzo_mcp.tools.common.base import BaseTool
8
10
  from hanzo_mcp.tools.common.permissions import PermissionManager
9
- from mcp.server import FastMCP
11
+
12
+ from .graph_add import GraphAddTool
10
13
 
11
14
  # Import database tools
12
15
  from .sql_query import SqlQueryTool
13
- from .sql_search import SqlSearchTool
14
16
  from .sql_stats import SqlStatsTool
15
- from .graph_add import GraphAddTool
16
- from .graph_remove import GraphRemoveTool
17
+ from .sql_search import SqlSearchTool
17
18
  from .graph_query import GraphQueryTool
18
- from .graph_search import GraphSearchTool
19
19
  from .graph_stats import GraphStatsTool
20
+ from .graph_remove import GraphRemoveTool
21
+ from .graph_search import GraphSearchTool
20
22
  from .database_manager import DatabaseManager
21
23
 
22
24
  __all__ = [
23
25
  "register_database_tools",
24
26
  "DatabaseManager",
25
27
  "SqlQueryTool",
26
- "SqlSearchTool",
28
+ "SqlSearchTool",
27
29
  "SqlStatsTool",
28
30
  "GraphAddTool",
29
31
  "GraphRemoveTool",
@@ -39,19 +41,19 @@ def register_database_tools(
39
41
  db_manager: DatabaseManager | None = None,
40
42
  ) -> list[BaseTool]:
41
43
  """Register database tools with the MCP server.
42
-
44
+
43
45
  Args:
44
46
  mcp_server: The FastMCP server instance
45
47
  permission_manager: Permission manager for access control
46
48
  db_manager: Optional database manager instance
47
-
49
+
48
50
  Returns:
49
51
  List of registered tools
50
52
  """
51
53
  # Create database manager if not provided
52
54
  if db_manager is None:
53
55
  db_manager = DatabaseManager(permission_manager)
54
-
56
+
55
57
  # Create tool instances
56
58
  tools = [
57
59
  SqlQueryTool(permission_manager, db_manager),
@@ -63,9 +65,10 @@ def register_database_tools(
63
65
  GraphSearchTool(permission_manager, db_manager),
64
66
  GraphStatsTool(permission_manager, db_manager),
65
67
  ]
66
-
68
+
67
69
  # Register with MCP server
68
70
  from hanzo_mcp.tools.common.base import ToolRegistry
71
+
69
72
  ToolRegistry.register_tools(mcp_server, tools)
70
-
71
- return tools
73
+
74
+ return tools