codedev-mcp 3.2.0
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/CHANGELOG.md +90 -0
- package/LICENSE +21 -0
- package/README.md +760 -0
- package/dist/analyzers/api-contract.d.ts +46 -0
- package/dist/analyzers/api-contract.d.ts.map +1 -0
- package/dist/analyzers/api-contract.js +319 -0
- package/dist/analyzers/api-contract.js.map +1 -0
- package/dist/analyzers/architecture.d.ts +37 -0
- package/dist/analyzers/architecture.d.ts.map +1 -0
- package/dist/analyzers/architecture.js +149 -0
- package/dist/analyzers/architecture.js.map +1 -0
- package/dist/analyzers/branch-compare.d.ts +46 -0
- package/dist/analyzers/branch-compare.d.ts.map +1 -0
- package/dist/analyzers/branch-compare.js +128 -0
- package/dist/analyzers/branch-compare.js.map +1 -0
- package/dist/analyzers/cicd.d.ts +42 -0
- package/dist/analyzers/cicd.d.ts.map +1 -0
- package/dist/analyzers/cicd.js +237 -0
- package/dist/analyzers/cicd.js.map +1 -0
- package/dist/analyzers/codebase.d.ts +64 -0
- package/dist/analyzers/codebase.d.ts.map +1 -0
- package/dist/analyzers/codebase.js +354 -0
- package/dist/analyzers/codebase.js.map +1 -0
- package/dist/analyzers/complexity-heatmap.d.ts +50 -0
- package/dist/analyzers/complexity-heatmap.d.ts.map +1 -0
- package/dist/analyzers/complexity-heatmap.js +156 -0
- package/dist/analyzers/complexity-heatmap.js.map +1 -0
- package/dist/analyzers/context-pack.d.ts +43 -0
- package/dist/analyzers/context-pack.d.ts.map +1 -0
- package/dist/analyzers/context-pack.js +232 -0
- package/dist/analyzers/context-pack.js.map +1 -0
- package/dist/analyzers/coverage.d.ts +70 -0
- package/dist/analyzers/coverage.d.ts.map +1 -0
- package/dist/analyzers/coverage.js +313 -0
- package/dist/analyzers/coverage.js.map +1 -0
- package/dist/analyzers/db-schema.d.ts +55 -0
- package/dist/analyzers/db-schema.d.ts.map +1 -0
- package/dist/analyzers/db-schema.js +237 -0
- package/dist/analyzers/db-schema.js.map +1 -0
- package/dist/analyzers/dead-code.d.ts +34 -0
- package/dist/analyzers/dead-code.d.ts.map +1 -0
- package/dist/analyzers/dead-code.js +131 -0
- package/dist/analyzers/dead-code.js.map +1 -0
- package/dist/analyzers/dep-vuln.d.ts +36 -0
- package/dist/analyzers/dep-vuln.d.ts.map +1 -0
- package/dist/analyzers/dep-vuln.js +342 -0
- package/dist/analyzers/dep-vuln.js.map +1 -0
- package/dist/analyzers/docs.d.ts +47 -0
- package/dist/analyzers/docs.d.ts.map +1 -0
- package/dist/analyzers/docs.js +473 -0
- package/dist/analyzers/docs.js.map +1 -0
- package/dist/analyzers/git.d.ts +115 -0
- package/dist/analyzers/git.d.ts.map +1 -0
- package/dist/analyzers/git.js +214 -0
- package/dist/analyzers/git.js.map +1 -0
- package/dist/analyzers/iac.d.ts +39 -0
- package/dist/analyzers/iac.d.ts.map +1 -0
- package/dist/analyzers/iac.js +233 -0
- package/dist/analyzers/iac.js.map +1 -0
- package/dist/analyzers/impact.d.ts +51 -0
- package/dist/analyzers/impact.d.ts.map +1 -0
- package/dist/analyzers/impact.js +235 -0
- package/dist/analyzers/impact.js.map +1 -0
- package/dist/analyzers/monorepo.d.ts +36 -0
- package/dist/analyzers/monorepo.d.ts.map +1 -0
- package/dist/analyzers/monorepo.js +233 -0
- package/dist/analyzers/monorepo.js.map +1 -0
- package/dist/analyzers/notebook.d.ts +53 -0
- package/dist/analyzers/notebook.d.ts.map +1 -0
- package/dist/analyzers/notebook.js +149 -0
- package/dist/analyzers/notebook.js.map +1 -0
- package/dist/analyzers/perf-profile.d.ts +39 -0
- package/dist/analyzers/perf-profile.d.ts.map +1 -0
- package/dist/analyzers/perf-profile.js +222 -0
- package/dist/analyzers/perf-profile.js.map +1 -0
- package/dist/analyzers/scaffold.d.ts +46 -0
- package/dist/analyzers/scaffold.d.ts.map +1 -0
- package/dist/analyzers/scaffold.js +313 -0
- package/dist/analyzers/scaffold.js.map +1 -0
- package/dist/analyzers/security.d.ts +42 -0
- package/dist/analyzers/security.d.ts.map +1 -0
- package/dist/analyzers/security.js +281 -0
- package/dist/analyzers/security.js.map +1 -0
- package/dist/analyzers/symbols.d.ts +49 -0
- package/dist/analyzers/symbols.d.ts.map +1 -0
- package/dist/analyzers/symbols.js +212 -0
- package/dist/analyzers/symbols.js.map +1 -0
- package/dist/analyzers/tree-sitter.d.ts +71 -0
- package/dist/analyzers/tree-sitter.d.ts.map +1 -0
- package/dist/analyzers/tree-sitter.js +333 -0
- package/dist/analyzers/tree-sitter.js.map +1 -0
- package/dist/analyzers/type-flow.d.ts +39 -0
- package/dist/analyzers/type-flow.d.ts.map +1 -0
- package/dist/analyzers/type-flow.js +75 -0
- package/dist/analyzers/type-flow.js.map +1 -0
- package/dist/cache/memory-cache.d.ts +130 -0
- package/dist/cache/memory-cache.d.ts.map +1 -0
- package/dist/cache/memory-cache.js +273 -0
- package/dist/cache/memory-cache.js.map +1 -0
- package/dist/config.d.ts +32 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +57 -0
- package/dist/config.js.map +1 -0
- package/dist/constants/instructions.d.ts +2 -0
- package/dist/constants/instructions.d.ts.map +1 -0
- package/dist/constants/instructions.js +82 -0
- package/dist/constants/instructions.js.map +1 -0
- package/dist/db/connection.d.ts +12 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +34 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/json-store.d.ts +111 -0
- package/dist/db/json-store.d.ts.map +1 -0
- package/dist/db/json-store.js +201 -0
- package/dist/db/json-store.js.map +1 -0
- package/dist/db/sqlite-store.d.ts +153 -0
- package/dist/db/sqlite-store.d.ts.map +1 -0
- package/dist/db/sqlite-store.js +388 -0
- package/dist/db/sqlite-store.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/health.d.ts +35 -0
- package/dist/resources/health.d.ts.map +1 -0
- package/dist/resources/health.js +81 -0
- package/dist/resources/health.js.map +1 -0
- package/dist/schemas/output-schemas.d.ts +517 -0
- package/dist/schemas/output-schemas.d.ts.map +1 -0
- package/dist/schemas/output-schemas.js +296 -0
- package/dist/schemas/output-schemas.js.map +1 -0
- package/dist/search/fast-search.d.ts +90 -0
- package/dist/search/fast-search.d.ts.map +1 -0
- package/dist/search/fast-search.js +387 -0
- package/dist/search/fast-search.js.map +1 -0
- package/dist/search/semantic.d.ts +26 -0
- package/dist/search/semantic.d.ts.map +1 -0
- package/dist/search/semantic.js +458 -0
- package/dist/search/semantic.js.map +1 -0
- package/dist/tools/analysis.d.ts +7 -0
- package/dist/tools/analysis.d.ts.map +1 -0
- package/dist/tools/analysis.js +491 -0
- package/dist/tools/analysis.js.map +1 -0
- package/dist/tools/architecture.d.ts +7 -0
- package/dist/tools/architecture.d.ts.map +1 -0
- package/dist/tools/architecture.js +176 -0
- package/dist/tools/architecture.js.map +1 -0
- package/dist/tools/devops.d.ts +7 -0
- package/dist/tools/devops.d.ts.map +1 -0
- package/dist/tools/devops.js +179 -0
- package/dist/tools/devops.js.map +1 -0
- package/dist/tools/docs.d.ts +7 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/docs.js +102 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/git.d.ts +7 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +475 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/nav.d.ts +7 -0
- package/dist/tools/nav.d.ts.map +1 -0
- package/dist/tools/nav.js +275 -0
- package/dist/tools/nav.js.map +1 -0
- package/dist/tools/notebook.d.ts +7 -0
- package/dist/tools/notebook.d.ts.map +1 -0
- package/dist/tools/notebook.js +102 -0
- package/dist/tools/notebook.js.map +1 -0
- package/dist/tools/performance.d.ts +7 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +59 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/tools/quality.d.ts +7 -0
- package/dist/tools/quality.d.ts.map +1 -0
- package/dist/tools/quality.js +279 -0
- package/dist/tools/quality.js.map +1 -0
- package/dist/tools/scaffold.d.ts +7 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +80 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/search.d.ts +7 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +308 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/security.d.ts +7 -0
- package/dist/tools/security.d.ts.map +1 -0
- package/dist/tools/security.js +138 -0
- package/dist/tools/security.js.map +1 -0
- package/dist/utils/analytics.d.ts +69 -0
- package/dist/utils/analytics.d.ts.map +1 -0
- package/dist/utils/analytics.js +144 -0
- package/dist/utils/analytics.js.map +1 -0
- package/dist/utils/concurrency.d.ts +43 -0
- package/dist/utils/concurrency.d.ts.map +1 -0
- package/dist/utils/concurrency.js +78 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/fallback.d.ts +52 -0
- package/dist/utils/fallback.d.ts.map +1 -0
- package/dist/utils/fallback.js +137 -0
- package/dist/utils/fallback.js.map +1 -0
- package/dist/utils/git-hooks.d.ts +24 -0
- package/dist/utils/git-hooks.d.ts.map +1 -0
- package/dist/utils/git-hooks.js +108 -0
- package/dist/utils/git-hooks.js.map +1 -0
- package/dist/utils/languages.d.ts +72 -0
- package/dist/utils/languages.d.ts.map +1 -0
- package/dist/utils/languages.js +463 -0
- package/dist/utils/languages.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +34 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/plugins.d.ts +105 -0
- package/dist/utils/plugins.d.ts.map +1 -0
- package/dist/utils/plugins.js +325 -0
- package/dist/utils/plugins.js.map +1 -0
- package/dist/utils/security.d.ts +17 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +48 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/streaming.d.ts +56 -0
- package/dist/utils/streaming.d.ts.map +1 -0
- package/dist/utils/streaming.js +95 -0
- package/dist/utils/streaming.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/mcp.json +100 -0
- package/package.json +89 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite-based persistent index for codebase data.
|
|
3
|
+
* Uses sql.js (WASM) — zero native compilation, works everywhere.
|
|
4
|
+
* Drop-in replacement for JsonStore with dramatically faster queries at scale.
|
|
5
|
+
*
|
|
6
|
+
* Storage: .codedev-mcp/index.sqlite in the project root.
|
|
7
|
+
*/
|
|
8
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { stat as fsStat } from 'node:fs/promises';
|
|
11
|
+
const INDEX_DIR = '.codedev-mcp';
|
|
12
|
+
const INDEX_FILE = 'index.sqlite';
|
|
13
|
+
const SCHEMA_VERSION = 2;
|
|
14
|
+
/**
|
|
15
|
+
* SQLite-backed persistent index for codebase data using sql.js WASM.
|
|
16
|
+
*/
|
|
17
|
+
export class SqliteStore {
|
|
18
|
+
dbPath;
|
|
19
|
+
db = null;
|
|
20
|
+
dirty = false;
|
|
21
|
+
SQL = null;
|
|
22
|
+
/**
|
|
23
|
+
* Create a new SqliteStore instance.
|
|
24
|
+
* @param cwd - The working directory for the database file.
|
|
25
|
+
*/
|
|
26
|
+
constructor(cwd) {
|
|
27
|
+
this.dbPath = path.join(cwd, INDEX_DIR, INDEX_FILE);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Initialize sql.js WASM module.
|
|
31
|
+
* @returns The initialized sql.js static instance.
|
|
32
|
+
*/
|
|
33
|
+
async initSqlJs() {
|
|
34
|
+
if (this.SQL)
|
|
35
|
+
return this.SQL;
|
|
36
|
+
const initSqlJs = (await import('sql.js')).default;
|
|
37
|
+
const sql = await initSqlJs();
|
|
38
|
+
this.SQL = sql;
|
|
39
|
+
return sql;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Run a query with bind parameters.
|
|
43
|
+
* Replaces db.run() which doesn't support params in all cases.
|
|
44
|
+
* @param sql - The SQL query string.
|
|
45
|
+
* @param params - Bind parameters for the query.
|
|
46
|
+
* @returns An array of result rows.
|
|
47
|
+
*/
|
|
48
|
+
query(sql, params = []) {
|
|
49
|
+
if (!this.db)
|
|
50
|
+
return [];
|
|
51
|
+
try {
|
|
52
|
+
const db = this.db;
|
|
53
|
+
const stmt = db.prepare(sql);
|
|
54
|
+
stmt.bind(params);
|
|
55
|
+
const rows = [];
|
|
56
|
+
while (stmt.step()) {
|
|
57
|
+
rows.push(stmt.get());
|
|
58
|
+
}
|
|
59
|
+
stmt.free();
|
|
60
|
+
return rows;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create tables if they don't exist.
|
|
68
|
+
*/
|
|
69
|
+
createSchema() {
|
|
70
|
+
if (!this.db)
|
|
71
|
+
return;
|
|
72
|
+
this.db.run(`
|
|
73
|
+
CREATE TABLE IF NOT EXISTS meta (
|
|
74
|
+
key TEXT PRIMARY KEY,
|
|
75
|
+
value TEXT
|
|
76
|
+
)
|
|
77
|
+
`);
|
|
78
|
+
this.db.run(`
|
|
79
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
80
|
+
path TEXT PRIMARY KEY,
|
|
81
|
+
mtime REAL NOT NULL,
|
|
82
|
+
lines INTEGER NOT NULL,
|
|
83
|
+
language TEXT NOT NULL,
|
|
84
|
+
size INTEGER NOT NULL
|
|
85
|
+
)
|
|
86
|
+
`);
|
|
87
|
+
this.db.run(`
|
|
88
|
+
CREATE TABLE IF NOT EXISTS symbols (
|
|
89
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
90
|
+
name TEXT NOT NULL,
|
|
91
|
+
type TEXT NOT NULL,
|
|
92
|
+
file TEXT NOT NULL,
|
|
93
|
+
line INTEGER NOT NULL,
|
|
94
|
+
exported INTEGER NOT NULL DEFAULT 0
|
|
95
|
+
)
|
|
96
|
+
`);
|
|
97
|
+
this.db.run(`
|
|
98
|
+
CREATE TABLE IF NOT EXISTS imports (
|
|
99
|
+
file TEXT NOT NULL,
|
|
100
|
+
import_path TEXT NOT NULL,
|
|
101
|
+
PRIMARY KEY (file, import_path)
|
|
102
|
+
)
|
|
103
|
+
`);
|
|
104
|
+
// Indices for fast lookups
|
|
105
|
+
this.db.run(`CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name)`);
|
|
106
|
+
this.db.run(`CREATE INDEX IF NOT EXISTS idx_symbols_file ON symbols(file)`);
|
|
107
|
+
this.db.run(`CREATE INDEX IF NOT EXISTS idx_symbols_type ON symbols(type)`);
|
|
108
|
+
this.db.run(`CREATE INDEX IF NOT EXISTS idx_imports_file ON imports(file)`);
|
|
109
|
+
this.db.run(`CREATE INDEX IF NOT EXISTS idx_imports_path ON imports(import_path)`);
|
|
110
|
+
// Analytics schema
|
|
111
|
+
this.db.run(`
|
|
112
|
+
CREATE TABLE IF NOT EXISTS usage_stats (
|
|
113
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
114
|
+
tool TEXT NOT NULL,
|
|
115
|
+
timestamp INTEGER NOT NULL,
|
|
116
|
+
duration INTEGER NOT NULL,
|
|
117
|
+
success INTEGER NOT NULL,
|
|
118
|
+
cached INTEGER NOT NULL
|
|
119
|
+
)
|
|
120
|
+
`);
|
|
121
|
+
this.db.run(`CREATE INDEX IF NOT EXISTS idx_usage_tool ON usage_stats(tool)`);
|
|
122
|
+
this.db.run(`CREATE INDEX IF NOT EXISTS idx_usage_ts ON usage_stats(timestamp)`);
|
|
123
|
+
// Set schema version
|
|
124
|
+
this.db.run(`INSERT OR REPLACE INTO meta (key, value) VALUES ('version', ?)`, [String(SCHEMA_VERSION)]);
|
|
125
|
+
this.db.run(`INSERT OR REPLACE INTO meta (key, value) VALUES ('updated', ?)`, [new Date().toISOString()]);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Load existing database from disk. Returns false if none exists or version mismatch.
|
|
129
|
+
* @returns True if the database was loaded successfully.
|
|
130
|
+
*/
|
|
131
|
+
async load() {
|
|
132
|
+
try {
|
|
133
|
+
const SQL = await this.initSqlJs();
|
|
134
|
+
const data = await readFile(this.dbPath);
|
|
135
|
+
this.db = new SQL.Database(data);
|
|
136
|
+
// Check schema version
|
|
137
|
+
const result = this.db.exec(`SELECT value FROM meta WHERE key = 'version'`);
|
|
138
|
+
if (!result.length || !result[0].values.length) {
|
|
139
|
+
this.db.close();
|
|
140
|
+
this.db = null;
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const version = parseInt(result[0].values[0][0], 10);
|
|
144
|
+
if (version !== SCHEMA_VERSION) {
|
|
145
|
+
this.db.close();
|
|
146
|
+
this.db = null;
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Save database to disk.
|
|
157
|
+
*/
|
|
158
|
+
async save() {
|
|
159
|
+
if (!this.db || !this.dirty)
|
|
160
|
+
return;
|
|
161
|
+
this.db.run(`INSERT OR REPLACE INTO meta (key, value) VALUES ('updated', ?)`, [new Date().toISOString()]);
|
|
162
|
+
const data = this.db.export();
|
|
163
|
+
const dir = path.dirname(this.dbPath);
|
|
164
|
+
await mkdir(dir, { recursive: true });
|
|
165
|
+
await writeFile(this.dbPath, Buffer.from(data));
|
|
166
|
+
this.dirty = false;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Initialize a new empty database.
|
|
170
|
+
* @param _ - The working directory (unused, kept for interface compatibility).
|
|
171
|
+
*/
|
|
172
|
+
async init(_) {
|
|
173
|
+
const SQL = await this.initSqlJs();
|
|
174
|
+
this.db = new SQL.Database();
|
|
175
|
+
this.createSchema();
|
|
176
|
+
this.db.run(`INSERT OR REPLACE INTO meta (key, value) VALUES ('created', ?)`, [new Date().toISOString()]);
|
|
177
|
+
this.dirty = true;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check if a file needs re-indexing (mtime changed).
|
|
181
|
+
* @param filePath - The file path to check.
|
|
182
|
+
* @returns True if the file needs re-indexing.
|
|
183
|
+
*/
|
|
184
|
+
async needsReindex(filePath) {
|
|
185
|
+
if (!this.db)
|
|
186
|
+
return true;
|
|
187
|
+
const rows = this.query('SELECT mtime FROM files WHERE path = ?', [filePath]);
|
|
188
|
+
if (!rows.length)
|
|
189
|
+
return true;
|
|
190
|
+
const storedMtime = rows[0][0];
|
|
191
|
+
try {
|
|
192
|
+
const s = await fsStat(filePath);
|
|
193
|
+
return s.mtimeMs !== storedMtime;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Update file entry in index.
|
|
201
|
+
* @param file - The file entry to update.
|
|
202
|
+
*/
|
|
203
|
+
updateFile(file) {
|
|
204
|
+
if (!this.db)
|
|
205
|
+
return;
|
|
206
|
+
this.db.run(`INSERT OR REPLACE INTO files (path, mtime, lines, language, size) VALUES (?, ?, ?, ?, ?)`, [
|
|
207
|
+
file.path,
|
|
208
|
+
file.mtime,
|
|
209
|
+
file.lines,
|
|
210
|
+
file.language,
|
|
211
|
+
file.size,
|
|
212
|
+
]);
|
|
213
|
+
this.dirty = true;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Update symbols for a file (replaces all).
|
|
217
|
+
* @param filePath - The file path whose symbols are being updated.
|
|
218
|
+
* @param symbols - The new symbols for the file.
|
|
219
|
+
*/
|
|
220
|
+
updateSymbols(filePath, symbols) {
|
|
221
|
+
if (!this.db)
|
|
222
|
+
return;
|
|
223
|
+
this.db.run(`DELETE FROM symbols WHERE file = ?`, [filePath]);
|
|
224
|
+
for (const s of symbols) {
|
|
225
|
+
this.db.run(`INSERT INTO symbols (name, type, file, line, exported) VALUES (?, ?, ?, ?, ?)`, [
|
|
226
|
+
s.name,
|
|
227
|
+
s.type,
|
|
228
|
+
s.file,
|
|
229
|
+
s.line,
|
|
230
|
+
s.exported ? 1 : 0,
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
this.dirty = true;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Update imports for a file.
|
|
237
|
+
* @param filePath - The file path whose imports are being updated.
|
|
238
|
+
* @param imports - The new import paths for the file.
|
|
239
|
+
*/
|
|
240
|
+
updateImports(filePath, imports) {
|
|
241
|
+
if (!this.db)
|
|
242
|
+
return;
|
|
243
|
+
this.db.run(`DELETE FROM imports WHERE file = ?`, [filePath]);
|
|
244
|
+
for (const imp of imports) {
|
|
245
|
+
this.db.run(`INSERT INTO imports (file, import_path) VALUES (?, ?)`, [filePath, imp]);
|
|
246
|
+
}
|
|
247
|
+
this.dirty = true;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Query symbols by name pattern.
|
|
251
|
+
* @param pattern - Pattern to match symbol names (uses SQL LIKE).
|
|
252
|
+
* @param type - Optional symbol type filter.
|
|
253
|
+
* @returns Matching symbols.
|
|
254
|
+
*/
|
|
255
|
+
findSymbols(pattern, type) {
|
|
256
|
+
if (!this.db)
|
|
257
|
+
return [];
|
|
258
|
+
let sql = 'SELECT name, type, file, line, exported FROM symbols WHERE name LIKE ?';
|
|
259
|
+
const params = [`%${pattern}%`];
|
|
260
|
+
if (type) {
|
|
261
|
+
sql += ' AND type = ?';
|
|
262
|
+
params.push(type);
|
|
263
|
+
}
|
|
264
|
+
const rows = this.query(sql, params);
|
|
265
|
+
return rows.map((row) => ({
|
|
266
|
+
name: row[0],
|
|
267
|
+
type: row[1],
|
|
268
|
+
file: row[2],
|
|
269
|
+
line: row[3],
|
|
270
|
+
exported: row[4] === 1,
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get all files in index.
|
|
275
|
+
* @returns All indexed files.
|
|
276
|
+
*/
|
|
277
|
+
getFiles() {
|
|
278
|
+
const rows = this.query('SELECT path, mtime, lines, language, size FROM files');
|
|
279
|
+
return rows.map((row) => ({
|
|
280
|
+
path: row[0],
|
|
281
|
+
mtime: row[1],
|
|
282
|
+
lines: row[2],
|
|
283
|
+
language: row[3],
|
|
284
|
+
size: row[4],
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Get imports for a file.
|
|
289
|
+
* @param filePath - The file path to look up.
|
|
290
|
+
* @returns The import paths for the file.
|
|
291
|
+
*/
|
|
292
|
+
getImports(filePath) {
|
|
293
|
+
const rows = this.query('SELECT import_path FROM imports WHERE file = ?', [filePath]);
|
|
294
|
+
return rows.map((row) => row[0]);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get importers of a file (reverse lookup).
|
|
298
|
+
* @param filePath - The file path to find importers for.
|
|
299
|
+
* @returns Files that import the given file.
|
|
300
|
+
*/
|
|
301
|
+
getImporters(filePath) {
|
|
302
|
+
const baseName = path.basename(filePath, path.extname(filePath));
|
|
303
|
+
const rows = this.query('SELECT DISTINCT file FROM imports WHERE import_path LIKE ?', [`%${baseName}%`]);
|
|
304
|
+
return rows.map((row) => row[0]);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Remove a file from the index.
|
|
308
|
+
* @param filePath - The file path to remove.
|
|
309
|
+
*/
|
|
310
|
+
removeFile(filePath) {
|
|
311
|
+
if (!this.db)
|
|
312
|
+
return;
|
|
313
|
+
this.db.run(`DELETE FROM files WHERE path = ?`, [filePath]);
|
|
314
|
+
this.db.run(`DELETE FROM symbols WHERE file = ?`, [filePath]);
|
|
315
|
+
this.db.run(`DELETE FROM imports WHERE file = ?`, [filePath]);
|
|
316
|
+
this.dirty = true;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Get index stats.
|
|
320
|
+
* @returns Stats object or null if no database loaded.
|
|
321
|
+
*/
|
|
322
|
+
stats() {
|
|
323
|
+
if (!this.db)
|
|
324
|
+
return null;
|
|
325
|
+
const files = this.query('SELECT COUNT(*) FROM files');
|
|
326
|
+
const symbols = this.query('SELECT COUNT(*) FROM symbols');
|
|
327
|
+
const imports = this.query('SELECT COUNT(DISTINCT file) FROM imports');
|
|
328
|
+
const updated = this.query("SELECT value FROM meta WHERE key = 'updated'");
|
|
329
|
+
return {
|
|
330
|
+
files: files[0]?.[0] || 0,
|
|
331
|
+
symbols: symbols[0]?.[0] || 0,
|
|
332
|
+
imports: imports[0]?.[0] || 0,
|
|
333
|
+
updated: updated[0]?.[0] || '',
|
|
334
|
+
engine: 'sqlite (sql.js WASM)',
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Close the database.
|
|
339
|
+
*/
|
|
340
|
+
close() {
|
|
341
|
+
if (this.db) {
|
|
342
|
+
this.db.close();
|
|
343
|
+
this.db = null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Log tool usage to DB.
|
|
348
|
+
* @param tool - Tool name.
|
|
349
|
+
* @param duration - Duration in milliseconds.
|
|
350
|
+
* @param success - Whether the operation succeeded.
|
|
351
|
+
* @param cached - Whether the result was cached.
|
|
352
|
+
*/
|
|
353
|
+
logUsage(tool, duration, success, cached) {
|
|
354
|
+
if (!this.db)
|
|
355
|
+
return;
|
|
356
|
+
this.db.run(`INSERT INTO usage_stats (tool, timestamp, duration, success, cached) VALUES (?, ?, ?, ?, ?)`, [
|
|
357
|
+
tool,
|
|
358
|
+
Date.now(),
|
|
359
|
+
duration,
|
|
360
|
+
success ? 1 : 0,
|
|
361
|
+
cached ? 1 : 0,
|
|
362
|
+
]);
|
|
363
|
+
this.dirty = true;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Get usage stats.
|
|
367
|
+
* @returns Aggregated usage statistics per tool.
|
|
368
|
+
*/
|
|
369
|
+
getUsageStats() {
|
|
370
|
+
const rows = this.query(`
|
|
371
|
+
SELECT
|
|
372
|
+
tool,
|
|
373
|
+
COUNT(*) as count,
|
|
374
|
+
SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) as errorCount,
|
|
375
|
+
AVG(duration) as avgDuration
|
|
376
|
+
FROM usage_stats
|
|
377
|
+
GROUP BY tool
|
|
378
|
+
ORDER BY count DESC
|
|
379
|
+
`);
|
|
380
|
+
return rows.map((r) => ({
|
|
381
|
+
tool: r[0],
|
|
382
|
+
count: r[1],
|
|
383
|
+
errorCount: r[2],
|
|
384
|
+
avgDuration: Math.round(r[3]),
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
//# sourceMappingURL=sqlite-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-store.js","sourceRoot":"","sources":["../../src/db/sqlite-store.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* codedev-mcp — Universal Code Development MCP Server
|
|
4
|
+
*
|
|
5
|
+
* A zero-API-key MCP server that provides code search, analysis,
|
|
6
|
+
* navigation, and git context tools to any LLM-powered IDE.
|
|
7
|
+
*
|
|
8
|
+
* The host LLM (Claude, Codex, Gemini) does all reasoning —
|
|
9
|
+
* this server just provides fast, structured access to your codebase.
|
|
10
|
+
*
|
|
11
|
+
* Works with: Claude Code, Codex CLI, Gemini CLI, Cursor, VS Code
|
|
12
|
+
* Copilot, Windsurf, Claude Desktop — any MCP client.
|
|
13
|
+
*
|
|
14
|
+
* Supports: 40+ programming languages, any codebase size.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;GAaG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* codedev-mcp — Universal Code Development MCP Server
|
|
4
|
+
*
|
|
5
|
+
* A zero-API-key MCP server that provides code search, analysis,
|
|
6
|
+
* navigation, and git context tools to any LLM-powered IDE.
|
|
7
|
+
*
|
|
8
|
+
* The host LLM (Claude, Codex, Gemini) does all reasoning —
|
|
9
|
+
* this server just provides fast, structured access to your codebase.
|
|
10
|
+
*
|
|
11
|
+
* Works with: Claude Code, Codex CLI, Gemini CLI, Cursor, VS Code
|
|
12
|
+
* Copilot, Windsurf, Claude Desktop — any MCP client.
|
|
13
|
+
*
|
|
14
|
+
* Supports: 40+ programming languages, any codebase size.
|
|
15
|
+
*/
|
|
16
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
17
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
18
|
+
// CLI argument handling
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
21
|
+
const pkg = await import('../package.json', { with: { type: 'json' } });
|
|
22
|
+
process.stdout.write(`codedev-mcp v${pkg.default.version}\n`);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
26
|
+
process.stdout.write(`
|
|
27
|
+
codedev-mcp — Universal Code Development MCP Server
|
|
28
|
+
|
|
29
|
+
Usage: codedev-mcp [options]
|
|
30
|
+
|
|
31
|
+
Options:
|
|
32
|
+
-v, --version Show version number
|
|
33
|
+
-h, --help Show this help message
|
|
34
|
+
--timeout <ms> Request timeout in milliseconds (default: 30000)
|
|
35
|
+
|
|
36
|
+
Environment Variables:
|
|
37
|
+
CODEDEV_MCP_CWD Working directory (default: current directory)
|
|
38
|
+
CODEDEV_ROOTS Multi-root workspace paths (comma-separated)
|
|
39
|
+
CODEDEV_TIMEOUT Request timeout in milliseconds
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
npx codedev-mcp
|
|
43
|
+
codedev-mcp --timeout 60000
|
|
44
|
+
\n`);
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
import { logger } from './utils/logger.js';
|
|
48
|
+
// Tool Registries
|
|
49
|
+
import { registerSearchTools } from './tools/search.js';
|
|
50
|
+
import { registerAnalysisTools } from './tools/analysis.js';
|
|
51
|
+
import { registerNavTools } from './tools/nav.js';
|
|
52
|
+
import { registerGitTools } from './tools/git.js';
|
|
53
|
+
import { registerQualityTools } from './tools/quality.js';
|
|
54
|
+
import { registerDocsTools } from './tools/docs.js';
|
|
55
|
+
import { registerSecurityTools } from './tools/security.js';
|
|
56
|
+
import { registerNotebookTools } from './tools/notebook.js';
|
|
57
|
+
import { registerArchitectureTools } from './tools/architecture.js';
|
|
58
|
+
import { registerDevOpsTools } from './tools/devops.js';
|
|
59
|
+
import { registerPerformanceTools } from './tools/performance.js';
|
|
60
|
+
import { registerScaffoldTools } from './tools/scaffold.js';
|
|
61
|
+
import { VERSION } from './version.js';
|
|
62
|
+
import { SERVER_INSTRUCTIONS } from './constants/instructions.js';
|
|
63
|
+
import { registerHealthResource } from './resources/health.js';
|
|
64
|
+
import { toolLimiter } from './utils/concurrency.js';
|
|
65
|
+
// Create MCP Server
|
|
66
|
+
const server = new McpServer({ name: 'codedev-mcp', version: VERSION }, {
|
|
67
|
+
capabilities: { tools: {}, resources: {}, prompts: {} },
|
|
68
|
+
instructions: SERVER_INSTRUCTIONS,
|
|
69
|
+
});
|
|
70
|
+
// Wrap all tool handlers with concurrency limiter to prevent resource exhaustion
|
|
71
|
+
// when MCP clients send many parallel tool calls.
|
|
72
|
+
const originalRegisterTool = server.registerTool.bind(server);
|
|
73
|
+
server.registerTool = (name, config, handler) => {
|
|
74
|
+
const wrappedHandler = async (...handlerArgs) => {
|
|
75
|
+
return toolLimiter.run(async () => handler(...handlerArgs));
|
|
76
|
+
};
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Config type is complex from MCP SDK
|
|
78
|
+
return originalRegisterTool(name, config, wrappedHandler);
|
|
79
|
+
};
|
|
80
|
+
// Register Tools
|
|
81
|
+
registerSearchTools(server);
|
|
82
|
+
registerAnalysisTools(server);
|
|
83
|
+
registerNavTools(server);
|
|
84
|
+
registerGitTools(server);
|
|
85
|
+
registerQualityTools(server);
|
|
86
|
+
registerDocsTools(server);
|
|
87
|
+
registerSecurityTools(server);
|
|
88
|
+
registerNotebookTools(server);
|
|
89
|
+
registerArchitectureTools(server);
|
|
90
|
+
registerDevOpsTools(server);
|
|
91
|
+
registerPerformanceTools(server);
|
|
92
|
+
registerScaffoldTools(server);
|
|
93
|
+
// Register Resources
|
|
94
|
+
registerHealthResource(server, VERSION);
|
|
95
|
+
/**
|
|
96
|
+
* Starts the MCP server using stdio transport and initializes the database.
|
|
97
|
+
* @returns A promise that resolves when the server is running.
|
|
98
|
+
*/
|
|
99
|
+
async function runServer() {
|
|
100
|
+
const transport = new StdioServerTransport();
|
|
101
|
+
await server.connect(transport);
|
|
102
|
+
// Initialize DB
|
|
103
|
+
try {
|
|
104
|
+
const { getDb } = await import('./db/connection.js');
|
|
105
|
+
await getDb();
|
|
106
|
+
logger.info('codedev-mcp server running on stdio', { version: '3.1.0', db: 'initialized' });
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
logger.warn('Failed to initialize database', { error: err });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
runServer().catch((error) => {
|
|
113
|
+
logger.error('Fatal error running server', error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health Check Resource
|
|
3
|
+
* Exposes server health status for monitoring
|
|
4
|
+
*/
|
|
5
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
interface HealthStatus {
|
|
7
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
8
|
+
uptime: number;
|
|
9
|
+
memory: {
|
|
10
|
+
used: number;
|
|
11
|
+
total: number;
|
|
12
|
+
percentage: number;
|
|
13
|
+
};
|
|
14
|
+
version: string;
|
|
15
|
+
timestamp: string;
|
|
16
|
+
checks: {
|
|
17
|
+
name: string;
|
|
18
|
+
status: 'pass' | 'fail';
|
|
19
|
+
message?: string;
|
|
20
|
+
}[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the current server health status including memory, uptime, and binary checks.
|
|
24
|
+
* @param version - The server version string.
|
|
25
|
+
* @returns The health status object.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getHealthStatus(version: string): Promise<HealthStatus>;
|
|
28
|
+
/**
|
|
29
|
+
* Register the health resource on the MCP server.
|
|
30
|
+
* @param server - The MCP server instance.
|
|
31
|
+
* @param version - The server version string.
|
|
32
|
+
*/
|
|
33
|
+
export declare function registerHealthResource(server: McpServer, version: string): void;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/resources/health.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOpE,UAAU,YAAY;IACpB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,EAAE,CAAC;CACL;AAaD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAsC5E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAa/E"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health Check Resource
|
|
3
|
+
* Exposes server health status for monitoring
|
|
4
|
+
*/
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import { execFile } from 'node:child_process';
|
|
7
|
+
import { promisify } from 'node:util';
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
const startTime = Date.now();
|
|
10
|
+
async function isBinaryAvailable(binary) {
|
|
11
|
+
try {
|
|
12
|
+
await execFileAsync('which', [binary]);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get the current server health status including memory, uptime, and binary checks.
|
|
21
|
+
* @param version - The server version string.
|
|
22
|
+
* @returns The health status object.
|
|
23
|
+
*/
|
|
24
|
+
export async function getHealthStatus(version) {
|
|
25
|
+
const memUsage = process.memoryUsage();
|
|
26
|
+
const totalMem = os.totalmem();
|
|
27
|
+
const checks = [];
|
|
28
|
+
// Check ripgrep availability (async)
|
|
29
|
+
if (await isBinaryAvailable('rg')) {
|
|
30
|
+
checks.push({ name: 'ripgrep', status: 'pass' });
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
checks.push({ name: 'ripgrep', status: 'fail', message: 'ripgrep not found, using fallback' });
|
|
34
|
+
}
|
|
35
|
+
// Check fd availability (async)
|
|
36
|
+
if (await isBinaryAvailable('fd')) {
|
|
37
|
+
checks.push({ name: 'fd', status: 'pass' });
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
checks.push({ name: 'fd', status: 'fail', message: 'fd not found, using fallback' });
|
|
41
|
+
}
|
|
42
|
+
// Determine overall status
|
|
43
|
+
const failedChecks = checks.filter((c) => c.status === 'fail').length;
|
|
44
|
+
let status = 'healthy';
|
|
45
|
+
if (failedChecks > 0)
|
|
46
|
+
status = 'degraded';
|
|
47
|
+
if (failedChecks === checks.length)
|
|
48
|
+
status = 'unhealthy';
|
|
49
|
+
return {
|
|
50
|
+
status,
|
|
51
|
+
uptime: Math.floor((Date.now() - startTime) / 1000),
|
|
52
|
+
memory: {
|
|
53
|
+
used: Math.round(memUsage.heapUsed / 1024 / 1024),
|
|
54
|
+
total: Math.round(totalMem / 1024 / 1024),
|
|
55
|
+
percentage: Math.round((memUsage.heapUsed / totalMem) * 100 * 100) / 100,
|
|
56
|
+
},
|
|
57
|
+
version,
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
checks,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Register the health resource on the MCP server.
|
|
64
|
+
* @param server - The MCP server instance.
|
|
65
|
+
* @param version - The server version string.
|
|
66
|
+
*/
|
|
67
|
+
export function registerHealthResource(server, version) {
|
|
68
|
+
server.resource('health://status', 'health://status', async () => {
|
|
69
|
+
const health = await getHealthStatus(version);
|
|
70
|
+
return {
|
|
71
|
+
contents: [
|
|
72
|
+
{
|
|
73
|
+
uri: 'health://status',
|
|
74
|
+
mimeType: 'application/json',
|
|
75
|
+
text: JSON.stringify(health, null, 2),
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/resources/health.ts"],"names":[],"mappings":"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"}
|