hanzo-mcp 0.5.1__py3-none-any.whl β†’ 0.6.1__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 (118) hide show
  1. hanzo_mcp/__init__.py +1 -1
  2. hanzo_mcp/cli.py +32 -0
  3. hanzo_mcp/dev_server.py +246 -0
  4. hanzo_mcp/prompts/__init__.py +1 -1
  5. hanzo_mcp/prompts/project_system.py +43 -7
  6. hanzo_mcp/server.py +5 -1
  7. hanzo_mcp/tools/__init__.py +168 -6
  8. hanzo_mcp/tools/agent/__init__.py +1 -1
  9. hanzo_mcp/tools/agent/agent.py +401 -0
  10. hanzo_mcp/tools/agent/agent_tool.py +3 -4
  11. hanzo_mcp/tools/common/__init__.py +1 -1
  12. hanzo_mcp/tools/common/base.py +9 -4
  13. hanzo_mcp/tools/common/batch_tool.py +3 -5
  14. hanzo_mcp/tools/common/config_tool.py +1 -1
  15. hanzo_mcp/tools/common/context.py +1 -1
  16. hanzo_mcp/tools/common/palette.py +344 -0
  17. hanzo_mcp/tools/common/palette_loader.py +108 -0
  18. hanzo_mcp/tools/common/stats.py +261 -0
  19. hanzo_mcp/tools/common/thinking_tool.py +3 -5
  20. hanzo_mcp/tools/common/tool_disable.py +144 -0
  21. hanzo_mcp/tools/common/tool_enable.py +182 -0
  22. hanzo_mcp/tools/common/tool_list.py +260 -0
  23. hanzo_mcp/tools/config/__init__.py +10 -0
  24. hanzo_mcp/tools/config/config_tool.py +212 -0
  25. hanzo_mcp/tools/config/index_config.py +176 -0
  26. hanzo_mcp/tools/config/palette_tool.py +166 -0
  27. hanzo_mcp/tools/database/__init__.py +71 -0
  28. hanzo_mcp/tools/database/database_manager.py +246 -0
  29. hanzo_mcp/tools/database/graph.py +482 -0
  30. hanzo_mcp/tools/database/graph_add.py +257 -0
  31. hanzo_mcp/tools/database/graph_query.py +536 -0
  32. hanzo_mcp/tools/database/graph_remove.py +267 -0
  33. hanzo_mcp/tools/database/graph_search.py +348 -0
  34. hanzo_mcp/tools/database/graph_stats.py +345 -0
  35. hanzo_mcp/tools/database/sql.py +411 -0
  36. hanzo_mcp/tools/database/sql_query.py +229 -0
  37. hanzo_mcp/tools/database/sql_search.py +296 -0
  38. hanzo_mcp/tools/database/sql_stats.py +254 -0
  39. hanzo_mcp/tools/editor/__init__.py +11 -0
  40. hanzo_mcp/tools/editor/neovim_command.py +272 -0
  41. hanzo_mcp/tools/editor/neovim_edit.py +290 -0
  42. hanzo_mcp/tools/editor/neovim_session.py +356 -0
  43. hanzo_mcp/tools/filesystem/__init__.py +52 -13
  44. hanzo_mcp/tools/filesystem/base.py +1 -1
  45. hanzo_mcp/tools/filesystem/batch_search.py +812 -0
  46. hanzo_mcp/tools/filesystem/content_replace.py +3 -5
  47. hanzo_mcp/tools/filesystem/diff.py +193 -0
  48. hanzo_mcp/tools/filesystem/directory_tree.py +3 -5
  49. hanzo_mcp/tools/filesystem/edit.py +3 -5
  50. hanzo_mcp/tools/filesystem/find.py +443 -0
  51. hanzo_mcp/tools/filesystem/find_files.py +348 -0
  52. hanzo_mcp/tools/filesystem/git_search.py +505 -0
  53. hanzo_mcp/tools/filesystem/grep.py +2 -2
  54. hanzo_mcp/tools/filesystem/multi_edit.py +3 -5
  55. hanzo_mcp/tools/filesystem/read.py +17 -5
  56. hanzo_mcp/tools/filesystem/{grep_ast_tool.py β†’ symbols.py} +17 -27
  57. hanzo_mcp/tools/filesystem/symbols_unified.py +376 -0
  58. hanzo_mcp/tools/filesystem/tree.py +268 -0
  59. hanzo_mcp/tools/filesystem/unified_search.py +465 -443
  60. hanzo_mcp/tools/filesystem/unix_aliases.py +99 -0
  61. hanzo_mcp/tools/filesystem/watch.py +174 -0
  62. hanzo_mcp/tools/filesystem/write.py +3 -5
  63. hanzo_mcp/tools/jupyter/__init__.py +9 -12
  64. hanzo_mcp/tools/jupyter/base.py +1 -1
  65. hanzo_mcp/tools/jupyter/jupyter.py +326 -0
  66. hanzo_mcp/tools/jupyter/notebook_edit.py +3 -4
  67. hanzo_mcp/tools/jupyter/notebook_read.py +3 -5
  68. hanzo_mcp/tools/llm/__init__.py +31 -0
  69. hanzo_mcp/tools/llm/consensus_tool.py +351 -0
  70. hanzo_mcp/tools/llm/llm_manage.py +413 -0
  71. hanzo_mcp/tools/llm/llm_tool.py +346 -0
  72. hanzo_mcp/tools/llm/llm_unified.py +851 -0
  73. hanzo_mcp/tools/llm/provider_tools.py +412 -0
  74. hanzo_mcp/tools/mcp/__init__.py +15 -0
  75. hanzo_mcp/tools/mcp/mcp_add.py +263 -0
  76. hanzo_mcp/tools/mcp/mcp_remove.py +127 -0
  77. hanzo_mcp/tools/mcp/mcp_stats.py +165 -0
  78. hanzo_mcp/tools/mcp/mcp_unified.py +503 -0
  79. hanzo_mcp/tools/shell/__init__.py +21 -23
  80. hanzo_mcp/tools/shell/base.py +1 -1
  81. hanzo_mcp/tools/shell/base_process.py +303 -0
  82. hanzo_mcp/tools/shell/bash_unified.py +134 -0
  83. hanzo_mcp/tools/shell/logs.py +265 -0
  84. hanzo_mcp/tools/shell/npx.py +194 -0
  85. hanzo_mcp/tools/shell/npx_background.py +254 -0
  86. hanzo_mcp/tools/shell/npx_unified.py +101 -0
  87. hanzo_mcp/tools/shell/open.py +107 -0
  88. hanzo_mcp/tools/shell/pkill.py +262 -0
  89. hanzo_mcp/tools/shell/process_unified.py +131 -0
  90. hanzo_mcp/tools/shell/processes.py +279 -0
  91. hanzo_mcp/tools/shell/run_background.py +326 -0
  92. hanzo_mcp/tools/shell/run_command.py +3 -4
  93. hanzo_mcp/tools/shell/run_command_windows.py +3 -4
  94. hanzo_mcp/tools/shell/uvx.py +187 -0
  95. hanzo_mcp/tools/shell/uvx_background.py +249 -0
  96. hanzo_mcp/tools/shell/uvx_unified.py +101 -0
  97. hanzo_mcp/tools/todo/__init__.py +1 -1
  98. hanzo_mcp/tools/todo/base.py +1 -1
  99. hanzo_mcp/tools/todo/todo.py +265 -0
  100. hanzo_mcp/tools/todo/todo_read.py +3 -5
  101. hanzo_mcp/tools/todo/todo_write.py +3 -5
  102. hanzo_mcp/tools/vector/__init__.py +6 -1
  103. hanzo_mcp/tools/vector/git_ingester.py +3 -0
  104. hanzo_mcp/tools/vector/index_tool.py +358 -0
  105. hanzo_mcp/tools/vector/infinity_store.py +98 -0
  106. hanzo_mcp/tools/vector/project_manager.py +27 -5
  107. hanzo_mcp/tools/vector/vector.py +311 -0
  108. hanzo_mcp/tools/vector/vector_index.py +1 -1
  109. hanzo_mcp/tools/vector/vector_search.py +12 -7
  110. hanzo_mcp-0.6.1.dist-info/METADATA +336 -0
  111. hanzo_mcp-0.6.1.dist-info/RECORD +134 -0
  112. hanzo_mcp-0.6.1.dist-info/entry_points.txt +3 -0
  113. hanzo_mcp-0.5.1.dist-info/METADATA +0 -276
  114. hanzo_mcp-0.5.1.dist-info/RECORD +0 -68
  115. hanzo_mcp-0.5.1.dist-info/entry_points.txt +0 -2
  116. {hanzo_mcp-0.5.1.dist-info β†’ hanzo_mcp-0.6.1.dist-info}/WHEEL +0 -0
  117. {hanzo_mcp-0.5.1.dist-info β†’ hanzo_mcp-0.6.1.dist-info}/licenses/LICENSE +0 -0
  118. {hanzo_mcp-0.5.1.dist-info β†’ hanzo_mcp-0.6.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,311 @@
1
+ """Unified vector store tool."""
2
+
3
+ from typing import Annotated, TypedDict, Unpack, final, override, Optional, List, Dict, Any
4
+ from pathlib import Path
5
+
6
+ from mcp.server.fastmcp import Context as MCPContext
7
+ from pydantic import Field
8
+
9
+ from hanzo_mcp.tools.common.base import BaseTool
10
+ from hanzo_mcp.tools.common.permissions import PermissionManager
11
+ from hanzo_mcp.tools.vector.project_manager import ProjectVectorManager
12
+
13
+
14
+ # Parameter types
15
+ Action = Annotated[
16
+ str,
17
+ Field(
18
+ description="Action: search (default), index, stats, clear",
19
+ default="search",
20
+ ),
21
+ ]
22
+
23
+ Query = Annotated[
24
+ Optional[str],
25
+ Field(
26
+ description="Search query for semantic similarity",
27
+ default=None,
28
+ ),
29
+ ]
30
+
31
+ Path = Annotated[
32
+ Optional[str],
33
+ Field(
34
+ description="Path to index or search within",
35
+ default=".",
36
+ ),
37
+ ]
38
+
39
+ Include = Annotated[
40
+ Optional[str],
41
+ Field(
42
+ description="File pattern to include (e.g., '*.py')",
43
+ default=None,
44
+ ),
45
+ ]
46
+
47
+ Exclude = Annotated[
48
+ Optional[str],
49
+ Field(
50
+ description="File pattern to exclude",
51
+ default=None,
52
+ ),
53
+ ]
54
+
55
+ Limit = Annotated[
56
+ int,
57
+ Field(
58
+ description="Maximum results to return",
59
+ default=10,
60
+ ),
61
+ ]
62
+
63
+ IncludeGit = Annotated[
64
+ bool,
65
+ Field(
66
+ description="Include git history in indexing",
67
+ default=True,
68
+ ),
69
+ ]
70
+
71
+ ForceReindex = Annotated[
72
+ bool,
73
+ Field(
74
+ description="Force reindexing even if up to date",
75
+ default=False,
76
+ ),
77
+ ]
78
+
79
+
80
+ class VectorParams(TypedDict, total=False):
81
+ """Parameters for vector tool."""
82
+ action: str
83
+ query: Optional[str]
84
+ path: Optional[str]
85
+ include: Optional[str]
86
+ exclude: Optional[str]
87
+ limit: int
88
+ include_git: bool
89
+ force_reindex: bool
90
+
91
+
92
+ @final
93
+ class VectorTool(BaseTool):
94
+ """Unified vector store tool for semantic search."""
95
+
96
+ def __init__(self, permission_manager: PermissionManager, project_manager: ProjectVectorManager):
97
+ """Initialize the vector tool."""
98
+ super().__init__(permission_manager)
99
+ self.project_manager = project_manager
100
+
101
+ @property
102
+ @override
103
+ def name(self) -> str:
104
+ """Get the tool name."""
105
+ return "vector"
106
+
107
+ @property
108
+ @override
109
+ def description(self) -> str:
110
+ """Get the tool description."""
111
+ return """Semantic search with embeddings. Actions: search (default), index, stats, clear.
112
+
113
+ Usage:
114
+ vector "find authentication logic"
115
+ vector --action index --path ./src --include "*.py"
116
+ vector --action stats
117
+ vector --action clear --path ./old_code
118
+ """
119
+
120
+ @override
121
+ async def call(
122
+ self,
123
+ ctx: MCPContext,
124
+ **params: Unpack[VectorParams],
125
+ ) -> str:
126
+ """Execute vector operation."""
127
+ tool_ctx = self.create_tool_context(ctx)
128
+
129
+ # Extract action
130
+ action = params.get("action", "search")
131
+
132
+ # Route to appropriate handler
133
+ if action == "search":
134
+ return await self._handle_search(params, tool_ctx)
135
+ elif action == "index":
136
+ return await self._handle_index(params, tool_ctx)
137
+ elif action == "stats":
138
+ return await self._handle_stats(params, tool_ctx)
139
+ elif action == "clear":
140
+ return await self._handle_clear(params, tool_ctx)
141
+ else:
142
+ return f"Error: Unknown action '{action}'. Valid actions: search, index, stats, clear"
143
+
144
+ async def _handle_search(self, params: Dict[str, Any], tool_ctx) -> str:
145
+ """Handle semantic search."""
146
+ query = params.get("query")
147
+ if not query:
148
+ return "Error: query is required for search action"
149
+
150
+ path = params.get("path", ".")
151
+ limit = params.get("limit", 10)
152
+
153
+ # Validate path
154
+ allowed, error_msg = await self.check_path_allowed(path, tool_ctx)
155
+ if not allowed:
156
+ return error_msg
157
+
158
+ try:
159
+ # Determine search scope
160
+ project = self.project_manager.get_project_for_path(path)
161
+ if not project:
162
+ return "Error: No indexed project found for this path. Run 'vector --action index' first."
163
+
164
+ # Search
165
+ await tool_ctx.info(f"Searching for: {query}")
166
+ results = project.search(query, k=limit)
167
+
168
+ if not results:
169
+ return f"No results found for: {query}"
170
+
171
+ # Format results
172
+ output = [f"=== Vector Search Results for '{query}' ==="]
173
+ output.append(f"Found {len(results)} matches\n")
174
+
175
+ for i, result in enumerate(results, 1):
176
+ score = result.get("score", 0)
177
+ file_path = result.get("file_path", "unknown")
178
+ content = result.get("content", "")
179
+ chunk_type = result.get("metadata", {}).get("type", "content")
180
+
181
+ output.append(f"Result {i} - Score: {score:.1%}")
182
+ output.append(f"File: {file_path}")
183
+ if chunk_type != "content":
184
+ output.append(f"Type: {chunk_type}")
185
+ output.append("-" * 60)
186
+
187
+ # Truncate content if too long
188
+ if len(content) > 300:
189
+ content = content[:300] + "..."
190
+ output.append(content)
191
+ output.append("")
192
+
193
+ return "\n".join(output)
194
+
195
+ except Exception as e:
196
+ await tool_ctx.error(f"Search failed: {str(e)}")
197
+ return f"Error during search: {str(e)}"
198
+
199
+ async def _handle_index(self, params: Dict[str, Any], tool_ctx) -> str:
200
+ """Handle indexing files."""
201
+ path = params.get("path", ".")
202
+ include = params.get("include")
203
+ exclude = params.get("exclude")
204
+ include_git = params.get("include_git", True)
205
+ force = params.get("force_reindex", False)
206
+
207
+ # Validate path
208
+ allowed, error_msg = await self.check_path_allowed(path, tool_ctx)
209
+ if not allowed:
210
+ return error_msg
211
+
212
+ try:
213
+ await tool_ctx.info(f"Indexing {path}...")
214
+
215
+ # Get or create project
216
+ project = self.project_manager.get_or_create_project(path)
217
+
218
+ # Index files
219
+ stats = await project.index_directory(
220
+ path,
221
+ include_pattern=include,
222
+ exclude_pattern=exclude,
223
+ force_reindex=force
224
+ )
225
+
226
+ # Index git history if requested
227
+ if include_git and Path(path).joinpath(".git").exists():
228
+ await tool_ctx.info("Indexing git history...")
229
+ git_stats = await project.index_git_history(path)
230
+ stats["git_commits"] = git_stats.get("commits_indexed", 0)
231
+
232
+ # Format output
233
+ output = [f"=== Indexing Complete ==="]
234
+ output.append(f"Path: {path}")
235
+ output.append(f"Files indexed: {stats.get('files_indexed', 0)}")
236
+ output.append(f"Chunks created: {stats.get('chunks_created', 0)}")
237
+ if stats.get("git_commits"):
238
+ output.append(f"Git commits indexed: {stats['git_commits']}")
239
+ output.append(f"Total documents: {project.get_stats().get('total_documents', 0)}")
240
+
241
+ return "\n".join(output)
242
+
243
+ except Exception as e:
244
+ await tool_ctx.error(f"Indexing failed: {str(e)}")
245
+ return f"Error during indexing: {str(e)}"
246
+
247
+ async def _handle_stats(self, params: Dict[str, Any], tool_ctx) -> str:
248
+ """Get vector store statistics."""
249
+ path = params.get("path")
250
+
251
+ try:
252
+ if path:
253
+ # Stats for specific project
254
+ project = self.project_manager.get_project_for_path(path)
255
+ if not project:
256
+ return f"No indexed project found for path: {path}"
257
+
258
+ stats = project.get_stats()
259
+ output = [f"=== Vector Store Stats for {project.name} ==="]
260
+ else:
261
+ # Global stats
262
+ stats = self.project_manager.get_global_stats()
263
+ output = ["=== Global Vector Store Stats ==="]
264
+
265
+ output.append(f"Total documents: {stats.get('total_documents', 0)}")
266
+ output.append(f"Total size: {stats.get('total_size_mb', 0):.1f} MB")
267
+
268
+ if stats.get("projects"):
269
+ output.append(f"\nProjects indexed: {len(stats['projects'])}")
270
+ for proj in stats["projects"]:
271
+ output.append(f" - {proj['name']}: {proj['documents']} docs, {proj['size_mb']:.1f} MB")
272
+
273
+ return "\n".join(output)
274
+
275
+ except Exception as e:
276
+ await tool_ctx.error(f"Failed to get stats: {str(e)}")
277
+ return f"Error getting stats: {str(e)}"
278
+
279
+ async def _handle_clear(self, params: Dict[str, Any], tool_ctx) -> str:
280
+ """Clear vector store."""
281
+ path = params.get("path")
282
+
283
+ if not path:
284
+ return "Error: path is required for clear action"
285
+
286
+ # Validate path
287
+ allowed, error_msg = await self.check_path_allowed(path, tool_ctx)
288
+ if not allowed:
289
+ return error_msg
290
+
291
+ try:
292
+ project = self.project_manager.get_project_for_path(path)
293
+ if not project:
294
+ return f"No indexed project found for path: {path}"
295
+
296
+ # Get stats before clearing
297
+ stats = project.get_stats()
298
+ doc_count = stats.get("total_documents", 0)
299
+
300
+ # Clear
301
+ project.clear()
302
+
303
+ return f"Cleared {doc_count} documents from vector store for {project.name}"
304
+
305
+ except Exception as e:
306
+ await tool_ctx.error(f"Failed to clear: {str(e)}")
307
+ return f"Error clearing vector store: {str(e)}"
308
+
309
+ def register(self, mcp_server) -> None:
310
+ """Register this tool with the MCP server."""
311
+ pass
@@ -3,7 +3,7 @@
3
3
  from typing import Dict, List, Optional, TypedDict, Unpack, final
4
4
  from pathlib import Path
5
5
 
6
- from fastmcp import Context as MCPContext
6
+ from mcp.server.fastmcp import Context as MCPContext
7
7
  from pydantic import Field
8
8
 
9
9
  from hanzo_mcp.tools.common.base import BaseTool
@@ -4,7 +4,7 @@ from typing import Dict, List, Optional, TypedDict, Unpack, final
4
4
  import json
5
5
  import asyncio
6
6
 
7
- from fastmcp import Context as MCPContext
7
+ from mcp.server.fastmcp import Context as MCPContext
8
8
  from pydantic import Field
9
9
 
10
10
  from hanzo_mcp.tools.common.base import BaseTool
@@ -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,
@@ -0,0 +1,336 @@
1
+ Metadata-Version: 2.4
2
+ Name: hanzo-mcp
3
+ Version: 0.6.1
4
+ Summary: The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others.
5
+ Author-email: Hanzo Industries Inc <dev@hanzo.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/hanzoai/mcp
8
+ Project-URL: Bug Tracker, https://github.com/hanzoai/mcp/issues
9
+ Project-URL: Documentation, https://mcp.hanzo.ai
10
+ Keywords: mcp,claude,hanzo,code,agent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.12
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: mcp>=1.6.0
18
+ Requires-Dist: fastmcp>=2.8.0
19
+ Requires-Dist: httpx>=0.27.0
20
+ Requires-Dist: uvicorn>=0.23.1
21
+ Requires-Dist: openai>=1.50.0
22
+ Requires-Dist: python-dotenv>=1.0.0
23
+ Requires-Dist: litellm>=1.40.14
24
+ Requires-Dist: grep-ast>=0.8.1
25
+ Requires-Dist: bashlex>=0.18
26
+ Requires-Dist: libtmux>=0.39.0
27
+ Requires-Dist: nbformat>=5.10.4
28
+ Requires-Dist: psutil>=6.1.0
29
+ Requires-Dist: pydantic>=2.10.0
30
+ Requires-Dist: typing-extensions>=4.12.2
31
+ Requires-Dist: watchdog>=3.0.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
34
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
35
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
36
+ Requires-Dist: black>=23.3.0; extra == "dev"
37
+ Requires-Dist: sphinx>=8.0.0; extra == "dev"
38
+ Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == "dev"
39
+ Requires-Dist: myst-parser>=4.0.0; extra == "dev"
40
+ Requires-Dist: sphinx-copybutton>=0.5.0; extra == "dev"
41
+ Provides-Extra: docs
42
+ Requires-Dist: sphinx>=8.0.0; extra == "docs"
43
+ Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == "docs"
44
+ Requires-Dist: myst-parser>=4.0.0; extra == "docs"
45
+ Requires-Dist: sphinx-copybutton>=0.5.0; extra == "docs"
46
+ Provides-Extra: test
47
+ Requires-Dist: pytest>=7.0.0; extra == "test"
48
+ Requires-Dist: pytest-cov>=4.1.0; extra == "test"
49
+ Requires-Dist: pytest-mock>=3.10.0; extra == "test"
50
+ Requires-Dist: pytest-asyncio>=0.25.3; extra == "test"
51
+ Requires-Dist: twisted; extra == "test"
52
+ Provides-Extra: performance
53
+ Requires-Dist: ujson>=5.7.0; extra == "performance"
54
+ Requires-Dist: orjson>=3.9.0; extra == "performance"
55
+ Provides-Extra: publish
56
+ Requires-Dist: twine>=4.0.2; extra == "publish"
57
+ Requires-Dist: build>=1.0.3; extra == "publish"
58
+ Dynamic: license-file
59
+
60
+ # Hanzo MCP - The Zen of Model Context Protocol
61
+
62
+ [![Documentation](https://img.shields.io/badge/docs-mcp.hanzo.ai-blue?style=for-the-badge)](https://mcp.hanzo.ai)
63
+ [![PyPI](https://img.shields.io/pypi/v/hanzo-mcp?style=for-the-badge)](https://pypi.org/project/hanzo-mcp/)
64
+ [![License](https://img.shields.io/github/license/hanzoai/mcp?style=for-the-badge)](https://github.com/hanzoai/mcp/blob/main/LICENSE)
65
+ [![Join our Discord](https://img.shields.io/discord/YOUR_DISCORD_ID?style=for-the-badge&logo=discord)](https://discord.gg/hanzoai)
66
+
67
+ ## πŸ₯· One MCP to Rule Them All
68
+
69
+ **Start here. Add other MCPs later. Control everything through one opinionated interface.**
70
+
71
+ Hanzo MCP isn't just another Model Context Protocol serverβ€”it's **THE** MCP server. While others give you fragments, we give you the complete toolkit. One server that orchestrates all others, with the power to add, remove, and control any MCP server dynamically.
72
+
73
+ ```bash
74
+ # Install and rule your development world
75
+ uvx hanzo-mcp
76
+ ```
77
+
78
+ ## 🎯 Why Hanzo MCP?
79
+
80
+ ### The Problem with Other MCPs
81
+ - **Fragmented Experience**: Install 10 different MCPs for 10 different tasks
82
+ - **Inconsistent Interfaces**: Each MCP has its own conventions and quirks
83
+ - **Limited Scope**: Most MCPs do one thing, leaving you to juggle multiple servers
84
+ - **No Orchestration**: No way to coordinate between different MCP servers
85
+
86
+ ### The Hanzo Way
87
+ - **One Installation**: 65+ professional tools out of the box
88
+ - **Unified Philosophy**: Consistent, opinionated interface following Unix principles
89
+ - **MCP Orchestration**: Install and control other MCP servers through Hanzo
90
+ - **Swappable Opinions**: Don't like our way? Load a different palette and change everything
91
+
92
+ ## πŸš€ Features That Set Us Apart
93
+
94
+ ### 🎨 Palette System - Opinions Are Just Configurations
95
+ ```python
96
+ # Don't like our shell tools? Swap the palette
97
+ palette_load(palette="minimal") # Just the essentials
98
+ palette_load(palette="pentesting") # Security focused tools
99
+ palette_load(palette="data-science") # Jupyter, pandas, numpy focused
100
+ palette_load(palette="your-custom") # Your tools, your way
101
+ ```
102
+
103
+ ### πŸ”Œ MCP Server Orchestration
104
+ ```python
105
+ # Add any MCP server dynamically
106
+ mcp_add(url="github.com/someone/their-mcp", alias="their")
107
+
108
+ # Use their tools through our unified interface
109
+ their_tool(action="whatever", params=...)
110
+
111
+ # Remove when done
112
+ mcp_remove(alias="their")
113
+ ```
114
+
115
+ ### πŸ› οΈ 65+ Battle-Tested Tools
116
+
117
+ #### Intelligent Multi-Modal Search
118
+ - **search**: Combines grep, AST analysis, vector embeddings, and git history
119
+ - **symbols**: Find any code symbol across languages instantly
120
+ - **git_search**: Search through git history, branches, and commits
121
+
122
+ #### Advanced Development
123
+ - **agent**: Delegate complex tasks to specialized AI agents
124
+ - **llm**: Query multiple LLM providers with consensus
125
+ - **jupyter**: Full Jupyter notebook support
126
+ - **neovim**: Integrated Neovim for power users
127
+
128
+ #### File Operations That Just Work
129
+ - **edit/multi_edit**: Intelligent pattern-based editing
130
+ - **read/write**: Automatic encoding detection
131
+ - **tree**: Visual directory structures
132
+ - **watch**: Monitor file changes in real-time
133
+
134
+ #### Process & System Control
135
+ - **run_command**: Secure command execution with timeout
136
+ - **processes**: Monitor and manage system processes
137
+ - **npx/uvx**: Package runners with background support
138
+
139
+ #### And So Much More
140
+ - Database tools (SQL, Graph)
141
+ - Vector search and indexing
142
+ - Todo management
143
+ - Configuration management
144
+ - MCP server management
145
+ - Statistical analysis
146
+ - Batch operations
147
+
148
+ ## 🎯 The Zen of Hanzo
149
+
150
+ 1. **One Tool, One Purpose** - Each tool does one thing exceptionally well
151
+ 2. **Actions Over Tools** - Complex tools support multiple actions, not multiple interfaces
152
+ 3. **Parallel by Default** - Run multiple operations concurrently
153
+ 4. **Smart Fallbacks** - Automatically choose the best available backend
154
+ 5. **Secure by Design** - Fine-grained permissions and audit trails
155
+ 6. **Opinionated but Flexible** - Strong defaults with palette customization
156
+
157
+ ## πŸš€ Quick Start
158
+
159
+ ### Installation
160
+
161
+ ```bash
162
+ # Install globally with uvx (recommended)
163
+ uvx hanzo-mcp
164
+
165
+ # Or install with pip
166
+ pip install hanzo-mcp
167
+
168
+ # Or install from source for development
169
+ git clone https://github.com/hanzoai/mcp
170
+ cd mcp
171
+ make install
172
+ ```
173
+
174
+ ### Add to Claude Desktop
175
+
176
+ ```bash
177
+ # Automatic installation
178
+ make install-desktop
179
+
180
+ # Or manual configuration
181
+ cat >> ~/Library/Application\ Support/Claude/claude_desktop_config.json << 'EOF'
182
+ {
183
+ "mcpServers": {
184
+ "hanzo": {
185
+ "command": "uvx",
186
+ "args": ["hanzo-mcp"]
187
+ }
188
+ }
189
+ }
190
+ EOF
191
+ ```
192
+
193
+ ### Your First Session
194
+
195
+ 1. Open Claude Desktop
196
+ 2. Start with `search` to explore any codebase
197
+ 3. Use `tree` to understand structure
198
+ 4. Edit files with `edit` or `multi_edit`
199
+ 5. Run commands with `run_command`
200
+ 6. Add other MCP servers with `mcp_add`
201
+
202
+ ## 🎨 Palette System
203
+
204
+ Palettes let you completely transform Hanzo MCP's behavior:
205
+
206
+ ```python
207
+ # List available palettes
208
+ palette_list()
209
+
210
+ # Load a different personality
211
+ palette_load(palette="minimal") # Just core tools
212
+ palette_load(palette="academic") # Research and writing focused
213
+ palette_load(palette="devops") # Infrastructure and deployment
214
+
215
+ # Create your own
216
+ palette_create(
217
+ name="my-workflow",
218
+ tools=["read", "write", "edit", "search", "my-custom-tool"],
219
+ config={"editor": "vim", "search_backend": "ripgrep"}
220
+ )
221
+ ```
222
+
223
+ ## πŸ”Œ MCP Orchestration
224
+
225
+ Hanzo MCP can manage other MCP servers:
226
+
227
+ ```python
228
+ # Add any MCP server
229
+ mcp_add(url="github.com/modelcontextprotocol/servers/tree/main/postgres")
230
+
231
+ # List installed servers
232
+ mcp_stats()
233
+
234
+ # Use tools from other servers seamlessly
235
+ postgres_query(query="SELECT * FROM users")
236
+
237
+ # Remove when done
238
+ mcp_remove(alias="postgres")
239
+ ```
240
+
241
+ ## πŸ“Š Advanced Features
242
+
243
+ ### Intelligent Search
244
+ ```python
245
+ # Multi-modal search across your codebase
246
+ results = search(
247
+ query="authentication",
248
+ include_git=True, # Search git history
249
+ include_vector=True, # Semantic search
250
+ include_ast=True, # AST symbol search
251
+ parallel=True # Search all modes concurrently
252
+ )
253
+ ```
254
+
255
+ ### Agent Orchestration
256
+ ```python
257
+ # Delegate complex tasks to specialized agents
258
+ agent(
259
+ task="Refactor this codebase to use async/await",
260
+ files=["src/**/*.py"],
261
+ instructions="Maintain backwards compatibility"
262
+ )
263
+ ```
264
+
265
+ ### Consensus LLM Queries
266
+ ```python
267
+ # Query multiple LLMs and get consensus
268
+ llm(
269
+ action="consensus",
270
+ prompt="Is this code secure?",
271
+ providers=["openai", "anthropic", "google"],
272
+ threshold=0.8
273
+ )
274
+ ```
275
+
276
+ ## πŸ—οΈ Architecture
277
+
278
+ Built on modern Python with:
279
+ - **FastMCP**: High-performance MCP framework
280
+ - **UV**: Lightning-fast Python package management
281
+ - **Parallel Execution**: Concurrent operations by default
282
+ - **Smart Backends**: Automatic selection of best available tools
283
+ - **Type Safety**: Full type hints and validation
284
+
285
+ ## 🀝 Contributing
286
+
287
+ We welcome contributions! The codebase is designed for extensibility:
288
+
289
+ 1. **Add a Tool**: Drop a file in `hanzo_mcp/tools/`
290
+ 2. **Create a Palette**: Define tool collections and configurations
291
+ 3. **Improve Existing Tools**: Each tool is independently testable
292
+
293
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
294
+
295
+ ## πŸ“š Documentation
296
+
297
+ - **[Quick Start Guide](https://mcp.hanzo.ai/quickstart)** - Get running in 5 minutes
298
+ - **[Tool Reference](https://mcp.hanzo.ai/tools)** - Detailed documentation for all 65+ tools
299
+ - **[Palette System](https://mcp.hanzo.ai/palettes)** - Customize your experience
300
+ - **[MCP Orchestration](https://mcp.hanzo.ai/orchestration)** - Control other MCP servers
301
+ - **[Best Practices](https://mcp.hanzo.ai/best-practices)** - Tips from power users
302
+
303
+ ## 🌟 Why Developers Choose Hanzo MCP
304
+
305
+ > "I replaced 12 different MCP servers with just Hanzo. The palette system means I can switch contexts instantlyβ€”from web dev to data science to DevOps." - *Power User*
306
+
307
+ > "The agent orchestration is incredible. I can delegate entire refactoring tasks and it just works." - *Sr. Engineer*
308
+
309
+ > "Finally, an MCP that thinks like a developer. Smart defaults, great errors, and everything is parallel." - *Tech Lead*
310
+
311
+ ## πŸ“ˆ Stats
312
+
313
+ - **65+** Professional Tools
314
+ - **10x** Faster than installing multiple MCPs
315
+ - **1** Unified interface to rule them all
316
+ - **∞** Possibilities with the palette system
317
+
318
+ ## πŸ“„ License
319
+
320
+ MIT - Use it, extend it, make it yours.
321
+
322
+ ## πŸ”— Links
323
+
324
+ - [GitHub](https://github.com/hanzoai/mcp)
325
+ - [Documentation](https://mcp.hanzo.ai)
326
+ - [PyPI](https://pypi.org/project/hanzo-mcp/)
327
+ - [Discord Community](https://discord.gg/hanzoai)
328
+ - [Report Issues](https://github.com/hanzoai/mcp/issues)
329
+
330
+ ---
331
+
332
+ <p align="center">
333
+ <b>The Zen of Hanzo MCP</b><br>
334
+ <i>One server. All tools. Your way.</i><br><br>
335
+ <code>uvx hanzo-mcp</code>
336
+ </p>