hanzo-mcp 0.1.25__py3-none-any.whl → 0.1.30__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 (48) hide show
  1. hanzo_mcp/__init__.py +2 -2
  2. hanzo_mcp/cli.py +80 -9
  3. hanzo_mcp/server.py +41 -10
  4. hanzo_mcp/tools/__init__.py +51 -32
  5. hanzo_mcp/tools/agent/__init__.py +59 -0
  6. hanzo_mcp/tools/agent/agent_tool.py +474 -0
  7. hanzo_mcp/tools/agent/prompt.py +137 -0
  8. hanzo_mcp/tools/agent/tool_adapter.py +75 -0
  9. hanzo_mcp/tools/common/__init__.py +17 -0
  10. hanzo_mcp/tools/common/base.py +216 -0
  11. hanzo_mcp/tools/common/context.py +7 -3
  12. hanzo_mcp/tools/common/permissions.py +63 -119
  13. hanzo_mcp/tools/common/session.py +91 -0
  14. hanzo_mcp/tools/common/thinking_tool.py +123 -0
  15. hanzo_mcp/tools/filesystem/__init__.py +85 -5
  16. hanzo_mcp/tools/filesystem/base.py +113 -0
  17. hanzo_mcp/tools/filesystem/content_replace.py +287 -0
  18. hanzo_mcp/tools/filesystem/directory_tree.py +286 -0
  19. hanzo_mcp/tools/filesystem/edit_file.py +287 -0
  20. hanzo_mcp/tools/filesystem/get_file_info.py +170 -0
  21. hanzo_mcp/tools/filesystem/read_files.py +198 -0
  22. hanzo_mcp/tools/filesystem/search_content.py +275 -0
  23. hanzo_mcp/tools/filesystem/write_file.py +162 -0
  24. hanzo_mcp/tools/jupyter/__init__.py +67 -4
  25. hanzo_mcp/tools/jupyter/base.py +284 -0
  26. hanzo_mcp/tools/jupyter/edit_notebook.py +295 -0
  27. hanzo_mcp/tools/jupyter/notebook_operations.py +72 -112
  28. hanzo_mcp/tools/jupyter/read_notebook.py +165 -0
  29. hanzo_mcp/tools/project/__init__.py +64 -1
  30. hanzo_mcp/tools/project/analysis.py +9 -6
  31. hanzo_mcp/tools/project/base.py +66 -0
  32. hanzo_mcp/tools/project/project_analyze.py +173 -0
  33. hanzo_mcp/tools/shell/__init__.py +58 -1
  34. hanzo_mcp/tools/shell/base.py +148 -0
  35. hanzo_mcp/tools/shell/command_executor.py +203 -322
  36. hanzo_mcp/tools/shell/run_command.py +204 -0
  37. hanzo_mcp/tools/shell/run_script.py +215 -0
  38. hanzo_mcp/tools/shell/script_tool.py +244 -0
  39. {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/METADATA +72 -77
  40. hanzo_mcp-0.1.30.dist-info/RECORD +45 -0
  41. {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/licenses/LICENSE +2 -2
  42. hanzo_mcp/tools/common/thinking.py +0 -65
  43. hanzo_mcp/tools/filesystem/file_operations.py +0 -1050
  44. hanzo_mcp-0.1.25.dist-info/RECORD +0 -24
  45. hanzo_mcp-0.1.25.dist-info/zip-safe +0 -1
  46. {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/WHEEL +0 -0
  47. {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/entry_points.txt +0 -0
  48. {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/top_level.txt +0 -0
hanzo_mcp/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- """Hanzo MCP - Implementation of Hanzo Platform capabilities using MCP."""
1
+ """Hanzo MCP - Implementation of Hanzo capabilities using MCP."""
2
2
 
3
- __version__ = "0.1.22"
3
+ __version__ = "0.1.8"
hanzo_mcp/cli.py CHANGED
@@ -7,13 +7,13 @@ import sys
7
7
  from pathlib import Path
8
8
  from typing import Any, cast
9
9
 
10
- from hanzo_mcp.server import HanzoMCPServer
10
+ from hanzo_mcp.server import HanzoServer
11
11
 
12
12
 
13
13
  def main() -> None:
14
14
  """Run the CLI for the Hanzo MCP server."""
15
15
  parser = argparse.ArgumentParser(
16
- description="MCP server for accessing Hanzo APIs and Platform capabilities"
16
+ description="MCP server implementing Hanzo capabilities"
17
17
  )
18
18
 
19
19
  _ = parser.add_argument(
@@ -25,20 +25,63 @@ def main() -> None:
25
25
 
26
26
  _ = parser.add_argument(
27
27
  "--name",
28
- default="hanzo",
29
- help="Name of the MCP server (default: hanzo)",
28
+ default="claude-code",
29
+ help="Name of the MCP server (default: claude-code)",
30
30
  )
31
31
 
32
32
  _ = parser.add_argument(
33
33
  "--allow-path",
34
34
  action="append",
35
35
  dest="allowed_paths",
36
- help="Add an allowed path (can be specified multiple times)",
36
+ help="Add an allowed path (can be specified multiple times, defaults to user's home directory)",
37
37
  )
38
38
 
39
39
  _ = parser.add_argument(
40
40
  "--project-dir", dest="project_dir", help="Set the project directory to analyze"
41
41
  )
42
+
43
+ _ = parser.add_argument(
44
+ "--agent-model",
45
+ dest="agent_model",
46
+ help="Specify the model name in LiteLLM format (e.g., 'openai/gpt-4o', 'anthropic/claude-3-sonnet')"
47
+ )
48
+
49
+ _ = parser.add_argument(
50
+ "--agent-max-tokens",
51
+ dest="agent_max_tokens",
52
+ type=int,
53
+ help="Specify the maximum tokens for agent responses"
54
+ )
55
+
56
+ _ = parser.add_argument(
57
+ "--agent-api-key",
58
+ dest="agent_api_key",
59
+ help="Specify the API key for the LLM provider (for development/testing only)"
60
+ )
61
+
62
+ _ = parser.add_argument(
63
+ "--agent-max-iterations",
64
+ dest="agent_max_iterations",
65
+ type=int,
66
+ default=10,
67
+ help="Maximum number of iterations for agent (default: 10)"
68
+ )
69
+
70
+ _ = parser.add_argument(
71
+ "--agent-max-tool-uses",
72
+ dest="agent_max_tool_uses",
73
+ type=int,
74
+ default=30,
75
+ help="Maximum number of total tool uses for agent (default: 30)"
76
+ )
77
+
78
+ _ = parser.add_argument(
79
+ "--enable-agent-tool",
80
+ dest="enable_agent_tool",
81
+ action="store_true",
82
+ default=False,
83
+ help="Enable the agent tool (disabled by default)"
84
+ )
42
85
 
43
86
  _ = parser.add_argument(
44
87
  "--install",
@@ -53,6 +96,12 @@ def main() -> None:
53
96
  install: bool = cast(bool, args.install)
54
97
  transport: str = cast(str, args.transport)
55
98
  project_dir: str | None = cast(str | None, args.project_dir)
99
+ agent_model: str | None = cast(str | None, args.agent_model)
100
+ agent_max_tokens: int | None = cast(int | None, args.agent_max_tokens)
101
+ agent_api_key: str | None = cast(str | None, args.agent_api_key)
102
+ agent_max_iterations: int = cast(int, args.agent_max_iterations)
103
+ agent_max_tool_uses: int = cast(int, args.agent_max_tool_uses)
104
+ enable_agent_tool: bool = cast(bool, args.enable_agent_tool)
56
105
  allowed_paths: list[str] = (
57
106
  cast(list[str], args.allowed_paths) if args.allowed_paths else []
58
107
  )
@@ -61,22 +110,44 @@ def main() -> None:
61
110
  install_claude_desktop_config(name, allowed_paths)
62
111
  return
63
112
 
64
- # If no allowed paths are specified, use the current directory
113
+ # If no allowed paths are specified, use the user's home directory
65
114
  if not allowed_paths:
66
- allowed_paths = [os.getcwd()]
115
+ allowed_paths = [str(Path.home())]
67
116
 
68
117
  # If project directory is specified, add it to allowed paths
69
118
  if project_dir and project_dir not in allowed_paths:
70
119
  allowed_paths.append(project_dir)
71
120
 
121
+ # Set project directory as initial working directory if provided
122
+ if project_dir:
123
+ # Expand user paths
124
+ project_dir = os.path.expanduser(project_dir)
125
+ # Make absolute
126
+ if not os.path.isabs(project_dir):
127
+ project_dir = os.path.abspath(project_dir)
128
+
129
+ # If no specific project directory, use the first allowed path
130
+ elif allowed_paths:
131
+ project_dir = allowed_paths[0]
132
+
72
133
  # Run the server
73
- server = HanzoMCPServer(name=name, allowed_paths=allowed_paths)
134
+ server = HanzoServer(
135
+ name=name,
136
+ allowed_paths=allowed_paths,
137
+ project_dir=project_dir, # Pass project_dir for initial working directory
138
+ agent_model=agent_model,
139
+ agent_max_tokens=agent_max_tokens,
140
+ agent_api_key=agent_api_key,
141
+ agent_max_iterations=agent_max_iterations,
142
+ agent_max_tool_uses=agent_max_tool_uses,
143
+ enable_agent_tool=enable_agent_tool
144
+ )
74
145
  # Transport will be automatically cast to Literal['stdio', 'sse'] by the server
75
146
  server.run(transport=transport)
76
147
 
77
148
 
78
149
  def install_claude_desktop_config(
79
- name: str = "hanzo", allowed_paths: list[str] | None = None
150
+ name: str = "claude-code", allowed_paths: list[str] | None = None
80
151
  ) -> None:
81
152
  """Install the server configuration in Claude Desktop.
82
153
 
hanzo_mcp/server.py CHANGED
@@ -1,4 +1,4 @@
1
- """MCP server for accessing Hanzo APIs and Platform capabilities."""
1
+ """MCP server implementing Hanzo capabilities."""
2
2
 
3
3
  from typing import Literal, cast, final
4
4
 
@@ -12,21 +12,35 @@ from hanzo_mcp.tools.shell.command_executor import CommandExecutor
12
12
 
13
13
 
14
14
  @final
15
- class HanzoMCPServer:
16
- """MCP server for accessing Hanzo APIs and Platform capabilities."""
15
+ class HanzoServer:
16
+ """MCP server implementing Hanzo capabilities."""
17
17
 
18
18
  def __init__(
19
19
  self,
20
- name: str = "hanzo",
20
+ name: str = "claude-code",
21
21
  allowed_paths: list[str] | None = None,
22
+ project_dir: str | None = None,
22
23
  mcp_instance: FastMCP | None = None,
24
+ agent_model: str | None = None,
25
+ agent_max_tokens: int | None = None,
26
+ agent_api_key: str | None = None,
27
+ agent_max_iterations: int = 10,
28
+ agent_max_tool_uses: int = 30,
29
+ enable_agent_tool: bool = False,
23
30
  ):
24
31
  """Initialize the Hanzo server.
25
32
 
26
33
  Args:
27
34
  name: The name of the server
28
35
  allowed_paths: list of paths that the server is allowed to access
36
+ project_dir: Optional project directory to use as initial working directory
29
37
  mcp_instance: Optional FastMCP instance for testing
38
+ agent_model: Optional model name for agent tool in LiteLLM format
39
+ agent_max_tokens: Optional maximum tokens for agent responses
40
+ agent_api_key: Optional API key for the LLM provider
41
+ agent_max_iterations: Maximum number of iterations for agent (default: 10)
42
+ agent_max_tool_uses: Maximum number of total tool uses for agent (default: 30)
43
+ enable_agent_tool: Whether to enable the agent tool (default: False)
30
44
  """
31
45
  self.mcp = mcp_instance if mcp_instance is not None else FastMCP(name)
32
46
 
@@ -39,6 +53,11 @@ class HanzoMCPServer:
39
53
  permission_manager=self.permission_manager,
40
54
  verbose=False, # Set to True for debugging
41
55
  )
56
+
57
+ # If project_dir is specified, set it as initial working directory for all sessions
58
+ if project_dir:
59
+ initial_session_id = name # Use server name as default session ID
60
+ self.command_executor.set_working_dir(initial_session_id, project_dir)
42
61
 
43
62
  # Initialize project analyzer
44
63
  self.project_analyzer = ProjectAnalyzer(self.command_executor)
@@ -54,13 +73,25 @@ class HanzoMCPServer:
54
73
  self.permission_manager.add_allowed_path(path)
55
74
  self.document_context.add_allowed_path(path)
56
75
 
76
+ # Store agent options
77
+ self.agent_model = agent_model
78
+ self.agent_max_tokens = agent_max_tokens
79
+ self.agent_api_key = agent_api_key
80
+ self.agent_max_iterations = agent_max_iterations
81
+ self.agent_max_tool_uses = agent_max_tool_uses
82
+ self.enable_agent_tool = enable_agent_tool
83
+
57
84
  # Register all tools
58
85
  register_all_tools(
59
86
  mcp_server=self.mcp,
60
87
  document_context=self.document_context,
61
88
  permission_manager=self.permission_manager,
62
- project_manager=self.project_manager,
63
- project_analyzer=self.project_analyzer,
89
+ agent_model=self.agent_model,
90
+ agent_max_tokens=self.agent_max_tokens,
91
+ agent_api_key=self.agent_api_key,
92
+ agent_max_iterations=self.agent_max_iterations,
93
+ agent_max_tool_uses=self.agent_max_tool_uses,
94
+ enable_agent_tool=self.enable_agent_tool,
64
95
  )
65
96
 
66
97
  def run(self, transport: str = "stdio", allowed_paths: list[str] | None = None):
@@ -86,13 +117,13 @@ def main():
86
117
  import argparse
87
118
 
88
119
  parser = argparse.ArgumentParser(
89
- description="MCP server for accessing Hanzo APIs and Platform capabilities"
120
+ description="MCP server implementing Hanzo capabilities"
90
121
  )
91
122
 
92
123
  _ = parser.add_argument(
93
124
  "--name",
94
- default="hanzo",
95
- help="Name of the MCP server (default: hanzo)",
125
+ default="claude-code",
126
+ help="Name of the MCP server (default: claude-code)",
96
127
  )
97
128
 
98
129
  _ = parser.add_argument(
@@ -117,7 +148,7 @@ def main():
117
148
  allowed_paths: list[str] | None = args.allowed_paths
118
149
 
119
150
  # Create and run the server
120
- server = HanzoMCPServer(name=name, allowed_paths=allowed_paths)
151
+ server = HanzoServer(name=name, allowed_paths=allowed_paths)
121
152
  server.run(transport=transport, allowed_paths=allowed_paths or [])
122
153
 
123
154
 
@@ -5,19 +5,20 @@ It provides a unified interface for registering all tools with an MCP server.
5
5
 
6
6
  This includes a "think" tool implementation based on Anthropic's research showing
7
7
  improved performance for complex tool-based interactions when Claude has a dedicated
8
- space for structured thinking.
8
+ space for structured thinking. It also includes an "agent" tool that enables Claude
9
+ to delegate tasks to sub-agents for concurrent execution and specialized processing.
9
10
  """
10
11
 
11
- from typing import Any
12
-
13
12
  from mcp.server.fastmcp import FastMCP
14
13
 
14
+ from hanzo_mcp.tools.agent import register_agent_tools
15
+ from hanzo_mcp.tools.common import register_thinking_tool
15
16
  from hanzo_mcp.tools.common.context import DocumentContext
16
17
  from hanzo_mcp.tools.common.permissions import PermissionManager
17
- from hanzo_mcp.tools.common.thinking import ThinkingTool
18
- from hanzo_mcp.tools.filesystem.file_operations import FileOperations
19
- from hanzo_mcp.tools.jupyter.notebook_operations import JupyterNotebookTools
20
- from hanzo_mcp.tools.project.analysis import ProjectAnalysis, ProjectManager
18
+ from hanzo_mcp.tools.filesystem import register_filesystem_tools
19
+ from hanzo_mcp.tools.jupyter import register_jupyter_tools
20
+ from hanzo_mcp.tools.project import register_project_tools
21
+ from hanzo_mcp.tools.shell import register_shell_tools
21
22
  from hanzo_mcp.tools.shell.command_executor import CommandExecutor
22
23
 
23
24
 
@@ -25,38 +26,56 @@ def register_all_tools(
25
26
  mcp_server: FastMCP,
26
27
  document_context: DocumentContext,
27
28
  permission_manager: PermissionManager,
28
- project_manager: ProjectManager,
29
- project_analyzer: Any,
29
+ agent_model: str | None = None,
30
+ agent_max_tokens: int | None = None,
31
+ agent_api_key: str | None = None,
32
+ agent_max_iterations: int = 10,
33
+ agent_max_tool_uses: int = 30,
34
+ enable_agent_tool: bool = False,
30
35
  ) -> None:
31
- """Register all Hanzo MCP tools with the MCP server.
36
+ """Register all Hanzo tools with the MCP server.
32
37
 
33
38
  Args:
34
39
  mcp_server: The FastMCP server instance
35
40
  document_context: Document context for tracking file contents
36
41
  permission_manager: Permission manager for access control
37
- command_executor: Enhanced command executor for running shell commands
38
- project_manager: Project manager for tracking projects
39
- project_analyzer: Project analyzer for analyzing project structure and dependencies
42
+ agent_model: Optional model name for agent tool in LiteLLM format
43
+ agent_max_tokens: Optional maximum tokens for agent responses
44
+ agent_api_key: Optional API key for the LLM provider
45
+ agent_max_iterations: Maximum number of iterations for agent (default: 10)
46
+ agent_max_tool_uses: Maximum number of total tool uses for agent (default: 30)
47
+ enable_agent_tool: Whether to enable the agent tool (default: False)
40
48
  """
41
- # Initialize and register file operations tools
42
- # Now includes all filesystem functionality (navigation + file operations)
43
- file_ops = FileOperations(document_context, permission_manager)
44
- file_ops.register_tools(mcp_server)
45
-
46
- # Initialize and register command execution tools
47
- cmd_exec = CommandExecutor(permission_manager)
48
- cmd_exec.register_tools(mcp_server)
49
-
50
- # Initialize and register project analysis tools
51
- proj_analysis = ProjectAnalysis(
52
- project_manager, project_analyzer, permission_manager
53
- )
54
- proj_analysis.register_tools(mcp_server)
49
+ # Register all filesystem tools
50
+ register_filesystem_tools(mcp_server, document_context, permission_manager)
51
+
52
+ # Register all jupyter tools
53
+ register_jupyter_tools(mcp_server, document_context, permission_manager)
55
54
 
56
- # Initialize and register Jupyter notebook tools
57
- jupyter_tools = JupyterNotebookTools(document_context, permission_manager)
58
- jupyter_tools.register_tools(mcp_server)
55
+ # Register shell tools
56
+ register_shell_tools(mcp_server, permission_manager)
57
+
58
+ # Register project analysis tools
59
+ register_project_tools(
60
+ mcp_server,
61
+ permission_manager,
62
+ document_context,
63
+ CommandExecutor(permission_manager)
64
+ )
59
65
 
66
+ # Register agent tools only if enabled
67
+ if enable_agent_tool:
68
+ register_agent_tools(
69
+ mcp_server,
70
+ document_context,
71
+ permission_manager,
72
+ CommandExecutor(permission_manager),
73
+ agent_model=agent_model,
74
+ agent_max_tokens=agent_max_tokens,
75
+ agent_api_key=agent_api_key,
76
+ agent_max_iterations=agent_max_iterations,
77
+ agent_max_tool_uses=agent_max_tool_uses
78
+ )
79
+
60
80
  # Initialize and register thinking tool
61
- thinking_tool = ThinkingTool()
62
- thinking_tool.register_tools(mcp_server)
81
+ register_thinking_tool(mcp_server)
@@ -0,0 +1,59 @@
1
+ """Agent tools for Hanzo MCP.
2
+
3
+ This module provides tools that allow Claude to delegate tasks to sub-agents,
4
+ enabling concurrent execution of multiple operations and specialized processing.
5
+ """
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+ from hanzo_mcp.tools.agent.agent_tool import AgentTool
10
+ from hanzo_mcp.tools.common.base import BaseTool, ToolRegistry
11
+ from hanzo_mcp.tools.common.context import DocumentContext
12
+ from hanzo_mcp.tools.common.permissions import PermissionManager
13
+ from hanzo_mcp.tools.shell.command_executor import CommandExecutor
14
+
15
+
16
+ def register_agent_tools(
17
+ mcp_server: FastMCP,
18
+ document_context: DocumentContext,
19
+ permission_manager: PermissionManager,
20
+ command_executor: CommandExecutor,
21
+ agent_model: str | None = None,
22
+ agent_max_tokens: int | None = None,
23
+ agent_api_key: str | None = None,
24
+ agent_max_iterations: int = 10,
25
+ agent_max_tool_uses: int = 30,
26
+ ) -> list[BaseTool]:
27
+ """Register agent tools with the MCP server.
28
+
29
+ Args:
30
+ mcp_server: The FastMCP server instance
31
+ document_context: Document context for tracking file contents
32
+ permission_manager: Permission manager for access control
33
+ command_executor: Command executor for running shell commands
34
+ agent_model: Optional model name for agent tool in LiteLLM format
35
+ agent_max_tokens: Optional maximum tokens for agent responses
36
+ agent_api_key: Optional API key for the LLM provider
37
+ agent_max_iterations: Maximum number of iterations for agent (default: 10)
38
+ agent_max_tool_uses: Maximum number of total tool uses for agent (default: 30)
39
+
40
+ Returns:
41
+ List of registered tools
42
+ """
43
+ # Create agent tool
44
+ agent_tool = AgentTool(
45
+ document_context=document_context,
46
+ permission_manager=permission_manager,
47
+ command_executor=command_executor,
48
+ model=agent_model,
49
+ api_key=agent_api_key,
50
+ max_tokens=agent_max_tokens,
51
+ max_iterations=agent_max_iterations,
52
+ max_tool_uses=agent_max_tool_uses
53
+ )
54
+
55
+ # Register agent tool
56
+ ToolRegistry.register_tool(mcp_server, agent_tool)
57
+
58
+ # Return list of registered tools
59
+ return [agent_tool]