codeatlas-mcp-server 2.20.2
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.
- package/LICENSE +21 -0
- package/README.md +338 -0
- package/dist/index.js +261 -0
- package/dist/index.js.map +1 -0
- package/dist/src/analyzer/parser.js +1072 -0
- package/dist/src/analyzer/parser.js.map +1 -0
- package/dist/src/analyzer/parser.test.js +73 -0
- package/dist/src/analyzer/parser.test.js.map +1 -0
- package/dist/src/analyzer/phpParser.js +147 -0
- package/dist/src/analyzer/phpParser.js.map +1 -0
- package/dist/src/analyzer/pythonParser.js +185 -0
- package/dist/src/analyzer/pythonParser.js.map +1 -0
- package/dist/src/analyzer/types.js +2 -0
- package/dist/src/analyzer/types.js.map +1 -0
- package/dist/src/context.js +3 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/memoryGenerator.js +293 -0
- package/dist/src/memoryGenerator.js.map +1 -0
- package/dist/src/oracleDatabase.js +298 -0
- package/dist/src/oracleDatabase.js.map +1 -0
- package/dist/src/presentation/httpServer.js +306 -0
- package/dist/src/presentation/httpServer.js.map +1 -0
- package/dist/src/presentation/mcpServer.js +1487 -0
- package/dist/src/presentation/mcpServer.js.map +1 -0
- package/dist/src/repositories.js +144 -0
- package/dist/src/repositories.js.map +1 -0
- package/dist/src/securityScanner.js +69 -0
- package/dist/src/securityScanner.js.map +1 -0
- package/dist/src/services/authService.js +24 -0
- package/dist/src/services/authService.js.map +1 -0
- package/dist/src/services/dreamingService.js +119 -0
- package/dist/src/services/dreamingService.js.map +1 -0
- package/dist/src/services/dreamingService.test.js +179 -0
- package/dist/src/services/dreamingService.test.js.map +1 -0
- package/dist/src/services/projectService.js +1068 -0
- package/dist/src/services/projectService.js.map +1 -0
- package/dist/src/services/projectService.test.js +217 -0
- package/dist/src/services/projectService.test.js.map +1 -0
- package/dist/src/services/watcherService.js +164 -0
- package/dist/src/services/watcherService.js.map +1 -0
- package/dist/src/services/watcherService.test.js +65 -0
- package/dist/src/services/watcherService.test.js.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 giauphan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# CodeAtlas MCP Enterprise
|
|
4
|
+
|
|
5
|
+
**Enterprise-Grade, Local-First MCP Server for AI-Powered Code Intelligence**
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://nodejs.org)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](https://modelcontextprotocol.io)
|
|
11
|
+
[](https://www.npmjs.com/package/codeatlas-enterprise)
|
|
12
|
+
[](https://github.com/giauphan/codeatlas-mcp-server/pulls)
|
|
13
|
+
|
|
14
|
+
**CodeAtlas MCP Enterprise** is an ultra-lightweight, local-first [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that securely indexes your codebase, performs deep AST-based analysis, and provides 20+ intelligent tools for AI code assistants. **Your source code never leaves your machine.**
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## π Table of Contents
|
|
21
|
+
|
|
22
|
+
- [Why CodeAtlas MCP?](#-why-codeatlas-mcp)
|
|
23
|
+
- [Features](#-features)
|
|
24
|
+
- [Architecture Overview](#-architecture-overview)
|
|
25
|
+
- [Quick Start](#-quick-start)
|
|
26
|
+
- [Authentication](#-authentication)
|
|
27
|
+
- [AI Editor Integration](#-ai-editor-integration)
|
|
28
|
+
- [Cursor](#cursor)
|
|
29
|
+
- [Claude Desktop](#claude-desktop)
|
|
30
|
+
- [VS Code / Windsurf / Copilot](#vs-code--windsurf--copilot)
|
|
31
|
+
- [MCP Tools Reference](#-mcp-tools-reference)
|
|
32
|
+
- [Analysis & Indexing](#analysis--indexing)
|
|
33
|
+
- [Code Exploration](#code-exploration)
|
|
34
|
+
- [Dependency & Impact Analysis](#dependency--impact-analysis)
|
|
35
|
+
- [Visualization & Diagrams](#visualization--diagrams)
|
|
36
|
+
- [Memory & Persistence](#memory--persistence)
|
|
37
|
+
- [Security & Architecture](#security--architecture)
|
|
38
|
+
- [Project Operations](#project-operations)
|
|
39
|
+
- [Security Model](#-security-model)
|
|
40
|
+
- [Multi-Tenant Mode](#-multi-tenant-mode)
|
|
41
|
+
- [Environment Configuration](#-environment-configuration)
|
|
42
|
+
- [How It Works](#-how-it-works)
|
|
43
|
+
- [License](#-license)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## π― Why CodeAtlas MCP?
|
|
48
|
+
|
|
49
|
+
AI code assistants are powerful β but they work best with **context**. CodeAtlas gives them X-ray vision into your codebase by:
|
|
50
|
+
|
|
51
|
+
- π **Deep parsing** β Understands JavaScript, TypeScript, Python, and PHP at the AST level
|
|
52
|
+
- π§ **Persistent memory** β Retains insights across conversations via Dreaming Memory
|
|
53
|
+
- π **Zero data leakage** β All parsing happens locally, no source code ever transmitted
|
|
54
|
+
- β‘ **Blazing fast** β Full codebase analysis in seconds, incremental re-indexing
|
|
55
|
+
- π **Universal compatibility** β Works with any MCP-compatible editor (Cursor, Claude, VS Code, Windsurf, Copilot)
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## β¨ Features
|
|
60
|
+
|
|
61
|
+
| Feature | Description |
|
|
62
|
+
|---------|-------------|
|
|
63
|
+
| π **Local-First Parsing** | AST analysis runs entirely on your machine β zero code uploaded |
|
|
64
|
+
| π **MCP Protocol** | Works with all MCP-compatible AI editors |
|
|
65
|
+
| π **Auto Workspace Discovery** | Automatically finds projects in your workspace |
|
|
66
|
+
| π **Multi-Language AST** | JavaScript, TypeScript, Python, PHP with deep dependency resolution |
|
|
67
|
+
| π§ **Dreaming Memory** | Persistent AI memory with vector search for cross-session context |
|
|
68
|
+
| π **Multi-Tenant Isolation** | Isolate projects by workspace with sandbox boundaries |
|
|
69
|
+
| π **API Key Auth** | Secure communication via cryptographic hash verification |
|
|
70
|
+
| β‘ **Incremental Indexing** | Only re-parses changed files for near-instant updates |
|
|
71
|
+
| ποΈ **Knowledge Graph** | Visualize modules, classes, and functions as an interactive graph |
|
|
72
|
+
| π **Remote Sync** | Optionally sync metadata to CodeAtlas Enterprise via HTTPS |
|
|
73
|
+
| π **Code Metrics** | LOC, complexity scores, function counts per project |
|
|
74
|
+
| π‘οΈ **Security Scanner** | Detect hardcoded secrets, unsafe functions, SQL injection |
|
|
75
|
+
| π **Real-time Watching** | Auto re-index on file changes via chokidar |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## π Architecture Overview
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
83
|
+
β Your Local Machine β
|
|
84
|
+
β β
|
|
85
|
+
β ββββββββββββ ββββββββββββββ ββββββββββββββββββ β
|
|
86
|
+
β β Source βββββΆβ AST βββββΆβ MCP Server β β
|
|
87
|
+
β β Code β β Parser β β (this tool) βββββΌβββΆ AI Editor
|
|
88
|
+
β β (JS/TS/ β β (local) β βββββββββ¬βββββββββ β
|
|
89
|
+
β β PY/PHP)β ββββββββββββββ β β
|
|
90
|
+
β ββββββββββββ β β
|
|
91
|
+
β βΌ β
|
|
92
|
+
β ββββββββββββββββββββ β
|
|
93
|
+
β β Dreaming Memory β β
|
|
94
|
+
β β (optional: sync) β β
|
|
95
|
+
β ββββββββββ¬ββββββββββ β
|
|
96
|
+
βββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββ
|
|
97
|
+
β HTTPS (optional)
|
|
98
|
+
βΌ
|
|
99
|
+
CodeAtlas Enterprise Server
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## π Quick Start
|
|
105
|
+
|
|
106
|
+
### Prerequisites
|
|
107
|
+
|
|
108
|
+
- **Node.js** v18.0.0 or higher (v20+ recommended)
|
|
109
|
+
|
|
110
|
+
### Install Globally
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm install -g codeatlas-enterprise
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Run
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Scan current directory and start MCP server
|
|
120
|
+
codeatlas-mcp
|
|
121
|
+
|
|
122
|
+
# With API key for remote sync
|
|
123
|
+
codeatlas-mcp --apiKey="your_api_key_here"
|
|
124
|
+
|
|
125
|
+
# Point to a specific project directory
|
|
126
|
+
codeatlas-mcp --projectDir="/path/to/your/project"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
That's it! Your AI editor can now connect to the MCP server running on stdio.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## π Authentication
|
|
134
|
+
|
|
135
|
+
Provide your API Key in one of these ways:
|
|
136
|
+
|
|
137
|
+
1. **Environment Variable**:
|
|
138
|
+
```bash
|
|
139
|
+
export CODEATLAS_API_KEY="your_api_key_here"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
2. **CLI Argument**:
|
|
143
|
+
```bash
|
|
144
|
+
codeatlas-mcp --apiKey="your_api_key_here"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
3. **Local `.env` File** (in the directory where you run the command):
|
|
148
|
+
```env
|
|
149
|
+
CODEATLAS_API_KEY=your_api_key_here
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## π AI Editor Integration
|
|
155
|
+
|
|
156
|
+
### Cursor
|
|
157
|
+
|
|
158
|
+
Add to `~/.cursor/mcp.json` or project-level `.cursor/mcp.json`:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"mcpServers": {
|
|
163
|
+
"codeatlas": {
|
|
164
|
+
"command": "codeatlas-mcp",
|
|
165
|
+
"args": ["--apiKey", "YOUR_API_KEY_HERE"]
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Claude Desktop
|
|
172
|
+
|
|
173
|
+
Add to `claude_desktop_config.json`:
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"mcpServers": {
|
|
178
|
+
"codeatlas": {
|
|
179
|
+
"command": "codeatlas-mcp",
|
|
180
|
+
"args": ["--apiKey", "YOUR_API_KEY_HERE"]
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### VS Code / Windsurf / Copilot
|
|
187
|
+
|
|
188
|
+
For any MCP-compatible editor, use the same JSON structure:
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"mcpServers": {
|
|
193
|
+
"codeatlas": {
|
|
194
|
+
"command": "codeatlas-mcp",
|
|
195
|
+
"args": ["--apiKey", "YOUR_API_KEY_HERE"]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
> **Note:** If you're running without a remote server, omit the `--apiKey` argument. The local MCP tools (analysis, search, graph) work fully offline.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## π MCP Tools Reference
|
|
206
|
+
|
|
207
|
+
CodeAtlas MCP exposes **20+ tools** organized into categories:
|
|
208
|
+
|
|
209
|
+
### Analysis & Indexing
|
|
210
|
+
| Tool | Description |
|
|
211
|
+
|------|-------------|
|
|
212
|
+
| `analyze` | Trigger full AST analysis of the current project |
|
|
213
|
+
| `get_project_structure` | Get entities tree (modules, classes, functions, variables) |
|
|
214
|
+
| `get_file_entities` | List all entities defined in a specific file |
|
|
215
|
+
|
|
216
|
+
### Code Exploration
|
|
217
|
+
| Tool | Description |
|
|
218
|
+
|------|-------------|
|
|
219
|
+
| `search_entities` | Search for functions, classes, modules by name (fuzzy) |
|
|
220
|
+
| `code_search` | Search source file contents for any text or regex |
|
|
221
|
+
| `get_file_content` | Read file contents with line numbers |
|
|
222
|
+
|
|
223
|
+
### Dependency & Impact Analysis
|
|
224
|
+
| Tool | Description |
|
|
225
|
+
|------|-------------|
|
|
226
|
+
| `get_callers` | Find all functions/callers that reference a symbol |
|
|
227
|
+
| `get_callees` | Find everything a function/module imports or calls |
|
|
228
|
+
| `impact_analysis` | Full blast radius: callers + callees + test files |
|
|
229
|
+
| `get_dependencies` | Get import/call/containment/implements relationships |
|
|
230
|
+
|
|
231
|
+
### Visualization & Diagrams
|
|
232
|
+
| Tool | Description |
|
|
233
|
+
|------|-------------|
|
|
234
|
+
| `generate_system_flow` | Mermaid flowchart of module architecture |
|
|
235
|
+
| `generate_feature_flow_diagram` | Mermaid sequence/flow diagram for a feature |
|
|
236
|
+
| `trace_feature_flow` | Ordered call chain from entry point to database |
|
|
237
|
+
|
|
238
|
+
### Memory & Persistence
|
|
239
|
+
| Tool | Description |
|
|
240
|
+
|------|-------------|
|
|
241
|
+
| `query_dream_memories` | Semantic vector search across past AI memories |
|
|
242
|
+
| `save_dream_memory` | Persist an AI insight or observation for future sessions |
|
|
243
|
+
| `get_system_memory` | Retrieve business rules and change logs |
|
|
244
|
+
| `sync_system_memory` | Save business rules or change descriptions |
|
|
245
|
+
|
|
246
|
+
### Security & Architecture
|
|
247
|
+
| Tool | Description |
|
|
248
|
+
|------|-------------|
|
|
249
|
+
| `scan_enterprise_vulnerabilities` | Scan all projects for hardcoded secrets, unsafe functions, SQL injection |
|
|
250
|
+
| `detect_architectural_smells` | Detect circular dependencies, God objects, dead code |
|
|
251
|
+
|
|
252
|
+
### Project Operations
|
|
253
|
+
| Tool | Description |
|
|
254
|
+
|------|-------------|
|
|
255
|
+
| `list_projects` | List all discovered and indexed projects |
|
|
256
|
+
| `refresh_projects` | Re-scan directories for new or removed projects |
|
|
257
|
+
| `get_project_insights` | AI-generated refactoring and maintainability suggestions |
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## π Security Model
|
|
262
|
+
|
|
263
|
+
### π Local-First by Design
|
|
264
|
+
|
|
265
|
+
CodeAtlas MCP Enterprise follows a **zero-trust, local-first architecture**:
|
|
266
|
+
|
|
267
|
+
1. **Parsing is local** β All source file reading, AST generation, and relationship mapping happens on your machine. No source code is ever uploaded.
|
|
268
|
+
|
|
269
|
+
2. **No credentials embedded** β The package contains zero database passwords, Firebase configs, or private server keys. All remote communication uses standard HTTPS with Bearer token auth.
|
|
270
|
+
|
|
271
|
+
3. **Encrypted sync** β If you enable remote sync, metadata is transmitted over HTTPS. The server authenticates via cryptographic hash of your API key.
|
|
272
|
+
|
|
273
|
+
### π What Gets Sent (When Sync is Enabled)
|
|
274
|
+
|
|
275
|
+
Only **structural metadata** is transmitted:
|
|
276
|
+
- File paths and names (relative to project root)
|
|
277
|
+
- Function/class/module names and line numbers
|
|
278
|
+
- Import/export relationships
|
|
279
|
+
- Analysis statistics (file count, LOC, complexity)
|
|
280
|
+
|
|
281
|
+
**Raw source code, credentials, and proprietary logic are never transmitted.**
|
|
282
|
+
|
|
283
|
+
### π Multi-Tenant Isolation
|
|
284
|
+
|
|
285
|
+
When multi-tenant mode is enabled:
|
|
286
|
+
- Each tenant's projects are isolated in separate sandbox directories
|
|
287
|
+
- Path traversal attacks are blocked by strict boundary validation
|
|
288
|
+
- Memory and analysis data are scoped per-tenant
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## π Multi-Tenant Mode
|
|
293
|
+
|
|
294
|
+
Enable tenant isolation via environment variables:
|
|
295
|
+
|
|
296
|
+
```env
|
|
297
|
+
CODEATLAS_MULTI_TENANT=true
|
|
298
|
+
CODEATLAS_PROJECTS_ROOT=./tenants
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Each tenant's projects live in `./tenants/{tenantId}/`, with strict path-boundary enforcement.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## π Environment Configuration
|
|
306
|
+
|
|
307
|
+
| Variable | Default | Description |
|
|
308
|
+
|----------|---------|-------------|
|
|
309
|
+
| `CODEATLAS_API_KEY` | β | API key for authenticating with remote server |
|
|
310
|
+
| `CODEATLAS_API_URL` | `https://your-server.com/api` | Remote CodeAtlas server URL |
|
|
311
|
+
| `CODEATLAS_MULTI_TENANT` | `false` | Enable multi-tenant isolation |
|
|
312
|
+
| `CODEATLAS_PROJECTS_ROOT` | `./tenants` | Root directory for tenant sandboxes |
|
|
313
|
+
| `CODEATLAS_PROJECT_DIR` | `process.cwd()` | Default project path |
|
|
314
|
+
| `NODE_ENV` | `production` | Environment mode |
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## βοΈ How It Works
|
|
319
|
+
|
|
320
|
+
1. **Start** β Run `codeatlas-mcp` in your project directory or point it with `--projectDir`
|
|
321
|
+
2. **Auto-Discover** β The server scans for projects by detecting `package.json`, `pyproject.toml`, `composer.json`
|
|
322
|
+
3. **AST Parse** β Each source file is parsed into an Abstract Syntax Tree
|
|
323
|
+
4. **Build Graph** β Modules, classes, functions, and their relationships form a Knowledge Graph
|
|
324
|
+
5. **Serve MCP** β AI editors query the graph through 20+ MCP tools
|
|
325
|
+
6. **Dream** β Insights persist across sessions via Dreaming Memory (optional remote vector store)
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## π License
|
|
330
|
+
|
|
331
|
+
[MIT](LICENSE) Β© 2026 Giau Phan
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## π Related Projects
|
|
336
|
+
|
|
337
|
+
- [CodeAtlas AI](https://github.com/giauphan/codeatlas-ai) β Full enterprise server with Oracle 26ai memory, dashboard, security scanner
|
|
338
|
+
- [npm package](https://www.npmjs.com/package/codeatlas-enterprise) β Install via npm
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import * as dotenv from "dotenv";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { RootsListChangedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import * as fs from "fs";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import * as os from "os";
|
|
9
|
+
// Configure centralized log file in ~/.codeatlas/mcp.log
|
|
10
|
+
const homeDir = os.homedir();
|
|
11
|
+
const logDir = path.join(homeDir, ".codeatlas");
|
|
12
|
+
const logFilePath = path.join(logDir, "mcp.log");
|
|
13
|
+
const pidFilePath = path.join(logDir, "mcp.pid");
|
|
14
|
+
try {
|
|
15
|
+
if (!fs.existsSync(logDir)) {
|
|
16
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
// Ignore directory creation errors
|
|
21
|
+
}
|
|
22
|
+
// ββ Single-instance PID guard ββββββββββββββββββββββββββββββββββββββββββ
|
|
23
|
+
// Prevents duplicate MCP server processes from consuming excessive memory.
|
|
24
|
+
// But allow --version and --help flags to pass through.
|
|
25
|
+
// Handle --version before PID guard
|
|
26
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
27
|
+
// Try both relative locations (source: index.ts, dist: dist/index.js)
|
|
28
|
+
let pkg;
|
|
29
|
+
for (const p of ['./package.json', '../package.json']) {
|
|
30
|
+
try {
|
|
31
|
+
pkg = JSON.parse(fs.readFileSync(new URL(p, import.meta.url), 'utf-8'));
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
}
|
|
36
|
+
if (pkg)
|
|
37
|
+
console.log(pkg.version);
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
if (!process.argv.includes('--help') && !process.argv.includes('-h')) {
|
|
41
|
+
try {
|
|
42
|
+
if (fs.existsSync(pidFilePath)) {
|
|
43
|
+
const existingPid = parseInt(fs.readFileSync(pidFilePath, "utf-8").trim(), 10);
|
|
44
|
+
if (!isNaN(existingPid) && existingPid > 0) {
|
|
45
|
+
try {
|
|
46
|
+
process.kill(existingPid, 0); // Check if alive
|
|
47
|
+
// Another instance is already running. Exit immediately to avoid duplicates.
|
|
48
|
+
// DO NOT kill the old instance β that would break the active MCP connection
|
|
49
|
+
// and cause Hermes to reconnect in an infinite kill-restart loop.
|
|
50
|
+
console.error(`[PID-Guard] π Instance already running (PID: ${existingPid}). New instance exiting.`);
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
if (e?.code === 'ESRCH') {
|
|
55
|
+
console.error(`[PID-Guard] ποΈ Stale PID ${existingPid} β old instance is gone. Starting fresh.`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.error(`[PID-Guard] β οΈ Cannot verify PID ${existingPid}. Will overwrite.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
fs.writeFileSync(pidFilePath, String(process.pid));
|
|
64
|
+
console.error(`[PID-Guard] π Lock acquired (PID: ${process.pid})`);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.error(`[PID-Guard] β οΈ Could not write PID file β running without guard: ${err}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
71
|
+
// β οΈ NOTE: API key must be set via CODEATLAS_API_KEY environment variable or .env file.
|
|
72
|
+
// Passing API keys via command-line arguments is NOT supported β they are visible
|
|
73
|
+
// to all users on the system via `ps aux`. Use environment variables instead.
|
|
74
|
+
// Parse command line arguments for projectDir (safe directory path, not a secret)
|
|
75
|
+
const projectDirArgIndex = process.argv.findIndex(arg => arg.startsWith('--projectDir'));
|
|
76
|
+
if (projectDirArgIndex !== -1) {
|
|
77
|
+
const arg = process.argv[projectDirArgIndex];
|
|
78
|
+
let val = '';
|
|
79
|
+
if (arg.includes('=')) {
|
|
80
|
+
val = arg.split('=')[1];
|
|
81
|
+
}
|
|
82
|
+
else if (projectDirArgIndex + 1 < process.argv.length) {
|
|
83
|
+
val = process.argv[projectDirArgIndex + 1];
|
|
84
|
+
}
|
|
85
|
+
if (val) {
|
|
86
|
+
process.env.CODEATLAS_PROJECT_DIR = val;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Async logging queue to prevent blocking the Event Loop on console.error
|
|
90
|
+
const logQueue = [];
|
|
91
|
+
let isWritingLogs = false;
|
|
92
|
+
async function flushLogQueue() {
|
|
93
|
+
if (isWritingLogs || logQueue.length === 0)
|
|
94
|
+
return;
|
|
95
|
+
isWritingLogs = true;
|
|
96
|
+
while (logQueue.length > 0) {
|
|
97
|
+
const message = logQueue.shift();
|
|
98
|
+
if (message) {
|
|
99
|
+
try {
|
|
100
|
+
await fs.promises.appendFile(logFilePath, message);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
// Ignore write errors
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
isWritingLogs = false;
|
|
108
|
+
}
|
|
109
|
+
const originalConsoleError = console.error;
|
|
110
|
+
console.error = (...args) => {
|
|
111
|
+
originalConsoleError(...args);
|
|
112
|
+
try {
|
|
113
|
+
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
|
|
114
|
+
const timestamp = new Date().toISOString();
|
|
115
|
+
// Cap log queue at 1000 entries to prevent unbounded memory growth
|
|
116
|
+
if (logQueue.length >= 1000) {
|
|
117
|
+
logQueue.shift();
|
|
118
|
+
}
|
|
119
|
+
logQueue.push(`[${timestamp}] ${message}\n`);
|
|
120
|
+
flushLogQueue().catch(() => { });
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
// Ignore queue errors
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
// Import Presentation Adapters
|
|
127
|
+
import { server } from "./src/presentation/mcpServer.js";
|
|
128
|
+
// Import Domain / Application Services
|
|
129
|
+
import { checkAuth } from "./src/services/authService.js";
|
|
130
|
+
import { getStats, discoverProjects, loadAnalysis, discoverProjectsAsync, loadAnalysisAsync, getWorkspaceFromAncestors, isSystemIdeDirectory, discoverGitSubProjects } from "./src/services/projectService.js";
|
|
131
|
+
import { startWatcher, stopWatcher, isIndexingEnabledForProject } from "./src/services/watcherService.js";
|
|
132
|
+
// Load environment variables
|
|
133
|
+
dotenv.config();
|
|
134
|
+
// Start server
|
|
135
|
+
async function main() {
|
|
136
|
+
startWatcher();
|
|
137
|
+
// Function to scan workspace roots from the client
|
|
138
|
+
async function scanRoots() {
|
|
139
|
+
let succeeded = false;
|
|
140
|
+
try {
|
|
141
|
+
const result = await server.server.listRoots();
|
|
142
|
+
if (result && result.roots && result.roots.length > 0) {
|
|
143
|
+
succeeded = true;
|
|
144
|
+
console.error(`[Auto-Scan] π Discovered ${result.roots.length} workspace root(s) from client.`);
|
|
145
|
+
for (const root of result.roots) {
|
|
146
|
+
if (root.uri.startsWith("file://")) {
|
|
147
|
+
const workspacePath = fileURLToPath(root.uri).trim();
|
|
148
|
+
if (isSystemIdeDirectory(workspacePath)) {
|
|
149
|
+
console.error(`[Auto-Scan] π‘οΈ Ignored IDE system/extensions directory: ${workspacePath}`);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
// Scan subdirectories for .git projects
|
|
153
|
+
const subProjects = await discoverGitSubProjects(workspacePath, true);
|
|
154
|
+
if (subProjects.length > 0) {
|
|
155
|
+
console.error(`[Auto-Scan] π¦ Found ${subProjects.length} project(s) with .git and open in IDE inside ${path.basename(workspacePath)}`);
|
|
156
|
+
for (const subDir of subProjects) {
|
|
157
|
+
const subName = path.basename(subDir);
|
|
158
|
+
isIndexingEnabledForProject(subName).then((enabled) => {
|
|
159
|
+
if (!enabled) {
|
|
160
|
+
console.error(`[Auto-Scan] βΈοΈ Auto-indexing disabled for [${subName}]. Skipping.`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
console.error(`[Auto-Scan] π Indexing sub-project: ${subDir}`);
|
|
164
|
+
loadAnalysisAsync(subDir, true).then((loaded) => {
|
|
165
|
+
if (loaded)
|
|
166
|
+
console.error(`[Auto-Scan] β
Indexed: ${subDir}`);
|
|
167
|
+
else
|
|
168
|
+
console.error(`[Auto-Scan] β οΈ Skipped: ${subDir}`);
|
|
169
|
+
}).catch((err) => {
|
|
170
|
+
console.error(`[Auto-Scan] β Failed: ${subDir}: ${err}`);
|
|
171
|
+
});
|
|
172
|
+
}).catch(() => { });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
console.error(`[Auto-Scan] βΉοΈ No .git projects found under container root: ${workspacePath}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
console.error(`[Auto-Scan] β οΈ Ignored non-file URI root: ${root.uri}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.error("[Auto-Scan] βΉοΈ No workspace roots returned by client. Falling back to active workspace.");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
console.error(`[Auto-Scan] β οΈ Failed to list workspace roots: ${err}. Falling back to active workspace.`);
|
|
190
|
+
}
|
|
191
|
+
if (!succeeded) {
|
|
192
|
+
const activeWorkspace = process.env.CODEATLAS_PROJECT_DIR || getWorkspaceFromAncestors() || process.env.GEMINI_CLI_IDE_WORKSPACE_PATH || process.cwd();
|
|
193
|
+
if (isSystemIdeDirectory(activeWorkspace)) {
|
|
194
|
+
console.error(`[Auto-Scan] π‘οΈ Ignored IDE system directory fallback: ${activeWorkspace}`);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const subProjects = await discoverGitSubProjects(activeWorkspace, true);
|
|
198
|
+
if (subProjects.length > 0) {
|
|
199
|
+
console.error(`[Auto-Scan] π¦ Fallback: found ${subProjects.length} IDE-open .git project(s) in ${activeWorkspace}`);
|
|
200
|
+
for (const subDir of subProjects) {
|
|
201
|
+
const subName = path.basename(subDir);
|
|
202
|
+
isIndexingEnabledForProject(subName).then((enabled) => {
|
|
203
|
+
if (!enabled)
|
|
204
|
+
return;
|
|
205
|
+
loadAnalysisAsync(subDir, true).catch(() => { });
|
|
206
|
+
}).catch(() => { });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
console.error(`[Auto-Scan] βΉοΈ No .git projects found in workspace fallback: ${activeWorkspace}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Hook into client initialized event to fetch and index workspace roots
|
|
215
|
+
server.server.oninitialized = () => {
|
|
216
|
+
console.error("[Auto-Scan] π MCP Client connection initialized. Checking workspace roots...");
|
|
217
|
+
scanRoots();
|
|
218
|
+
};
|
|
219
|
+
// Listen for changes to workspace roots
|
|
220
|
+
server.server.setNotificationHandler(RootsListChangedNotificationSchema, (notification) => {
|
|
221
|
+
console.error("[Auto-Scan] π Received roots/list_changed notification from client. Re-scanning workspace roots...");
|
|
222
|
+
scanRoots();
|
|
223
|
+
});
|
|
224
|
+
// Stdio Mode - for local use (e.g. Claude Desktop, Cursor)
|
|
225
|
+
const transport = new StdioServerTransport();
|
|
226
|
+
await server.connect(transport);
|
|
227
|
+
console.error("CodeAtlas MCP server running on stdio");
|
|
228
|
+
}
|
|
229
|
+
main().catch(console.error);
|
|
230
|
+
// ββ Graceful shutdown handlers βββββββββββββββββββββββββββββββββββββββββ
|
|
231
|
+
// Prevent zombie processes by cleaning up watchers, cache, and PID file.
|
|
232
|
+
function cleanup(signal) {
|
|
233
|
+
console.error(`[Cleanup] π§Ή Received ${signal}. Shutting down...`);
|
|
234
|
+
try {
|
|
235
|
+
stopWatcher();
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
console.error(`[Cleanup] β οΈ Watcher cleanup error: ${e}`);
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
if (fs.existsSync(pidFilePath)) {
|
|
242
|
+
fs.unlinkSync(pidFilePath);
|
|
243
|
+
console.error(`[Cleanup] ποΈ PID file removed.`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch (e) {
|
|
247
|
+
console.error(`[Cleanup] β οΈ PID file cleanup error: ${e}`);
|
|
248
|
+
}
|
|
249
|
+
process.exit(0);
|
|
250
|
+
}
|
|
251
|
+
process.on("SIGTERM", () => cleanup("SIGTERM"));
|
|
252
|
+
process.on("SIGINT", () => cleanup("SIGINT"));
|
|
253
|
+
process.on("SIGQUIT", () => cleanup("SIGQUIT"));
|
|
254
|
+
process.on("uncaughtException", (err) => {
|
|
255
|
+
console.error(`[Fatal] π₯ Uncaught exception: ${err}`);
|
|
256
|
+
cleanup("uncaughtException");
|
|
257
|
+
});
|
|
258
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
259
|
+
// Re-export core modules/helpers to maintain compatibility with test suite
|
|
260
|
+
export { server, checkAuth, getStats, discoverProjects, loadAnalysis, discoverProjectsAsync, loadAnalysisAsync };
|
|
261
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|