hanzo-mcp 0.7.7__py3-none-any.whl → 0.8.1__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 +6 -0
- hanzo_mcp/__main__.py +1 -1
- hanzo_mcp/analytics/__init__.py +2 -2
- hanzo_mcp/analytics/posthog_analytics.py +76 -82
- hanzo_mcp/cli.py +31 -36
- hanzo_mcp/cli_enhanced.py +94 -72
- hanzo_mcp/cli_plugin.py +27 -17
- hanzo_mcp/config/__init__.py +2 -2
- hanzo_mcp/config/settings.py +112 -88
- hanzo_mcp/config/tool_config.py +32 -34
- hanzo_mcp/dev_server.py +66 -67
- hanzo_mcp/prompts/__init__.py +94 -12
- hanzo_mcp/prompts/enhanced_prompts.py +809 -0
- hanzo_mcp/prompts/example_custom_prompt.py +6 -5
- hanzo_mcp/prompts/project_todo_reminder.py +0 -1
- hanzo_mcp/prompts/tool_explorer.py +10 -7
- hanzo_mcp/server.py +17 -21
- hanzo_mcp/server_enhanced.py +15 -22
- hanzo_mcp/tools/__init__.py +56 -28
- hanzo_mcp/tools/agent/__init__.py +16 -19
- hanzo_mcp/tools/agent/agent.py +82 -65
- hanzo_mcp/tools/agent/agent_tool.py +152 -122
- hanzo_mcp/tools/agent/agent_tool_v1_deprecated.py +66 -62
- hanzo_mcp/tools/agent/clarification_protocol.py +55 -50
- hanzo_mcp/tools/agent/clarification_tool.py +11 -10
- hanzo_mcp/tools/agent/claude_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/claude_desktop_auth.py +130 -144
- hanzo_mcp/tools/agent/cli_agent_base.py +59 -53
- hanzo_mcp/tools/agent/code_auth.py +102 -107
- hanzo_mcp/tools/agent/code_auth_tool.py +28 -27
- hanzo_mcp/tools/agent/codex_cli_tool.py +20 -19
- hanzo_mcp/tools/agent/critic_tool.py +86 -73
- hanzo_mcp/tools/agent/gemini_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/grok_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/iching_tool.py +404 -139
- hanzo_mcp/tools/agent/network_tool.py +89 -73
- hanzo_mcp/tools/agent/prompt.py +2 -1
- hanzo_mcp/tools/agent/review_tool.py +101 -98
- hanzo_mcp/tools/agent/swarm_alias.py +87 -0
- hanzo_mcp/tools/agent/swarm_tool.py +246 -161
- hanzo_mcp/tools/agent/swarm_tool_v1_deprecated.py +134 -92
- hanzo_mcp/tools/agent/tool_adapter.py +21 -11
- hanzo_mcp/tools/common/__init__.py +1 -1
- hanzo_mcp/tools/common/base.py +3 -5
- hanzo_mcp/tools/common/batch_tool.py +46 -39
- hanzo_mcp/tools/common/config_tool.py +120 -84
- hanzo_mcp/tools/common/context.py +1 -5
- hanzo_mcp/tools/common/context_fix.py +5 -3
- hanzo_mcp/tools/common/critic_tool.py +4 -8
- hanzo_mcp/tools/common/decorators.py +58 -56
- hanzo_mcp/tools/common/enhanced_base.py +29 -32
- hanzo_mcp/tools/common/fastmcp_pagination.py +91 -94
- hanzo_mcp/tools/common/forgiving_edit.py +91 -87
- hanzo_mcp/tools/common/mode.py +15 -17
- hanzo_mcp/tools/common/mode_loader.py +27 -24
- hanzo_mcp/tools/common/paginated_base.py +61 -53
- hanzo_mcp/tools/common/paginated_response.py +72 -79
- hanzo_mcp/tools/common/pagination.py +50 -53
- hanzo_mcp/tools/common/permissions.py +4 -4
- hanzo_mcp/tools/common/personality.py +186 -138
- hanzo_mcp/tools/common/plugin_loader.py +54 -54
- hanzo_mcp/tools/common/stats.py +65 -47
- hanzo_mcp/tools/common/test_helpers.py +31 -0
- hanzo_mcp/tools/common/thinking_tool.py +4 -8
- hanzo_mcp/tools/common/tool_disable.py +17 -12
- hanzo_mcp/tools/common/tool_enable.py +13 -14
- hanzo_mcp/tools/common/tool_list.py +36 -28
- hanzo_mcp/tools/common/truncate.py +23 -23
- hanzo_mcp/tools/config/__init__.py +4 -4
- hanzo_mcp/tools/config/config_tool.py +42 -29
- hanzo_mcp/tools/config/index_config.py +37 -34
- hanzo_mcp/tools/config/mode_tool.py +175 -55
- hanzo_mcp/tools/database/__init__.py +15 -12
- hanzo_mcp/tools/database/database_manager.py +77 -75
- hanzo_mcp/tools/database/graph.py +137 -91
- hanzo_mcp/tools/database/graph_add.py +30 -18
- hanzo_mcp/tools/database/graph_query.py +178 -102
- hanzo_mcp/tools/database/graph_remove.py +33 -28
- hanzo_mcp/tools/database/graph_search.py +97 -75
- hanzo_mcp/tools/database/graph_stats.py +91 -59
- hanzo_mcp/tools/database/sql.py +107 -79
- hanzo_mcp/tools/database/sql_query.py +30 -24
- hanzo_mcp/tools/database/sql_search.py +29 -25
- hanzo_mcp/tools/database/sql_stats.py +47 -35
- hanzo_mcp/tools/editor/neovim_command.py +25 -28
- hanzo_mcp/tools/editor/neovim_edit.py +21 -23
- hanzo_mcp/tools/editor/neovim_session.py +60 -54
- hanzo_mcp/tools/filesystem/__init__.py +31 -30
- hanzo_mcp/tools/filesystem/ast_multi_edit.py +329 -249
- hanzo_mcp/tools/filesystem/ast_tool.py +4 -4
- hanzo_mcp/tools/filesystem/base.py +1 -1
- hanzo_mcp/tools/filesystem/batch_search.py +316 -224
- hanzo_mcp/tools/filesystem/content_replace.py +4 -4
- hanzo_mcp/tools/filesystem/diff.py +71 -59
- hanzo_mcp/tools/filesystem/directory_tree.py +7 -7
- hanzo_mcp/tools/filesystem/directory_tree_paginated.py +49 -37
- hanzo_mcp/tools/filesystem/edit.py +4 -4
- hanzo_mcp/tools/filesystem/find.py +173 -80
- hanzo_mcp/tools/filesystem/find_files.py +73 -52
- hanzo_mcp/tools/filesystem/git_search.py +157 -104
- hanzo_mcp/tools/filesystem/grep.py +8 -8
- hanzo_mcp/tools/filesystem/multi_edit.py +4 -8
- hanzo_mcp/tools/filesystem/read.py +12 -10
- hanzo_mcp/tools/filesystem/rules_tool.py +59 -43
- hanzo_mcp/tools/filesystem/search_tool.py +263 -207
- hanzo_mcp/tools/filesystem/symbols_tool.py +94 -54
- hanzo_mcp/tools/filesystem/tree.py +35 -33
- hanzo_mcp/tools/filesystem/unix_aliases.py +13 -18
- hanzo_mcp/tools/filesystem/watch.py +37 -36
- hanzo_mcp/tools/filesystem/write.py +4 -8
- hanzo_mcp/tools/jupyter/__init__.py +4 -4
- hanzo_mcp/tools/jupyter/base.py +4 -5
- hanzo_mcp/tools/jupyter/jupyter.py +67 -47
- hanzo_mcp/tools/jupyter/notebook_edit.py +4 -4
- hanzo_mcp/tools/jupyter/notebook_read.py +4 -7
- hanzo_mcp/tools/llm/__init__.py +5 -7
- hanzo_mcp/tools/llm/consensus_tool.py +72 -52
- hanzo_mcp/tools/llm/llm_manage.py +101 -60
- hanzo_mcp/tools/llm/llm_tool.py +226 -166
- hanzo_mcp/tools/llm/provider_tools.py +25 -26
- hanzo_mcp/tools/lsp/__init__.py +1 -1
- hanzo_mcp/tools/lsp/lsp_tool.py +228 -143
- hanzo_mcp/tools/mcp/__init__.py +2 -3
- hanzo_mcp/tools/mcp/mcp_add.py +27 -25
- hanzo_mcp/tools/mcp/mcp_remove.py +7 -8
- hanzo_mcp/tools/mcp/mcp_stats.py +23 -22
- hanzo_mcp/tools/mcp/mcp_tool.py +129 -98
- hanzo_mcp/tools/memory/__init__.py +39 -21
- hanzo_mcp/tools/memory/knowledge_tools.py +124 -99
- hanzo_mcp/tools/memory/memory_tools.py +90 -108
- hanzo_mcp/tools/search/__init__.py +7 -2
- hanzo_mcp/tools/search/find_tool.py +297 -212
- hanzo_mcp/tools/search/unified_search.py +366 -314
- hanzo_mcp/tools/shell/__init__.py +8 -7
- hanzo_mcp/tools/shell/auto_background.py +56 -49
- hanzo_mcp/tools/shell/base.py +1 -1
- hanzo_mcp/tools/shell/base_process.py +75 -75
- hanzo_mcp/tools/shell/bash_session.py +2 -2
- hanzo_mcp/tools/shell/bash_session_executor.py +4 -4
- hanzo_mcp/tools/shell/bash_tool.py +24 -31
- hanzo_mcp/tools/shell/command_executor.py +12 -12
- hanzo_mcp/tools/shell/logs.py +43 -33
- hanzo_mcp/tools/shell/npx.py +13 -13
- hanzo_mcp/tools/shell/npx_background.py +24 -21
- hanzo_mcp/tools/shell/npx_tool.py +18 -22
- hanzo_mcp/tools/shell/open.py +19 -21
- hanzo_mcp/tools/shell/pkill.py +31 -26
- hanzo_mcp/tools/shell/process_tool.py +32 -32
- hanzo_mcp/tools/shell/processes.py +57 -58
- hanzo_mcp/tools/shell/run_background.py +24 -25
- hanzo_mcp/tools/shell/run_command.py +5 -5
- hanzo_mcp/tools/shell/run_command_windows.py +5 -5
- hanzo_mcp/tools/shell/session_storage.py +3 -3
- hanzo_mcp/tools/shell/streaming_command.py +141 -126
- hanzo_mcp/tools/shell/uvx.py +24 -25
- hanzo_mcp/tools/shell/uvx_background.py +35 -33
- hanzo_mcp/tools/shell/uvx_tool.py +18 -22
- hanzo_mcp/tools/todo/__init__.py +6 -2
- hanzo_mcp/tools/todo/todo.py +50 -37
- hanzo_mcp/tools/todo/todo_read.py +5 -8
- hanzo_mcp/tools/todo/todo_write.py +5 -7
- hanzo_mcp/tools/vector/__init__.py +40 -28
- hanzo_mcp/tools/vector/ast_analyzer.py +176 -143
- hanzo_mcp/tools/vector/git_ingester.py +170 -179
- hanzo_mcp/tools/vector/index_tool.py +96 -44
- hanzo_mcp/tools/vector/infinity_store.py +283 -228
- hanzo_mcp/tools/vector/mock_infinity.py +39 -40
- hanzo_mcp/tools/vector/project_manager.py +88 -78
- hanzo_mcp/tools/vector/vector.py +59 -42
- hanzo_mcp/tools/vector/vector_index.py +30 -27
- hanzo_mcp/tools/vector/vector_search.py +64 -45
- hanzo_mcp/types.py +6 -4
- {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/METADATA +1 -1
- hanzo_mcp-0.8.1.dist-info/RECORD +185 -0
- hanzo_mcp-0.7.7.dist-info/RECORD +0 -182
- {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/WHEEL +0 -0
- {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/entry_points.txt +0 -0
- {hanzo_mcp-0.7.7.dist-info → hanzo_mcp-0.8.1.dist-info}/top_level.txt +0 -0
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
"""Index tool for managing vector store indexing."""
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
import os
|
|
5
4
|
import time
|
|
5
|
+
from typing import Unpack, Annotated, TypedDict, final, override
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Annotated, TypedDict, Unpack, final, override
|
|
8
7
|
|
|
9
|
-
from mcp.server.fastmcp import Context as MCPContext
|
|
10
8
|
from pydantic import Field
|
|
9
|
+
from mcp.server.fastmcp import Context as MCPContext
|
|
11
10
|
|
|
12
11
|
from hanzo_mcp.tools.common.base import BaseTool
|
|
13
12
|
from hanzo_mcp.tools.common.context import create_tool_context
|
|
14
13
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
15
14
|
from hanzo_mcp.tools.vector.git_ingester import GitIngester
|
|
16
|
-
from hanzo_mcp.tools.vector.infinity_store import InfinityVectorStore
|
|
17
15
|
from hanzo_mcp.tools.vector.project_manager import ProjectVectorManager
|
|
18
16
|
|
|
19
|
-
|
|
20
17
|
Path_str = Annotated[
|
|
21
18
|
str,
|
|
22
19
|
Field(
|
|
@@ -135,7 +132,7 @@ Usage:
|
|
|
135
132
|
|
|
136
133
|
# Resolve absolute path
|
|
137
134
|
abs_path = os.path.abspath(path)
|
|
138
|
-
|
|
135
|
+
|
|
139
136
|
# Check permissions
|
|
140
137
|
if not self.permission_manager.has_permission(abs_path):
|
|
141
138
|
return f"Permission denied: {abs_path}"
|
|
@@ -149,32 +146,76 @@ Usage:
|
|
|
149
146
|
try:
|
|
150
147
|
# Get or create vector store for this project
|
|
151
148
|
vector_store = self.project_manager.get_project_store(abs_path)
|
|
152
|
-
|
|
149
|
+
|
|
153
150
|
# Check if already indexed (unless force)
|
|
154
151
|
if not force:
|
|
155
152
|
stats = await vector_store.get_stats()
|
|
156
153
|
if stats and stats.get("document_count", 0) > 0:
|
|
157
|
-
await tool_ctx.info(
|
|
154
|
+
await tool_ctx.info(
|
|
155
|
+
"Project already indexed, use --force to re-index"
|
|
156
|
+
)
|
|
158
157
|
if show_stats:
|
|
159
|
-
return self._format_stats(
|
|
158
|
+
return self._format_stats(
|
|
159
|
+
stats, abs_path, time.time() - start_time
|
|
160
|
+
)
|
|
160
161
|
return "Project is already indexed. Use --force to re-index."
|
|
161
162
|
|
|
162
163
|
# Prepare file patterns
|
|
163
164
|
if file_patterns is None:
|
|
164
165
|
# Default patterns for code files
|
|
165
166
|
file_patterns = [
|
|
166
|
-
"*.py",
|
|
167
|
-
"*.
|
|
168
|
-
"*.
|
|
169
|
-
"*.
|
|
170
|
-
"*.
|
|
171
|
-
"*.
|
|
172
|
-
"*.
|
|
173
|
-
"*.
|
|
174
|
-
"*.
|
|
175
|
-
"
|
|
176
|
-
"
|
|
177
|
-
"
|
|
167
|
+
"*.py",
|
|
168
|
+
"*.js",
|
|
169
|
+
"*.ts",
|
|
170
|
+
"*.jsx",
|
|
171
|
+
"*.tsx",
|
|
172
|
+
"*.java",
|
|
173
|
+
"*.cpp",
|
|
174
|
+
"*.c",
|
|
175
|
+
"*.h",
|
|
176
|
+
"*.hpp",
|
|
177
|
+
"*.go",
|
|
178
|
+
"*.rs",
|
|
179
|
+
"*.rb",
|
|
180
|
+
"*.php",
|
|
181
|
+
"*.swift",
|
|
182
|
+
"*.kt",
|
|
183
|
+
"*.scala",
|
|
184
|
+
"*.cs",
|
|
185
|
+
"*.vb",
|
|
186
|
+
"*.fs",
|
|
187
|
+
"*.sh",
|
|
188
|
+
"*.bash",
|
|
189
|
+
"*.zsh",
|
|
190
|
+
"*.fish",
|
|
191
|
+
"*.md",
|
|
192
|
+
"*.rst",
|
|
193
|
+
"*.txt",
|
|
194
|
+
"*.json",
|
|
195
|
+
"*.yaml",
|
|
196
|
+
"*.yml",
|
|
197
|
+
"*.toml",
|
|
198
|
+
"*.ini",
|
|
199
|
+
"*.cfg",
|
|
200
|
+
"*.conf",
|
|
201
|
+
"*.html",
|
|
202
|
+
"*.css",
|
|
203
|
+
"*.scss",
|
|
204
|
+
"*.sass",
|
|
205
|
+
"*.less",
|
|
206
|
+
"*.sql",
|
|
207
|
+
"*.graphql",
|
|
208
|
+
"*.proto",
|
|
209
|
+
"Dockerfile",
|
|
210
|
+
"Makefile",
|
|
211
|
+
"*.mk",
|
|
212
|
+
".gitignore",
|
|
213
|
+
".dockerignore",
|
|
214
|
+
"requirements.txt",
|
|
215
|
+
"package.json",
|
|
216
|
+
"Cargo.toml",
|
|
217
|
+
"go.mod",
|
|
218
|
+
"pom.xml",
|
|
178
219
|
]
|
|
179
220
|
|
|
180
221
|
# Clear existing index if force
|
|
@@ -216,7 +257,7 @@ Usage:
|
|
|
216
257
|
"absolute_path": file_path,
|
|
217
258
|
"size": file_size,
|
|
218
259
|
"extension": Path(file_path).suffix,
|
|
219
|
-
}
|
|
260
|
+
},
|
|
220
261
|
)
|
|
221
262
|
indexed_files += 1
|
|
222
263
|
total_size += file_size
|
|
@@ -227,13 +268,15 @@ Usage:
|
|
|
227
268
|
except Exception as e:
|
|
228
269
|
errors.append(f"{file_path}: {str(e)}")
|
|
229
270
|
|
|
230
|
-
await tool_ctx.info(
|
|
271
|
+
await tool_ctx.info(
|
|
272
|
+
f"Indexed {indexed_files} files ({total_size / 1024 / 1024:.1f} MB)"
|
|
273
|
+
)
|
|
231
274
|
|
|
232
275
|
# Index git history if requested
|
|
233
276
|
git_stats = {}
|
|
234
277
|
if include_git_history and os.path.exists(os.path.join(abs_path, ".git")):
|
|
235
278
|
await tool_ctx.info("Indexing git history...")
|
|
236
|
-
|
|
279
|
+
|
|
237
280
|
git_ingester = GitIngester(vector_store)
|
|
238
281
|
git_stats = await git_ingester.ingest_repository(
|
|
239
282
|
repo_path=abs_path,
|
|
@@ -242,29 +285,30 @@ Usage:
|
|
|
242
285
|
include_blame=True,
|
|
243
286
|
file_patterns=file_patterns,
|
|
244
287
|
)
|
|
245
|
-
|
|
288
|
+
|
|
246
289
|
await tool_ctx.info(
|
|
247
|
-
f"Indexed {git_stats.get('commits_indexed', 0)} commits, "
|
|
248
|
-
f"{git_stats.get('diffs_indexed', 0)} diffs"
|
|
290
|
+
f"Indexed {git_stats.get('commits_indexed', 0)} commits, {git_stats.get('diffs_indexed', 0)} diffs"
|
|
249
291
|
)
|
|
250
292
|
|
|
251
293
|
# Get final statistics
|
|
252
294
|
if show_stats:
|
|
253
295
|
stats = await vector_store.get_stats()
|
|
254
|
-
stats.update(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
296
|
+
stats.update(
|
|
297
|
+
{
|
|
298
|
+
"files_indexed": indexed_files,
|
|
299
|
+
"total_size_mb": total_size / 1024 / 1024,
|
|
300
|
+
"errors": len(errors),
|
|
301
|
+
**git_stats,
|
|
302
|
+
}
|
|
303
|
+
)
|
|
260
304
|
result = self._format_stats(stats, abs_path, time.time() - start_time)
|
|
261
|
-
|
|
305
|
+
|
|
262
306
|
if errors:
|
|
263
307
|
result += f"\n\nErrors ({len(errors)}):\n"
|
|
264
308
|
result += "\n".join(errors[:10]) # Show first 10 errors
|
|
265
309
|
if len(errors) > 10:
|
|
266
310
|
result += f"\n... and {len(errors) - 10} more errors"
|
|
267
|
-
|
|
311
|
+
|
|
268
312
|
return result
|
|
269
313
|
else:
|
|
270
314
|
return f"Successfully indexed {indexed_files} files"
|
|
@@ -301,8 +345,16 @@ Usage:
|
|
|
301
345
|
|
|
302
346
|
# Filter out hidden directories and common ignore patterns
|
|
303
347
|
filtered_files = []
|
|
304
|
-
ignore_dirs = {
|
|
305
|
-
|
|
348
|
+
ignore_dirs = {
|
|
349
|
+
".git",
|
|
350
|
+
"__pycache__",
|
|
351
|
+
"node_modules",
|
|
352
|
+
".venv",
|
|
353
|
+
"venv",
|
|
354
|
+
"dist",
|
|
355
|
+
"build",
|
|
356
|
+
}
|
|
357
|
+
|
|
306
358
|
for file_path in files:
|
|
307
359
|
# Check if any parent directory is in ignore list
|
|
308
360
|
parts = Path(file_path).parts
|
|
@@ -326,33 +378,33 @@ Usage:
|
|
|
326
378
|
Formatted statistics string
|
|
327
379
|
"""
|
|
328
380
|
result = f"=== Index Statistics for {path} ===\n\n"
|
|
329
|
-
|
|
381
|
+
|
|
330
382
|
# Basic stats
|
|
331
383
|
result += f"Indexing completed in {elapsed_time:.1f} seconds\n\n"
|
|
332
|
-
|
|
384
|
+
|
|
333
385
|
result += "Content Statistics:\n"
|
|
334
386
|
result += f" Documents: {stats.get('document_count', 0):,}\n"
|
|
335
387
|
result += f" Files indexed: {stats.get('files_indexed', 0):,}\n"
|
|
336
388
|
result += f" Total size: {stats.get('total_size_mb', 0):.1f} MB\n"
|
|
337
|
-
|
|
389
|
+
|
|
338
390
|
if stats.get("commits_indexed", 0) > 0:
|
|
339
391
|
result += f"\nGit History:\n"
|
|
340
392
|
result += f" Commits: {stats.get('commits_indexed', 0):,}\n"
|
|
341
393
|
result += f" Diffs: {stats.get('diffs_indexed', 0):,}\n"
|
|
342
394
|
result += f" Blame entries: {stats.get('blame_entries', 0):,}\n"
|
|
343
|
-
|
|
395
|
+
|
|
344
396
|
# Vector store info
|
|
345
397
|
result += f"\nVector Store:\n"
|
|
346
398
|
result += f" Database: {stats.get('database_name', 'default')}\n"
|
|
347
399
|
result += f" Table: {stats.get('table_name', 'documents')}\n"
|
|
348
400
|
result += f" Vectors: {stats.get('vector_count', stats.get('document_count', 0)):,}\n"
|
|
349
|
-
|
|
401
|
+
|
|
350
402
|
if stats.get("errors", 0) > 0:
|
|
351
403
|
result += f"\nErrors: {stats.get('errors', 0)}\n"
|
|
352
|
-
|
|
404
|
+
|
|
353
405
|
return result
|
|
354
406
|
|
|
355
407
|
def register(self, mcp_server) -> None:
|
|
356
408
|
"""Register this tool with the MCP server."""
|
|
357
409
|
# Tool registration is handled by the ToolRegistry
|
|
358
|
-
pass
|
|
410
|
+
pass
|