codexa 0.4.0__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.
Files changed (189) hide show
  1. codexa-0.4.0.dist-info/METADATA +650 -0
  2. codexa-0.4.0.dist-info/RECORD +189 -0
  3. codexa-0.4.0.dist-info/WHEEL +5 -0
  4. codexa-0.4.0.dist-info/entry_points.txt +2 -0
  5. codexa-0.4.0.dist-info/licenses/LICENSE +21 -0
  6. codexa-0.4.0.dist-info/top_level.txt +1 -0
  7. semantic_code_intelligence/__init__.py +5 -0
  8. semantic_code_intelligence/analysis/__init__.py +21 -0
  9. semantic_code_intelligence/analysis/ai_features.py +351 -0
  10. semantic_code_intelligence/bridge/__init__.py +28 -0
  11. semantic_code_intelligence/bridge/context_provider.py +245 -0
  12. semantic_code_intelligence/bridge/protocol.py +167 -0
  13. semantic_code_intelligence/bridge/server.py +348 -0
  14. semantic_code_intelligence/bridge/vscode.py +271 -0
  15. semantic_code_intelligence/ci/__init__.py +13 -0
  16. semantic_code_intelligence/ci/hooks.py +98 -0
  17. semantic_code_intelligence/ci/hotspots.py +272 -0
  18. semantic_code_intelligence/ci/impact.py +246 -0
  19. semantic_code_intelligence/ci/metrics.py +591 -0
  20. semantic_code_intelligence/ci/pr.py +412 -0
  21. semantic_code_intelligence/ci/quality.py +557 -0
  22. semantic_code_intelligence/ci/templates.py +164 -0
  23. semantic_code_intelligence/ci/trace.py +224 -0
  24. semantic_code_intelligence/cli/__init__.py +0 -0
  25. semantic_code_intelligence/cli/commands/__init__.py +0 -0
  26. semantic_code_intelligence/cli/commands/ask_cmd.py +153 -0
  27. semantic_code_intelligence/cli/commands/benchmark_cmd.py +303 -0
  28. semantic_code_intelligence/cli/commands/chat_cmd.py +252 -0
  29. semantic_code_intelligence/cli/commands/ci_gen_cmd.py +74 -0
  30. semantic_code_intelligence/cli/commands/context_cmd.py +120 -0
  31. semantic_code_intelligence/cli/commands/cross_refactor_cmd.py +113 -0
  32. semantic_code_intelligence/cli/commands/deps_cmd.py +91 -0
  33. semantic_code_intelligence/cli/commands/docs_cmd.py +101 -0
  34. semantic_code_intelligence/cli/commands/doctor_cmd.py +147 -0
  35. semantic_code_intelligence/cli/commands/evolve_cmd.py +171 -0
  36. semantic_code_intelligence/cli/commands/explain_cmd.py +112 -0
  37. semantic_code_intelligence/cli/commands/gate_cmd.py +135 -0
  38. semantic_code_intelligence/cli/commands/grep_cmd.py +234 -0
  39. semantic_code_intelligence/cli/commands/hotspots_cmd.py +119 -0
  40. semantic_code_intelligence/cli/commands/impact_cmd.py +131 -0
  41. semantic_code_intelligence/cli/commands/index_cmd.py +138 -0
  42. semantic_code_intelligence/cli/commands/init_cmd.py +152 -0
  43. semantic_code_intelligence/cli/commands/investigate_cmd.py +163 -0
  44. semantic_code_intelligence/cli/commands/languages_cmd.py +101 -0
  45. semantic_code_intelligence/cli/commands/lsp_cmd.py +49 -0
  46. semantic_code_intelligence/cli/commands/mcp_cmd.py +50 -0
  47. semantic_code_intelligence/cli/commands/metrics_cmd.py +264 -0
  48. semantic_code_intelligence/cli/commands/models_cmd.py +157 -0
  49. semantic_code_intelligence/cli/commands/plugin_cmd.py +275 -0
  50. semantic_code_intelligence/cli/commands/pr_summary_cmd.py +178 -0
  51. semantic_code_intelligence/cli/commands/quality_cmd.py +208 -0
  52. semantic_code_intelligence/cli/commands/refactor_cmd.py +103 -0
  53. semantic_code_intelligence/cli/commands/review_cmd.py +88 -0
  54. semantic_code_intelligence/cli/commands/search_cmd.py +236 -0
  55. semantic_code_intelligence/cli/commands/serve_cmd.py +117 -0
  56. semantic_code_intelligence/cli/commands/suggest_cmd.py +100 -0
  57. semantic_code_intelligence/cli/commands/summary_cmd.py +78 -0
  58. semantic_code_intelligence/cli/commands/tool_cmd.py +282 -0
  59. semantic_code_intelligence/cli/commands/trace_cmd.py +123 -0
  60. semantic_code_intelligence/cli/commands/tui_cmd.py +58 -0
  61. semantic_code_intelligence/cli/commands/viz_cmd.py +127 -0
  62. semantic_code_intelligence/cli/commands/watch_cmd.py +72 -0
  63. semantic_code_intelligence/cli/commands/web_cmd.py +61 -0
  64. semantic_code_intelligence/cli/commands/workspace_cmd.py +250 -0
  65. semantic_code_intelligence/cli/main.py +65 -0
  66. semantic_code_intelligence/cli/router.py +92 -0
  67. semantic_code_intelligence/config/__init__.py +0 -0
  68. semantic_code_intelligence/config/settings.py +260 -0
  69. semantic_code_intelligence/context/__init__.py +19 -0
  70. semantic_code_intelligence/context/engine.py +429 -0
  71. semantic_code_intelligence/context/memory.py +253 -0
  72. semantic_code_intelligence/daemon/__init__.py +1 -0
  73. semantic_code_intelligence/daemon/watcher.py +515 -0
  74. semantic_code_intelligence/docs/__init__.py +1080 -0
  75. semantic_code_intelligence/embeddings/__init__.py +0 -0
  76. semantic_code_intelligence/embeddings/enhanced.py +131 -0
  77. semantic_code_intelligence/embeddings/generator.py +149 -0
  78. semantic_code_intelligence/embeddings/model_registry.py +100 -0
  79. semantic_code_intelligence/evolution/__init__.py +1 -0
  80. semantic_code_intelligence/evolution/budget_guard.py +111 -0
  81. semantic_code_intelligence/evolution/commit_manager.py +88 -0
  82. semantic_code_intelligence/evolution/context_builder.py +131 -0
  83. semantic_code_intelligence/evolution/engine.py +249 -0
  84. semantic_code_intelligence/evolution/patch_generator.py +229 -0
  85. semantic_code_intelligence/evolution/task_selector.py +214 -0
  86. semantic_code_intelligence/evolution/test_runner.py +111 -0
  87. semantic_code_intelligence/indexing/__init__.py +0 -0
  88. semantic_code_intelligence/indexing/chunker.py +174 -0
  89. semantic_code_intelligence/indexing/parallel.py +86 -0
  90. semantic_code_intelligence/indexing/scanner.py +146 -0
  91. semantic_code_intelligence/indexing/semantic_chunker.py +337 -0
  92. semantic_code_intelligence/llm/__init__.py +62 -0
  93. semantic_code_intelligence/llm/cache.py +219 -0
  94. semantic_code_intelligence/llm/cached_provider.py +145 -0
  95. semantic_code_intelligence/llm/conversation.py +190 -0
  96. semantic_code_intelligence/llm/cross_refactor.py +272 -0
  97. semantic_code_intelligence/llm/investigation.py +274 -0
  98. semantic_code_intelligence/llm/mock_provider.py +77 -0
  99. semantic_code_intelligence/llm/ollama_provider.py +122 -0
  100. semantic_code_intelligence/llm/openai_provider.py +100 -0
  101. semantic_code_intelligence/llm/provider.py +92 -0
  102. semantic_code_intelligence/llm/rate_limiter.py +164 -0
  103. semantic_code_intelligence/llm/reasoning.py +438 -0
  104. semantic_code_intelligence/llm/safety.py +110 -0
  105. semantic_code_intelligence/llm/streaming.py +251 -0
  106. semantic_code_intelligence/lsp/__init__.py +609 -0
  107. semantic_code_intelligence/mcp/__init__.py +393 -0
  108. semantic_code_intelligence/parsing/__init__.py +19 -0
  109. semantic_code_intelligence/parsing/parser.py +375 -0
  110. semantic_code_intelligence/plugins/__init__.py +255 -0
  111. semantic_code_intelligence/plugins/examples/__init__.py +1 -0
  112. semantic_code_intelligence/plugins/examples/code_quality.py +73 -0
  113. semantic_code_intelligence/plugins/examples/search_annotator.py +56 -0
  114. semantic_code_intelligence/scalability/__init__.py +205 -0
  115. semantic_code_intelligence/search/__init__.py +0 -0
  116. semantic_code_intelligence/search/formatter.py +123 -0
  117. semantic_code_intelligence/search/grep.py +361 -0
  118. semantic_code_intelligence/search/hybrid_search.py +170 -0
  119. semantic_code_intelligence/search/keyword_search.py +311 -0
  120. semantic_code_intelligence/search/section_expander.py +103 -0
  121. semantic_code_intelligence/services/__init__.py +0 -0
  122. semantic_code_intelligence/services/indexing_service.py +630 -0
  123. semantic_code_intelligence/services/search_service.py +269 -0
  124. semantic_code_intelligence/storage/__init__.py +0 -0
  125. semantic_code_intelligence/storage/chunk_hash_store.py +86 -0
  126. semantic_code_intelligence/storage/hash_store.py +66 -0
  127. semantic_code_intelligence/storage/index_manifest.py +85 -0
  128. semantic_code_intelligence/storage/index_stats.py +138 -0
  129. semantic_code_intelligence/storage/query_history.py +160 -0
  130. semantic_code_intelligence/storage/symbol_registry.py +209 -0
  131. semantic_code_intelligence/storage/vector_store.py +297 -0
  132. semantic_code_intelligence/tests/__init__.py +0 -0
  133. semantic_code_intelligence/tests/test_ai_features.py +351 -0
  134. semantic_code_intelligence/tests/test_chunker.py +119 -0
  135. semantic_code_intelligence/tests/test_cli.py +188 -0
  136. semantic_code_intelligence/tests/test_config.py +154 -0
  137. semantic_code_intelligence/tests/test_context.py +381 -0
  138. semantic_code_intelligence/tests/test_embeddings.py +73 -0
  139. semantic_code_intelligence/tests/test_endtoend.py +1142 -0
  140. semantic_code_intelligence/tests/test_enhanced_embeddings.py +92 -0
  141. semantic_code_intelligence/tests/test_hash_store.py +79 -0
  142. semantic_code_intelligence/tests/test_logging.py +55 -0
  143. semantic_code_intelligence/tests/test_new_cli.py +138 -0
  144. semantic_code_intelligence/tests/test_parser.py +495 -0
  145. semantic_code_intelligence/tests/test_phase10.py +355 -0
  146. semantic_code_intelligence/tests/test_phase11.py +593 -0
  147. semantic_code_intelligence/tests/test_phase12.py +375 -0
  148. semantic_code_intelligence/tests/test_phase13.py +663 -0
  149. semantic_code_intelligence/tests/test_phase14.py +568 -0
  150. semantic_code_intelligence/tests/test_phase15.py +814 -0
  151. semantic_code_intelligence/tests/test_phase16.py +792 -0
  152. semantic_code_intelligence/tests/test_phase17.py +815 -0
  153. semantic_code_intelligence/tests/test_phase18.py +934 -0
  154. semantic_code_intelligence/tests/test_phase19.py +986 -0
  155. semantic_code_intelligence/tests/test_phase20.py +2753 -0
  156. semantic_code_intelligence/tests/test_phase20b.py +2058 -0
  157. semantic_code_intelligence/tests/test_phase20c.py +962 -0
  158. semantic_code_intelligence/tests/test_phase21.py +428 -0
  159. semantic_code_intelligence/tests/test_phase22.py +799 -0
  160. semantic_code_intelligence/tests/test_phase23.py +783 -0
  161. semantic_code_intelligence/tests/test_phase24.py +715 -0
  162. semantic_code_intelligence/tests/test_phase25.py +496 -0
  163. semantic_code_intelligence/tests/test_phase26.py +251 -0
  164. semantic_code_intelligence/tests/test_phase27.py +531 -0
  165. semantic_code_intelligence/tests/test_phase8.py +592 -0
  166. semantic_code_intelligence/tests/test_phase9.py +643 -0
  167. semantic_code_intelligence/tests/test_plugins.py +293 -0
  168. semantic_code_intelligence/tests/test_priority_features.py +727 -0
  169. semantic_code_intelligence/tests/test_router.py +41 -0
  170. semantic_code_intelligence/tests/test_scalability.py +138 -0
  171. semantic_code_intelligence/tests/test_scanner.py +125 -0
  172. semantic_code_intelligence/tests/test_search.py +160 -0
  173. semantic_code_intelligence/tests/test_semantic_chunker.py +255 -0
  174. semantic_code_intelligence/tests/test_tools.py +182 -0
  175. semantic_code_intelligence/tests/test_vector_store.py +151 -0
  176. semantic_code_intelligence/tests/test_watcher.py +211 -0
  177. semantic_code_intelligence/tools/__init__.py +442 -0
  178. semantic_code_intelligence/tools/executor.py +232 -0
  179. semantic_code_intelligence/tools/protocol.py +200 -0
  180. semantic_code_intelligence/tui/__init__.py +454 -0
  181. semantic_code_intelligence/utils/__init__.py +0 -0
  182. semantic_code_intelligence/utils/logging.py +112 -0
  183. semantic_code_intelligence/version.py +3 -0
  184. semantic_code_intelligence/web/__init__.py +11 -0
  185. semantic_code_intelligence/web/api.py +289 -0
  186. semantic_code_intelligence/web/server.py +397 -0
  187. semantic_code_intelligence/web/ui.py +659 -0
  188. semantic_code_intelligence/web/visualize.py +226 -0
  189. semantic_code_intelligence/workspace/__init__.py +427 -0
@@ -0,0 +1,393 @@
1
+ """MCP server — Model Context Protocol server for AI agent integration.
2
+
3
+ Uses the official ``mcp`` SDK (https://pypi.org/project/mcp/) to expose
4
+ CodexA as a tool provider for Claude Desktop, Cursor, and other
5
+ MCP-compatible clients.
6
+
7
+ Exposes 11 tools: semantic_search, keyword_search, hybrid_search,
8
+ regex_search, explain_symbol, index_status, reindex, health_check,
9
+ get_quality_score, find_duplicates, grep_files.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import asyncio
15
+ import json
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ try:
20
+ from mcp.server import Server
21
+ from mcp.server.stdio import stdio_server
22
+ from mcp.types import TextContent, Tool
23
+ _HAS_MCP = True
24
+ except ImportError: # mcp SDK not installed (e.g. Python 3.13)
25
+ _HAS_MCP = False
26
+ Server = None # type: ignore[assignment,misc]
27
+ TextContent = None # type: ignore[assignment,misc]
28
+ Tool = None # type: ignore[assignment,misc]
29
+
30
+ from semantic_code_intelligence.config.settings import AppConfig
31
+ from semantic_code_intelligence.utils.logging import get_logger
32
+
33
+ logger = get_logger("mcp")
34
+
35
+
36
+ # ---- Tool definitions ---------------------------------------------------
37
+
38
+ if _HAS_MCP:
39
+ MCP_TOOLS = [
40
+ Tool(
41
+ name="semantic_search",
42
+ description="Semantic vector similarity search over the indexed codebase.",
43
+ inputSchema={
44
+ "type": "object",
45
+ "properties": {
46
+ "query": {"type": "string", "description": "Natural language search query."},
47
+ "top_k": {"type": "integer", "description": "Number of results.", "default": 10},
48
+ },
49
+ "required": ["query"],
50
+ },
51
+ ),
52
+ Tool(
53
+ name="keyword_search",
54
+ description="BM25-ranked keyword search over indexed code chunks.",
55
+ inputSchema={
56
+ "type": "object",
57
+ "properties": {
58
+ "query": {"type": "string", "description": "Keyword query."},
59
+ "top_k": {"type": "integer", "default": 10},
60
+ },
61
+ "required": ["query"],
62
+ },
63
+ ),
64
+ Tool(
65
+ name="hybrid_search",
66
+ description="Fused semantic + BM25 search via Reciprocal Rank Fusion.",
67
+ inputSchema={
68
+ "type": "object",
69
+ "properties": {
70
+ "query": {"type": "string", "description": "Search query."},
71
+ "top_k": {"type": "integer", "default": 10},
72
+ },
73
+ "required": ["query"],
74
+ },
75
+ ),
76
+ Tool(
77
+ name="regex_search",
78
+ description="Grep-compatible regex search over indexed code.",
79
+ inputSchema={
80
+ "type": "object",
81
+ "properties": {
82
+ "pattern": {"type": "string", "description": "Regex pattern."},
83
+ "top_k": {"type": "integer", "default": 10},
84
+ "case_insensitive": {"type": "boolean", "default": True},
85
+ },
86
+ "required": ["pattern"],
87
+ },
88
+ ),
89
+ Tool(
90
+ name="explain_symbol",
91
+ description="Get detailed info about a code symbol (function, class, method).",
92
+ inputSchema={
93
+ "type": "object",
94
+ "properties": {
95
+ "symbol_name": {"type": "string", "description": "Name of the symbol."},
96
+ },
97
+ "required": ["symbol_name"],
98
+ },
99
+ ),
100
+ Tool(
101
+ name="index_status",
102
+ description="Get the current index health and stats.",
103
+ inputSchema={"type": "object", "properties": {}},
104
+ ),
105
+ Tool(
106
+ name="reindex",
107
+ description="Trigger a full or incremental re-index of the codebase.",
108
+ inputSchema={
109
+ "type": "object",
110
+ "properties": {
111
+ "force": {"type": "boolean", "default": False},
112
+ },
113
+ },
114
+ ),
115
+ Tool(
116
+ name="health_check",
117
+ description="Check if the MCP server is running and responsive.",
118
+ inputSchema={"type": "object", "properties": {}},
119
+ ),
120
+ Tool(
121
+ name="get_quality_score",
122
+ description="Run code quality analysis: complexity, dead code, duplicates, safety.",
123
+ inputSchema={
124
+ "type": "object",
125
+ "properties": {
126
+ "file_path": {"type": "string", "description": "Specific file to analyze (omit for full project)."},
127
+ },
128
+ },
129
+ ),
130
+ Tool(
131
+ name="find_duplicates",
132
+ description="Detect duplicate or near-duplicate code blocks.",
133
+ inputSchema={
134
+ "type": "object",
135
+ "properties": {
136
+ "threshold": {"type": "number", "default": 0.75, "description": "Similarity threshold (0-1)."},
137
+ },
138
+ },
139
+ ),
140
+ Tool(
141
+ name="grep_files",
142
+ description="Search raw files using regex — no index required. Uses ripgrep when available.",
143
+ inputSchema={
144
+ "type": "object",
145
+ "properties": {
146
+ "pattern": {"type": "string", "description": "Regex pattern."},
147
+ "file_glob": {"type": "string", "description": "Glob filter (e.g. '*.py')."},
148
+ "max_results": {"type": "integer", "default": 50},
149
+ },
150
+ "required": ["pattern"],
151
+ },
152
+ ),
153
+ Tool(
154
+ name="get_file_context",
155
+ description="Retrieve full surrounding function/class context for a symbol or line in a file.",
156
+ inputSchema={
157
+ "type": "object",
158
+ "properties": {
159
+ "file_path": {"type": "string", "description": "Relative file path."},
160
+ "line": {"type": "integer", "description": "Line number to get context for."},
161
+ "symbol_name": {"type": "string", "description": "Symbol name to locate."},
162
+ },
163
+ "required": ["file_path"],
164
+ },
165
+ ),
166
+ Tool(
167
+ name="list_languages",
168
+ description="List all programming languages supported by the tree-sitter parser.",
169
+ inputSchema={"type": "object", "properties": {}},
170
+ ),
171
+ ]
172
+ else:
173
+ MCP_TOOLS: list = [] # type: ignore[no-redef]
174
+
175
+
176
+ # ---- Tool dispatch -------------------------------------------------------
177
+
178
+ def _dispatch_tool(name: str, args: dict[str, Any], project_root: Path) -> Any:
179
+ """Execute a tool and return its result."""
180
+ from semantic_code_intelligence.services.search_service import search_codebase
181
+ from semantic_code_intelligence.services.indexing_service import run_indexing
182
+ from semantic_code_intelligence.storage.index_stats import IndexStats
183
+ from semantic_code_intelligence.storage.symbol_registry import SymbolRegistry
184
+
185
+ index_dir = AppConfig.index_dir(project_root)
186
+
187
+ if name == "semantic_search":
188
+ results = search_codebase(
189
+ query=args["query"], project_root=project_root,
190
+ top_k=args.get("top_k", 10), mode="semantic",
191
+ )
192
+ return [r.to_dict() for r in results]
193
+
194
+ if name == "keyword_search":
195
+ results = search_codebase(
196
+ query=args["query"], project_root=project_root,
197
+ top_k=args.get("top_k", 10), mode="keyword",
198
+ )
199
+ return [r.to_dict() for r in results]
200
+
201
+ if name == "hybrid_search":
202
+ results = search_codebase(
203
+ query=args["query"], project_root=project_root,
204
+ top_k=args.get("top_k", 10), mode="hybrid",
205
+ )
206
+ return [r.to_dict() for r in results]
207
+
208
+ if name == "regex_search":
209
+ results = search_codebase(
210
+ query=args["pattern"], project_root=project_root,
211
+ top_k=args.get("top_k", 10), mode="regex",
212
+ case_insensitive=args.get("case_insensitive", True),
213
+ )
214
+ return [r.to_dict() for r in results]
215
+
216
+ if name == "explain_symbol":
217
+ registry = SymbolRegistry.load(index_dir)
218
+ entries = registry.find_by_name(args["symbol_name"])
219
+ return [
220
+ {
221
+ "name": e.name, "kind": e.kind, "file_path": e.file_path,
222
+ "start_line": e.start_line, "end_line": e.end_line,
223
+ "parent": e.parent, "parameters": e.parameters,
224
+ "language": e.language,
225
+ }
226
+ for e in entries
227
+ ]
228
+
229
+ if name == "index_status":
230
+ try:
231
+ stats = IndexStats.load(index_dir)
232
+ return stats.to_dict() if stats else {"status": "no index"}
233
+ except Exception:
234
+ return {"status": "no index"}
235
+
236
+ if name == "reindex":
237
+ result = run_indexing(project_root, force=args.get("force", False))
238
+ return {
239
+ "files_indexed": result.files_indexed,
240
+ "chunks_created": result.chunks_created,
241
+ "chunks_reused": result.chunks_reused,
242
+ "total_vectors": result.total_vectors,
243
+ }
244
+
245
+ if name == "health_check":
246
+ return {"status": "ok", "project_root": str(project_root)}
247
+
248
+ if name == "get_quality_score":
249
+ from semantic_code_intelligence.ci.quality import analyze_project
250
+ file_paths = [args["file_path"]] if args.get("file_path") else None
251
+ report = analyze_project(project_root, file_paths=file_paths)
252
+ return {
253
+ "complexity_issues": len(report.complexity_issues),
254
+ "dead_code": len(report.dead_code),
255
+ "duplicates": len(report.duplicates),
256
+ "safety_issues": len(report.bandit_issues),
257
+ "maintainability_index": report.maintainability_index,
258
+ }
259
+
260
+ if name == "find_duplicates":
261
+ from semantic_code_intelligence.ci.quality import detect_duplicates
262
+ from semantic_code_intelligence.context.engine import ContextBuilder
263
+ builder = ContextBuilder()
264
+ from semantic_code_intelligence.indexing.scanner import scan_repository
265
+ from semantic_code_intelligence.config.settings import load_config
266
+ config = load_config(project_root)
267
+ scanned = scan_repository(project_root, config.index)
268
+ for sf in scanned:
269
+ try:
270
+ builder.index_file(str(project_root / sf.relative_path))
271
+ except Exception:
272
+ pass
273
+ all_syms = builder.get_all_symbols()
274
+ threshold = args.get("threshold", 0.75)
275
+ dupes = detect_duplicates(all_syms, threshold=threshold)
276
+ return [
277
+ {"symbol_a": d.symbol_a, "symbol_b": d.symbol_b,
278
+ "similarity": round(d.similarity, 3),
279
+ "file_a": d.file_a, "file_b": d.file_b}
280
+ for d in dupes[:20]
281
+ ]
282
+
283
+ if name == "grep_files":
284
+ from semantic_code_intelligence.search.grep import grep_search
285
+ result = grep_search(
286
+ args["pattern"], project_root,
287
+ max_results=args.get("max_results", 50),
288
+ file_glob=args.get("file_glob"),
289
+ )
290
+ return result.to_dict()
291
+
292
+ if name == "get_file_context":
293
+ file_path = args.get("file_path", "")
294
+ target_line = args.get("line")
295
+ symbol_name = args.get("symbol_name")
296
+ full_path = project_root / file_path
297
+ if not full_path.is_file():
298
+ return {"error": f"File not found: {file_path}"}
299
+ try:
300
+ content = full_path.read_text(encoding="utf-8", errors="replace")
301
+ except OSError as exc:
302
+ return {"error": str(exc)}
303
+
304
+ lines = content.splitlines()
305
+
306
+ # If symbol_name given, find its line
307
+ if symbol_name and not target_line:
308
+ for i, ln in enumerate(lines, 1):
309
+ if symbol_name in ln:
310
+ target_line = i
311
+ break
312
+ if not target_line:
313
+ return {"error": f"Symbol '{symbol_name}' not found in {file_path}"}
314
+
315
+ if not target_line:
316
+ return {"error": "Provide either 'line' or 'symbol_name'."}
317
+
318
+ # Return a generous context window (±30 lines)
319
+ start = max(0, target_line - 31)
320
+ end = min(len(lines), target_line + 30)
321
+ context_lines = lines[start:end]
322
+ return {
323
+ "file_path": file_path,
324
+ "start_line": start + 1,
325
+ "end_line": end,
326
+ "content": "\n".join(context_lines),
327
+ }
328
+
329
+ if name == "list_languages":
330
+ from semantic_code_intelligence.parsing.parser import (
331
+ _LANGUAGE_MODULES,
332
+ EXTENSION_TO_LANGUAGE,
333
+ )
334
+ ext_map: dict[str, list[str]] = {}
335
+ for ext, lang in EXTENSION_TO_LANGUAGE.items():
336
+ ext_map.setdefault(lang, []).append(ext)
337
+ return [
338
+ {"language": lang, "module": mod, "extensions": sorted(ext_map.get(lang, []))}
339
+ for lang, mod in sorted(_LANGUAGE_MODULES.items())
340
+ ]
341
+
342
+ return {"error": f"Unknown tool: {name}"}
343
+
344
+
345
+ # ---- Server factory ------------------------------------------------------
346
+
347
+ def _create_server(project_root: Path) -> "Server":
348
+ """Create and configure an MCP ``Server`` with all CodexA tools."""
349
+ if not _HAS_MCP:
350
+ raise RuntimeError("The 'mcp' package is required but not installed.")
351
+ server = Server("codexa-mcp")
352
+
353
+ @server.list_tools()
354
+ async def handle_list_tools() -> list:
355
+ return MCP_TOOLS
356
+
357
+ @server.call_tool()
358
+ async def handle_call_tool(name: str, arguments: dict | None) -> list:
359
+ args = arguments or {}
360
+ try:
361
+ result = _dispatch_tool(name, args, project_root)
362
+ return [TextContent(type="text", text=json.dumps(result, indent=2))]
363
+ except Exception as e:
364
+ return [TextContent(type="text", text=f"Error: {e}")]
365
+
366
+ return server
367
+
368
+
369
+ # ---- Entry point ---------------------------------------------------------
370
+
371
+ def run_mcp_server(project_root: Path) -> None:
372
+ """Run the MCP server in stdio mode.
373
+
374
+ Uses the official MCP SDK to handle JSON-RPC over stdio.
375
+ Compatible with Claude Desktop, Cursor, and other MCP clients.
376
+ """
377
+ if not _HAS_MCP:
378
+ raise RuntimeError("The 'mcp' package is required but not installed.")
379
+ project_root = project_root.resolve()
380
+ logger.info("MCP server starting for %s", project_root)
381
+
382
+ server = _create_server(project_root)
383
+
384
+ async def _run() -> None:
385
+ async with stdio_server() as (read_stream, write_stream):
386
+ await server.run(
387
+ read_stream,
388
+ write_stream,
389
+ server.create_initialization_options(),
390
+ )
391
+
392
+ asyncio.run(_run())
393
+ logger.info("MCP server stopped.")
@@ -0,0 +1,19 @@
1
+ """Parsing package — tree-sitter based code analysis."""
2
+
3
+ from semantic_code_intelligence.parsing.parser import (
4
+ Symbol,
5
+ detect_language,
6
+ extract_classes,
7
+ extract_functions,
8
+ extract_imports,
9
+ parse_file,
10
+ )
11
+
12
+ __all__ = [
13
+ "Symbol",
14
+ "detect_language",
15
+ "extract_classes",
16
+ "extract_functions",
17
+ "extract_imports",
18
+ "parse_file",
19
+ ]