hanzo-mcp 0.1.21__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 +1 -1
  2. hanzo_mcp/cli.py +81 -10
  3. hanzo_mcp/server.py +42 -11
  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 +18 -1
  10. hanzo_mcp/tools/common/base.py +216 -0
  11. hanzo_mcp/tools/common/context.py +9 -5
  12. hanzo_mcp/tools/common/permissions.py +7 -3
  13. hanzo_mcp/tools/common/session.py +91 -0
  14. hanzo_mcp/tools/common/thinking_tool.py +123 -0
  15. hanzo_mcp/tools/common/validation.py +1 -1
  16. hanzo_mcp/tools/filesystem/__init__.py +85 -5
  17. hanzo_mcp/tools/filesystem/base.py +113 -0
  18. hanzo_mcp/tools/filesystem/content_replace.py +287 -0
  19. hanzo_mcp/tools/filesystem/directory_tree.py +286 -0
  20. hanzo_mcp/tools/filesystem/edit_file.py +287 -0
  21. hanzo_mcp/tools/filesystem/get_file_info.py +170 -0
  22. hanzo_mcp/tools/filesystem/read_files.py +198 -0
  23. hanzo_mcp/tools/filesystem/search_content.py +275 -0
  24. hanzo_mcp/tools/filesystem/write_file.py +162 -0
  25. hanzo_mcp/tools/jupyter/__init__.py +67 -4
  26. hanzo_mcp/tools/jupyter/base.py +284 -0
  27. hanzo_mcp/tools/jupyter/edit_notebook.py +295 -0
  28. hanzo_mcp/tools/jupyter/notebook_operations.py +73 -113
  29. hanzo_mcp/tools/jupyter/read_notebook.py +165 -0
  30. hanzo_mcp/tools/project/__init__.py +64 -1
  31. hanzo_mcp/tools/project/analysis.py +8 -5
  32. hanzo_mcp/tools/project/base.py +66 -0
  33. hanzo_mcp/tools/project/project_analyze.py +173 -0
  34. hanzo_mcp/tools/shell/__init__.py +58 -1
  35. hanzo_mcp/tools/shell/base.py +148 -0
  36. hanzo_mcp/tools/shell/command_executor.py +198 -317
  37. hanzo_mcp/tools/shell/run_command.py +204 -0
  38. hanzo_mcp/tools/shell/run_script.py +215 -0
  39. hanzo_mcp/tools/shell/script_tool.py +244 -0
  40. {hanzo_mcp-0.1.21.dist-info → hanzo_mcp-0.1.30.dist-info}/METADATA +72 -77
  41. hanzo_mcp-0.1.30.dist-info/RECORD +45 -0
  42. {hanzo_mcp-0.1.21.dist-info → hanzo_mcp-0.1.30.dist-info}/WHEEL +1 -1
  43. {hanzo_mcp-0.1.21.dist-info → hanzo_mcp-0.1.30.dist-info}/licenses/LICENSE +2 -2
  44. hanzo_mcp/tools/common/thinking.py +0 -65
  45. hanzo_mcp/tools/filesystem/file_operations.py +0 -1050
  46. hanzo_mcp-0.1.21.dist-info/RECORD +0 -23
  47. {hanzo_mcp-0.1.21.dist-info → hanzo_mcp-0.1.30.dist-info}/entry_points.txt +0 -0
  48. {hanzo_mcp-0.1.21.dist-info → hanzo_mcp-0.1.30.dist-info}/top_level.txt +0 -0
@@ -1 +1,18 @@
1
- """Common utilities for Hanzo Dev MCP tools."""
1
+ """Common utilities for Hanzo MCP tools."""
2
+
3
+ from mcp.server.fastmcp import FastMCP
4
+
5
+ from hanzo_mcp.tools.common.base import ToolRegistry
6
+ from hanzo_mcp.tools.common.thinking_tool import ThinkingTool
7
+
8
+
9
+ def register_thinking_tool(
10
+ mcp_server: FastMCP,
11
+ ) -> None:
12
+ """Register all thinking tools with the MCP server.
13
+
14
+ Args:
15
+ mcp_server: The FastMCP server instance
16
+ """
17
+ thinking_tool = ThinkingTool()
18
+ ToolRegistry.register_tool(mcp_server, thinking_tool)
@@ -0,0 +1,216 @@
1
+ """Base classes for Hanzo MCP tools.
2
+
3
+ This module provides abstract base classes that define interfaces and common functionality
4
+ for all tools used in Hanzo MCP. These abstractions help ensure consistent tool
5
+ behavior and provide a foundation for tool registration and management.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Any, final
10
+
11
+ from mcp.server.fastmcp import Context as MCPContext
12
+ from mcp.server.fastmcp import FastMCP
13
+
14
+ from hanzo_mcp.tools.common.context import DocumentContext
15
+ from hanzo_mcp.tools.common.permissions import PermissionManager
16
+ from hanzo_mcp.tools.common.validation import ValidationResult, validate_path_parameter
17
+
18
+
19
+ class BaseTool(ABC):
20
+ """Abstract base class for all Hanzo MCP tools.
21
+
22
+ This class defines the core interface that all tools must implement, ensuring
23
+ consistency in how tools are registered, documented, and called.
24
+ """
25
+
26
+ @property
27
+ @abstractmethod
28
+ def name(self) -> str:
29
+ """Get the tool name.
30
+
31
+ Returns:
32
+ The tool name as it will appear in the MCP server
33
+ """
34
+ pass
35
+
36
+ @property
37
+ @abstractmethod
38
+ def description(self) -> str:
39
+ """Get the tool description.
40
+
41
+ Returns:
42
+ Detailed description of the tool's purpose and usage
43
+ """
44
+ pass
45
+
46
+ @property
47
+ def mcp_description(self) -> str:
48
+ """Get the complete tool description for MCP.
49
+
50
+ This method combines the tool description with parameter descriptions.
51
+
52
+ Returns:
53
+ Complete tool description including parameter details
54
+ """
55
+ # Start with the base description
56
+ desc = self.description.strip()
57
+
58
+ # Add parameter descriptions section if there are parameters
59
+ if self.parameters and "properties" in self.parameters:
60
+ # Add Args section header
61
+ desc += "\n\nArgs:"
62
+
63
+ # Get the properties dictionary
64
+ properties = self.parameters["properties"]
65
+
66
+ # Add each parameter description
67
+ for param_name, param_info in properties.items():
68
+ # Get the title if available, otherwise use the parameter name and capitalize it
69
+ if "title" in param_info:
70
+ title = param_info["title"]
71
+ else:
72
+ # Convert snake_case to Title Case
73
+ title = " ".join(word.capitalize() for word in param_name.split("_"))
74
+
75
+ # Check if the parameter is required
76
+ required = param_name in self.required
77
+ required_text = "" if required else " (optional)"
78
+
79
+ # Add the parameter description line
80
+ desc += f"\n {param_name}: {title}{required_text}"
81
+
82
+ # Add Returns section
83
+ desc += "\n\nReturns:\n "
84
+
85
+ # Add a generic return description based on the tool's purpose
86
+ # This could be enhanced with more specific return descriptions
87
+ if "read" in self.name or "get" in self.name or "search" in self.name:
88
+ desc += f"{self.name.replace('_', ' ').capitalize()} results"
89
+ elif "write" in self.name or "edit" in self.name or "create" in self.name:
90
+ desc += "Result of the operation"
91
+ else:
92
+ desc += "Tool execution results"
93
+
94
+ return desc
95
+
96
+ @property
97
+ @abstractmethod
98
+ def parameters(self) -> dict[str, Any]:
99
+ """Get the parameter specifications for the tool.
100
+
101
+ Returns:
102
+ Dictionary containing parameter specifications in JSON Schema format
103
+ """
104
+ pass
105
+
106
+ @property
107
+ @abstractmethod
108
+ def required(self) -> list[str]:
109
+ """Get the list of required parameter names.
110
+
111
+ Returns:
112
+ List of parameter names that are required for the tool
113
+ """
114
+ pass
115
+
116
+ @abstractmethod
117
+ async def call(self, ctx: MCPContext, **params: Any) -> str:
118
+ """Execute the tool with the given parameters.
119
+
120
+ Args:
121
+ ctx: MCP context for the tool call
122
+ **params: Tool parameters provided by the caller
123
+
124
+ Returns:
125
+ Tool execution result as a string
126
+ """
127
+ pass
128
+
129
+ @abstractmethod
130
+ def register(self, mcp_server: FastMCP) -> None:
131
+ """Register this tool with the MCP server.
132
+
133
+ This method must be implemented by each tool class to create a wrapper function
134
+ with explicitly defined parameters that calls this tool's call method.
135
+ The wrapper function is then registered with the MCP server.
136
+
137
+ Args:
138
+ mcp_server: The FastMCP server instance
139
+ """
140
+ pass
141
+
142
+
143
+ class FileSystemTool(BaseTool,ABC):
144
+ """Base class for filesystem-related tools.
145
+
146
+ Provides common functionality for working with files and directories,
147
+ including permission checking and path validation.
148
+ """
149
+
150
+ def __init__(
151
+ self,
152
+ document_context: DocumentContext,
153
+ permission_manager: PermissionManager
154
+ ) -> None:
155
+ """Initialize filesystem tool.
156
+
157
+ Args:
158
+ document_context: Document context for tracking file contents
159
+ permission_manager: Permission manager for access control
160
+ """
161
+ self.document_context:DocumentContext = document_context
162
+ self.permission_manager:PermissionManager = permission_manager
163
+
164
+ def validate_path(self, path: str, param_name: str = "path") -> ValidationResult:
165
+ """Validate a path parameter.
166
+
167
+ Args:
168
+ path: Path to validate
169
+ param_name: Name of the parameter (for error messages)
170
+
171
+ Returns:
172
+ Validation result containing validation status and error message if any
173
+ """
174
+ return validate_path_parameter(path, param_name)
175
+
176
+ def is_path_allowed(self, path: str) -> bool:
177
+ """Check if a path is allowed according to permission settings.
178
+
179
+ Args:
180
+ path: Path to check
181
+
182
+ Returns:
183
+ True if the path is allowed, False otherwise
184
+ """
185
+ return self.permission_manager.is_path_allowed(path)
186
+
187
+
188
+ @final
189
+ class ToolRegistry:
190
+ """Registry for Hanzo MCP tools.
191
+
192
+ Provides functionality for registering tool implementations with an MCP server,
193
+ handling the conversion between tool classes and MCP tool functions.
194
+ """
195
+
196
+ @staticmethod
197
+ def register_tool(mcp_server: FastMCP, tool: BaseTool) -> None:
198
+ """Register a tool with the MCP server.
199
+
200
+ Args:
201
+ mcp_server: The FastMCP server instance
202
+ tool: The tool to register
203
+ """
204
+ # Use the tool's register method which handles all the details
205
+ tool.register(mcp_server)
206
+
207
+ @staticmethod
208
+ def register_tools(mcp_server: FastMCP, tools: list[BaseTool]) -> None:
209
+ """Register multiple tools with the MCP server.
210
+
211
+ Args:
212
+ mcp_server: The FastMCP server instance
213
+ tools: List of tools to register
214
+ """
215
+ for tool in tools:
216
+ ToolRegistry.register_tool(mcp_server, tool)
@@ -1,7 +1,7 @@
1
- """Enhanced Context for Hanzo Dev MCP tools.
1
+ """Enhanced Context for Hanzo MCP tools.
2
2
 
3
3
  This module provides an enhanced Context class that wraps the MCP Context
4
- and adds additional functionality specific to Claude Code tools.
4
+ and adds additional functionality specific to Hanzo tools.
5
5
  """
6
6
 
7
7
  import json
@@ -17,7 +17,7 @@ from mcp.server.lowlevel.helper_types import ReadResourceContents
17
17
 
18
18
  @final
19
19
  class ToolContext:
20
- """Enhanced context for Hanzo Dev MCP tools.
20
+ """Enhanced context for Hanzo MCP tools.
21
21
 
22
22
  This class wraps the MCP Context and adds additional functionality
23
23
  for tracking tool execution, progress reporting, and resource access.
@@ -179,7 +179,9 @@ class DocumentContext:
179
179
  Args:
180
180
  path: The path to allow
181
181
  """
182
- resolved_path: Path = Path(path).resolve()
182
+ # Expand user path (e.g., ~/ or $HOME)
183
+ expanded_path = os.path.expanduser(path)
184
+ resolved_path: Path = Path(expanded_path).resolve()
183
185
  self.allowed_paths.add(resolved_path)
184
186
 
185
187
  def is_path_allowed(self, path: str) -> bool:
@@ -191,7 +193,9 @@ class DocumentContext:
191
193
  Returns:
192
194
  True if the path is allowed, False otherwise
193
195
  """
194
- resolved_path: Path = Path(path).resolve()
196
+ # Expand user path (e.g., ~/ or $HOME)
197
+ expanded_path = os.path.expanduser(path)
198
+ resolved_path: Path = Path(expanded_path).resolve()
195
199
 
196
200
  # Check if the path is within any allowed path
197
201
  for allowed_path in self.allowed_paths:
@@ -1,4 +1,4 @@
1
- """Permission system for the Hanzo Dev MCP server."""
1
+ """Permission system for the Hanzo MCP server."""
2
2
 
3
3
  import json
4
4
  import os
@@ -69,7 +69,9 @@ class PermissionManager:
69
69
  Args:
70
70
  path: The path to allow
71
71
  """
72
- resolved_path: Path = Path(path).resolve()
72
+ # Expand user path (e.g., ~/ or $HOME)
73
+ expanded_path = os.path.expanduser(path)
74
+ resolved_path: Path = Path(expanded_path).resolve()
73
75
  self.allowed_paths.add(resolved_path)
74
76
 
75
77
  def remove_allowed_path(self, path: str) -> None:
@@ -108,7 +110,9 @@ class PermissionManager:
108
110
  Returns:
109
111
  True if the path is allowed, False otherwise
110
112
  """
111
- resolved_path: Path = Path(path).resolve()
113
+ # Expand user path (e.g., ~/ or $HOME)
114
+ expanded_path = os.path.expanduser(path)
115
+ resolved_path: Path = Path(expanded_path).resolve()
112
116
 
113
117
  # Check exclusions first
114
118
  if self._is_path_excluded(resolved_path):
@@ -0,0 +1,91 @@
1
+ """Session management for maintaining state across tool executions."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+ from typing import Dict, Optional, final
6
+
7
+
8
+ @final
9
+ class SessionManager:
10
+ """Manages session state across tool executions."""
11
+
12
+ _instances: Dict[str, "SessionManager"] = {}
13
+
14
+ @classmethod
15
+ def get_instance(cls, session_id: str) -> "SessionManager":
16
+ """Get or create a session manager instance for the given session ID.
17
+
18
+ Args:
19
+ session_id: The session ID
20
+
21
+ Returns:
22
+ The session manager instance
23
+ """
24
+ if session_id not in cls._instances:
25
+ cls._instances[session_id] = cls(session_id)
26
+ return cls._instances[session_id]
27
+
28
+ def __init__(self, session_id: str):
29
+ """Initialize the session manager.
30
+
31
+ Args:
32
+ session_id: The session ID
33
+ """
34
+ self.session_id = session_id
35
+ self._current_working_dir: Optional[Path] = None
36
+ self._initial_working_dir: Optional[Path] = None
37
+ self._environment_vars: Dict[str, str] = {}
38
+
39
+ @property
40
+ def current_working_dir(self) -> Path:
41
+ """Get the current working directory.
42
+
43
+ Returns:
44
+ The current working directory
45
+ """
46
+ if self._current_working_dir is None:
47
+ # Default to project directory if set, otherwise use current directory
48
+ self._current_working_dir = Path(os.getcwd())
49
+ self._initial_working_dir = self._current_working_dir
50
+ return self._current_working_dir
51
+
52
+ def set_working_dir(self, path: Path) -> None:
53
+ """Set the current working directory.
54
+
55
+ Args:
56
+ path: The path to set as the current working directory
57
+ """
58
+ self._current_working_dir = path
59
+
60
+ def reset_working_dir(self) -> None:
61
+ """Reset the working directory to the initial directory."""
62
+ if self._initial_working_dir is not None:
63
+ self._current_working_dir = self._initial_working_dir
64
+
65
+ def set_env_var(self, key: str, value: str) -> None:
66
+ """Set an environment variable.
67
+
68
+ Args:
69
+ key: The environment variable name
70
+ value: The environment variable value
71
+ """
72
+ self._environment_vars[key] = value
73
+
74
+ def get_env_var(self, key: str) -> Optional[str]:
75
+ """Get an environment variable.
76
+
77
+ Args:
78
+ key: The environment variable name
79
+
80
+ Returns:
81
+ The environment variable value, or None if not set
82
+ """
83
+ return self._environment_vars.get(key)
84
+
85
+ def get_env_vars(self) -> Dict[str, str]:
86
+ """Get all environment variables.
87
+
88
+ Returns:
89
+ A dictionary of environment variables
90
+ """
91
+ return self._environment_vars.copy()
@@ -0,0 +1,123 @@
1
+ """Thinking tool implementation.
2
+
3
+ This module provides the ThinkingTool for Claude to engage in structured thinking.
4
+ """
5
+
6
+ from typing import Any, final, override
7
+
8
+ from mcp.server.fastmcp import Context as MCPContext
9
+ from mcp.server.fastmcp import FastMCP
10
+
11
+ from hanzo_mcp.tools.common.base import BaseTool
12
+ from hanzo_mcp.tools.common.context import create_tool_context
13
+
14
+
15
+ @final
16
+ class ThinkingTool(BaseTool):
17
+ """Tool for Claude to engage in structured thinking."""
18
+
19
+ @property
20
+ @override
21
+ def name(self) -> str:
22
+ """Get the tool name.
23
+
24
+ Returns:
25
+ Tool name
26
+ """
27
+ return "think"
28
+
29
+ @property
30
+ @override
31
+ def description(self) -> str:
32
+ """Get the tool description.
33
+
34
+ Returns:
35
+ Tool description
36
+ """
37
+ return """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
+ @property
42
+ @override
43
+ def parameters(self) -> dict[str, Any]:
44
+ """Get the parameter specifications for the tool.
45
+
46
+ Returns:
47
+ Parameter specifications
48
+ """
49
+ return {
50
+ "properties": {
51
+ "thought": {
52
+ "title": "Thought",
53
+ "type": "string"
54
+ }
55
+ },
56
+ "required": ["thought"],
57
+ "title": "thinkArguments",
58
+ "type": "object"
59
+ }
60
+
61
+ @property
62
+ @override
63
+ def required(self) -> list[str]:
64
+ """Get the list of required parameter names.
65
+
66
+ Returns:
67
+ List of required parameter names
68
+ """
69
+ return ["thought"]
70
+
71
+ def __init__(self) -> None:
72
+ """Initialize the thinking tool."""
73
+ pass
74
+
75
+ @override
76
+ async def call(self, ctx: MCPContext, **params: Any) -> str:
77
+ """Execute the tool with the given parameters.
78
+
79
+ Args:
80
+ ctx: MCP context
81
+ **params: Tool parameters
82
+
83
+ Returns:
84
+ Tool result
85
+ """
86
+ tool_ctx = create_tool_context(ctx)
87
+ tool_ctx.set_tool_info(self.name)
88
+
89
+ # Extract parameters
90
+ thought = params.get("thought")
91
+
92
+ # Validate required thought parameter
93
+ if not thought:
94
+ await tool_ctx.error(
95
+ "Parameter 'thought' is required but was None or empty"
96
+ )
97
+ return "Error: Parameter 'thought' is required but was None or empty"
98
+
99
+ if thought.strip() == "":
100
+ await tool_ctx.error("Parameter 'thought' cannot be empty")
101
+ return "Error: Parameter 'thought' cannot be empty"
102
+
103
+ # Log the thought but don't take action
104
+ await tool_ctx.info("Thinking process recorded")
105
+
106
+ # Return confirmation
107
+ return "I've recorded your thinking process. You can continue with your next action based on this analysis."
108
+
109
+ @override
110
+ def register(self, mcp_server: FastMCP) -> None:
111
+ """Register this thinking tool with the MCP server.
112
+
113
+ Creates a wrapper function with explicitly defined parameters that match
114
+ the tool's parameter schema and registers it with the MCP server.
115
+
116
+ Args:
117
+ mcp_server: The FastMCP server instance
118
+ """
119
+ tool_self = self # Create a reference to self for use in the closure
120
+
121
+ @mcp_server.tool(name=self.name, description=self.mcp_description)
122
+ async def think(thought: str, ctx: MCPContext) -> str:
123
+ return await tool_self.call(ctx, thought=thought)
@@ -1,4 +1,4 @@
1
- """Parameter validation utilities for Hanzo Dev MCP tools.
1
+ """Parameter validation utilities for Hanzo MCP tools.
2
2
 
3
3
  This module provides utilities for validating parameters in tool functions.
4
4
  """
@@ -1,9 +1,89 @@
1
- """Filesystem tools for Hanzo Dev MCP.
1
+ """Filesystem tools package for Hanzo MCP.
2
2
 
3
- This module provides comprehensive tools for interacting with the filesystem,
4
- including reading, writing, editing files, directory operations, and searching.
3
+ This package provides tools for interacting with the filesystem, including reading, writing,
4
+ and editing files, directory navigation, and content searching.
5
5
  """
6
6
 
7
- from hanzo_mcp.tools.filesystem.file_operations import FileOperations
7
+ from mcp.server.fastmcp import FastMCP
8
8
 
9
- __all__ = ["FileOperations"]
9
+ from hanzo_mcp.tools.common.base import BaseTool, ToolRegistry
10
+ from hanzo_mcp.tools.common.context import DocumentContext
11
+ from hanzo_mcp.tools.common.permissions import PermissionManager
12
+ from hanzo_mcp.tools.filesystem.content_replace import ContentReplaceTool
13
+ from hanzo_mcp.tools.filesystem.directory_tree import DirectoryTreeTool
14
+ from hanzo_mcp.tools.filesystem.edit_file import EditFileTool
15
+ from hanzo_mcp.tools.filesystem.get_file_info import GetFileInfoTool
16
+ from hanzo_mcp.tools.filesystem.read_files import ReadFilesTool
17
+ from hanzo_mcp.tools.filesystem.search_content import SearchContentTool
18
+ from hanzo_mcp.tools.filesystem.write_file import WriteFileTool
19
+
20
+ # Export all tool classes
21
+ __all__ = [
22
+ "ReadFilesTool",
23
+ "WriteFileTool",
24
+ "EditFileTool",
25
+ "DirectoryTreeTool",
26
+ "GetFileInfoTool",
27
+ "SearchContentTool",
28
+ "ContentReplaceTool",
29
+ "get_filesystem_tools",
30
+ "register_filesystem_tools",
31
+ ]
32
+
33
+ def get_read_only_filesystem_tools(
34
+ document_context: DocumentContext, permission_manager: PermissionManager
35
+ ) -> list[BaseTool]:
36
+ """Create instances of read-only filesystem tools.
37
+
38
+ Args:
39
+ document_context: Document context for tracking file contents
40
+ permission_manager: Permission manager for access control
41
+
42
+ Returns:
43
+ List of read-only filesystem tool instances
44
+ """
45
+ return [
46
+ ReadFilesTool(document_context, permission_manager),
47
+ DirectoryTreeTool(document_context, permission_manager),
48
+ GetFileInfoTool(document_context, permission_manager),
49
+ SearchContentTool(document_context, permission_manager),
50
+ ]
51
+
52
+
53
+ def get_filesystem_tools(
54
+ document_context: DocumentContext, permission_manager: PermissionManager
55
+ ) -> list[BaseTool]:
56
+ """Create instances of all filesystem tools.
57
+
58
+ Args:
59
+ document_context: Document context for tracking file contents
60
+ permission_manager: Permission manager for access control
61
+
62
+ Returns:
63
+ List of filesystem tool instances
64
+ """
65
+ return [
66
+ ReadFilesTool(document_context, permission_manager),
67
+ WriteFileTool(document_context, permission_manager),
68
+ EditFileTool(document_context, permission_manager),
69
+ DirectoryTreeTool(document_context, permission_manager),
70
+ GetFileInfoTool(document_context, permission_manager),
71
+ SearchContentTool(document_context, permission_manager),
72
+ ContentReplaceTool(document_context, permission_manager),
73
+ ]
74
+
75
+
76
+ def register_filesystem_tools(
77
+ mcp_server: FastMCP,
78
+ document_context: DocumentContext,
79
+ permission_manager: PermissionManager,
80
+ ) -> None:
81
+ """Register all filesystem tools with the MCP server.
82
+
83
+ Args:
84
+ mcp_server: The FastMCP server instance
85
+ document_context: Document context for tracking file contents
86
+ permission_manager: Permission manager for access control
87
+ """
88
+ tools = get_filesystem_tools(document_context, permission_manager)
89
+ ToolRegistry.register_tools(mcp_server, tools)