tree-sitter-analyzer 1.7.3__py3-none-any.whl → 1.7.5__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 tree-sitter-analyzer might be problematic. Click here for more details.
- tree_sitter_analyzer/__init__.py +1 -1
- tree_sitter_analyzer/core/query_service.py +13 -3
- tree_sitter_analyzer/formatters/markdown_formatter.py +140 -9
- tree_sitter_analyzer/languages/markdown_plugin.py +148 -22
- tree_sitter_analyzer/mcp/server.py +5 -74
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +8 -18
- tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +1 -1
- tree_sitter_analyzer/mcp/tools/list_files_tool.py +1 -1
- tree_sitter_analyzer/mcp/tools/query_tool.py +86 -3
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py +91 -23
- tree_sitter_analyzer/mcp/tools/search_content_tool.py +1 -1
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +7 -17
- tree_sitter_analyzer/queries/javascript.py +20 -0
- tree_sitter_analyzer/queries/typescript.py +22 -0
- {tree_sitter_analyzer-1.7.3.dist-info → tree_sitter_analyzer-1.7.5.dist-info}/METADATA +36 -42
- {tree_sitter_analyzer-1.7.3.dist-info → tree_sitter_analyzer-1.7.5.dist-info}/RECORD +18 -18
- {tree_sitter_analyzer-1.7.3.dist-info → tree_sitter_analyzer-1.7.5.dist-info}/WHEEL +0 -0
- {tree_sitter_analyzer-1.7.3.dist-info → tree_sitter_analyzer-1.7.5.dist-info}/entry_points.txt +0 -0
|
@@ -446,80 +446,9 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
446
446
|
logger.info("Client requesting tools list")
|
|
447
447
|
|
|
448
448
|
tools = [
|
|
449
|
-
Tool(
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
inputSchema={
|
|
453
|
-
"type": "object",
|
|
454
|
-
"properties": {
|
|
455
|
-
"file_path": {
|
|
456
|
-
"type": "string",
|
|
457
|
-
"description": "Path to the code file (relative to project root)",
|
|
458
|
-
}
|
|
459
|
-
},
|
|
460
|
-
"required": ["file_path"],
|
|
461
|
-
"additionalProperties": False,
|
|
462
|
-
},
|
|
463
|
-
),
|
|
464
|
-
Tool(
|
|
465
|
-
name="analyze_code_structure",
|
|
466
|
-
description="Analyze code structure and generate tables with line positions, optionally save to file",
|
|
467
|
-
inputSchema={
|
|
468
|
-
"type": "object",
|
|
469
|
-
"properties": {
|
|
470
|
-
"file_path": {
|
|
471
|
-
"type": "string",
|
|
472
|
-
"description": "Path to the code file (relative to project root)",
|
|
473
|
-
},
|
|
474
|
-
"format_type": {
|
|
475
|
-
"type": "string",
|
|
476
|
-
"description": "Table format type",
|
|
477
|
-
"enum": ["full", "compact", "csv", "json"],
|
|
478
|
-
"default": "full",
|
|
479
|
-
},
|
|
480
|
-
"language": {
|
|
481
|
-
"type": "string",
|
|
482
|
-
"description": "Programming language (optional, auto-detected if not specified)",
|
|
483
|
-
},
|
|
484
|
-
"output_file": {
|
|
485
|
-
"type": "string",
|
|
486
|
-
"description": "Optional filename to save output to file (extension auto-detected based on content)",
|
|
487
|
-
},
|
|
488
|
-
"suppress_output": {
|
|
489
|
-
"type": "boolean",
|
|
490
|
-
"description": "When true and output_file is specified, suppress table_output in response to save tokens",
|
|
491
|
-
"default": False,
|
|
492
|
-
},
|
|
493
|
-
},
|
|
494
|
-
"required": ["file_path"],
|
|
495
|
-
"additionalProperties": False,
|
|
496
|
-
},
|
|
497
|
-
),
|
|
498
|
-
Tool(
|
|
499
|
-
name="extract_code_section",
|
|
500
|
-
description="Extract a code section by line range",
|
|
501
|
-
inputSchema={
|
|
502
|
-
"type": "object",
|
|
503
|
-
"properties": {
|
|
504
|
-
"file_path": {
|
|
505
|
-
"type": "string",
|
|
506
|
-
"description": "Path to the code file (relative to project root)",
|
|
507
|
-
},
|
|
508
|
-
"start_line": {
|
|
509
|
-
"type": "integer",
|
|
510
|
-
"description": "Start line (1-based)",
|
|
511
|
-
"minimum": 1,
|
|
512
|
-
},
|
|
513
|
-
"end_line": {
|
|
514
|
-
"type": "integer",
|
|
515
|
-
"description": "End line (optional, 1-based)",
|
|
516
|
-
"minimum": 1,
|
|
517
|
-
},
|
|
518
|
-
},
|
|
519
|
-
"required": ["file_path", "start_line"],
|
|
520
|
-
"additionalProperties": False,
|
|
521
|
-
},
|
|
522
|
-
),
|
|
449
|
+
Tool(**self.analyze_scale_tool.get_tool_definition()),
|
|
450
|
+
Tool(**self.table_format_tool.get_tool_definition()),
|
|
451
|
+
Tool(**self.read_partial_tool.get_tool_definition()),
|
|
523
452
|
Tool(
|
|
524
453
|
name="set_project_path",
|
|
525
454
|
description="Set or override the project root path used for security boundaries",
|
|
@@ -603,6 +532,8 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
603
532
|
"start_column": arguments.get("start_column"),
|
|
604
533
|
"end_column": arguments.get("end_column"),
|
|
605
534
|
"format": arguments.get("format", "text"),
|
|
535
|
+
"output_file": arguments.get("output_file"),
|
|
536
|
+
"suppress_output": arguments.get("suppress_output", False),
|
|
606
537
|
}
|
|
607
538
|
result = await self.read_partial_tool.execute(full_args)
|
|
608
539
|
|
|
@@ -688,28 +688,18 @@ class AnalyzeScaleTool(BaseMCPTool):
|
|
|
688
688
|
|
|
689
689
|
return True
|
|
690
690
|
|
|
691
|
-
def get_tool_definition(self) -> Any:
|
|
691
|
+
def get_tool_definition(self) -> dict[str, Any]:
|
|
692
692
|
"""
|
|
693
|
-
Get the MCP tool definition for
|
|
693
|
+
Get the MCP tool definition for check_code_scale.
|
|
694
694
|
|
|
695
695
|
Returns:
|
|
696
|
-
Tool definition
|
|
696
|
+
Tool definition dictionary compatible with MCP server
|
|
697
697
|
"""
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
description="Analyze code scale, complexity, and structure metrics with LLM-optimized guidance for efficient large file analysis",
|
|
704
|
-
inputSchema=self.get_tool_schema(),
|
|
705
|
-
)
|
|
706
|
-
except ImportError:
|
|
707
|
-
# Fallback for when MCP is not available
|
|
708
|
-
return {
|
|
709
|
-
"name": "analyze_code_scale",
|
|
710
|
-
"description": "Analyze code scale, complexity, and structure metrics with LLM-optimized guidance for efficient large file analysis",
|
|
711
|
-
"inputSchema": self.get_tool_schema(),
|
|
712
|
-
}
|
|
698
|
+
return {
|
|
699
|
+
"name": "check_code_scale",
|
|
700
|
+
"description": "Analyze code scale, complexity, and structure metrics with LLM-optimized guidance for efficient large file analysis and token-aware workflow recommendations",
|
|
701
|
+
"inputSchema": self.get_tool_schema(),
|
|
702
|
+
}
|
|
713
703
|
|
|
714
704
|
|
|
715
705
|
# Tool instance for easy access
|
|
@@ -32,7 +32,7 @@ class FindAndGrepTool(BaseMCPTool):
|
|
|
32
32
|
def get_tool_definition(self) -> dict[str, Any]:
|
|
33
33
|
return {
|
|
34
34
|
"name": "find_and_grep",
|
|
35
|
-
"description": "Two-stage search: first use fd to find files matching criteria, then use ripgrep to search content within those files. Combines file filtering with content search for precise results.",
|
|
35
|
+
"description": "Two-stage search: first use fd to find files matching criteria, then use ripgrep to search content within those files. Combines file filtering with content search for precise results with advanced token optimization (summary_only, group_by_file, total_only, suppress_output).",
|
|
36
36
|
"inputSchema": {
|
|
37
37
|
"type": "object",
|
|
38
38
|
"properties": {
|
|
@@ -27,7 +27,7 @@ class ListFilesTool(BaseMCPTool):
|
|
|
27
27
|
def get_tool_definition(self) -> dict[str, Any]:
|
|
28
28
|
return {
|
|
29
29
|
"name": "list_files",
|
|
30
|
-
"description": "List files and directories using fd with advanced filtering options. Supports glob patterns, file types, size filters, and more. Returns file paths with metadata or just counts.",
|
|
30
|
+
"description": "List files and directories using fd with advanced filtering options. Supports glob patterns, file types, size filters, and more. Returns file paths with metadata or just counts, with optional file output and token optimization.",
|
|
31
31
|
"inputSchema": {
|
|
32
32
|
"type": "object",
|
|
33
33
|
"properties": {
|
|
@@ -7,11 +7,13 @@ Supports both predefined query keys and custom query strings.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import logging
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
from typing import Any
|
|
11
12
|
|
|
12
13
|
from ...core.query_service import QueryService
|
|
13
14
|
from ...language_detector import detect_language_from_file
|
|
14
15
|
from ..utils.error_handler import handle_mcp_errors
|
|
16
|
+
from ..utils.file_output_manager import FileOutputManager
|
|
15
17
|
from .base_tool import BaseMCPTool
|
|
16
18
|
|
|
17
19
|
logger = logging.getLogger(__name__)
|
|
@@ -24,6 +26,7 @@ class QueryTool(BaseMCPTool):
|
|
|
24
26
|
"""Initialize query tool"""
|
|
25
27
|
super().__init__(project_root)
|
|
26
28
|
self.query_service = QueryService(project_root)
|
|
29
|
+
self.file_output_manager = FileOutputManager(project_root)
|
|
27
30
|
|
|
28
31
|
def set_project_path(self, project_path: str) -> None:
|
|
29
32
|
"""
|
|
@@ -34,6 +37,7 @@ class QueryTool(BaseMCPTool):
|
|
|
34
37
|
"""
|
|
35
38
|
super().set_project_path(project_path)
|
|
36
39
|
self.query_service = QueryService(project_path)
|
|
40
|
+
self.file_output_manager.set_project_root(project_path)
|
|
37
41
|
logger.info(f"QueryTool project path updated to: {project_path}")
|
|
38
42
|
|
|
39
43
|
def get_tool_definition(self) -> dict[str, Any]:
|
|
@@ -45,7 +49,7 @@ class QueryTool(BaseMCPTool):
|
|
|
45
49
|
"""
|
|
46
50
|
return {
|
|
47
51
|
"name": "query_code",
|
|
48
|
-
"description": "Execute tree-sitter queries on code files to extract specific code elements",
|
|
52
|
+
"description": "Execute tree-sitter queries on code files to extract specific code elements with filtering, multiple output formats, and optional file saving with token optimization",
|
|
49
53
|
"inputSchema": {
|
|
50
54
|
"type": "object",
|
|
51
55
|
"properties": {
|
|
@@ -75,6 +79,15 @@ class QueryTool(BaseMCPTool):
|
|
|
75
79
|
"default": "json",
|
|
76
80
|
"description": "Output format",
|
|
77
81
|
},
|
|
82
|
+
"output_file": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"description": "Optional filename to save output to file (extension auto-detected based on content)",
|
|
85
|
+
},
|
|
86
|
+
"suppress_output": {
|
|
87
|
+
"type": "boolean",
|
|
88
|
+
"description": "When true and output_file is specified, suppress detailed output in response to save tokens",
|
|
89
|
+
"default": False,
|
|
90
|
+
},
|
|
78
91
|
},
|
|
79
92
|
"required": ["file_path"],
|
|
80
93
|
"anyOf": [
|
|
@@ -118,6 +131,8 @@ class QueryTool(BaseMCPTool):
|
|
|
118
131
|
query_string = arguments.get("query_string")
|
|
119
132
|
filter_expression = arguments.get("filter")
|
|
120
133
|
output_format = arguments.get("output_format", "json")
|
|
134
|
+
output_file = arguments.get("output_file")
|
|
135
|
+
suppress_output = arguments.get("suppress_output", False)
|
|
121
136
|
|
|
122
137
|
if not query_key and not query_string:
|
|
123
138
|
raise ValueError("Either query_key or query_string must be provided")
|
|
@@ -148,9 +163,9 @@ class QueryTool(BaseMCPTool):
|
|
|
148
163
|
|
|
149
164
|
# Format output
|
|
150
165
|
if output_format == "summary":
|
|
151
|
-
|
|
166
|
+
formatted_result = self._format_summary(results, query_key or "custom", language)
|
|
152
167
|
else:
|
|
153
|
-
|
|
168
|
+
formatted_result = {
|
|
154
169
|
"success": True,
|
|
155
170
|
"results": results,
|
|
156
171
|
"count": len(results),
|
|
@@ -159,6 +174,60 @@ class QueryTool(BaseMCPTool):
|
|
|
159
174
|
"query": query_key or query_string,
|
|
160
175
|
}
|
|
161
176
|
|
|
177
|
+
# Handle file output if requested
|
|
178
|
+
if output_file:
|
|
179
|
+
try:
|
|
180
|
+
import json
|
|
181
|
+
|
|
182
|
+
# Generate base name from original file path if not provided
|
|
183
|
+
if not output_file or output_file.strip() == "":
|
|
184
|
+
base_name = f"{Path(file_path).stem}_query_{query_key or 'custom'}"
|
|
185
|
+
else:
|
|
186
|
+
base_name = output_file
|
|
187
|
+
|
|
188
|
+
# Convert result to JSON string for file output
|
|
189
|
+
json_content = json.dumps(formatted_result, indent=2, ensure_ascii=False)
|
|
190
|
+
|
|
191
|
+
# Save to file with automatic extension detection
|
|
192
|
+
saved_file_path = self.file_output_manager.save_to_file(
|
|
193
|
+
content=json_content,
|
|
194
|
+
base_name=base_name
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Add file output info to result
|
|
198
|
+
formatted_result["output_file_path"] = saved_file_path
|
|
199
|
+
formatted_result["file_saved"] = True
|
|
200
|
+
|
|
201
|
+
logger.info(f"Query output saved to: {saved_file_path}")
|
|
202
|
+
|
|
203
|
+
except Exception as e:
|
|
204
|
+
logger.error(f"Failed to save output to file: {e}")
|
|
205
|
+
formatted_result["file_save_error"] = str(e)
|
|
206
|
+
formatted_result["file_saved"] = False
|
|
207
|
+
|
|
208
|
+
# Apply suppress_output logic
|
|
209
|
+
if suppress_output and output_file:
|
|
210
|
+
# Create minimal result when output is suppressed
|
|
211
|
+
minimal_result = {
|
|
212
|
+
"success": formatted_result.get("success", True),
|
|
213
|
+
"count": formatted_result.get("count", len(results)),
|
|
214
|
+
"file_path": file_path,
|
|
215
|
+
"language": language,
|
|
216
|
+
"query": query_key or query_string,
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
# Include file output info if present
|
|
220
|
+
if "output_file_path" in formatted_result:
|
|
221
|
+
minimal_result["output_file_path"] = formatted_result["output_file_path"]
|
|
222
|
+
minimal_result["file_saved"] = formatted_result["file_saved"]
|
|
223
|
+
if "file_save_error" in formatted_result:
|
|
224
|
+
minimal_result["file_save_error"] = formatted_result["file_save_error"]
|
|
225
|
+
minimal_result["file_saved"] = formatted_result["file_saved"]
|
|
226
|
+
|
|
227
|
+
return minimal_result
|
|
228
|
+
else:
|
|
229
|
+
return formatted_result
|
|
230
|
+
|
|
162
231
|
except Exception as e:
|
|
163
232
|
logger.error(f"Query execution failed: {e}")
|
|
164
233
|
return {
|
|
@@ -314,4 +383,18 @@ class QueryTool(BaseMCPTool):
|
|
|
314
383
|
if output_format not in ["json", "summary"]:
|
|
315
384
|
raise ValueError("output_format must be one of: json, summary")
|
|
316
385
|
|
|
386
|
+
# Validate output_file if provided
|
|
387
|
+
if "output_file" in arguments:
|
|
388
|
+
output_file = arguments["output_file"]
|
|
389
|
+
if not isinstance(output_file, str):
|
|
390
|
+
raise ValueError("output_file must be a string")
|
|
391
|
+
if not output_file.strip():
|
|
392
|
+
raise ValueError("output_file cannot be empty")
|
|
393
|
+
|
|
394
|
+
# Validate suppress_output if provided
|
|
395
|
+
if "suppress_output" in arguments:
|
|
396
|
+
suppress_output = arguments["suppress_output"]
|
|
397
|
+
if not isinstance(suppress_output, bool):
|
|
398
|
+
raise ValueError("suppress_output must be a boolean")
|
|
399
|
+
|
|
317
400
|
return True
|
|
@@ -12,6 +12,7 @@ from typing import Any
|
|
|
12
12
|
|
|
13
13
|
from ...file_handler import read_file_partial
|
|
14
14
|
from ...utils import setup_logger
|
|
15
|
+
from ..utils.file_output_manager import FileOutputManager
|
|
15
16
|
from .base_tool import BaseMCPTool
|
|
16
17
|
|
|
17
18
|
# Set up logging
|
|
@@ -29,6 +30,7 @@ class ReadPartialTool(BaseMCPTool):
|
|
|
29
30
|
def __init__(self, project_root: str = None) -> None:
|
|
30
31
|
"""Initialize the read partial tool."""
|
|
31
32
|
super().__init__(project_root)
|
|
33
|
+
self.file_output_manager = FileOutputManager(project_root)
|
|
32
34
|
logger.info("ReadPartialTool initialized with security validation")
|
|
33
35
|
|
|
34
36
|
def get_tool_schema(self) -> dict[str, Any]:
|
|
@@ -68,12 +70,20 @@ class ReadPartialTool(BaseMCPTool):
|
|
|
68
70
|
"format": {
|
|
69
71
|
"type": "string",
|
|
70
72
|
"description": "Output format for the content",
|
|
71
|
-
"enum": ["text", "json"],
|
|
73
|
+
"enum": ["text", "json", "raw"],
|
|
72
74
|
"default": "text",
|
|
73
75
|
},
|
|
76
|
+
"output_file": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "Optional filename to save output to file (extension auto-detected based on content)",
|
|
79
|
+
},
|
|
80
|
+
"suppress_output": {
|
|
81
|
+
"type": "boolean",
|
|
82
|
+
"description": "When true and output_file is specified, suppress partial_content_result in response to save tokens",
|
|
83
|
+
"default": False,
|
|
84
|
+
},
|
|
74
85
|
},
|
|
75
86
|
"required": ["file_path", "start_line"],
|
|
76
|
-
"additionalProperties": False,
|
|
77
87
|
}
|
|
78
88
|
|
|
79
89
|
async def execute(self, arguments: dict[str, Any]) -> dict[str, Any]:
|
|
@@ -102,7 +112,9 @@ class ReadPartialTool(BaseMCPTool):
|
|
|
102
112
|
end_line = arguments.get("end_line")
|
|
103
113
|
start_column = arguments.get("start_column")
|
|
104
114
|
end_column = arguments.get("end_column")
|
|
105
|
-
|
|
115
|
+
output_file = arguments.get("output_file")
|
|
116
|
+
suppress_output = arguments.get("suppress_output", False)
|
|
117
|
+
output_format = arguments.get("format", "text")
|
|
106
118
|
|
|
107
119
|
# Resolve file path using common path resolver
|
|
108
120
|
resolved_path = self.path_resolver.resolve(file_path)
|
|
@@ -186,7 +198,59 @@ class ReadPartialTool(BaseMCPTool):
|
|
|
186
198
|
f"Successfully read {len(content)} characters from {file_path}"
|
|
187
199
|
)
|
|
188
200
|
|
|
189
|
-
|
|
201
|
+
# Build result - conditionally include partial_content_result based on suppress_output
|
|
202
|
+
result = {
|
|
203
|
+
"file_path": file_path,
|
|
204
|
+
"range": {
|
|
205
|
+
"start_line": start_line,
|
|
206
|
+
"end_line": end_line,
|
|
207
|
+
"start_column": start_column,
|
|
208
|
+
"end_column": end_column,
|
|
209
|
+
},
|
|
210
|
+
"content_length": len(content),
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
# Only include partial_content_result if not suppressed or no output file specified
|
|
214
|
+
if not suppress_output or not output_file:
|
|
215
|
+
result["partial_content_result"] = cli_output
|
|
216
|
+
|
|
217
|
+
# Handle file output if requested
|
|
218
|
+
if output_file:
|
|
219
|
+
try:
|
|
220
|
+
# Generate base name from original file path if not provided
|
|
221
|
+
if not output_file or output_file.strip() == "":
|
|
222
|
+
base_name = Path(file_path).stem + "_extract"
|
|
223
|
+
else:
|
|
224
|
+
base_name = output_file
|
|
225
|
+
|
|
226
|
+
# Determine what content to save based on format preference
|
|
227
|
+
if output_format == "raw":
|
|
228
|
+
# Save only the extracted code content (no metadata)
|
|
229
|
+
content_to_save = content
|
|
230
|
+
elif output_format == "json":
|
|
231
|
+
# Save structured JSON data
|
|
232
|
+
content_to_save = json_output
|
|
233
|
+
else: # format == "text" (default)
|
|
234
|
+
# Save CLI-compatible format with headers
|
|
235
|
+
content_to_save = cli_output
|
|
236
|
+
|
|
237
|
+
# Save to file with automatic extension detection
|
|
238
|
+
saved_file_path = self.file_output_manager.save_to_file(
|
|
239
|
+
content=content_to_save,
|
|
240
|
+
base_name=base_name
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
result["output_file_path"] = saved_file_path
|
|
244
|
+
result["file_saved"] = True
|
|
245
|
+
|
|
246
|
+
logger.info(f"Extract output saved to: {saved_file_path}")
|
|
247
|
+
|
|
248
|
+
except Exception as e:
|
|
249
|
+
logger.error(f"Failed to save output to file: {e}")
|
|
250
|
+
result["file_save_error"] = str(e)
|
|
251
|
+
result["file_saved"] = False
|
|
252
|
+
|
|
253
|
+
return result
|
|
190
254
|
|
|
191
255
|
except Exception as e:
|
|
192
256
|
logger.error(f"Error reading partial content from {file_path}: {e}")
|
|
@@ -280,33 +344,37 @@ class ReadPartialTool(BaseMCPTool):
|
|
|
280
344
|
format_value = arguments["format"]
|
|
281
345
|
if not isinstance(format_value, str):
|
|
282
346
|
raise ValueError("format must be a string")
|
|
283
|
-
if format_value not in ["text", "json"]:
|
|
284
|
-
raise ValueError("format must be 'text' or '
|
|
347
|
+
if format_value not in ["text", "json", "raw"]:
|
|
348
|
+
raise ValueError("format must be 'text', 'json', or 'raw'")
|
|
349
|
+
|
|
350
|
+
# Validate output_file if provided
|
|
351
|
+
if "output_file" in arguments:
|
|
352
|
+
output_file = arguments["output_file"]
|
|
353
|
+
if not isinstance(output_file, str):
|
|
354
|
+
raise ValueError("output_file must be a string")
|
|
355
|
+
if not output_file.strip():
|
|
356
|
+
raise ValueError("output_file cannot be empty")
|
|
357
|
+
|
|
358
|
+
# Validate suppress_output if provided
|
|
359
|
+
if "suppress_output" in arguments:
|
|
360
|
+
suppress_output = arguments["suppress_output"]
|
|
361
|
+
if not isinstance(suppress_output, bool):
|
|
362
|
+
raise ValueError("suppress_output must be a boolean")
|
|
285
363
|
|
|
286
364
|
return True
|
|
287
365
|
|
|
288
|
-
def get_tool_definition(self) -> Any:
|
|
366
|
+
def get_tool_definition(self) -> dict[str, Any]:
|
|
289
367
|
"""
|
|
290
368
|
Get the MCP tool definition for read_code_partial.
|
|
291
369
|
|
|
292
370
|
Returns:
|
|
293
|
-
Tool definition
|
|
371
|
+
Tool definition dictionary compatible with MCP server
|
|
294
372
|
"""
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
description="Extract specific code sections by line range (equivalent to CLI --partial-read option)",
|
|
301
|
-
inputSchema=self.get_tool_schema(),
|
|
302
|
-
)
|
|
303
|
-
except ImportError:
|
|
304
|
-
# Fallback for when MCP is not available
|
|
305
|
-
return {
|
|
306
|
-
"name": "extract_code_section",
|
|
307
|
-
"description": "Extract specific code sections by line range (equivalent to CLI --partial-read option)",
|
|
308
|
-
"inputSchema": self.get_tool_schema(),
|
|
309
|
-
}
|
|
373
|
+
return {
|
|
374
|
+
"name": "extract_code_section",
|
|
375
|
+
"description": "Extract specific code sections by line/column range with multiple output formats (text/json/raw), optionally save to file with token optimization",
|
|
376
|
+
"inputSchema": self.get_tool_schema(),
|
|
377
|
+
}
|
|
310
378
|
|
|
311
379
|
|
|
312
380
|
# Tool instance for easy access
|
|
@@ -42,7 +42,7 @@ class SearchContentTool(BaseMCPTool):
|
|
|
42
42
|
def get_tool_definition(self) -> dict[str, Any]:
|
|
43
43
|
return {
|
|
44
44
|
"name": "search_content",
|
|
45
|
-
"description": "Search text content inside files using ripgrep. Supports regex patterns, case sensitivity, context lines, and various output formats. Can search in directories or specific files.",
|
|
45
|
+
"description": "Search text content inside files using ripgrep. Supports regex patterns, case sensitivity, context lines, and various output formats. Can search in directories or specific files with advanced token optimization (summary_only, group_by_file, total_only, suppress_output).",
|
|
46
46
|
"inputSchema": {
|
|
47
47
|
"type": "object",
|
|
48
48
|
"properties": {
|
|
@@ -511,28 +511,18 @@ class TableFormatTool(BaseMCPTool):
|
|
|
511
511
|
self.logger.error(f"Error in code structure analysis tool: {e}")
|
|
512
512
|
raise
|
|
513
513
|
|
|
514
|
-
def get_tool_definition(self) -> Any:
|
|
514
|
+
def get_tool_definition(self) -> dict[str, Any]:
|
|
515
515
|
"""
|
|
516
516
|
Get the MCP tool definition for analyze_code_structure.
|
|
517
517
|
|
|
518
518
|
Returns:
|
|
519
|
-
Tool definition
|
|
519
|
+
Tool definition dictionary compatible with MCP server
|
|
520
520
|
"""
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
description="Analyze code structure and generate detailed overview tables (classes, methods, fields) for large files",
|
|
527
|
-
inputSchema=self.get_tool_schema(),
|
|
528
|
-
)
|
|
529
|
-
except ImportError:
|
|
530
|
-
# Fallback for when MCP is not available
|
|
531
|
-
return {
|
|
532
|
-
"name": "analyze_code_structure",
|
|
533
|
-
"description": "Analyze code structure and generate detailed overview tables (classes, methods, fields) for large files",
|
|
534
|
-
"inputSchema": self.get_tool_schema(),
|
|
535
|
-
}
|
|
521
|
+
return {
|
|
522
|
+
"name": "analyze_code_structure",
|
|
523
|
+
"description": "Analyze code structure and generate detailed overview tables (classes, methods, fields) with line positions for large files, optionally save to file",
|
|
524
|
+
"inputSchema": self.get_tool_schema(),
|
|
525
|
+
}
|
|
536
526
|
|
|
537
527
|
|
|
538
528
|
# Tool instance for easy access
|
|
@@ -644,6 +644,26 @@ ALL_QUERIES["objects"] = {
|
|
|
644
644
|
}
|
|
645
645
|
ALL_QUERIES["comments"] = {"query": COMMENTS, "description": "Search all comments"}
|
|
646
646
|
|
|
647
|
+
# Add missing method queries
|
|
648
|
+
ALL_QUERIES["method"] = {
|
|
649
|
+
"query": """
|
|
650
|
+
(method_definition
|
|
651
|
+
name: (property_identifier) @method_name
|
|
652
|
+
parameters: (formal_parameters) @parameters
|
|
653
|
+
body: (statement_block) @body) @method_definition
|
|
654
|
+
""",
|
|
655
|
+
"description": "Search method definitions",
|
|
656
|
+
}
|
|
657
|
+
ALL_QUERIES["methods"] = {
|
|
658
|
+
"query": """
|
|
659
|
+
(method_definition
|
|
660
|
+
name: (property_identifier) @method_name
|
|
661
|
+
parameters: (formal_parameters) @parameters
|
|
662
|
+
body: (statement_block) @body) @method_definition
|
|
663
|
+
""",
|
|
664
|
+
"description": "Search method definitions",
|
|
665
|
+
}
|
|
666
|
+
|
|
647
667
|
|
|
648
668
|
def get_javascript_query(name: str) -> str:
|
|
649
669
|
"""
|
|
@@ -213,6 +213,28 @@ ALL_QUERIES["methods"] = {
|
|
|
213
213
|
"description": "Search all methods declarations (alias for functions)",
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
# Add singular form aliases
|
|
217
|
+
ALL_QUERIES["function"] = {
|
|
218
|
+
"query": FUNCTIONS,
|
|
219
|
+
"description": "Search all functions (alias for functions)",
|
|
220
|
+
}
|
|
221
|
+
ALL_QUERIES["class"] = {
|
|
222
|
+
"query": CLASSES,
|
|
223
|
+
"description": "Search all classes (alias for classes)",
|
|
224
|
+
}
|
|
225
|
+
ALL_QUERIES["interface"] = {
|
|
226
|
+
"query": INTERFACES,
|
|
227
|
+
"description": "Search all interfaces (alias for interfaces)",
|
|
228
|
+
}
|
|
229
|
+
ALL_QUERIES["type"] = {
|
|
230
|
+
"query": TYPE_ALIASES,
|
|
231
|
+
"description": "Search all type aliases (alias for type_aliases)",
|
|
232
|
+
}
|
|
233
|
+
ALL_QUERIES["types"] = {
|
|
234
|
+
"query": TYPE_ALIASES,
|
|
235
|
+
"description": "Search all types (alias for type_aliases)",
|
|
236
|
+
}
|
|
237
|
+
|
|
216
238
|
# Add more specific function queries
|
|
217
239
|
ALL_QUERIES["function_declaration"] = {
|
|
218
240
|
"query": """
|