hanzo-mcp 0.5.1__py3-none-any.whl → 0.5.2__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 (54) hide show
  1. hanzo_mcp/__init__.py +1 -1
  2. hanzo_mcp/tools/__init__.py +135 -4
  3. hanzo_mcp/tools/common/base.py +7 -2
  4. hanzo_mcp/tools/common/stats.py +261 -0
  5. hanzo_mcp/tools/common/tool_disable.py +144 -0
  6. hanzo_mcp/tools/common/tool_enable.py +182 -0
  7. hanzo_mcp/tools/common/tool_list.py +263 -0
  8. hanzo_mcp/tools/database/__init__.py +71 -0
  9. hanzo_mcp/tools/database/database_manager.py +246 -0
  10. hanzo_mcp/tools/database/graph_add.py +257 -0
  11. hanzo_mcp/tools/database/graph_query.py +536 -0
  12. hanzo_mcp/tools/database/graph_remove.py +267 -0
  13. hanzo_mcp/tools/database/graph_search.py +348 -0
  14. hanzo_mcp/tools/database/graph_stats.py +345 -0
  15. hanzo_mcp/tools/database/sql_query.py +229 -0
  16. hanzo_mcp/tools/database/sql_search.py +296 -0
  17. hanzo_mcp/tools/database/sql_stats.py +254 -0
  18. hanzo_mcp/tools/editor/__init__.py +11 -0
  19. hanzo_mcp/tools/editor/neovim_command.py +272 -0
  20. hanzo_mcp/tools/editor/neovim_edit.py +290 -0
  21. hanzo_mcp/tools/editor/neovim_session.py +356 -0
  22. hanzo_mcp/tools/filesystem/__init__.py +15 -5
  23. hanzo_mcp/tools/filesystem/{unified_search.py → batch_search.py} +254 -131
  24. hanzo_mcp/tools/filesystem/find_files.py +348 -0
  25. hanzo_mcp/tools/filesystem/git_search.py +505 -0
  26. hanzo_mcp/tools/llm/__init__.py +27 -0
  27. hanzo_mcp/tools/llm/consensus_tool.py +351 -0
  28. hanzo_mcp/tools/llm/llm_manage.py +413 -0
  29. hanzo_mcp/tools/llm/llm_tool.py +346 -0
  30. hanzo_mcp/tools/llm/provider_tools.py +412 -0
  31. hanzo_mcp/tools/mcp/__init__.py +11 -0
  32. hanzo_mcp/tools/mcp/mcp_add.py +263 -0
  33. hanzo_mcp/tools/mcp/mcp_remove.py +127 -0
  34. hanzo_mcp/tools/mcp/mcp_stats.py +165 -0
  35. hanzo_mcp/tools/shell/__init__.py +27 -7
  36. hanzo_mcp/tools/shell/logs.py +265 -0
  37. hanzo_mcp/tools/shell/npx.py +194 -0
  38. hanzo_mcp/tools/shell/npx_background.py +254 -0
  39. hanzo_mcp/tools/shell/pkill.py +262 -0
  40. hanzo_mcp/tools/shell/processes.py +279 -0
  41. hanzo_mcp/tools/shell/run_background.py +326 -0
  42. hanzo_mcp/tools/shell/uvx.py +187 -0
  43. hanzo_mcp/tools/shell/uvx_background.py +249 -0
  44. hanzo_mcp/tools/vector/__init__.py +5 -0
  45. hanzo_mcp/tools/vector/git_ingester.py +3 -0
  46. hanzo_mcp/tools/vector/index_tool.py +358 -0
  47. hanzo_mcp/tools/vector/infinity_store.py +98 -0
  48. hanzo_mcp/tools/vector/vector_search.py +11 -6
  49. {hanzo_mcp-0.5.1.dist-info → hanzo_mcp-0.5.2.dist-info}/METADATA +1 -1
  50. {hanzo_mcp-0.5.1.dist-info → hanzo_mcp-0.5.2.dist-info}/RECORD +54 -16
  51. {hanzo_mcp-0.5.1.dist-info → hanzo_mcp-0.5.2.dist-info}/WHEEL +0 -0
  52. {hanzo_mcp-0.5.1.dist-info → hanzo_mcp-0.5.2.dist-info}/entry_points.txt +0 -0
  53. {hanzo_mcp-0.5.1.dist-info → hanzo_mcp-0.5.2.dist-info}/licenses/LICENSE +0 -0
  54. {hanzo_mcp-0.5.1.dist-info → hanzo_mcp-0.5.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,358 @@
1
+ """Index tool for managing vector store indexing."""
2
+
3
+ import asyncio
4
+ import os
5
+ import time
6
+ from pathlib import Path
7
+ from typing import Annotated, TypedDict, Unpack, final, override
8
+
9
+ from fastmcp import Context as MCPContext
10
+ from pydantic import Field
11
+
12
+ from hanzo_mcp.tools.common.base import BaseTool
13
+ from hanzo_mcp.tools.common.context import create_tool_context
14
+ from hanzo_mcp.tools.common.permissions import PermissionManager
15
+ from hanzo_mcp.tools.vector.git_ingester import GitIngester
16
+ from hanzo_mcp.tools.vector.infinity_store import InfinityVectorStore
17
+ from hanzo_mcp.tools.vector.project_manager import ProjectVectorManager
18
+
19
+
20
+ Path_str = Annotated[
21
+ str,
22
+ Field(
23
+ description="Path to index (defaults to current working directory)",
24
+ min_length=1,
25
+ ),
26
+ ]
27
+
28
+ IncludeGitHistory = Annotated[
29
+ bool,
30
+ Field(
31
+ description="Include git history in the index",
32
+ default=True,
33
+ ),
34
+ ]
35
+
36
+ FilePatterns = Annotated[
37
+ list[str] | None,
38
+ Field(
39
+ description="File patterns to include (e.g., ['*.py', '*.js'])",
40
+ default=None,
41
+ ),
42
+ ]
43
+
44
+ ShowStats = Annotated[
45
+ bool,
46
+ Field(
47
+ description="Show detailed statistics after indexing",
48
+ default=True,
49
+ ),
50
+ ]
51
+
52
+ Force = Annotated[
53
+ bool,
54
+ Field(
55
+ description="Force re-indexing even if already indexed",
56
+ default=False,
57
+ ),
58
+ ]
59
+
60
+
61
+ class IndexToolParams(TypedDict, total=False):
62
+ """Parameters for the index tool."""
63
+
64
+ path: str
65
+ include_git_history: bool
66
+ file_patterns: list[str] | None
67
+ show_stats: bool
68
+ force: bool
69
+
70
+
71
+ @final
72
+ class IndexTool(BaseTool):
73
+ """Tool for indexing files and git history into vector store."""
74
+
75
+ def __init__(self, permission_manager: PermissionManager):
76
+ """Initialize the index tool.
77
+
78
+ Args:
79
+ permission_manager: Permission manager for access control
80
+ """
81
+ self.permission_manager = permission_manager
82
+ self.project_manager = ProjectVectorManager(permission_manager)
83
+
84
+ @property
85
+ @override
86
+ def name(self) -> str:
87
+ """Get the tool name."""
88
+ return "index"
89
+
90
+ @property
91
+ @override
92
+ def description(self) -> str:
93
+ """Get the tool description."""
94
+ return """Index files and git history into the vector store for semantic search.
95
+
96
+ This tool:
97
+ - Indexes all project files into a vector database
98
+ - Includes git history (commits, diffs, blame) when available
99
+ - Supports incremental updates
100
+ - Shows statistics about indexed content
101
+ - Automatically creates project-specific databases
102
+
103
+ Usage:
104
+ - index: Index the current directory
105
+ - index --path /path/to/project: Index a specific path
106
+ - index --file-patterns "*.py" "*.js": Index only specific file types
107
+ - index --no-git-history: Skip git history indexing
108
+ - index --force: Force re-indexing of all files"""
109
+
110
+ @override
111
+ async def call(
112
+ self,
113
+ ctx: MCPContext,
114
+ **params: Unpack[IndexToolParams],
115
+ ) -> str:
116
+ """Execute the index tool.
117
+
118
+ Args:
119
+ ctx: MCP context
120
+ **params: Tool parameters
121
+
122
+ Returns:
123
+ Indexing result and statistics
124
+ """
125
+ start_time = time.time()
126
+ tool_ctx = create_tool_context(ctx)
127
+ await tool_ctx.set_tool_info(self.name)
128
+
129
+ # Extract parameters
130
+ path = params.get("path", os.getcwd())
131
+ include_git_history = params.get("include_git_history", True)
132
+ file_patterns = params.get("file_patterns")
133
+ show_stats = params.get("show_stats", True)
134
+ force = params.get("force", False)
135
+
136
+ # Resolve absolute path
137
+ abs_path = os.path.abspath(path)
138
+
139
+ # Check permissions
140
+ if not self.permission_manager.has_permission(abs_path):
141
+ return f"Permission denied: {abs_path}"
142
+
143
+ # Check if path exists
144
+ if not os.path.exists(abs_path):
145
+ return f"Path does not exist: {abs_path}"
146
+
147
+ await tool_ctx.info(f"Starting indexing of {abs_path}")
148
+
149
+ try:
150
+ # Get or create vector store for this project
151
+ vector_store = self.project_manager.get_project_store(abs_path)
152
+
153
+ # Check if already indexed (unless force)
154
+ if not force:
155
+ stats = await vector_store.get_stats()
156
+ if stats and stats.get("document_count", 0) > 0:
157
+ await tool_ctx.info("Project already indexed, use --force to re-index")
158
+ if show_stats:
159
+ return self._format_stats(stats, abs_path, time.time() - start_time)
160
+ return "Project is already indexed. Use --force to re-index."
161
+
162
+ # Prepare file patterns
163
+ if file_patterns is None:
164
+ # Default patterns for code files
165
+ file_patterns = [
166
+ "*.py", "*.js", "*.ts", "*.jsx", "*.tsx",
167
+ "*.java", "*.cpp", "*.c", "*.h", "*.hpp",
168
+ "*.go", "*.rs", "*.rb", "*.php", "*.swift",
169
+ "*.kt", "*.scala", "*.cs", "*.vb", "*.fs",
170
+ "*.sh", "*.bash", "*.zsh", "*.fish",
171
+ "*.md", "*.rst", "*.txt", "*.json", "*.yaml", "*.yml",
172
+ "*.toml", "*.ini", "*.cfg", "*.conf",
173
+ "*.html", "*.css", "*.scss", "*.sass", "*.less",
174
+ "*.sql", "*.graphql", "*.proto",
175
+ "Dockerfile", "Makefile", "*.mk",
176
+ ".gitignore", ".dockerignore", "requirements.txt",
177
+ "package.json", "Cargo.toml", "go.mod", "pom.xml",
178
+ ]
179
+
180
+ # Clear existing index if force
181
+ if force:
182
+ await tool_ctx.info("Clearing existing index...")
183
+ await vector_store.clear()
184
+
185
+ # Index files
186
+ await tool_ctx.info("Indexing files...")
187
+ indexed_files = 0
188
+ total_size = 0
189
+ errors = []
190
+
191
+ for pattern in file_patterns:
192
+ pattern_files = await self._find_files(abs_path, pattern)
193
+ for file_path in pattern_files:
194
+ try:
195
+ # Check file size (skip very large files)
196
+ file_size = os.path.getsize(file_path)
197
+ if file_size > 10 * 1024 * 1024: # 10MB
198
+ await tool_ctx.warning(f"Skipping large file: {file_path}")
199
+ continue
200
+
201
+ # Read file content
202
+ try:
203
+ with open(file_path, "r", encoding="utf-8") as f:
204
+ content = f.read()
205
+ except UnicodeDecodeError:
206
+ # Skip binary files
207
+ continue
208
+
209
+ # Index the file
210
+ rel_path = os.path.relpath(file_path, abs_path)
211
+ await vector_store.index_document(
212
+ content=content,
213
+ metadata={
214
+ "type": "file",
215
+ "path": rel_path,
216
+ "absolute_path": file_path,
217
+ "size": file_size,
218
+ "extension": Path(file_path).suffix,
219
+ }
220
+ )
221
+ indexed_files += 1
222
+ total_size += file_size
223
+
224
+ if indexed_files % 100 == 0:
225
+ await tool_ctx.info(f"Indexed {indexed_files} files...")
226
+
227
+ except Exception as e:
228
+ errors.append(f"{file_path}: {str(e)}")
229
+
230
+ await tool_ctx.info(f"Indexed {indexed_files} files ({total_size / 1024 / 1024:.1f} MB)")
231
+
232
+ # Index git history if requested
233
+ git_stats = {}
234
+ if include_git_history and os.path.exists(os.path.join(abs_path, ".git")):
235
+ await tool_ctx.info("Indexing git history...")
236
+
237
+ git_ingester = GitIngester(vector_store)
238
+ git_stats = await git_ingester.ingest_repository(
239
+ repo_path=abs_path,
240
+ include_history=True,
241
+ include_diffs=True,
242
+ include_blame=True,
243
+ file_patterns=file_patterns,
244
+ )
245
+
246
+ await tool_ctx.info(
247
+ f"Indexed {git_stats.get('commits_indexed', 0)} commits, "
248
+ f"{git_stats.get('diffs_indexed', 0)} diffs"
249
+ )
250
+
251
+ # Get final statistics
252
+ if show_stats:
253
+ stats = await vector_store.get_stats()
254
+ stats.update({
255
+ "files_indexed": indexed_files,
256
+ "total_size_mb": total_size / 1024 / 1024,
257
+ "errors": len(errors),
258
+ **git_stats,
259
+ })
260
+ result = self._format_stats(stats, abs_path, time.time() - start_time)
261
+
262
+ if errors:
263
+ result += f"\n\nErrors ({len(errors)}):\n"
264
+ result += "\n".join(errors[:10]) # Show first 10 errors
265
+ if len(errors) > 10:
266
+ result += f"\n... and {len(errors) - 10} more errors"
267
+
268
+ return result
269
+ else:
270
+ return f"Successfully indexed {indexed_files} files"
271
+
272
+ except Exception as e:
273
+ await tool_ctx.error(f"Indexing failed: {str(e)}")
274
+ return f"Error during indexing: {str(e)}"
275
+
276
+ async def _find_files(self, base_path: str, pattern: str) -> list[str]:
277
+ """Find files matching a pattern.
278
+
279
+ Args:
280
+ base_path: Base directory to search
281
+ pattern: File pattern to match
282
+
283
+ Returns:
284
+ List of matching file paths
285
+ """
286
+ import glob
287
+
288
+ # Use glob to find files
289
+ if pattern.startswith("*."):
290
+ # Extension pattern
291
+ files = glob.glob(
292
+ os.path.join(base_path, "**", pattern),
293
+ recursive=True,
294
+ )
295
+ else:
296
+ # Exact filename
297
+ files = glob.glob(
298
+ os.path.join(base_path, "**", pattern),
299
+ recursive=True,
300
+ )
301
+
302
+ # Filter out hidden directories and common ignore patterns
303
+ filtered_files = []
304
+ ignore_dirs = {".git", "__pycache__", "node_modules", ".venv", "venv", "dist", "build"}
305
+
306
+ for file_path in files:
307
+ # Check if any parent directory is in ignore list
308
+ parts = Path(file_path).parts
309
+ if any(part in ignore_dirs for part in parts):
310
+ continue
311
+ if any(part.startswith(".") and part != "." for part in parts[:-1]):
312
+ continue # Skip hidden directories (but allow hidden files like .gitignore)
313
+ filtered_files.append(file_path)
314
+
315
+ return filtered_files
316
+
317
+ def _format_stats(self, stats: dict, path: str, elapsed_time: float) -> str:
318
+ """Format statistics for display.
319
+
320
+ Args:
321
+ stats: Statistics dictionary
322
+ path: Indexed path
323
+ elapsed_time: Time taken for indexing
324
+
325
+ Returns:
326
+ Formatted statistics string
327
+ """
328
+ result = f"=== Index Statistics for {path} ===\n\n"
329
+
330
+ # Basic stats
331
+ result += f"Indexing completed in {elapsed_time:.1f} seconds\n\n"
332
+
333
+ result += "Content Statistics:\n"
334
+ result += f" Documents: {stats.get('document_count', 0):,}\n"
335
+ result += f" Files indexed: {stats.get('files_indexed', 0):,}\n"
336
+ result += f" Total size: {stats.get('total_size_mb', 0):.1f} MB\n"
337
+
338
+ if stats.get("commits_indexed", 0) > 0:
339
+ result += f"\nGit History:\n"
340
+ result += f" Commits: {stats.get('commits_indexed', 0):,}\n"
341
+ result += f" Diffs: {stats.get('diffs_indexed', 0):,}\n"
342
+ result += f" Blame entries: {stats.get('blame_entries', 0):,}\n"
343
+
344
+ # Vector store info
345
+ result += f"\nVector Store:\n"
346
+ result += f" Database: {stats.get('database_name', 'default')}\n"
347
+ result += f" Table: {stats.get('table_name', 'documents')}\n"
348
+ result += f" Vectors: {stats.get('vector_count', stats.get('document_count', 0)):,}\n"
349
+
350
+ if stats.get("errors", 0) > 0:
351
+ result += f"\nErrors: {stats.get('errors', 0)}\n"
352
+
353
+ return result
354
+
355
+ def register(self, mcp_server) -> None:
356
+ """Register this tool with the MCP server."""
357
+ # Tool registration is handled by the ToolRegistry
358
+ pass
@@ -725,6 +725,104 @@ class InfinityVectorStore:
725
725
  import random
726
726
  return [random.random() for _ in range(self.dimension)]
727
727
 
728
+ async def get_stats(self) -> Dict[str, Any]:
729
+ """Get statistics about the vector store.
730
+
731
+ Returns:
732
+ Dictionary with statistics
733
+ """
734
+ try:
735
+ # Get document count
736
+ doc_count_result = self.documents_table.output(["count(*)"]).to_pl()
737
+ doc_count = doc_count_result.item(0, 0) if len(doc_count_result) > 0 else 0
738
+
739
+ # Get unique file count
740
+ file_result = self.documents_table.output(["file_path"]).to_pl()
741
+ unique_files = set()
742
+ for row in file_result.iter_rows():
743
+ if row[0]:
744
+ unique_files.add(row[0])
745
+
746
+ # Get symbol count
747
+ symbol_count = 0
748
+ try:
749
+ symbol_result = self.symbols_table.output(["count(*)"]).to_pl()
750
+ symbol_count = symbol_result.item(0, 0) if len(symbol_result) > 0 else 0
751
+ except:
752
+ pass
753
+
754
+ # Get AST count
755
+ ast_count = 0
756
+ try:
757
+ ast_result = self.ast_table.output(["count(*)"]).to_pl()
758
+ ast_count = ast_result.item(0, 0) if len(ast_result) > 0 else 0
759
+ except:
760
+ pass
761
+
762
+ return {
763
+ "document_count": doc_count,
764
+ "vector_count": doc_count, # Each document has a vector
765
+ "unique_files": len(unique_files),
766
+ "symbol_count": symbol_count,
767
+ "ast_count": ast_count,
768
+ "database_name": self.db_name,
769
+ "table_name": "documents",
770
+ "dimension": self.dimension,
771
+ }
772
+ except Exception as e:
773
+ return {
774
+ "error": str(e),
775
+ "document_count": 0,
776
+ "vector_count": 0,
777
+ }
778
+
779
+ async def clear(self) -> bool:
780
+ """Clear all data from the vector store.
781
+
782
+ Returns:
783
+ True if successful
784
+ """
785
+ try:
786
+ # Delete all records from all tables
787
+ self.documents_table.delete()
788
+
789
+ try:
790
+ self.symbols_table.delete()
791
+ except:
792
+ pass
793
+
794
+ try:
795
+ self.ast_table.delete()
796
+ except:
797
+ pass
798
+
799
+ try:
800
+ self.references_table.delete()
801
+ except:
802
+ pass
803
+
804
+ return True
805
+ except Exception as e:
806
+ print(f"Error clearing vector store: {e}")
807
+ return False
808
+
809
+ async def index_document(
810
+ self,
811
+ content: str,
812
+ metadata: Dict[str, Any] = None,
813
+ ) -> str:
814
+ """Async version of add_document for consistency.
815
+
816
+ Args:
817
+ content: Document content
818
+ metadata: Additional metadata
819
+
820
+ Returns:
821
+ Document ID
822
+ """
823
+ file_path = metadata.get("path") if metadata else None
824
+ return self.add_document(content, metadata, file_path)
825
+
728
826
  def close(self):
729
827
  """Close the database connection."""
730
828
  if hasattr(self, 'infinity'):
@@ -48,13 +48,18 @@ class VectorSearchTool(BaseTool):
48
48
  @property
49
49
  def description(self) -> str:
50
50
  """Get the tool description."""
51
- return """Search for documents using semantic similarity across project-aware vector databases.
52
-
53
- Performs intelligent text search that understands meaning and context, not just keywords.
54
- Can search across all projects, specific projects, or just the global database. Projects are
55
- automatically detected based on LLM.md files.
51
+ return """Pure semantic/vector search using Infinity embedded database.
52
+
53
+ Searches indexed documents using vector embeddings to find semantically similar content.
54
+ This is NOT keyword search - it finds documents based on meaning and context similarity.
55
+
56
+ Features:
57
+ - Searches across project-specific vector databases
58
+ - Returns similarity scores (0-1, higher is better)
59
+ - Supports filtering by project or file
60
+ - Automatically detects projects via LLM.md files
56
61
 
57
- Returns ranked results with similarity scores, project context, and document metadata."""
62
+ Use 'grep' for exact text/pattern matching, 'vector_search' for semantic similarity."""
58
63
 
59
64
  async def call(
60
65
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hanzo-mcp
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: MCP implementation of Hanzo capabilities
5
5
  Author-email: Hanzo Industries Inc <dev@hanzo.ai>
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- hanzo_mcp/__init__.py,sha256=0KU0gpacbuUqTpVgroypALQ6fncKjBbdh_l7rr_LYUI,89
1
+ hanzo_mcp/__init__.py,sha256=_4GbNO6P83JxRoxDqEGtbxEuFjE9k2nPrWmTPz2Kngo,89
2
2
  hanzo_mcp/cli.py,sha256=fX8HtsD44elZhYre7Dn6RmH5lUt2AFRWz6ehGeoCkUY,9784
3
3
  hanzo_mcp/cli_enhanced.py,sha256=rqh9gqyjMuUznIlPTC5pcIGYZTKAScacMsDb1e68ReE,15819
4
4
  hanzo_mcp/server.py,sha256=mYiIcsAtQO2c_MGExYbzk5tj2U-MjcDWfTU5T22KuwQ,8107
@@ -11,58 +11,96 @@ hanzo_mcp/prompts/create_release.py,sha256=1Z8xSTtz5vAm0rWFnERpFu7wIYExT4iXhM6nG
11
11
  hanzo_mcp/prompts/project_system.py,sha256=fQhOM6AGb6VIZQE_fSPDeS9slBGVkz_f_UbNNhxPRdw,7031
12
12
  hanzo_mcp/prompts/project_todo_reminder.py,sha256=otiBdmzxssBSb3MZZSQsjYDGLBqi1bM0HgraELP_Nf4,3645
13
13
  hanzo_mcp/prompts/utils.py,sha256=IwxIhzZfYJ2anToPulbrpcc07u4Dozo9ok6VE3BC_4A,9963
14
- hanzo_mcp/tools/__init__.py,sha256=HqslpYbLiD1PjW8W2jy1Sc7D_U-R_Qjhr4_jitUjU70,7707
14
+ hanzo_mcp/tools/__init__.py,sha256=1_DWUUamBvBKFbsLcWFwAndbbXs4qODcqV0fyzMFBY4,12704
15
15
  hanzo_mcp/tools/agent/__init__.py,sha256=MZ-LMIYptodQn1JpAEyNMbqRlioS4R8scgzNgsU189E,1897
16
16
  hanzo_mcp/tools/agent/agent_tool.py,sha256=w-Oy2wPPTz79SCzmi7NsI8RU4eLbFKMTXDi-sFKrrbo,21268
17
17
  hanzo_mcp/tools/agent/prompt.py,sha256=Wi9Z45hmQ92eUNZbOWzj9ZVCCr-fM1K9iyaRvTCAgrQ,4529
18
18
  hanzo_mcp/tools/agent/tool_adapter.py,sha256=Od7VtD9qqDbgxhDHj0L-rohX4wOSMtYjZnU2BRuWSqI,2151
19
19
  hanzo_mcp/tools/common/__init__.py,sha256=6LOEE9anSTsiPofgGNcD8CVHdU4SiaHjoQcRzNT2xos,921
20
- hanzo_mcp/tools/common/base.py,sha256=HB7glx3O9eq2B8nHQu1FbRjtlQZM77CKB1lwMGb-CuE,5631
20
+ hanzo_mcp/tools/common/base.py,sha256=Es67mEZXFVYFUroxTV94YiPirsLvX-GNLjUMF95k1P0,5874
21
21
  hanzo_mcp/tools/common/batch_tool.py,sha256=-FaZtH1cqd3xSHUrMaIvB664WEK0rKtTvzpUeEl0DhY,12073
22
22
  hanzo_mcp/tools/common/config_tool.py,sha256=Tmjf4e6z_EfuOjS5acUQnzGo43GZxSqJC329FmQ5QFE,16241
23
23
  hanzo_mcp/tools/common/context.py,sha256=XrgzJwPQP8ooKoReveezVgRyOSJe-zfD5-knhusBgbg,5175
24
24
  hanzo_mcp/tools/common/permissions.py,sha256=LR1tuQAPMoaKvqNtHPRaiB0ZUb0Tbsg3e9L6vvd4FLU,7562
25
+ hanzo_mcp/tools/common/stats.py,sha256=urc3sS92e75D1wQCYG9GP1ZQRel3SmVPm8-htaEIF4I,9758
25
26
  hanzo_mcp/tools/common/thinking_tool.py,sha256=pEBSymlJZJIS2X0pc-2VX2dUAPi4ho2un-wa69yYTD8,5142
27
+ hanzo_mcp/tools/common/tool_disable.py,sha256=Wx3PN7j9CQ2f1cMGNBJlJfqdaB13qPFcEV3idJXGZe8,4246
28
+ hanzo_mcp/tools/common/tool_enable.py,sha256=KK_gP-hjZRpEACxBJfZDAjNl89bnC7ueJu5fwGfbI_k,5033
29
+ hanzo_mcp/tools/common/tool_list.py,sha256=-pxT-pbxDLoHBXZShdy_Zjvsn4-Y2688q65PgSsg0Fk,8922
26
30
  hanzo_mcp/tools/common/validation.py,sha256=VV3VbDvYlAYl2Bi98xE7gFo0xnmqHHUGJGNPswm97qo,1694
27
- hanzo_mcp/tools/filesystem/__init__.py,sha256=mFgBEZFGxdZNOdVjp5Mnt1Ro-dEmluPrT2-N3c6pP5w,5034
31
+ hanzo_mcp/tools/database/__init__.py,sha256=6LnN5EsHFCFMQjg_jqxfOIExanAT2pLfaHyvOrvvO4U,2164
32
+ hanzo_mcp/tools/database/database_manager.py,sha256=urbP3T4QpTPBOH7JKjgjRbgMZAZxGm5Q_skZnZ9aHXQ,8807
33
+ hanzo_mcp/tools/database/graph_add.py,sha256=0Cdt5KPTVduE9c7C--HzIjx-12kmP3JEdsy28ZXtuh4,7730
34
+ hanzo_mcp/tools/database/graph_query.py,sha256=AgEKt-nqTALS0P9aPxMtANyEN3ik40tV8muCK9rydVc,19742
35
+ hanzo_mcp/tools/database/graph_remove.py,sha256=rlANurnV0cuz86IlAM1BovUUkme5V4GLsLxzdCajf_M,8765
36
+ hanzo_mcp/tools/database/graph_search.py,sha256=eqB3tk5g71c7GzilhIqXVsNQRzvvs1-MUxmfbSUjq0o,12555
37
+ hanzo_mcp/tools/database/graph_stats.py,sha256=yyxlCyClmLHC3X9lv9fU-O5YBOOg7GD-f8FSekXNVvw,13013
38
+ hanzo_mcp/tools/database/sql_query.py,sha256=7yhGJGkfjy339AINr8QVQICkpG3C0nTEGDzf20IN-zE,7279
39
+ hanzo_mcp/tools/database/sql_search.py,sha256=GyzKeVYo-pal4J2gvM_tjBnXbKYMNcURnnfJZ_oeFoI,9820
40
+ hanzo_mcp/tools/database/sql_stats.py,sha256=4gAIHRAVa1ydRChKGGhyA6cR8Z2cawGoxZBKQsnNJjI,8997
41
+ hanzo_mcp/tools/editor/__init__.py,sha256=RZKbXadNnh5fZ0-Wow-A5gAYCEfEuV_GapaR4mdjzW0,332
42
+ hanzo_mcp/tools/editor/neovim_command.py,sha256=_k6muOEVOBQx6ILJnUghMKlPKvO_1E9PDyM0qGC7twk,8272
43
+ hanzo_mcp/tools/editor/neovim_edit.py,sha256=BLZdQO7w0Aa61rf8SoLLkqPv0Zh-NGpX3fWMPAih7i8,8805
44
+ hanzo_mcp/tools/editor/neovim_session.py,sha256=f-iOnG5jsPrO7UrO77aMcwo0ZaP-us-KgIglVGe6bAs,11951
45
+ hanzo_mcp/tools/filesystem/__init__.py,sha256=8n_NklE5rTcvfVkwv-j720Ahtg6eE8HG2HHruHzJXYo,5436
28
46
  hanzo_mcp/tools/filesystem/base.py,sha256=qwxer1jHgPIfyaUeC4QLzR9pjGWJCLP2L3qggUAulFY,3807
47
+ hanzo_mcp/tools/filesystem/batch_search.py,sha256=Rzp8yFzeHdnj2uR7YRIC85iz23yTr7uAl5U1_hGVjns,34467
29
48
  hanzo_mcp/tools/filesystem/content_replace.py,sha256=hCiw9oQXS2_b6CjgC7XHOrRo5NH6H8zOFaSDS6Uwfgw,10015
30
49
  hanzo_mcp/tools/filesystem/directory_tree.py,sha256=LZTJRmrDdSFpq9EpcTmVytimCp_glpCVKDxf7UCyq20,10755
31
50
  hanzo_mcp/tools/filesystem/edit.py,sha256=PIlFsMjBG9WQw9IWC6dzLZly6UIBUcAUrohRkqyKFZY,10699
51
+ hanzo_mcp/tools/filesystem/find_files.py,sha256=AdwtY2Mz9oTPZ66juHe34_6fK_mVT-uNFVF6hhhdx8w,10948
52
+ hanzo_mcp/tools/filesystem/git_search.py,sha256=pab3PHI8wPxSHaaIuIWJwq1ULcdhye77xB4ORW05e7k,16209
32
53
  hanzo_mcp/tools/filesystem/grep.py,sha256=-JKrBUk04tmObvwPh8UvBpLOc27NNndNt6eR5qSkCLs,16818
33
54
  hanzo_mcp/tools/filesystem/grep_ast_tool.py,sha256=F-HacdAISZI_jDGJrxIcZ-dyj3OG919JUVimpvgAZNA,8142
34
55
  hanzo_mcp/tools/filesystem/multi_edit.py,sha256=j8ytsFVsdQqJ9AWCJMQa8kWHyH4UpbBdHRIc7XepEJc,14313
35
56
  hanzo_mcp/tools/filesystem/read.py,sha256=uF1KdIAsKL8-oQiwOfL9-dkTzKOqQK0nKLVe6hW-5KE,8892
36
- hanzo_mcp/tools/filesystem/unified_search.py,sha256=zSarczfFoImqtddJnfnv-OuhENN8hPKdgptxiopmqf8,29483
37
57
  hanzo_mcp/tools/filesystem/write.py,sha256=dkbZ61kYGRTzKPVtMG8ETYw8YHyo6YXb1cLI70ePYcQ,4833
38
58
  hanzo_mcp/tools/jupyter/__init__.py,sha256=IJnkx6vwxP2ZJOGvUxG25fhstlny-uFnNBLjGlUt5hs,2515
39
59
  hanzo_mcp/tools/jupyter/base.py,sha256=oxTz_exSsYni2cQJvL4gHZtC4EG5EU_1-nWyEdc-ZQ8,10090
40
60
  hanzo_mcp/tools/jupyter/notebook_edit.py,sha256=wKEEQJ36pfgB0JHQi2nV_X7ApXqy6HXZY9XO4lZ9Efg,11848
41
61
  hanzo_mcp/tools/jupyter/notebook_read.py,sha256=t2fkP5wAp8SBBaWHrty-uWsnn6l5WO2zIqISVSHnQus,5293
42
- hanzo_mcp/tools/shell/__init__.py,sha256=CcVnsAqSd8FLtVpkuHQK4cbKHWrac6o9enEIqNlxz4k,1951
62
+ hanzo_mcp/tools/llm/__init__.py,sha256=MdGOvR91CACz3W90U00YQs-gNnIg0OAr7sz6qTFfWXw,594
63
+ hanzo_mcp/tools/llm/consensus_tool.py,sha256=3mC5kNempHYxXq0I6kr19_Rit1NQxKXNGsal-iNTUpw,11611
64
+ hanzo_mcp/tools/llm/llm_manage.py,sha256=FHf0U7YAW8EPMwFLdTlq_u1m1V3cPPYjKTc9S_hc8Bk,15655
65
+ hanzo_mcp/tools/llm/llm_tool.py,sha256=I-onULpskIs3wCX4OI5vShhwYGGe472lynJ9CczwSNg,11147
66
+ hanzo_mcp/tools/llm/provider_tools.py,sha256=PvcapPUg4gGzlLHm-s6X1q6S841yHKjTO43tDOx1-ZE,11535
67
+ hanzo_mcp/tools/mcp/__init__.py,sha256=Bix1Vl4wxT2BxFI-y6fOphFZCG57oNhNqmnlBV4edZE,266
68
+ hanzo_mcp/tools/mcp/mcp_add.py,sha256=QEv43rb_c-xHOWAMIw9VET8r0NOdUjmu1aNBiMTJIu0,7913
69
+ hanzo_mcp/tools/mcp/mcp_remove.py,sha256=wQLcx4kpZapD_Kd5iet6dp_7u6GzCrxhv66Z9c5C-j8,3255
70
+ hanzo_mcp/tools/mcp/mcp_stats.py,sha256=sdm6KFQwCox477r03RdOOvYodnJ1vByGXy84v2CmHrs,5467
71
+ hanzo_mcp/tools/shell/__init__.py,sha256=LLMhZU8Fq7Rc4T0e2lBatt8cZS_G2kl6skFj346gLio,2718
43
72
  hanzo_mcp/tools/shell/base.py,sha256=twbz3EuX64cwvNlcHraZ5CcEhDpUvMI5mLTZvMADtbQ,5821
44
73
  hanzo_mcp/tools/shell/bash_session.py,sha256=YPtdtC0pc6Q04RJqKUy0u0RPTbiT2IGtsvFqejK5Hu4,27271
45
74
  hanzo_mcp/tools/shell/bash_session_executor.py,sha256=zRnrzj4sdQOxO22XXBENT6k2dXt3LDk5fxjWjUYyU_Q,10723
46
75
  hanzo_mcp/tools/shell/command_executor.py,sha256=IuoRY48PMmpKHL5CFIExebjoiRRS5ZEl73UDzYTR3kU,36406
76
+ hanzo_mcp/tools/shell/logs.py,sha256=c0SBlHrpTAY7eckJ0DrPUDzb5OnJTbzuyt4BoE2aTuA,8457
77
+ hanzo_mcp/tools/shell/npx.py,sha256=PWPp64nNQr16l1qp3fZpL4EYxuVFtJO6l8JRjQrMcyg,5072
78
+ hanzo_mcp/tools/shell/npx_background.py,sha256=TZncVB3RqKDLOLNWKDFCoRCFlQ7tiBIyvPCmf_K_oTg,7109
79
+ hanzo_mcp/tools/shell/pkill.py,sha256=j8Y7aETUonGCRF4Ikivc_3Qde4BVqNbgVypUxUuMdvs,8665
80
+ hanzo_mcp/tools/shell/processes.py,sha256=J3aSxacjEAhch3U8jtseYS2bHH3oav-zaFTjoM_Xgrg,9384
81
+ hanzo_mcp/tools/shell/run_background.py,sha256=uYcPtmP2dZPgPPTzToHiO1hToUwJ67KggQm-sN8QWKY,9702
47
82
  hanzo_mcp/tools/shell/run_command.py,sha256=Io6LyLm8XWZKZ-Zjhx3L-H5vmdNGoqbkU9jJzwL7zLs,16137
48
83
  hanzo_mcp/tools/shell/run_command_windows.py,sha256=MGXC76b0uYKhxg1-d9CijPP36ufRusgyq9Zurpo1vSc,15363
49
84
  hanzo_mcp/tools/shell/session_manager.py,sha256=o8iS4PFCnq28vPqYtdtH9M8lfGyzyhtNL0hmNI13Uuc,6509
50
85
  hanzo_mcp/tools/shell/session_storage.py,sha256=elnyFgn0FwsmVvoWAoJFAqiEeNaK4_yByT8-zXa6r-o,10141
86
+ hanzo_mcp/tools/shell/uvx.py,sha256=NY_f3c-llI5IwkbdiE4r5pHCUS3KI37RTcmrRqlKIRI,5023
87
+ hanzo_mcp/tools/shell/uvx_background.py,sha256=lY1T0k_k28VqPyFx0bfF0qmeKbpTgvj3zhHd4OcU8rs,7094
51
88
  hanzo_mcp/tools/todo/__init__.py,sha256=Ai-rlVWcy-CkJf1H2zIsbyx0wkxzWNLR3WAbGszbXKg,1720
52
89
  hanzo_mcp/tools/todo/base.py,sha256=8sYZYAsFE5SjHRqynZCmCIKEobWB3aZwwSApg26keDo,10655
53
90
  hanzo_mcp/tools/todo/todo_read.py,sha256=zXI9jn-kWXGSj88tI63yoAv-EWPDpkX1E6m0QfMUQHE,4759
54
91
  hanzo_mcp/tools/todo/todo_write.py,sha256=fTAvrxrzkpdYwi7nYcJky2wjukChYsdXu5axqIUJg_c,15465
55
- hanzo_mcp/tools/vector/__init__.py,sha256=McH23f6sKBT22rRfdyj0V_Okn1sq42-RNRRaZbeoE-4,3682
92
+ hanzo_mcp/tools/vector/__init__.py,sha256=TAxOaWOnzC756n7byfdfwTcaxjuHITs586bGHZ1B6Ww,3850
56
93
  hanzo_mcp/tools/vector/ast_analyzer.py,sha256=2bUM9j9rCNARNXXF2cuFSp2ercwZAJWlAqeRIwn46Ck,15653
57
- hanzo_mcp/tools/vector/git_ingester.py,sha256=VwHJYWzlpBTcmtUGoZLgEBTFFGoppewHqzXaPUM8Lk8,16214
58
- hanzo_mcp/tools/vector/infinity_store.py,sha256=co8EZ3ohiivgwUAEkI31BzpmPe6E2lOeZEiJnjIosBQ,25287
94
+ hanzo_mcp/tools/vector/git_ingester.py,sha256=pR4_HRMT7trGhr1kGHASvhgm7Vjwh6UY-UVdXCNj07s,16367
95
+ hanzo_mcp/tools/vector/index_tool.py,sha256=6VWDEfA_R6ySwVCg85h4rGw_uh4ROtpL2_Ab5kMDl8A,12758
96
+ hanzo_mcp/tools/vector/infinity_store.py,sha256=E3YotdY798HTPs4X2IMv-SOjt-VjCC2XAFaWPeSVUQU,28382
59
97
  hanzo_mcp/tools/vector/mock_infinity.py,sha256=QyU7FM2eTCP0BeuX8xhRe0En7hG9EFt-XzgDu-BefrI,4990
60
98
  hanzo_mcp/tools/vector/project_manager.py,sha256=JZ6c0m4RWKbV4JjkxAI6ZgyOy2Ymk8-o4ficTLZrIo0,12500
61
99
  hanzo_mcp/tools/vector/vector_index.py,sha256=Idp9w4g_7WVbIDY3oEX4-o7bWWQadeo3XC9lVtyS7Wg,4392
62
- hanzo_mcp/tools/vector/vector_search.py,sha256=_LgoUNEyVHMFwVlCgJ-zJlCDNAiM4C1zKifqwPhMX6k,9516
63
- hanzo_mcp-0.5.1.dist-info/licenses/LICENSE,sha256=mf1qZGFsPGskoPgytp9B-RsahfKvXsBpmaAbTLGTt8Y,1063
64
- hanzo_mcp-0.5.1.dist-info/METADATA,sha256=PLxRkm_2YYNfg5GsATWOS2BWBuqVJ7by8tGvRAY93AI,11995
65
- hanzo_mcp-0.5.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
66
- hanzo_mcp-0.5.1.dist-info/entry_points.txt,sha256=aRKOKXtuQr-idSr-yH4efnRl2v8te94AcgN3ysqqSYs,49
67
- hanzo_mcp-0.5.1.dist-info/top_level.txt,sha256=eGFANatA0MHWiVlpS56fTYRIShtibrSom1uXI6XU0GU,10
68
- hanzo_mcp-0.5.1.dist-info/RECORD,,
100
+ hanzo_mcp/tools/vector/vector_search.py,sha256=QErsckzvwrBl_DkELIkBRE2kH-WOMxSgHLiwAFkiyMA,9636
101
+ hanzo_mcp-0.5.2.dist-info/licenses/LICENSE,sha256=mf1qZGFsPGskoPgytp9B-RsahfKvXsBpmaAbTLGTt8Y,1063
102
+ hanzo_mcp-0.5.2.dist-info/METADATA,sha256=Mk3SPG1yAlh9gooa9EvcA72JhsWIauW87RBNSLhgP5A,11995
103
+ hanzo_mcp-0.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
104
+ hanzo_mcp-0.5.2.dist-info/entry_points.txt,sha256=aRKOKXtuQr-idSr-yH4efnRl2v8te94AcgN3ysqqSYs,49
105
+ hanzo_mcp-0.5.2.dist-info/top_level.txt,sha256=eGFANatA0MHWiVlpS56fTYRIShtibrSom1uXI6XU0GU,10
106
+ hanzo_mcp-0.5.2.dist-info/RECORD,,