tree-sitter-analyzer 1.9.17.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.
- tree_sitter_analyzer/__init__.py +132 -0
- tree_sitter_analyzer/__main__.py +11 -0
- tree_sitter_analyzer/api.py +853 -0
- tree_sitter_analyzer/cli/__init__.py +39 -0
- tree_sitter_analyzer/cli/__main__.py +12 -0
- tree_sitter_analyzer/cli/argument_validator.py +89 -0
- tree_sitter_analyzer/cli/commands/__init__.py +26 -0
- tree_sitter_analyzer/cli/commands/advanced_command.py +226 -0
- tree_sitter_analyzer/cli/commands/base_command.py +181 -0
- tree_sitter_analyzer/cli/commands/default_command.py +18 -0
- tree_sitter_analyzer/cli/commands/find_and_grep_cli.py +188 -0
- tree_sitter_analyzer/cli/commands/list_files_cli.py +133 -0
- tree_sitter_analyzer/cli/commands/partial_read_command.py +139 -0
- tree_sitter_analyzer/cli/commands/query_command.py +109 -0
- tree_sitter_analyzer/cli/commands/search_content_cli.py +161 -0
- tree_sitter_analyzer/cli/commands/structure_command.py +156 -0
- tree_sitter_analyzer/cli/commands/summary_command.py +116 -0
- tree_sitter_analyzer/cli/commands/table_command.py +414 -0
- tree_sitter_analyzer/cli/info_commands.py +124 -0
- tree_sitter_analyzer/cli_main.py +472 -0
- tree_sitter_analyzer/constants.py +85 -0
- tree_sitter_analyzer/core/__init__.py +15 -0
- tree_sitter_analyzer/core/analysis_engine.py +580 -0
- tree_sitter_analyzer/core/cache_service.py +333 -0
- tree_sitter_analyzer/core/engine.py +585 -0
- tree_sitter_analyzer/core/parser.py +293 -0
- tree_sitter_analyzer/core/query.py +605 -0
- tree_sitter_analyzer/core/query_filter.py +200 -0
- tree_sitter_analyzer/core/query_service.py +340 -0
- tree_sitter_analyzer/encoding_utils.py +530 -0
- tree_sitter_analyzer/exceptions.py +747 -0
- tree_sitter_analyzer/file_handler.py +246 -0
- tree_sitter_analyzer/formatters/__init__.py +1 -0
- tree_sitter_analyzer/formatters/base_formatter.py +201 -0
- tree_sitter_analyzer/formatters/csharp_formatter.py +367 -0
- tree_sitter_analyzer/formatters/formatter_config.py +197 -0
- tree_sitter_analyzer/formatters/formatter_factory.py +84 -0
- tree_sitter_analyzer/formatters/formatter_registry.py +377 -0
- tree_sitter_analyzer/formatters/formatter_selector.py +96 -0
- tree_sitter_analyzer/formatters/go_formatter.py +368 -0
- tree_sitter_analyzer/formatters/html_formatter.py +498 -0
- tree_sitter_analyzer/formatters/java_formatter.py +423 -0
- tree_sitter_analyzer/formatters/javascript_formatter.py +611 -0
- tree_sitter_analyzer/formatters/kotlin_formatter.py +268 -0
- tree_sitter_analyzer/formatters/language_formatter_factory.py +123 -0
- tree_sitter_analyzer/formatters/legacy_formatter_adapters.py +228 -0
- tree_sitter_analyzer/formatters/markdown_formatter.py +725 -0
- tree_sitter_analyzer/formatters/php_formatter.py +301 -0
- tree_sitter_analyzer/formatters/python_formatter.py +830 -0
- tree_sitter_analyzer/formatters/ruby_formatter.py +278 -0
- tree_sitter_analyzer/formatters/rust_formatter.py +233 -0
- tree_sitter_analyzer/formatters/sql_formatter_wrapper.py +689 -0
- tree_sitter_analyzer/formatters/sql_formatters.py +536 -0
- tree_sitter_analyzer/formatters/typescript_formatter.py +543 -0
- tree_sitter_analyzer/formatters/yaml_formatter.py +462 -0
- tree_sitter_analyzer/interfaces/__init__.py +9 -0
- tree_sitter_analyzer/interfaces/cli.py +535 -0
- tree_sitter_analyzer/interfaces/cli_adapter.py +359 -0
- tree_sitter_analyzer/interfaces/mcp_adapter.py +224 -0
- tree_sitter_analyzer/interfaces/mcp_server.py +428 -0
- tree_sitter_analyzer/language_detector.py +553 -0
- tree_sitter_analyzer/language_loader.py +271 -0
- tree_sitter_analyzer/languages/__init__.py +10 -0
- tree_sitter_analyzer/languages/csharp_plugin.py +1076 -0
- tree_sitter_analyzer/languages/css_plugin.py +449 -0
- tree_sitter_analyzer/languages/go_plugin.py +836 -0
- tree_sitter_analyzer/languages/html_plugin.py +496 -0
- tree_sitter_analyzer/languages/java_plugin.py +1299 -0
- tree_sitter_analyzer/languages/javascript_plugin.py +1622 -0
- tree_sitter_analyzer/languages/kotlin_plugin.py +656 -0
- tree_sitter_analyzer/languages/markdown_plugin.py +1928 -0
- tree_sitter_analyzer/languages/php_plugin.py +862 -0
- tree_sitter_analyzer/languages/python_plugin.py +1636 -0
- tree_sitter_analyzer/languages/ruby_plugin.py +757 -0
- tree_sitter_analyzer/languages/rust_plugin.py +673 -0
- tree_sitter_analyzer/languages/sql_plugin.py +2444 -0
- tree_sitter_analyzer/languages/typescript_plugin.py +1892 -0
- tree_sitter_analyzer/languages/yaml_plugin.py +695 -0
- tree_sitter_analyzer/legacy_table_formatter.py +860 -0
- tree_sitter_analyzer/mcp/__init__.py +34 -0
- tree_sitter_analyzer/mcp/resources/__init__.py +43 -0
- tree_sitter_analyzer/mcp/resources/code_file_resource.py +208 -0
- tree_sitter_analyzer/mcp/resources/project_stats_resource.py +586 -0
- tree_sitter_analyzer/mcp/server.py +869 -0
- tree_sitter_analyzer/mcp/tools/__init__.py +28 -0
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +779 -0
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +291 -0
- tree_sitter_analyzer/mcp/tools/base_tool.py +139 -0
- tree_sitter_analyzer/mcp/tools/fd_rg_utils.py +816 -0
- tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +686 -0
- tree_sitter_analyzer/mcp/tools/list_files_tool.py +413 -0
- tree_sitter_analyzer/mcp/tools/output_format_validator.py +148 -0
- tree_sitter_analyzer/mcp/tools/query_tool.py +443 -0
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py +464 -0
- tree_sitter_analyzer/mcp/tools/search_content_tool.py +836 -0
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +572 -0
- tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +653 -0
- tree_sitter_analyzer/mcp/utils/__init__.py +113 -0
- tree_sitter_analyzer/mcp/utils/error_handler.py +569 -0
- tree_sitter_analyzer/mcp/utils/file_output_factory.py +217 -0
- tree_sitter_analyzer/mcp/utils/file_output_manager.py +322 -0
- tree_sitter_analyzer/mcp/utils/gitignore_detector.py +358 -0
- tree_sitter_analyzer/mcp/utils/path_resolver.py +414 -0
- tree_sitter_analyzer/mcp/utils/search_cache.py +343 -0
- tree_sitter_analyzer/models.py +840 -0
- tree_sitter_analyzer/mypy_current_errors.txt +2 -0
- tree_sitter_analyzer/output_manager.py +255 -0
- tree_sitter_analyzer/platform_compat/__init__.py +3 -0
- tree_sitter_analyzer/platform_compat/adapter.py +324 -0
- tree_sitter_analyzer/platform_compat/compare.py +224 -0
- tree_sitter_analyzer/platform_compat/detector.py +67 -0
- tree_sitter_analyzer/platform_compat/fixtures.py +228 -0
- tree_sitter_analyzer/platform_compat/profiles.py +217 -0
- tree_sitter_analyzer/platform_compat/record.py +55 -0
- tree_sitter_analyzer/platform_compat/recorder.py +155 -0
- tree_sitter_analyzer/platform_compat/report.py +92 -0
- tree_sitter_analyzer/plugins/__init__.py +280 -0
- tree_sitter_analyzer/plugins/base.py +647 -0
- tree_sitter_analyzer/plugins/manager.py +384 -0
- tree_sitter_analyzer/project_detector.py +328 -0
- tree_sitter_analyzer/queries/__init__.py +27 -0
- tree_sitter_analyzer/queries/csharp.py +216 -0
- tree_sitter_analyzer/queries/css.py +615 -0
- tree_sitter_analyzer/queries/go.py +275 -0
- tree_sitter_analyzer/queries/html.py +543 -0
- tree_sitter_analyzer/queries/java.py +402 -0
- tree_sitter_analyzer/queries/javascript.py +724 -0
- tree_sitter_analyzer/queries/kotlin.py +192 -0
- tree_sitter_analyzer/queries/markdown.py +258 -0
- tree_sitter_analyzer/queries/php.py +95 -0
- tree_sitter_analyzer/queries/python.py +859 -0
- tree_sitter_analyzer/queries/ruby.py +92 -0
- tree_sitter_analyzer/queries/rust.py +223 -0
- tree_sitter_analyzer/queries/sql.py +555 -0
- tree_sitter_analyzer/queries/typescript.py +871 -0
- tree_sitter_analyzer/queries/yaml.py +236 -0
- tree_sitter_analyzer/query_loader.py +272 -0
- tree_sitter_analyzer/security/__init__.py +22 -0
- tree_sitter_analyzer/security/boundary_manager.py +277 -0
- tree_sitter_analyzer/security/regex_checker.py +297 -0
- tree_sitter_analyzer/security/validator.py +599 -0
- tree_sitter_analyzer/table_formatter.py +782 -0
- tree_sitter_analyzer/utils/__init__.py +53 -0
- tree_sitter_analyzer/utils/logging.py +433 -0
- tree_sitter_analyzer/utils/tree_sitter_compat.py +289 -0
- tree_sitter_analyzer-1.9.17.1.dist-info/METADATA +485 -0
- tree_sitter_analyzer-1.9.17.1.dist-info/RECORD +149 -0
- tree_sitter_analyzer-1.9.17.1.dist-info/WHEEL +4 -0
- tree_sitter_analyzer-1.9.17.1.dist-info/entry_points.txt +25 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
MCP Server Interface
|
|
4
|
+
|
|
5
|
+
New MCP server implementation that uses the API facade for all operations.
|
|
6
|
+
Provides a clean separation between MCP protocol concerns and core analysis logic.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import json
|
|
11
|
+
import logging
|
|
12
|
+
import sys
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from .. import __version__
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from mcp.server import Server
|
|
19
|
+
from mcp.server.models import InitializationOptions
|
|
20
|
+
from mcp.server.stdio import stdio_server
|
|
21
|
+
from mcp.types import Resource, TextContent, Tool
|
|
22
|
+
|
|
23
|
+
MCP_AVAILABLE = True
|
|
24
|
+
except ImportError:
|
|
25
|
+
MCP_AVAILABLE = False
|
|
26
|
+
|
|
27
|
+
# Fallback types for development without MCP
|
|
28
|
+
class Server: # type: ignore
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
class InitializationOptions: # type: ignore
|
|
32
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
class Tool: # type: ignore
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
class Resource: # type: ignore
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
class TextContent: # type: ignore
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
def stdio_server() -> None: # type: ignore[misc]
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
from .. import api
|
|
49
|
+
from ..utils import log_error, log_info
|
|
50
|
+
|
|
51
|
+
# Configure logging for MCP
|
|
52
|
+
logging.basicConfig(
|
|
53
|
+
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
54
|
+
)
|
|
55
|
+
logger = logging.getLogger(__name__)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TreeSitterAnalyzerMCPServer:
|
|
59
|
+
"""
|
|
60
|
+
MCP Server for Tree-sitter Analyzer using the new API facade.
|
|
61
|
+
|
|
62
|
+
This server provides code analysis capabilities through the Model Context Protocol,
|
|
63
|
+
using the unified API facade for all operations.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self) -> None:
|
|
67
|
+
"""Initialize the MCP server."""
|
|
68
|
+
if not MCP_AVAILABLE:
|
|
69
|
+
raise ImportError("MCP library not available. Please install mcp package.")
|
|
70
|
+
|
|
71
|
+
self.server: Server | None = None
|
|
72
|
+
self.name = "tree-sitter-analyzer"
|
|
73
|
+
self.version = __version__
|
|
74
|
+
|
|
75
|
+
log_info(f"Initializing {self.name} v{self.version}")
|
|
76
|
+
|
|
77
|
+
def create_server(self) -> Server:
|
|
78
|
+
"""Create and configure the MCP server."""
|
|
79
|
+
server: Any = Server(self.name)
|
|
80
|
+
|
|
81
|
+
@server.list_tools() # type: ignore
|
|
82
|
+
async def handle_list_tools() -> list[Tool]:
|
|
83
|
+
"""List available tools."""
|
|
84
|
+
return [
|
|
85
|
+
Tool(
|
|
86
|
+
name="analyze_file",
|
|
87
|
+
description="Analyze a source code file comprehensively",
|
|
88
|
+
inputSchema={
|
|
89
|
+
"type": "object",
|
|
90
|
+
"properties": {
|
|
91
|
+
"file_path": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"description": "Path to the source file to analyze",
|
|
94
|
+
},
|
|
95
|
+
"language": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"description": "Programming language (optional, auto-detected if not specified)",
|
|
98
|
+
},
|
|
99
|
+
"queries": {
|
|
100
|
+
"type": "array",
|
|
101
|
+
"items": {"type": "string"},
|
|
102
|
+
"description": "List of query names to execute (optional)",
|
|
103
|
+
},
|
|
104
|
+
"include_elements": {
|
|
105
|
+
"type": "boolean",
|
|
106
|
+
"description": "Whether to extract code elements",
|
|
107
|
+
"default": True,
|
|
108
|
+
},
|
|
109
|
+
"include_queries": {
|
|
110
|
+
"type": "boolean",
|
|
111
|
+
"description": "Whether to execute queries",
|
|
112
|
+
"default": True,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
"required": ["file_path"],
|
|
116
|
+
"additionalProperties": False,
|
|
117
|
+
},
|
|
118
|
+
),
|
|
119
|
+
Tool(
|
|
120
|
+
name="analyze_code",
|
|
121
|
+
description="Analyze source code directly (without file)",
|
|
122
|
+
inputSchema={
|
|
123
|
+
"type": "object",
|
|
124
|
+
"properties": {
|
|
125
|
+
"source_code": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"description": "Source code string to analyze",
|
|
128
|
+
},
|
|
129
|
+
"language": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"description": "Programming language",
|
|
132
|
+
},
|
|
133
|
+
"queries": {
|
|
134
|
+
"type": "array",
|
|
135
|
+
"items": {"type": "string"},
|
|
136
|
+
"description": "List of query names to execute (optional)",
|
|
137
|
+
},
|
|
138
|
+
"include_elements": {
|
|
139
|
+
"type": "boolean",
|
|
140
|
+
"description": "Whether to extract code elements",
|
|
141
|
+
"default": True,
|
|
142
|
+
},
|
|
143
|
+
"include_queries": {
|
|
144
|
+
"type": "boolean",
|
|
145
|
+
"description": "Whether to execute queries",
|
|
146
|
+
"default": True,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
"required": ["source_code", "language"],
|
|
150
|
+
"additionalProperties": False,
|
|
151
|
+
},
|
|
152
|
+
),
|
|
153
|
+
Tool(
|
|
154
|
+
name="extract_elements",
|
|
155
|
+
description="Extract code elements from a file",
|
|
156
|
+
inputSchema={
|
|
157
|
+
"type": "object",
|
|
158
|
+
"properties": {
|
|
159
|
+
"file_path": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"description": "Path to the source file",
|
|
162
|
+
},
|
|
163
|
+
"language": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"description": "Programming language (optional, auto-detected if not specified)",
|
|
166
|
+
},
|
|
167
|
+
"element_types": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"items": {"type": "string"},
|
|
170
|
+
"description": "Types of elements to extract (optional)",
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
"required": ["file_path"],
|
|
174
|
+
"additionalProperties": False,
|
|
175
|
+
},
|
|
176
|
+
),
|
|
177
|
+
Tool(
|
|
178
|
+
name="execute_query",
|
|
179
|
+
description="Execute a specific query on a file",
|
|
180
|
+
inputSchema={
|
|
181
|
+
"type": "object",
|
|
182
|
+
"properties": {
|
|
183
|
+
"file_path": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"description": "Path to the source file",
|
|
186
|
+
},
|
|
187
|
+
"query_name": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"description": "Name of the query to execute",
|
|
190
|
+
},
|
|
191
|
+
"language": {
|
|
192
|
+
"type": "string",
|
|
193
|
+
"description": "Programming language (optional, auto-detected if not specified)",
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
"required": ["file_path", "query_name"],
|
|
197
|
+
"additionalProperties": False,
|
|
198
|
+
},
|
|
199
|
+
),
|
|
200
|
+
Tool(
|
|
201
|
+
name="validate_file",
|
|
202
|
+
description="Validate a source code file",
|
|
203
|
+
inputSchema={
|
|
204
|
+
"type": "object",
|
|
205
|
+
"properties": {
|
|
206
|
+
"file_path": {
|
|
207
|
+
"type": "string",
|
|
208
|
+
"description": "Path to the source file to validate",
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
"required": ["file_path"],
|
|
212
|
+
"additionalProperties": False,
|
|
213
|
+
},
|
|
214
|
+
),
|
|
215
|
+
Tool(
|
|
216
|
+
name="get_supported_languages",
|
|
217
|
+
description="Get list of supported programming languages",
|
|
218
|
+
inputSchema={
|
|
219
|
+
"type": "object",
|
|
220
|
+
"properties": {},
|
|
221
|
+
"additionalProperties": False,
|
|
222
|
+
},
|
|
223
|
+
),
|
|
224
|
+
Tool(
|
|
225
|
+
name="get_available_queries",
|
|
226
|
+
description="Get available queries for a specific language",
|
|
227
|
+
inputSchema={
|
|
228
|
+
"type": "object",
|
|
229
|
+
"properties": {
|
|
230
|
+
"language": {
|
|
231
|
+
"type": "string",
|
|
232
|
+
"description": "Programming language name",
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
"required": ["language"],
|
|
236
|
+
"additionalProperties": False,
|
|
237
|
+
},
|
|
238
|
+
),
|
|
239
|
+
Tool(
|
|
240
|
+
name="get_framework_info",
|
|
241
|
+
description="Get information about the analyzer framework",
|
|
242
|
+
inputSchema={
|
|
243
|
+
"type": "object",
|
|
244
|
+
"properties": {},
|
|
245
|
+
"additionalProperties": False,
|
|
246
|
+
},
|
|
247
|
+
),
|
|
248
|
+
]
|
|
249
|
+
|
|
250
|
+
@server.call_tool() # type: ignore
|
|
251
|
+
async def handle_call_tool(
|
|
252
|
+
name: str, arguments: dict[str, Any]
|
|
253
|
+
) -> list[TextContent]:
|
|
254
|
+
"""Handle tool calls."""
|
|
255
|
+
try:
|
|
256
|
+
result = None
|
|
257
|
+
|
|
258
|
+
if name == "analyze_file":
|
|
259
|
+
result = api.analyze_file(
|
|
260
|
+
file_path=arguments["file_path"],
|
|
261
|
+
language=arguments.get("language"),
|
|
262
|
+
queries=arguments.get("queries"),
|
|
263
|
+
include_elements=arguments.get("include_elements", True),
|
|
264
|
+
include_queries=arguments.get("include_queries", True),
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
elif name == "analyze_code":
|
|
268
|
+
result = api.analyze_code(
|
|
269
|
+
source_code=arguments["source_code"],
|
|
270
|
+
language=arguments["language"],
|
|
271
|
+
queries=arguments.get("queries"),
|
|
272
|
+
include_elements=arguments.get("include_elements", True),
|
|
273
|
+
include_queries=arguments.get("include_queries", True),
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
elif name == "extract_elements":
|
|
277
|
+
result = api.extract_elements(
|
|
278
|
+
file_path=arguments["file_path"],
|
|
279
|
+
language=arguments.get("language"),
|
|
280
|
+
element_types=arguments.get("element_types"),
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
elif name == "execute_query":
|
|
284
|
+
result = api.execute_query(
|
|
285
|
+
file_path=arguments["file_path"],
|
|
286
|
+
query_name=arguments["query_name"],
|
|
287
|
+
language=arguments.get("language"),
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
elif name == "validate_file":
|
|
291
|
+
result = api.validate_file(arguments["file_path"])
|
|
292
|
+
|
|
293
|
+
elif name == "get_supported_languages":
|
|
294
|
+
result = {
|
|
295
|
+
"languages": api.get_supported_languages(),
|
|
296
|
+
"total": len(api.get_supported_languages()),
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
elif name == "get_available_queries":
|
|
300
|
+
queries = api.get_available_queries(arguments["language"])
|
|
301
|
+
result = {
|
|
302
|
+
"language": arguments["language"],
|
|
303
|
+
"queries": queries,
|
|
304
|
+
"total": len(queries),
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
elif name == "get_framework_info":
|
|
308
|
+
result = api.get_framework_info()
|
|
309
|
+
|
|
310
|
+
else:
|
|
311
|
+
raise ValueError(f"Unknown tool: {name}")
|
|
312
|
+
|
|
313
|
+
return [
|
|
314
|
+
TextContent(
|
|
315
|
+
type="text",
|
|
316
|
+
text=json.dumps(result, indent=2, ensure_ascii=False),
|
|
317
|
+
)
|
|
318
|
+
]
|
|
319
|
+
|
|
320
|
+
except Exception as e:
|
|
321
|
+
log_error(f"Tool call error for {name}: {e}")
|
|
322
|
+
error_result = {
|
|
323
|
+
"error": str(e),
|
|
324
|
+
"tool": name,
|
|
325
|
+
"arguments": arguments,
|
|
326
|
+
"success": False,
|
|
327
|
+
}
|
|
328
|
+
return [
|
|
329
|
+
TextContent(
|
|
330
|
+
type="text",
|
|
331
|
+
text=json.dumps(error_result, indent=2, ensure_ascii=False),
|
|
332
|
+
)
|
|
333
|
+
]
|
|
334
|
+
|
|
335
|
+
@server.list_resources() # type: ignore
|
|
336
|
+
async def handle_list_resources() -> list[Resource]:
|
|
337
|
+
"""List available resources."""
|
|
338
|
+
return [
|
|
339
|
+
Resource(
|
|
340
|
+
uri="code://file/{file_path}", # type: ignore[arg-type]
|
|
341
|
+
name="Code File Analysis",
|
|
342
|
+
description="Access to code file content and analysis",
|
|
343
|
+
mimeType="application/json",
|
|
344
|
+
),
|
|
345
|
+
Resource(
|
|
346
|
+
uri="code://stats/{stats_type}", # type: ignore[arg-type]
|
|
347
|
+
name="Project Statistics",
|
|
348
|
+
description="Access to project statistics and analysis data",
|
|
349
|
+
mimeType="application/json",
|
|
350
|
+
),
|
|
351
|
+
]
|
|
352
|
+
|
|
353
|
+
@server.read_resource() # type: ignore
|
|
354
|
+
async def handle_read_resource(uri: str) -> str:
|
|
355
|
+
"""Read resource content."""
|
|
356
|
+
try:
|
|
357
|
+
if uri.startswith("code://file/"):
|
|
358
|
+
# Extract file path from URI
|
|
359
|
+
file_path = uri[len("code://file/") :]
|
|
360
|
+
|
|
361
|
+
# Analyze the file
|
|
362
|
+
result = api.analyze_file(file_path)
|
|
363
|
+
return json.dumps(result, indent=2, ensure_ascii=False)
|
|
364
|
+
|
|
365
|
+
elif uri.startswith("code://stats/"):
|
|
366
|
+
# Extract stats type from URI
|
|
367
|
+
stats_type = uri[len("code://stats/") :]
|
|
368
|
+
|
|
369
|
+
# Get framework info as basic stats
|
|
370
|
+
if stats_type == "framework":
|
|
371
|
+
result = api.get_framework_info()
|
|
372
|
+
elif stats_type == "languages":
|
|
373
|
+
result = {
|
|
374
|
+
"supported_languages": api.get_supported_languages(),
|
|
375
|
+
"total_languages": len(api.get_supported_languages()),
|
|
376
|
+
}
|
|
377
|
+
else:
|
|
378
|
+
raise ValueError(f"Unknown stats type: {stats_type}")
|
|
379
|
+
|
|
380
|
+
return json.dumps(result, indent=2, ensure_ascii=False)
|
|
381
|
+
|
|
382
|
+
else:
|
|
383
|
+
raise ValueError(f"Resource not found: {uri}")
|
|
384
|
+
|
|
385
|
+
except Exception as e:
|
|
386
|
+
log_error(f"Resource read error for {uri}: {e}")
|
|
387
|
+
error_result = {"error": str(e), "uri": uri, "success": False}
|
|
388
|
+
return json.dumps(error_result, indent=2, ensure_ascii=False)
|
|
389
|
+
|
|
390
|
+
self.server = server
|
|
391
|
+
log_info("MCP server created successfully")
|
|
392
|
+
return server # type: ignore[no-any-return]
|
|
393
|
+
|
|
394
|
+
async def run(self) -> None:
|
|
395
|
+
"""Run the MCP server."""
|
|
396
|
+
server = self.create_server()
|
|
397
|
+
|
|
398
|
+
# Initialize server options
|
|
399
|
+
options = InitializationOptions(
|
|
400
|
+
server_name=self.name,
|
|
401
|
+
server_version=self.version,
|
|
402
|
+
capabilities={"tools": {}, "resources": {}}, # type: ignore[arg-type]
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
log_info(f"Starting MCP server: {self.name} v{self.version}")
|
|
406
|
+
|
|
407
|
+
try:
|
|
408
|
+
async with stdio_server() as (read_stream, write_stream):
|
|
409
|
+
await server.run(read_stream, write_stream, options)
|
|
410
|
+
except Exception as e:
|
|
411
|
+
log_error(f"Server error: {e}")
|
|
412
|
+
raise
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
async def main() -> None:
|
|
416
|
+
"""Main entry point for the MCP server."""
|
|
417
|
+
try:
|
|
418
|
+
server = TreeSitterAnalyzerMCPServer()
|
|
419
|
+
await server.run()
|
|
420
|
+
except KeyboardInterrupt:
|
|
421
|
+
log_info("Server stopped by user")
|
|
422
|
+
except Exception as e:
|
|
423
|
+
log_error(f"Server failed: {e}")
|
|
424
|
+
sys.exit(1)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
if __name__ == "__main__":
|
|
428
|
+
asyncio.run(main())
|