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.
- hanzo_mcp/__init__.py +2 -2
- hanzo_mcp/cli.py +80 -9
- hanzo_mcp/server.py +41 -10
- hanzo_mcp/tools/__init__.py +51 -32
- hanzo_mcp/tools/agent/__init__.py +59 -0
- hanzo_mcp/tools/agent/agent_tool.py +474 -0
- hanzo_mcp/tools/agent/prompt.py +137 -0
- hanzo_mcp/tools/agent/tool_adapter.py +75 -0
- hanzo_mcp/tools/common/__init__.py +17 -0
- hanzo_mcp/tools/common/base.py +216 -0
- hanzo_mcp/tools/common/context.py +7 -3
- hanzo_mcp/tools/common/permissions.py +63 -119
- hanzo_mcp/tools/common/session.py +91 -0
- hanzo_mcp/tools/common/thinking_tool.py +123 -0
- hanzo_mcp/tools/filesystem/__init__.py +85 -5
- hanzo_mcp/tools/filesystem/base.py +113 -0
- hanzo_mcp/tools/filesystem/content_replace.py +287 -0
- hanzo_mcp/tools/filesystem/directory_tree.py +286 -0
- hanzo_mcp/tools/filesystem/edit_file.py +287 -0
- hanzo_mcp/tools/filesystem/get_file_info.py +170 -0
- hanzo_mcp/tools/filesystem/read_files.py +198 -0
- hanzo_mcp/tools/filesystem/search_content.py +275 -0
- hanzo_mcp/tools/filesystem/write_file.py +162 -0
- hanzo_mcp/tools/jupyter/__init__.py +67 -4
- hanzo_mcp/tools/jupyter/base.py +284 -0
- hanzo_mcp/tools/jupyter/edit_notebook.py +295 -0
- hanzo_mcp/tools/jupyter/notebook_operations.py +72 -112
- hanzo_mcp/tools/jupyter/read_notebook.py +165 -0
- hanzo_mcp/tools/project/__init__.py +64 -1
- hanzo_mcp/tools/project/analysis.py +9 -6
- hanzo_mcp/tools/project/base.py +66 -0
- hanzo_mcp/tools/project/project_analyze.py +173 -0
- hanzo_mcp/tools/shell/__init__.py +58 -1
- hanzo_mcp/tools/shell/base.py +148 -0
- hanzo_mcp/tools/shell/command_executor.py +203 -322
- hanzo_mcp/tools/shell/run_command.py +204 -0
- hanzo_mcp/tools/shell/run_script.py +215 -0
- hanzo_mcp/tools/shell/script_tool.py +244 -0
- {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/METADATA +72 -77
- hanzo_mcp-0.1.30.dist-info/RECORD +45 -0
- {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/licenses/LICENSE +2 -2
- hanzo_mcp/tools/common/thinking.py +0 -65
- hanzo_mcp/tools/filesystem/file_operations.py +0 -1050
- hanzo_mcp-0.1.25.dist-info/RECORD +0 -24
- hanzo_mcp-0.1.25.dist-info/zip-safe +0 -1
- {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/WHEEL +0 -0
- {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/entry_points.txt +0 -0
- {hanzo_mcp-0.1.25.dist-info → hanzo_mcp-0.1.30.dist-info}/top_level.txt +0 -0
|
@@ -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,9 +1,89 @@
|
|
|
1
|
-
"""Filesystem tools for Hanzo MCP.
|
|
1
|
+
"""Filesystem tools package for Hanzo MCP.
|
|
2
2
|
|
|
3
|
-
This
|
|
4
|
-
|
|
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
|
|
7
|
+
from mcp.server.fastmcp import FastMCP
|
|
8
8
|
|
|
9
|
-
|
|
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)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Base functionality for filesystem tools.
|
|
2
|
+
|
|
3
|
+
This module provides common functionality for filesystem tools including path handling,
|
|
4
|
+
error formatting, and shared utilities for file operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from mcp.server.fastmcp import Context as MCPContext
|
|
12
|
+
|
|
13
|
+
from hanzo_mcp.tools.common.base import FileSystemTool
|
|
14
|
+
from hanzo_mcp.tools.common.context import ToolContext, create_tool_context
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FilesystemBaseTool(FileSystemTool,ABC):
|
|
18
|
+
"""Enhanced base class for all filesystem tools.
|
|
19
|
+
|
|
20
|
+
Provides additional utilities specific to filesystem operations beyond
|
|
21
|
+
the base functionality in FileSystemTool.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
async def check_path_allowed(self, path: str, tool_ctx: Any, error_prefix: str = "Error") -> tuple[bool, str]:
|
|
25
|
+
"""Check if a path is allowed and log an error if not.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
path: Path to check
|
|
29
|
+
tool_ctx: Tool context for logging
|
|
30
|
+
error_prefix: Prefix for error messages
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
tuple of (is_allowed, error_message)
|
|
34
|
+
"""
|
|
35
|
+
if not self.is_path_allowed(path):
|
|
36
|
+
message = f"Access denied - path outside allowed directories: {path}"
|
|
37
|
+
await tool_ctx.error(message)
|
|
38
|
+
return False, f"{error_prefix}: {message}"
|
|
39
|
+
return True, ""
|
|
40
|
+
|
|
41
|
+
async def check_path_exists(self, path: str, tool_ctx: Any, error_prefix: str = "Error") -> tuple[bool, str]:
|
|
42
|
+
"""Check if a path exists and log an error if not.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
path: Path to check
|
|
46
|
+
tool_ctx: Tool context for logging
|
|
47
|
+
error_prefix: Prefix for error messages
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
tuple of (exists, error_message)
|
|
51
|
+
"""
|
|
52
|
+
file_path = Path(path)
|
|
53
|
+
if not file_path.exists():
|
|
54
|
+
message = f"Path does not exist: {path}"
|
|
55
|
+
await tool_ctx.error(message)
|
|
56
|
+
return False, f"{error_prefix}: {message}"
|
|
57
|
+
return True, ""
|
|
58
|
+
|
|
59
|
+
async def check_is_file(self, path: str, tool_ctx: Any, error_prefix: str = "Error") -> tuple[bool, str]:
|
|
60
|
+
"""Check if a path is a file and log an error if not.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
path: Path to check
|
|
64
|
+
tool_ctx: Tool context for logging
|
|
65
|
+
error_prefix: Prefix for error messages
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
tuple of (is_file, error_message)
|
|
69
|
+
"""
|
|
70
|
+
file_path = Path(path)
|
|
71
|
+
if not file_path.is_file():
|
|
72
|
+
message = f"Path is not a file: {path}"
|
|
73
|
+
await tool_ctx.error(message)
|
|
74
|
+
return False, f"{error_prefix}: {message}"
|
|
75
|
+
return True, ""
|
|
76
|
+
|
|
77
|
+
async def check_is_directory(self, path: str, tool_ctx: Any, error_prefix: str = "Error") -> tuple[bool, str]:
|
|
78
|
+
"""Check if a path is a directory and log an error if not.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
path: Path to check
|
|
82
|
+
tool_ctx: Tool context for logging
|
|
83
|
+
error_prefix: Prefix for error messages
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
tuple of (is_directory, error_message)
|
|
87
|
+
"""
|
|
88
|
+
dir_path = Path(path)
|
|
89
|
+
if not dir_path.is_dir():
|
|
90
|
+
message = f"Path is not a directory: {path}"
|
|
91
|
+
await tool_ctx.error(message)
|
|
92
|
+
return False, f"{error_prefix}: {message}"
|
|
93
|
+
return True, ""
|
|
94
|
+
|
|
95
|
+
def create_tool_context(self, ctx: MCPContext) -> ToolContext:
|
|
96
|
+
"""Create a tool context with the tool name.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
ctx: MCP context
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Tool context
|
|
103
|
+
"""
|
|
104
|
+
tool_ctx = create_tool_context(ctx)
|
|
105
|
+
return tool_ctx
|
|
106
|
+
|
|
107
|
+
def set_tool_context_info(self, tool_ctx: ToolContext) -> None:
|
|
108
|
+
"""Set the tool info on the context.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
tool_ctx: Tool context
|
|
112
|
+
"""
|
|
113
|
+
tool_ctx.set_tool_info(self.name)
|