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,18 +4,18 @@ This module provides utilities for implementing cursor-based pagination
4
4
  according to the MCP pagination protocol.
5
5
  """
6
6
 
7
- import base64
8
7
  import json
9
- from typing import Any, Dict, List, Optional, Tuple, TypeVar, Generic
8
+ import base64
9
+ from typing import Any, Dict, List, Generic, TypeVar, Optional
10
10
  from dataclasses import dataclass
11
11
 
12
-
13
- T = TypeVar('T')
12
+ T = TypeVar("T")
14
13
 
15
14
 
16
15
  @dataclass
17
16
  class PaginationParams:
18
17
  """Parameters for pagination."""
18
+
19
19
  cursor: Optional[str] = None
20
20
  page_size: int = 100 # Default page size
21
21
 
@@ -23,15 +23,16 @@ class PaginationParams:
23
23
  @dataclass
24
24
  class PaginatedResponse(Generic[T]):
25
25
  """A paginated response containing items and optional next cursor."""
26
+
26
27
  items: List[T]
27
28
  next_cursor: Optional[str] = None
28
-
29
+
29
30
  def to_dict(self, items_key: str = "items") -> Dict[str, Any]:
30
31
  """Convert to dictionary format for MCP response.
31
-
32
+
32
33
  Args:
33
34
  items_key: The key to use for items in the response
34
-
35
+
35
36
  Returns:
36
37
  Dictionary with items and optional nextCursor
37
38
  """
@@ -43,27 +44,27 @@ class PaginatedResponse(Generic[T]):
43
44
 
44
45
  class CursorManager:
45
46
  """Manages cursor creation and parsing for pagination."""
46
-
47
+
47
48
  @staticmethod
48
49
  def create_cursor(data: Dict[str, Any]) -> str:
49
50
  """Create an opaque cursor from data.
50
-
51
+
51
52
  Args:
52
53
  data: Data to encode in the cursor
53
-
54
+
54
55
  Returns:
55
56
  Base64-encoded cursor string
56
57
  """
57
- json_data = json.dumps(data, separators=(',', ':'))
58
+ json_data = json.dumps(data, separators=(",", ":"))
58
59
  return base64.b64encode(json_data.encode()).decode()
59
-
60
+
60
61
  @staticmethod
61
62
  def parse_cursor(cursor: str) -> Optional[Dict[str, Any]]:
62
63
  """Parse a cursor string back to data.
63
-
64
+
64
65
  Args:
65
66
  cursor: Base64-encoded cursor string
66
-
67
+
67
68
  Returns:
68
69
  Decoded data or None if invalid
69
70
  """
@@ -72,141 +73,137 @@ class CursorManager:
72
73
  return json.loads(decoded)
73
74
  except (ValueError, json.JSONDecodeError):
74
75
  return None
75
-
76
+
76
77
  @staticmethod
77
78
  def create_offset_cursor(offset: int) -> str:
78
79
  """Create a cursor for offset-based pagination.
79
-
80
+
80
81
  Args:
81
82
  offset: The offset for the next page
82
-
83
+
83
84
  Returns:
84
85
  Cursor string
85
86
  """
86
87
  return CursorManager.create_cursor({"offset": offset})
87
-
88
+
88
89
  @staticmethod
89
90
  def parse_offset_cursor(cursor: Optional[str]) -> int:
90
91
  """Parse an offset cursor.
91
-
92
+
92
93
  Args:
93
94
  cursor: Cursor string or None
94
-
95
+
95
96
  Returns:
96
97
  Offset value (0 if cursor is None or invalid)
97
98
  """
98
99
  if not cursor:
99
100
  return 0
100
-
101
+
101
102
  data = CursorManager.parse_cursor(cursor)
102
103
  if not data or "offset" not in data:
103
104
  return 0
104
-
105
+
105
106
  return int(data["offset"])
106
107
 
107
108
 
108
109
  class Paginator(Generic[T]):
109
110
  """Generic paginator for any list of items."""
110
-
111
+
111
112
  def __init__(self, items: List[T], page_size: int = 100):
112
113
  """Initialize paginator.
113
-
114
+
114
115
  Args:
115
116
  items: List of items to paginate
116
117
  page_size: Number of items per page
117
118
  """
118
119
  self.items = items
119
120
  self.page_size = page_size
120
-
121
+
121
122
  def get_page(self, cursor: Optional[str] = None) -> PaginatedResponse[T]:
122
123
  """Get a page of results.
123
-
124
+
124
125
  Args:
125
126
  cursor: Optional cursor for the page
126
-
127
+
127
128
  Returns:
128
129
  Paginated response with items and next cursor
129
130
  """
130
131
  offset = CursorManager.parse_offset_cursor(cursor)
131
-
132
+
132
133
  # Get the page of items
133
134
  start = offset
134
135
  end = min(start + self.page_size, len(self.items))
135
136
  page_items = self.items[start:end]
136
-
137
+
137
138
  # Create next cursor if there are more items
138
139
  next_cursor = None
139
140
  if end < len(self.items):
140
141
  next_cursor = CursorManager.create_offset_cursor(end)
141
-
142
+
142
143
  return PaginatedResponse(items=page_items, next_cursor=next_cursor)
143
144
 
144
145
 
145
146
  class StreamPaginator(Generic[T]):
146
147
  """Paginator for streaming/generator-based results."""
147
-
148
+
148
149
  def __init__(self, page_size: int = 100):
149
150
  """Initialize stream paginator.
150
-
151
+
151
152
  Args:
152
153
  page_size: Number of items per page
153
154
  """
154
155
  self.page_size = page_size
155
-
156
+
156
157
  def paginate_stream(
157
- self,
158
- stream_generator,
159
- cursor: Optional[str] = None
158
+ self, stream_generator, cursor: Optional[str] = None
160
159
  ) -> PaginatedResponse[T]:
161
160
  """Paginate results from a stream/generator.
162
-
161
+
163
162
  Args:
164
163
  stream_generator: Generator function that yields items
165
164
  cursor: Optional cursor for resuming
166
-
165
+
167
166
  Returns:
168
167
  Paginated response
169
168
  """
170
169
  items = []
171
170
  skip_count = 0
172
-
171
+
173
172
  # Parse cursor to get skip count
174
173
  if cursor:
175
174
  cursor_data = CursorManager.parse_cursor(cursor)
176
175
  if cursor_data and "skip" in cursor_data:
177
176
  skip_count = cursor_data["skip"]
178
-
177
+
179
178
  # Skip items based on cursor
180
179
  item_count = 0
181
180
  for item in stream_generator():
182
181
  if item_count < skip_count:
183
182
  item_count += 1
184
183
  continue
185
-
184
+
186
185
  items.append(item)
187
186
  if len(items) >= self.page_size:
188
187
  # We have a full page, create cursor for next page
189
- next_cursor = CursorManager.create_cursor({
190
- "skip": skip_count + len(items)
191
- })
188
+ next_cursor = CursorManager.create_cursor(
189
+ {"skip": skip_count + len(items)}
190
+ )
192
191
  return PaginatedResponse(items=items, next_cursor=next_cursor)
193
-
192
+
194
193
  # No more items
195
194
  return PaginatedResponse(items=items, next_cursor=None)
196
195
 
197
196
 
198
197
  def paginate_list(
199
- items: List[T],
200
- cursor: Optional[str] = None,
201
- page_size: int = 100
198
+ items: List[T], cursor: Optional[str] = None, page_size: int = 100
202
199
  ) -> PaginatedResponse[T]:
203
200
  """Convenience function to paginate a list.
204
-
201
+
205
202
  Args:
206
203
  items: List to paginate
207
204
  cursor: Optional cursor
208
205
  page_size: Items per page
209
-
206
+
210
207
  Returns:
211
208
  Paginated response
212
209
  """
@@ -216,11 +213,11 @@ def paginate_list(
216
213
 
217
214
  def validate_cursor(cursor: str) -> bool:
218
215
  """Validate that a cursor is properly formatted.
219
-
216
+
220
217
  Args:
221
218
  cursor: Cursor string to validate
222
-
219
+
223
220
  Returns:
224
221
  True if valid, False otherwise
225
222
  """
226
- return CursorManager.parse_cursor(cursor) is not None
223
+ return CursorManager.parse_cursor(cursor) is not None
@@ -1,12 +1,12 @@
1
1
  """Permission system for the Hanzo AI server."""
2
2
 
3
- import json
4
3
  import os
5
4
  import sys
5
+ import json
6
6
  import tempfile
7
- from collections.abc import Awaitable, Callable
8
- from pathlib import Path
9
7
  from typing import Any, TypeVar, final
8
+ from pathlib import Path
9
+ from collections.abc import Callable, Awaitable
10
10
 
11
11
  # Define type variables for better type annotations
12
12
  T = TypeVar("T")
@@ -28,7 +28,7 @@ class PermissionManager:
28
28
  else: # Unix/Linux/Mac
29
29
  self.allowed_paths.add(Path("/tmp").resolve())
30
30
  self.allowed_paths.add(Path("/var").resolve())
31
-
31
+
32
32
  # Also allow user's home directory work folders
33
33
  home = Path.home()
34
34
  if home.exists():