hanzo-mcp 0.1.21__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.
- hanzo_mcp/__init__.py +3 -0
- hanzo_mcp/cli.py +155 -0
- hanzo_mcp/server.py +125 -0
- hanzo_mcp/tools/__init__.py +62 -0
- hanzo_mcp/tools/common/__init__.py +1 -0
- hanzo_mcp/tools/common/context.py +444 -0
- hanzo_mcp/tools/common/permissions.py +253 -0
- hanzo_mcp/tools/common/thinking.py +65 -0
- hanzo_mcp/tools/common/validation.py +124 -0
- hanzo_mcp/tools/filesystem/__init__.py +9 -0
- hanzo_mcp/tools/filesystem/file_operations.py +1050 -0
- hanzo_mcp/tools/jupyter/__init__.py +8 -0
- hanzo_mcp/tools/jupyter/notebook_operations.py +554 -0
- hanzo_mcp/tools/project/__init__.py +1 -0
- hanzo_mcp/tools/project/analysis.py +879 -0
- hanzo_mcp/tools/shell/__init__.py +1 -0
- hanzo_mcp/tools/shell/command_executor.py +1001 -0
- hanzo_mcp-0.1.21.dist-info/METADATA +168 -0
- hanzo_mcp-0.1.21.dist-info/RECORD +23 -0
- hanzo_mcp-0.1.21.dist-info/WHEEL +5 -0
- hanzo_mcp-0.1.21.dist-info/entry_points.txt +2 -0
- hanzo_mcp-0.1.21.dist-info/licenses/LICENSE +21 -0
- hanzo_mcp-0.1.21.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Thinking tool for Hanzo MCP.
|
|
2
|
+
|
|
3
|
+
This module provides a tool for Claude to engage in structured thinking
|
|
4
|
+
when performing complex multi-step operations or reasoning through policies.
|
|
5
|
+
Following the pattern described in Anthropic's "Claude Think Tool" article.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import final
|
|
9
|
+
|
|
10
|
+
from mcp.server.fastmcp import Context as MCPContext
|
|
11
|
+
from mcp.server.fastmcp import FastMCP
|
|
12
|
+
|
|
13
|
+
from hanzo_mcp.tools.common.context import create_tool_context
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@final
|
|
17
|
+
class ThinkingTool:
|
|
18
|
+
"""Think tool for Hanzo MCP.
|
|
19
|
+
|
|
20
|
+
This class provides a "think" tool that enables Claude to engage in more structured
|
|
21
|
+
thinking when processing complex information or making multi-step decisions.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self) -> None:
|
|
25
|
+
"""Initialize the thinking tool."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
def register_tools(self, mcp_server: FastMCP) -> None:
|
|
29
|
+
"""Register thinking tools with the MCP server.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
mcp_server: The FastMCP server instance
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
@mcp_server.tool()
|
|
36
|
+
async def think(thought: str, ctx: MCPContext) -> str:
|
|
37
|
+
"""Use the tool to think about something.
|
|
38
|
+
|
|
39
|
+
It will not obtain new information or make any changes to the repository, but just log the thought. Use it when complex reasoning or brainstorming is needed. For example, if you explore the repo and discover the source of a bug, call this tool to brainstorm several unique ways of fixing the bug, and assess which change(s) are likely to be simplest and most effective. Alternatively, if you receive some test results, call this tool to brainstorm ways to fix the failing tests.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
thought: Your thoughts or analysis
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Confirmation that the thinking process has been recorded
|
|
46
|
+
"""
|
|
47
|
+
tool_ctx = create_tool_context(ctx)
|
|
48
|
+
tool_ctx.set_tool_info("think")
|
|
49
|
+
|
|
50
|
+
# Validate required thought parameter
|
|
51
|
+
if not thought:
|
|
52
|
+
await tool_ctx.error(
|
|
53
|
+
"Parameter 'thought' is required but was None or empty"
|
|
54
|
+
)
|
|
55
|
+
return "Error: Parameter 'thought' is required but was None or empty"
|
|
56
|
+
|
|
57
|
+
if thought.strip() == "":
|
|
58
|
+
await tool_ctx.error("Parameter 'thought' cannot be empty")
|
|
59
|
+
return "Error: Parameter 'thought' cannot be empty"
|
|
60
|
+
|
|
61
|
+
# Log the thought but don't take action
|
|
62
|
+
await tool_ctx.info("Thinking process recorded")
|
|
63
|
+
|
|
64
|
+
# Return confirmation
|
|
65
|
+
return "I've recorded your thinking process. You can continue with your next action based on this analysis."
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Parameter validation utilities for Hanzo Dev MCP tools.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for validating parameters in tool functions.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any, TypeVar, final
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@final
|
|
12
|
+
class ValidationResult:
|
|
13
|
+
"""Result of a parameter validation."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, is_valid: bool, error_message: str = ""):
|
|
16
|
+
"""Initialize a validation result.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
is_valid: Whether the parameter is valid
|
|
20
|
+
error_message: Optional error message for invalid parameters
|
|
21
|
+
"""
|
|
22
|
+
self.is_valid: bool = is_valid
|
|
23
|
+
self.error_message: str = error_message
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def is_error(self) -> bool:
|
|
27
|
+
"""Check if the validation resulted in an error.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
True if there was a validation error, False otherwise
|
|
31
|
+
"""
|
|
32
|
+
return not self.is_valid
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def validate_parameter(
|
|
36
|
+
parameter: Any, parameter_name: str, allow_empty: bool = False
|
|
37
|
+
) -> ValidationResult:
|
|
38
|
+
"""Validate a single parameter.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
parameter: The parameter value to validate
|
|
42
|
+
parameter_name: The name of the parameter (for error messages)
|
|
43
|
+
allow_empty: Whether to allow empty strings, lists, etc.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
A ValidationResult indicating whether the parameter is valid
|
|
47
|
+
"""
|
|
48
|
+
# Check for None
|
|
49
|
+
if parameter is None:
|
|
50
|
+
return ValidationResult(
|
|
51
|
+
is_valid=False,
|
|
52
|
+
error_message=f"Parameter '{parameter_name}' is required but was None",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Check for empty strings
|
|
56
|
+
if isinstance(parameter, str) and not allow_empty and parameter.strip() == "":
|
|
57
|
+
return ValidationResult(
|
|
58
|
+
is_valid=False,
|
|
59
|
+
error_message=f"Parameter '{parameter_name}' is required but was empty string",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Check for empty collections
|
|
63
|
+
if (
|
|
64
|
+
isinstance(parameter, (list, tuple, dict, set))
|
|
65
|
+
and not allow_empty
|
|
66
|
+
and len(parameter) == 0
|
|
67
|
+
):
|
|
68
|
+
return ValidationResult(
|
|
69
|
+
is_valid=False,
|
|
70
|
+
error_message=f"Parameter '{parameter_name}' is required but was empty {type(parameter).__name__}",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Parameter is valid
|
|
74
|
+
return ValidationResult(is_valid=True)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def validate_path_parameter(
|
|
78
|
+
path: str | None, parameter_name: str = "path"
|
|
79
|
+
) -> ValidationResult:
|
|
80
|
+
"""Validate a path parameter.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
path: The path parameter to validate
|
|
84
|
+
parameter_name: The name of the parameter (for error messages)
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
A ValidationResult indicating whether the parameter is valid
|
|
88
|
+
"""
|
|
89
|
+
# Check for None
|
|
90
|
+
if path is None:
|
|
91
|
+
return ValidationResult(
|
|
92
|
+
is_valid=False,
|
|
93
|
+
error_message=f"Path parameter '{parameter_name}' is required but was None",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Check for empty path
|
|
97
|
+
if path.strip() == "":
|
|
98
|
+
return ValidationResult(
|
|
99
|
+
is_valid=False,
|
|
100
|
+
error_message=f"Path parameter '{parameter_name}' is required but was empty string",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Path is valid
|
|
104
|
+
return ValidationResult(is_valid=True)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def validate_parameters(**kwargs: Any) -> ValidationResult:
|
|
108
|
+
"""Validate multiple parameters.
|
|
109
|
+
|
|
110
|
+
Accepts keyword arguments where the key is the parameter name and the value is the parameter value.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
**kwargs: Parameters to validate as name=value pairs
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
A ValidationResult for the first invalid parameter, or a valid result if all are valid
|
|
117
|
+
"""
|
|
118
|
+
for name, value in kwargs.items():
|
|
119
|
+
result = validate_parameter(value, name)
|
|
120
|
+
if result.is_error:
|
|
121
|
+
return result
|
|
122
|
+
|
|
123
|
+
# All parameters are valid
|
|
124
|
+
return ValidationResult(is_valid=True)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Filesystem tools for Hanzo Dev MCP.
|
|
2
|
+
|
|
3
|
+
This module provides comprehensive tools for interacting with the filesystem,
|
|
4
|
+
including reading, writing, editing files, directory operations, and searching.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from hanzo_mcp.tools.filesystem.file_operations import FileOperations
|
|
8
|
+
|
|
9
|
+
__all__ = ["FileOperations"]
|