hanzo-mcp 0.8.3__py3-none-any.whl → 0.8.5__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.

@@ -0,0 +1,266 @@
1
+ """Zsh shell tool for command execution with enhanced features."""
2
+
3
+ import os
4
+ import shutil
5
+ import platform
6
+ from typing import Optional, override
7
+ from pathlib import Path
8
+
9
+ from mcp.server import FastMCP
10
+ from mcp.server.fastmcp import Context as MCPContext
11
+
12
+ from hanzo_mcp.tools.shell.base_process import BaseScriptTool
13
+
14
+
15
+ class ZshTool(BaseScriptTool):
16
+ """Tool for running commands in Zsh shell with enhanced features."""
17
+
18
+ name = "zsh"
19
+
20
+ def register(self, server: FastMCP) -> None:
21
+ """Register the tool with the MCP server."""
22
+ tool_self = self
23
+
24
+ @server.tool(name=self.name, description=self.description)
25
+ async def zsh(
26
+ ctx: MCPContext,
27
+ command: str,
28
+ cwd: Optional[str] = None,
29
+ env: Optional[dict[str, str]] = None,
30
+ timeout: Optional[int] = None,
31
+ ) -> str:
32
+ return await tool_self.run(
33
+ ctx, command=command, cwd=cwd, env=env, timeout=timeout
34
+ )
35
+
36
+ async def call(self, ctx: MCPContext, **params) -> str:
37
+ """Call the tool with arguments."""
38
+ return await self.run(
39
+ ctx,
40
+ command=params["command"],
41
+ cwd=params.get("cwd"),
42
+ env=params.get("env"),
43
+ timeout=params.get("timeout"),
44
+ )
45
+
46
+ @property
47
+ @override
48
+ def description(self) -> str:
49
+ """Get the tool description."""
50
+ return """Run commands in Zsh shell with enhanced features like better globbing and completion.
51
+
52
+ Zsh provides advanced features over bash:
53
+ - Extended globbing patterns
54
+ - Better tab completion
55
+ - Array and associative array support
56
+ - Powerful command line editing
57
+ - Plugin ecosystem (oh-my-zsh, etc.)
58
+
59
+ Commands that run for more than 2 minutes will automatically continue in the background.
60
+
61
+ Usage:
62
+ zsh "ls -la"
63
+ zsh "echo $ZSH_VERSION"
64
+ zsh "git status && git diff"
65
+ zsh "npm run dev" --cwd ./frontend # Auto-backgrounds if needed"""
66
+
67
+ @override
68
+ def get_interpreter(self) -> str:
69
+ """Get the zsh interpreter path."""
70
+ if platform.system() == "Windows":
71
+ # Try to find zsh on Windows (WSL, Git Bash, etc.)
72
+ zsh_paths = [
73
+ "C:\\Program Files\\Git\\usr\\bin\\zsh.exe",
74
+ "C:\\cygwin64\\bin\\zsh.exe",
75
+ "C:\\msys64\\usr\\bin\\zsh.exe",
76
+ ]
77
+ for path in zsh_paths:
78
+ if Path(path).exists():
79
+ return path
80
+ # Fall back to bash if no zsh found
81
+ return "bash"
82
+
83
+ # On Unix-like systems, check for zsh
84
+ zsh_path = shutil.which("zsh")
85
+ if zsh_path:
86
+ return zsh_path
87
+
88
+ # Fall back to bash if zsh not found
89
+ return "bash"
90
+
91
+ @override
92
+ def get_script_flags(self) -> list[str]:
93
+ """Get interpreter flags."""
94
+ if platform.system() == "Windows" and self.get_interpreter().endswith(".exe"):
95
+ return ["-c"]
96
+ return ["-c"]
97
+
98
+ @override
99
+ def get_tool_name(self) -> str:
100
+ """Get the tool name."""
101
+ return "zsh"
102
+
103
+ @override
104
+ async def run(
105
+ self,
106
+ ctx: MCPContext,
107
+ command: str,
108
+ cwd: Optional[str] = None,
109
+ env: Optional[dict[str, str]] = None,
110
+ timeout: Optional[int] = None,
111
+ ) -> str:
112
+ """Run a zsh command with auto-backgrounding.
113
+
114
+ Args:
115
+ ctx: MCP context
116
+ command: Zsh command to execute
117
+ cwd: Working directory
118
+ env: Environment variables
119
+ timeout: Command timeout in seconds (ignored - auto-backgrounds after 2 minutes)
120
+
121
+ Returns:
122
+ Command output or background status
123
+ """
124
+ # Check if zsh is available
125
+ if not shutil.which("zsh") and platform.system() != "Windows":
126
+ return "Error: Zsh is not installed. Please install zsh first."
127
+
128
+ # Prepare working directory
129
+ work_dir = Path(cwd).resolve() if cwd else Path.cwd()
130
+
131
+ # Use execute_sync which has auto-backgrounding
132
+ output = await self.execute_sync(
133
+ command, cwd=work_dir, env=env, timeout=timeout
134
+ )
135
+ return output if output else "Command completed successfully (no output)"
136
+
137
+
138
+ class ShellTool(BaseScriptTool):
139
+ """Smart shell tool that uses the best available shell (zsh > bash)."""
140
+
141
+ name = "shell"
142
+
143
+ def __init__(self):
144
+ """Initialize and detect the best shell."""
145
+ super().__init__()
146
+ self._best_shell = self._detect_best_shell()
147
+
148
+ def _detect_best_shell(self) -> str:
149
+ """Detect the best available shell."""
150
+ # Check for zsh first
151
+ if shutil.which("zsh"):
152
+ # Also check if .zshrc exists
153
+ if (Path.home() / ".zshrc").exists():
154
+ return "zsh"
155
+
156
+ # Check for user's preferred shell
157
+ user_shell = os.environ.get("SHELL", "")
158
+ if user_shell and Path(user_shell).exists():
159
+ return user_shell
160
+
161
+ # Default to bash
162
+ return "bash"
163
+
164
+ def register(self, server: FastMCP) -> None:
165
+ """Register the tool with the MCP server."""
166
+ tool_self = self
167
+
168
+ @server.tool(name=self.name, description=self.description)
169
+ async def shell(
170
+ ctx: MCPContext,
171
+ command: str,
172
+ cwd: Optional[str] = None,
173
+ env: Optional[dict[str, str]] = None,
174
+ timeout: Optional[int] = None,
175
+ ) -> str:
176
+ return await tool_self.run(
177
+ ctx, command=command, cwd=cwd, env=env, timeout=timeout
178
+ )
179
+
180
+ async def call(self, ctx: MCPContext, **params) -> str:
181
+ """Call the tool with arguments."""
182
+ return await self.run(
183
+ ctx,
184
+ command=params["command"],
185
+ cwd=params.get("cwd"),
186
+ env=params.get("env"),
187
+ timeout=params.get("timeout"),
188
+ )
189
+
190
+ @property
191
+ @override
192
+ def description(self) -> str:
193
+ """Get the tool description."""
194
+ return f"""Run shell commands using the best available shell (currently: {os.path.basename(self._best_shell)}).
195
+
196
+ Automatically selects:
197
+ - Zsh if available (with .zshrc)
198
+ - User's preferred shell ($SHELL)
199
+ - Bash as fallback
200
+
201
+ Commands that run for more than 2 minutes will automatically continue in the background.
202
+
203
+ Usage:
204
+ shell "ls -la"
205
+ shell "echo $SHELL" # Shows which shell is being used
206
+ shell "git status && git diff"
207
+ shell "npm run dev" --cwd ./frontend # Auto-backgrounds if needed"""
208
+
209
+ @override
210
+ def get_interpreter(self) -> str:
211
+ """Get the best shell interpreter."""
212
+ return self._best_shell
213
+
214
+ @override
215
+ def get_script_flags(self) -> list[str]:
216
+ """Get interpreter flags."""
217
+ if platform.system() == "Windows":
218
+ return ["/c"] if self._best_shell == "cmd.exe" else ["-c"]
219
+ return ["-c"]
220
+
221
+ @override
222
+ def get_tool_name(self) -> str:
223
+ """Get the tool name."""
224
+ return "shell"
225
+
226
+ @override
227
+ async def run(
228
+ self,
229
+ ctx: MCPContext,
230
+ command: str,
231
+ cwd: Optional[str] = None,
232
+ env: Optional[dict[str, str]] = None,
233
+ timeout: Optional[int] = None,
234
+ ) -> str:
235
+ """Run a shell command with auto-backgrounding.
236
+
237
+ Args:
238
+ ctx: MCP context
239
+ command: Shell command to execute
240
+ cwd: Working directory
241
+ env: Environment variables
242
+ timeout: Command timeout in seconds (ignored - auto-backgrounds after 2 minutes)
243
+
244
+ Returns:
245
+ Command output or background status
246
+ """
247
+ # Prepare working directory
248
+ work_dir = Path(cwd).resolve() if cwd else Path.cwd()
249
+
250
+ # Add shell info to output if verbose
251
+ shell_name = os.path.basename(self._best_shell)
252
+
253
+ # Use execute_sync which has auto-backgrounding
254
+ output = await self.execute_sync(
255
+ command, cwd=work_dir, env=env, timeout=timeout
256
+ )
257
+
258
+ if output:
259
+ return output
260
+ else:
261
+ return f"Command completed successfully in {shell_name} (no output)"
262
+
263
+
264
+ # Create tool instances
265
+ zsh_tool = ZshTool()
266
+ shell_tool = ShellTool() # Smart shell that prefers zsh
@@ -0,0 +1,411 @@
1
+ Metadata-Version: 2.4
2
+ Name: hanzo-mcp
3
+ Version: 0.8.5
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
+ Requires-Dist: mcp>=1.9.4
17
+ Requires-Dist: fastmcp>=2.9.2
18
+ Requires-Dist: httpx>=0.28.1
19
+ Requires-Dist: uvicorn>=0.34.0
20
+ Requires-Dist: openai>=1.62.0
21
+ Requires-Dist: python-dotenv>=1.0.1
22
+ Requires-Dist: litellm>=1.73.2
23
+ Requires-Dist: grep-ast>=0.8.1
24
+ Requires-Dist: bashlex>=0.18
25
+ Requires-Dist: libtmux>=0.39.0
26
+ Requires-Dist: nbformat>=5.10.4
27
+ Requires-Dist: psutil>=6.0.0
28
+ Requires-Dist: pydantic>=2.9.2
29
+ Requires-Dist: pydantic-settings>=2.7.0
30
+ Requires-Dist: typing-extensions>=4.13.0
31
+ Requires-Dist: watchdog>=6.0.0
32
+ Requires-Dist: keyring>=24.0.0
33
+ Requires-Dist: ffind>=1.3.0
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
36
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
37
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
38
+ Requires-Dist: black>=23.3.0; extra == "dev"
39
+ Requires-Dist: sphinx>=8.0.0; extra == "dev"
40
+ Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == "dev"
41
+ Requires-Dist: myst-parser>=4.0.0; extra == "dev"
42
+ Requires-Dist: sphinx-copybutton>=0.5.0; extra == "dev"
43
+ Requires-Dist: mypy>=1.10.0; extra == "dev"
44
+ Requires-Dist: types-aiofiles>=23.2.0; extra == "dev"
45
+ Requires-Dist: types-psutil>=5.9.5; extra == "dev"
46
+ Requires-Dist: types-setuptools>=69.5.0; extra == "dev"
47
+ Provides-Extra: docs
48
+ Requires-Dist: sphinx>=8.0.0; extra == "docs"
49
+ Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == "docs"
50
+ Requires-Dist: myst-parser>=4.0.0; extra == "docs"
51
+ Requires-Dist: sphinx-copybutton>=0.5.0; extra == "docs"
52
+ Provides-Extra: analytics
53
+ Requires-Dist: posthog>=3.0.0; extra == "analytics"
54
+ Provides-Extra: test
55
+ Requires-Dist: pytest>=7.0.0; extra == "test"
56
+ Requires-Dist: pytest-cov>=4.1.0; extra == "test"
57
+ Requires-Dist: pytest-mock>=3.10.0; extra == "test"
58
+ Requires-Dist: pytest-asyncio>=0.25.3; extra == "test"
59
+ Requires-Dist: twisted; extra == "test"
60
+ Provides-Extra: agents
61
+ Requires-Dist: hanzo-agents>=0.1.0; extra == "agents"
62
+ Provides-Extra: memory
63
+ Requires-Dist: hanzo-memory>=1.0.0; extra == "memory"
64
+ Provides-Extra: performance
65
+ Requires-Dist: ujson>=5.7.0; extra == "performance"
66
+ Requires-Dist: orjson>=3.9.0; extra == "performance"
67
+ Provides-Extra: publish
68
+ Requires-Dist: twine>=4.0.2; extra == "publish"
69
+ Requires-Dist: build>=1.0.3; extra == "publish"
70
+
71
+ # Hanzo Model Context Protocol (MCP)
72
+
73
+ [![PyPI](https://img.shields.io/pypi/v/hanzo-mcp.svg)](https://pypi.org/project/hanzo-mcp/)
74
+ [![Python Version](https://img.shields.io/pypi/pyversions/hanzo-mcp.svg)](https://pypi.org/project/hanzo-mcp/)
75
+
76
+ Model Context Protocol implementation for advanced tool use and context management.
77
+
78
+ ## Installation
79
+
80
+ ```bash
81
+ pip install hanzo-mcp
82
+ ```
83
+
84
+ ## Features
85
+
86
+ - **Tool Management**: Register and manage AI tools
87
+ - **File Operations**: Read, write, edit files
88
+ - **Code Intelligence**: AST analysis, symbol search
89
+ - **Shell Execution**: Run commands safely
90
+ - **Agent Delegation**: Recursive agent capabilities
91
+ - **Memory Integration**: Persistent context storage
92
+ - **Batch Operations**: Execute multiple tools efficiently
93
+
94
+ ## Quick Start
95
+
96
+ ### Basic Usage
97
+
98
+ ```python
99
+ from hanzo_mcp import create_mcp_server
100
+
101
+ # Create MCP server
102
+ server = create_mcp_server()
103
+
104
+ # Register tools
105
+ server.register_filesystem_tools()
106
+ server.register_shell_tools()
107
+ server.register_agent_tools()
108
+
109
+ # Start server
110
+ await server.start()
111
+ ```
112
+
113
+ ### Tool Categories
114
+
115
+ #### Filesystem Tools
116
+
117
+ ```python
118
+ # Read file
119
+ content = await server.tools.read(file_path="/path/to/file.py")
120
+
121
+ # Write file
122
+ await server.tools.write(
123
+ file_path="/path/to/new.py",
124
+ content="print('Hello')"
125
+ )
126
+
127
+ # Edit file
128
+ await server.tools.edit(
129
+ file_path="/path/to/file.py",
130
+ old_string="old code",
131
+ new_string="new code"
132
+ )
133
+
134
+ # Multi-edit
135
+ await server.tools.multi_edit(
136
+ file_path="/path/to/file.py",
137
+ edits=[
138
+ {"old_string": "foo", "new_string": "bar"},
139
+ {"old_string": "baz", "new_string": "qux"}
140
+ ]
141
+ )
142
+ ```
143
+
144
+ #### Search Tools
145
+
146
+ ```python
147
+ # Unified search (grep + AST + semantic)
148
+ results = await server.tools.search(
149
+ pattern="function_name",
150
+ path="/project"
151
+ )
152
+
153
+ # AST-aware search
154
+ results = await server.tools.grep_ast(
155
+ pattern="class.*Service",
156
+ path="/src"
157
+ )
158
+
159
+ # Symbol search
160
+ symbols = await server.tools.symbols(
161
+ pattern="def test_",
162
+ path="/tests"
163
+ )
164
+ ```
165
+
166
+ #### Shell Tools
167
+
168
+ ```python
169
+ # Run command
170
+ result = await server.tools.bash(
171
+ command="ls -la",
172
+ cwd="/project"
173
+ )
174
+
175
+ # Run with auto-backgrounding
176
+ result = await server.tools.bash(
177
+ command="python server.py",
178
+ timeout=120000 # Auto-backgrounds after 2 min
179
+ )
180
+
181
+ # Manage processes
182
+ processes = await server.tools.process(action="list")
183
+ logs = await server.tools.process(
184
+ action="logs",
185
+ id="bash_abc123"
186
+ )
187
+ ```
188
+
189
+ #### Agent Tools
190
+
191
+ ```python
192
+ # Dispatch agent for complex tasks
193
+ result = await server.tools.dispatch_agent(
194
+ prompt="Analyze the codebase architecture",
195
+ path="/project"
196
+ )
197
+
198
+ # Network of agents
199
+ result = await server.tools.network(
200
+ task="Implement user authentication",
201
+ agents=["architect", "developer", "tester"]
202
+ )
203
+
204
+ # CLI tool integration
205
+ result = await server.tools.claude(
206
+ args=["--analyze", "main.py"]
207
+ )
208
+ ```
209
+
210
+ #### Batch Operations
211
+
212
+ ```python
213
+ # Execute multiple tools in parallel
214
+ results = await server.tools.batch(
215
+ description="Read multiple files",
216
+ invocations=[
217
+ {"tool_name": "read", "input": {"file_path": "file1.py"}},
218
+ {"tool_name": "read", "input": {"file_path": "file2.py"}},
219
+ {"tool_name": "grep", "input": {"pattern": "TODO"}}
220
+ ]
221
+ )
222
+ ```
223
+
224
+ ## Advanced Features
225
+
226
+ ### Custom Tools
227
+
228
+ ```python
229
+ from hanzo_mcp import Tool
230
+
231
+ class MyCustomTool(Tool):
232
+ name = "my_tool"
233
+ description = "Custom tool"
234
+
235
+ async def call(self, ctx, **params):
236
+ # Tool implementation
237
+ return "Result"
238
+
239
+ # Register custom tool
240
+ server.register_tool(MyCustomTool())
241
+ ```
242
+
243
+ ### Permission Management
244
+
245
+ ```python
246
+ from hanzo_mcp import PermissionManager
247
+
248
+ # Create permission manager
249
+ pm = PermissionManager()
250
+
251
+ # Set permission mode
252
+ pm.set_mode("review") # review, auto_approve, auto_deny
253
+
254
+ # Check permission
255
+ allowed = await pm.check_permission(
256
+ tool="write",
257
+ params={"file_path": "/etc/passwd"}
258
+ )
259
+ ```
260
+
261
+ ### Context Management
262
+
263
+ ```python
264
+ from hanzo_mcp import ToolContext
265
+
266
+ # Create context
267
+ ctx = ToolContext(
268
+ cwd="/project",
269
+ env={"API_KEY": "secret"},
270
+ timeout=30000
271
+ )
272
+
273
+ # Use with tools
274
+ result = await tool.call(ctx, **params)
275
+ ```
276
+
277
+ ## Configuration
278
+
279
+ ### Environment Variables
280
+
281
+ ```bash
282
+ # API keys for agent tools
283
+ ANTHROPIC_API_KEY=sk-ant-...
284
+ OPENAI_API_KEY=sk-...
285
+
286
+ # Tool settings
287
+ MCP_PERMISSION_MODE=review
288
+ MCP_MAX_FILE_SIZE=10485760
289
+ MCP_TIMEOUT=120000
290
+
291
+ # Search settings
292
+ MCP_SEARCH_IGNORE=node_modules,*.pyc
293
+ MCP_SEARCH_MAX_RESULTS=100
294
+ ```
295
+
296
+ ### Configuration File
297
+
298
+ ```yaml
299
+ tools:
300
+ filesystem:
301
+ enabled: true
302
+ max_file_size: 10MB
303
+ allowed_paths:
304
+ - /home/user/projects
305
+ - /tmp
306
+
307
+ shell:
308
+ enabled: true
309
+ timeout: 120000
310
+ auto_background: true
311
+
312
+ agent:
313
+ enabled: true
314
+ models:
315
+ - claude-3-opus
316
+ - gpt-4
317
+
318
+ search:
319
+ ignore_patterns:
320
+ - node_modules
321
+ - "*.pyc"
322
+ - .git
323
+ max_results: 100
324
+
325
+ permissions:
326
+ mode: review # review, auto_approve, auto_deny
327
+ whitelist:
328
+ - read
329
+ - grep
330
+ - search
331
+ blacklist:
332
+ - rm
333
+ - sudo
334
+ ```
335
+
336
+ ## CLI Usage
337
+
338
+ ### Installation to Claude Desktop
339
+
340
+ ```bash
341
+ # Install to Claude Desktop
342
+ hanzo-mcp install-desktop
343
+
344
+ # Serve MCP
345
+ hanzo-mcp serve --port 3000
346
+ ```
347
+
348
+ ### Standalone Server
349
+
350
+ ```bash
351
+ # Start MCP server
352
+ hanzo-mcp serve
353
+
354
+ # With custom config
355
+ hanzo-mcp serve --config mcp-config.yaml
356
+
357
+ # With specific tools
358
+ hanzo-mcp serve --tools filesystem,shell,agent
359
+ ```
360
+
361
+ ## Development
362
+
363
+ ### Setup
364
+
365
+ ```bash
366
+ cd pkg/hanzo-mcp
367
+ uv sync --all-extras
368
+ ```
369
+
370
+ ### Testing
371
+
372
+ ```bash
373
+ # Unit tests
374
+ pytest tests/ -v
375
+
376
+ # Integration tests
377
+ pytest tests/ -m integration
378
+
379
+ # With coverage
380
+ pytest tests/ --cov=hanzo_mcp
381
+ ```
382
+
383
+ ### Building
384
+
385
+ ```bash
386
+ uv build
387
+ ```
388
+
389
+ ## Architecture
390
+
391
+ ### Tool Categories
392
+
393
+ - **Filesystem**: File operations (read, write, edit)
394
+ - **Search**: Code search (grep, AST, semantic)
395
+ - **Shell**: Command execution and process management
396
+ - **Agent**: AI agent delegation and orchestration
397
+ - **Memory**: Context and knowledge persistence
398
+ - **Config**: Configuration management
399
+ - **LLM**: Direct LLM interactions
400
+
401
+ ### Security
402
+
403
+ - Permission system for dangerous operations
404
+ - Path validation and sandboxing
405
+ - Command injection protection
406
+ - Rate limiting on operations
407
+ - Audit logging
408
+
409
+ ## License
410
+
411
+ Apache License 2.0