@danainnovations/cortex-mcp 1.0.69 → 1.0.70
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/dist/cli.js +686 -55
- package/dist/cli.js.map +1 -1
- package/dist/index.js +702 -70
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1005,7 +1005,7 @@ function getWizardHtml() {
|
|
|
1005
1005
|
}
|
|
1006
1006
|
|
|
1007
1007
|
// \u2500\u2500 Step 3: Select MCPs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1008
|
-
var REQUIRED_MCPS = ['github', 'supabase', 'vercel', 'bestbuy'];
|
|
1008
|
+
var REQUIRED_MCPS = ['github', 'supabase', 'vercel', 'databricks', 'bestbuy'];
|
|
1009
1009
|
|
|
1010
1010
|
var MCP_TOOLTIPS = {
|
|
1011
1011
|
asana: 'Manage projects, tasks, and team workflows',
|
|
@@ -1019,6 +1019,7 @@ function getWizardHtml() {
|
|
|
1019
1019
|
slack: 'Send messages, search conversations, and manage channels',
|
|
1020
1020
|
powerbi: 'Build dashboards and run data queries on your reports',
|
|
1021
1021
|
bestbuy: 'Search products, compare prices, and find store locations',
|
|
1022
|
+
databricks: 'Query data warehouses, explore Unity Catalog, and manage jobs',
|
|
1022
1023
|
};
|
|
1023
1024
|
|
|
1024
1025
|
async function renderMcps() {
|
|
@@ -1851,17 +1852,17 @@ function getState() {
|
|
|
1851
1852
|
return wizardState;
|
|
1852
1853
|
}
|
|
1853
1854
|
function parseBody(req) {
|
|
1854
|
-
return new Promise((
|
|
1855
|
+
return new Promise((resolve2) => {
|
|
1855
1856
|
const chunks = [];
|
|
1856
1857
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
1857
1858
|
req.on("end", () => {
|
|
1858
1859
|
try {
|
|
1859
|
-
|
|
1860
|
+
resolve2(JSON.parse(Buffer.concat(chunks).toString()));
|
|
1860
1861
|
} catch {
|
|
1861
|
-
|
|
1862
|
+
resolve2({});
|
|
1862
1863
|
}
|
|
1863
1864
|
});
|
|
1864
|
-
req.on("error", () =>
|
|
1865
|
+
req.on("error", () => resolve2({}));
|
|
1865
1866
|
});
|
|
1866
1867
|
}
|
|
1867
1868
|
function json(res, data, status = 200) {
|
|
@@ -1904,8 +1905,8 @@ async function handleApiRoute(path, searchParams, req, res, options, onComplete)
|
|
|
1904
1905
|
}
|
|
1905
1906
|
const data = await resp.json();
|
|
1906
1907
|
json(res, data);
|
|
1907
|
-
} catch (
|
|
1908
|
-
const msg =
|
|
1908
|
+
} catch (err2) {
|
|
1909
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
1909
1910
|
json(res, { error: `Could not reach Cortex server: ${msg}` }, 502);
|
|
1910
1911
|
}
|
|
1911
1912
|
return true;
|
|
@@ -1953,8 +1954,8 @@ async function handleApiRoute(path, searchParams, req, res, options, onComplete)
|
|
|
1953
1954
|
mcps
|
|
1954
1955
|
);
|
|
1955
1956
|
results.push({ client: clientType, success: true, message: msg });
|
|
1956
|
-
} catch (
|
|
1957
|
-
const msg =
|
|
1957
|
+
} catch (err2) {
|
|
1958
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
1958
1959
|
results.push({ client: clientType, success: false, error: msg });
|
|
1959
1960
|
}
|
|
1960
1961
|
}
|
|
@@ -2003,14 +2004,14 @@ async function handleApiRoute(path, searchParams, req, res, options, onComplete)
|
|
|
2003
2004
|
json(res, { error: "Session expired. Please re-login." }, 401);
|
|
2004
2005
|
return true;
|
|
2005
2006
|
}
|
|
2006
|
-
const
|
|
2007
|
-
json(res, { error:
|
|
2007
|
+
const err2 = await resp.json().catch(() => ({}));
|
|
2008
|
+
json(res, { error: err2.detail || `HTTP ${resp.status}` }, resp.status);
|
|
2008
2009
|
return true;
|
|
2009
2010
|
}
|
|
2010
2011
|
const data = await resp.json();
|
|
2011
2012
|
json(res, data);
|
|
2012
|
-
} catch (
|
|
2013
|
-
const msg =
|
|
2013
|
+
} catch (err2) {
|
|
2014
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
2014
2015
|
json(res, { error: `Could not reach Cortex server: ${msg}` }, 502);
|
|
2015
2016
|
}
|
|
2016
2017
|
return true;
|
|
@@ -2050,7 +2051,7 @@ async function handleApiRoute(path, searchParams, req, res, options, onComplete)
|
|
|
2050
2051
|
|
|
2051
2052
|
// src/wizard/server.ts
|
|
2052
2053
|
function startWizardServer(options) {
|
|
2053
|
-
return new Promise((
|
|
2054
|
+
return new Promise((resolve2, reject) => {
|
|
2054
2055
|
let completionResolve;
|
|
2055
2056
|
const completionPromise = new Promise((r) => {
|
|
2056
2057
|
completionResolve = r;
|
|
@@ -2075,8 +2076,8 @@ function startWizardServer(options) {
|
|
|
2075
2076
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2076
2077
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
2077
2078
|
}
|
|
2078
|
-
} catch (
|
|
2079
|
-
const msg =
|
|
2079
|
+
} catch (err2) {
|
|
2080
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
2080
2081
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
2081
2082
|
res.end(JSON.stringify({ error: msg }));
|
|
2082
2083
|
}
|
|
@@ -2087,7 +2088,7 @@ function startWizardServer(options) {
|
|
|
2087
2088
|
});
|
|
2088
2089
|
server.listen(0, "127.0.0.1", () => {
|
|
2089
2090
|
const addr = server.address();
|
|
2090
|
-
|
|
2091
|
+
resolve2({
|
|
2091
2092
|
port: addr.port,
|
|
2092
2093
|
close: () => new Promise((r) => {
|
|
2093
2094
|
server.close(() => r());
|
|
@@ -2172,8 +2173,8 @@ async function runConfigure(options) {
|
|
|
2172
2173
|
selectedMcps
|
|
2173
2174
|
);
|
|
2174
2175
|
console.log(result);
|
|
2175
|
-
} catch (
|
|
2176
|
-
const msg =
|
|
2176
|
+
} catch (err2) {
|
|
2177
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
2177
2178
|
console.error(`Failed to configure ${client}: ${msg}`);
|
|
2178
2179
|
process.exit(1);
|
|
2179
2180
|
}
|
|
@@ -2184,7 +2185,7 @@ async function runConfigure(options) {
|
|
|
2184
2185
|
}
|
|
2185
2186
|
|
|
2186
2187
|
// src/proxy/stdio-server.ts
|
|
2187
|
-
import { readFileSync as
|
|
2188
|
+
import { readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
2188
2189
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2189
2190
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2190
2191
|
import {
|
|
@@ -2296,6 +2297,633 @@ var CortexHttpClient = class {
|
|
|
2296
2297
|
}
|
|
2297
2298
|
};
|
|
2298
2299
|
|
|
2300
|
+
// src/proxy/local-filesystem.ts
|
|
2301
|
+
import {
|
|
2302
|
+
copyFileSync,
|
|
2303
|
+
cpSync,
|
|
2304
|
+
existsSync as existsSync4,
|
|
2305
|
+
mkdirSync as mkdirSync4,
|
|
2306
|
+
readFileSync as readFileSync4,
|
|
2307
|
+
readdirSync,
|
|
2308
|
+
rmSync,
|
|
2309
|
+
statSync,
|
|
2310
|
+
unlinkSync as unlinkSync2,
|
|
2311
|
+
writeFileSync as writeFileSync4,
|
|
2312
|
+
appendFileSync,
|
|
2313
|
+
renameSync
|
|
2314
|
+
} from "fs";
|
|
2315
|
+
import { basename, dirname as dirname2, extname, join as join4, relative, resolve } from "path";
|
|
2316
|
+
var FILESYSTEM_TOOLS = /* @__PURE__ */ new Set([
|
|
2317
|
+
"read_file",
|
|
2318
|
+
"read_file_lines",
|
|
2319
|
+
"write_file",
|
|
2320
|
+
"append_file",
|
|
2321
|
+
"create_directory",
|
|
2322
|
+
"delete",
|
|
2323
|
+
"move",
|
|
2324
|
+
"copy",
|
|
2325
|
+
"list_directory",
|
|
2326
|
+
"exists",
|
|
2327
|
+
"get_file_info",
|
|
2328
|
+
"search_files",
|
|
2329
|
+
"find_in_files",
|
|
2330
|
+
"get_tree"
|
|
2331
|
+
]);
|
|
2332
|
+
var MAX_READ_SIZE = 50 * 1024 * 1024;
|
|
2333
|
+
var BINARY_CHECK_SIZE = 8192;
|
|
2334
|
+
var BINARY_SIGNATURES = [
|
|
2335
|
+
Buffer.from([137, 80, 78, 71]),
|
|
2336
|
+
// PNG
|
|
2337
|
+
Buffer.from([255, 216, 255]),
|
|
2338
|
+
// JPEG
|
|
2339
|
+
Buffer.from("GIF8"),
|
|
2340
|
+
// GIF
|
|
2341
|
+
Buffer.from([80, 75, 3, 4]),
|
|
2342
|
+
// ZIP / DOCX / XLSX
|
|
2343
|
+
Buffer.from("%PDF"),
|
|
2344
|
+
// PDF
|
|
2345
|
+
Buffer.from([127, 69, 76, 70]),
|
|
2346
|
+
// ELF
|
|
2347
|
+
Buffer.from([254, 237, 250]),
|
|
2348
|
+
// Mach-O
|
|
2349
|
+
Buffer.from([207, 250, 237, 254]),
|
|
2350
|
+
// Mach-O (reversed)
|
|
2351
|
+
Buffer.from("MZ")
|
|
2352
|
+
// Windows executable
|
|
2353
|
+
];
|
|
2354
|
+
function resolvePath(p) {
|
|
2355
|
+
return resolve(p);
|
|
2356
|
+
}
|
|
2357
|
+
function isBinaryFile(filePath) {
|
|
2358
|
+
try {
|
|
2359
|
+
const fd = readFileSync4(filePath, { flag: "r" });
|
|
2360
|
+
const chunk = fd.subarray(0, BINARY_CHECK_SIZE);
|
|
2361
|
+
if (chunk.length === 0) return false;
|
|
2362
|
+
for (const sig of BINARY_SIGNATURES) {
|
|
2363
|
+
if (chunk.length >= sig.length && chunk.subarray(0, sig.length).equals(sig)) {
|
|
2364
|
+
return true;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
return chunk.includes(0);
|
|
2368
|
+
} catch {
|
|
2369
|
+
return false;
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
function globToRegex(pattern) {
|
|
2373
|
+
let re = "^";
|
|
2374
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
2375
|
+
const c = pattern[i];
|
|
2376
|
+
if (c === "*") {
|
|
2377
|
+
re += ".*";
|
|
2378
|
+
} else if (c === "?") {
|
|
2379
|
+
re += ".";
|
|
2380
|
+
} else if (c === "[") {
|
|
2381
|
+
const close = pattern.indexOf("]", i + 1);
|
|
2382
|
+
if (close !== -1) {
|
|
2383
|
+
re += "[" + pattern.slice(i + 1, close) + "]";
|
|
2384
|
+
i = close;
|
|
2385
|
+
} else {
|
|
2386
|
+
re += "\\[";
|
|
2387
|
+
}
|
|
2388
|
+
} else if (".+^${}()|\\".includes(c)) {
|
|
2389
|
+
re += "\\" + c;
|
|
2390
|
+
} else {
|
|
2391
|
+
re += c;
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
re += "$";
|
|
2395
|
+
return new RegExp(re);
|
|
2396
|
+
}
|
|
2397
|
+
function fileType(isDir, isSymlink) {
|
|
2398
|
+
if (isSymlink) return "symlink";
|
|
2399
|
+
if (isDir) return "directory";
|
|
2400
|
+
return "file";
|
|
2401
|
+
}
|
|
2402
|
+
function countDirectoryContents(dirPath) {
|
|
2403
|
+
let files = 0;
|
|
2404
|
+
let bytes = 0;
|
|
2405
|
+
try {
|
|
2406
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
2407
|
+
for (const entry of entries) {
|
|
2408
|
+
const full = join4(dirPath, entry.name);
|
|
2409
|
+
if (entry.isDirectory()) {
|
|
2410
|
+
const sub = countDirectoryContents(full);
|
|
2411
|
+
files += sub.files;
|
|
2412
|
+
bytes += sub.bytes;
|
|
2413
|
+
} else {
|
|
2414
|
+
files += 1;
|
|
2415
|
+
try {
|
|
2416
|
+
bytes += statSync(full).size;
|
|
2417
|
+
} catch {
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
} catch {
|
|
2422
|
+
}
|
|
2423
|
+
return { files, bytes };
|
|
2424
|
+
}
|
|
2425
|
+
function ok(data) {
|
|
2426
|
+
return {
|
|
2427
|
+
content: [{ type: "text", text: JSON.stringify(data) }],
|
|
2428
|
+
isError: false
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
function err(message) {
|
|
2432
|
+
return {
|
|
2433
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: message }) }],
|
|
2434
|
+
isError: true
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
function handleReadFile(args) {
|
|
2438
|
+
const filePath = resolvePath(args.path);
|
|
2439
|
+
const encoding = args.encoding || "utf-8";
|
|
2440
|
+
const stat = statSync(filePath);
|
|
2441
|
+
if (!stat.isFile()) throw new Error("Not a file.");
|
|
2442
|
+
if (stat.size > MAX_READ_SIZE) {
|
|
2443
|
+
throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size (${MAX_READ_SIZE} bytes).`);
|
|
2444
|
+
}
|
|
2445
|
+
if (isBinaryFile(filePath)) {
|
|
2446
|
+
const raw = readFileSync4(filePath);
|
|
2447
|
+
return ok({
|
|
2448
|
+
content: raw.toString("base64"),
|
|
2449
|
+
is_binary: true,
|
|
2450
|
+
size: stat.size,
|
|
2451
|
+
encoding: "base64",
|
|
2452
|
+
path: filePath
|
|
2453
|
+
});
|
|
2454
|
+
}
|
|
2455
|
+
const text = readFileSync4(filePath, encoding);
|
|
2456
|
+
return ok({
|
|
2457
|
+
content: text,
|
|
2458
|
+
is_binary: false,
|
|
2459
|
+
size: stat.size,
|
|
2460
|
+
encoding,
|
|
2461
|
+
path: filePath
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2464
|
+
function handleReadFileLines(args) {
|
|
2465
|
+
const filePath = resolvePath(args.path);
|
|
2466
|
+
const encoding = args.encoding || "utf-8";
|
|
2467
|
+
const startLine = args.start_line || 1;
|
|
2468
|
+
const endLine = args.end_line;
|
|
2469
|
+
const stat = statSync(filePath);
|
|
2470
|
+
if (!stat.isFile()) throw new Error("Not a file.");
|
|
2471
|
+
if (stat.size > MAX_READ_SIZE) {
|
|
2472
|
+
throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size.`);
|
|
2473
|
+
}
|
|
2474
|
+
if (startLine < 1) throw new Error("start_line must be >= 1.");
|
|
2475
|
+
if (endLine !== void 0 && endLine < startLine) throw new Error("end_line must be >= start_line.");
|
|
2476
|
+
const text = readFileSync4(filePath, encoding);
|
|
2477
|
+
const allLines = text.split(/\n/);
|
|
2478
|
+
const totalLines = allLines.length;
|
|
2479
|
+
const startIdx = startLine - 1;
|
|
2480
|
+
const endIdx = endLine !== void 0 ? endLine : totalLines;
|
|
2481
|
+
const selected = allLines.slice(startIdx, endIdx);
|
|
2482
|
+
const actualEnd = Math.min(endIdx, totalLines);
|
|
2483
|
+
return ok({
|
|
2484
|
+
content: selected.join("\n"),
|
|
2485
|
+
start_line: startLine,
|
|
2486
|
+
end_line: actualEnd,
|
|
2487
|
+
total_lines: totalLines,
|
|
2488
|
+
size: stat.size,
|
|
2489
|
+
path: filePath
|
|
2490
|
+
});
|
|
2491
|
+
}
|
|
2492
|
+
function handleWriteFile(args) {
|
|
2493
|
+
const filePath = resolvePath(args.path);
|
|
2494
|
+
const content = args.content;
|
|
2495
|
+
const encoding = args.encoding || "utf-8";
|
|
2496
|
+
const isBinary = args.is_binary || false;
|
|
2497
|
+
const overwrite = args.overwrite !== false;
|
|
2498
|
+
const createParents = args.create_parents || false;
|
|
2499
|
+
const created = !existsSync4(filePath);
|
|
2500
|
+
if (!overwrite && !created) {
|
|
2501
|
+
throw new Error("File already exists.");
|
|
2502
|
+
}
|
|
2503
|
+
if (createParents) {
|
|
2504
|
+
mkdirSync4(dirname2(filePath), { recursive: true });
|
|
2505
|
+
}
|
|
2506
|
+
let bytesWritten;
|
|
2507
|
+
let usedEncoding;
|
|
2508
|
+
if (isBinary) {
|
|
2509
|
+
const raw = Buffer.from(content, "base64");
|
|
2510
|
+
writeFileSync4(filePath, raw);
|
|
2511
|
+
bytesWritten = raw.length;
|
|
2512
|
+
usedEncoding = "base64";
|
|
2513
|
+
} else {
|
|
2514
|
+
const encoded = Buffer.from(content, encoding);
|
|
2515
|
+
writeFileSync4(filePath, content, encoding);
|
|
2516
|
+
bytesWritten = encoded.length;
|
|
2517
|
+
usedEncoding = encoding;
|
|
2518
|
+
}
|
|
2519
|
+
return ok({
|
|
2520
|
+
path: filePath,
|
|
2521
|
+
bytes_written: bytesWritten,
|
|
2522
|
+
created,
|
|
2523
|
+
encoding: usedEncoding
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
function handleAppendFile(args) {
|
|
2527
|
+
const filePath = resolvePath(args.path);
|
|
2528
|
+
const content = args.content;
|
|
2529
|
+
const encoding = args.encoding || "utf-8";
|
|
2530
|
+
if (!existsSync4(filePath)) throw new Error("File not found.");
|
|
2531
|
+
const encoded = Buffer.from(content, encoding);
|
|
2532
|
+
appendFileSync(filePath, content, encoding);
|
|
2533
|
+
const newSize = statSync(filePath).size;
|
|
2534
|
+
return ok({
|
|
2535
|
+
path: filePath,
|
|
2536
|
+
bytes_written: encoded.length,
|
|
2537
|
+
new_size: newSize
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
function handleCreateDirectory(args) {
|
|
2541
|
+
const dirPath = resolvePath(args.path);
|
|
2542
|
+
const parents = args.parents !== false;
|
|
2543
|
+
if (existsSync4(dirPath)) {
|
|
2544
|
+
return ok({ path: dirPath, created: false });
|
|
2545
|
+
}
|
|
2546
|
+
if (parents) {
|
|
2547
|
+
mkdirSync4(dirPath, { recursive: true });
|
|
2548
|
+
} else {
|
|
2549
|
+
mkdirSync4(dirPath);
|
|
2550
|
+
}
|
|
2551
|
+
return ok({ path: dirPath, created: true });
|
|
2552
|
+
}
|
|
2553
|
+
function handleDelete(args) {
|
|
2554
|
+
const targetPath = resolvePath(args.path);
|
|
2555
|
+
const recursive = args.recursive || false;
|
|
2556
|
+
if (!existsSync4(targetPath)) throw new Error("Path not found.");
|
|
2557
|
+
const stat = statSync(targetPath, { throwIfNoEntry: false });
|
|
2558
|
+
if (!stat) throw new Error("Path not found.");
|
|
2559
|
+
if (stat.isDirectory()) {
|
|
2560
|
+
const { files: filesDeleted, bytes: bytesFreed } = countDirectoryContents(targetPath);
|
|
2561
|
+
if (recursive) {
|
|
2562
|
+
rmSync(targetPath, { recursive: true });
|
|
2563
|
+
} else {
|
|
2564
|
+
rmSync(targetPath);
|
|
2565
|
+
}
|
|
2566
|
+
return ok({
|
|
2567
|
+
path: targetPath,
|
|
2568
|
+
type: "directory",
|
|
2569
|
+
files_deleted: recursive ? filesDeleted : 0,
|
|
2570
|
+
bytes_freed: recursive ? bytesFreed : 0
|
|
2571
|
+
});
|
|
2572
|
+
}
|
|
2573
|
+
const size = stat.size;
|
|
2574
|
+
unlinkSync2(targetPath);
|
|
2575
|
+
return ok({
|
|
2576
|
+
path: targetPath,
|
|
2577
|
+
type: "file",
|
|
2578
|
+
files_deleted: 1,
|
|
2579
|
+
bytes_freed: size
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
function handleMove(args) {
|
|
2583
|
+
const source = resolvePath(args.source);
|
|
2584
|
+
const destination = resolvePath(args.destination);
|
|
2585
|
+
const overwrite = args.overwrite || false;
|
|
2586
|
+
if (!existsSync4(source)) throw new Error("Source path not found.");
|
|
2587
|
+
if (existsSync4(destination) && !overwrite) throw new Error("Destination already exists.");
|
|
2588
|
+
const stat = statSync(source);
|
|
2589
|
+
const type = stat.isDirectory() ? "directory" : "file";
|
|
2590
|
+
const bytesMoved = stat.isDirectory() ? countDirectoryContents(source).bytes : stat.size;
|
|
2591
|
+
try {
|
|
2592
|
+
renameSync(source, destination);
|
|
2593
|
+
} catch (e) {
|
|
2594
|
+
if (e.code === "EXDEV") {
|
|
2595
|
+
if (stat.isDirectory()) {
|
|
2596
|
+
cpSync(source, destination, { recursive: true });
|
|
2597
|
+
rmSync(source, { recursive: true });
|
|
2598
|
+
} else {
|
|
2599
|
+
copyFileSync(source, destination);
|
|
2600
|
+
unlinkSync2(source);
|
|
2601
|
+
}
|
|
2602
|
+
} else {
|
|
2603
|
+
throw e;
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
return ok({
|
|
2607
|
+
source,
|
|
2608
|
+
destination,
|
|
2609
|
+
type,
|
|
2610
|
+
bytes_moved: bytesMoved
|
|
2611
|
+
});
|
|
2612
|
+
}
|
|
2613
|
+
function handleCopy(args) {
|
|
2614
|
+
const source = resolvePath(args.source);
|
|
2615
|
+
const destination = resolvePath(args.destination);
|
|
2616
|
+
const overwrite = args.overwrite || false;
|
|
2617
|
+
if (!existsSync4(source)) throw new Error("Source path not found.");
|
|
2618
|
+
if (existsSync4(destination) && !overwrite) throw new Error("Destination already exists.");
|
|
2619
|
+
const stat = statSync(source);
|
|
2620
|
+
if (stat.isDirectory()) {
|
|
2621
|
+
if (existsSync4(destination) && overwrite) {
|
|
2622
|
+
rmSync(destination, { recursive: true });
|
|
2623
|
+
}
|
|
2624
|
+
cpSync(source, destination, { recursive: true });
|
|
2625
|
+
const { bytes } = countDirectoryContents(destination);
|
|
2626
|
+
return ok({ source, destination, type: "directory", bytes_copied: bytes });
|
|
2627
|
+
}
|
|
2628
|
+
copyFileSync(source, destination);
|
|
2629
|
+
const bytesCopied = statSync(destination).size;
|
|
2630
|
+
return ok({ source, destination, type: "file", bytes_copied: bytesCopied });
|
|
2631
|
+
}
|
|
2632
|
+
function handleListDirectory(args) {
|
|
2633
|
+
const dirPath = resolvePath(args.path);
|
|
2634
|
+
const recursive = args.recursive || false;
|
|
2635
|
+
const maxDepth = args.max_depth || 1;
|
|
2636
|
+
const pattern = args.pattern;
|
|
2637
|
+
const includeHidden = args.include_hidden || false;
|
|
2638
|
+
if (!existsSync4(dirPath)) throw new Error("Directory not found.");
|
|
2639
|
+
const stat = statSync(dirPath);
|
|
2640
|
+
if (!stat.isDirectory()) throw new Error("Path is not a directory.");
|
|
2641
|
+
const effectiveDepth = recursive ? maxDepth : 1;
|
|
2642
|
+
const patternRe = pattern ? globToRegex(pattern) : null;
|
|
2643
|
+
const entries = [];
|
|
2644
|
+
function scan(dir, depth) {
|
|
2645
|
+
if (depth >= effectiveDepth) return;
|
|
2646
|
+
let dirents;
|
|
2647
|
+
try {
|
|
2648
|
+
dirents = readdirSync(dir, { withFileTypes: true });
|
|
2649
|
+
} catch {
|
|
2650
|
+
return;
|
|
2651
|
+
}
|
|
2652
|
+
dirents.sort((a, b) => a.name.localeCompare(b.name));
|
|
2653
|
+
for (const d of dirents) {
|
|
2654
|
+
if (!includeHidden && d.name.startsWith(".")) continue;
|
|
2655
|
+
const fullPath = join4(dir, d.name);
|
|
2656
|
+
const isDir = d.isDirectory();
|
|
2657
|
+
if (patternRe && !patternRe.test(d.name)) {
|
|
2658
|
+
if (isDir && effectiveDepth > 1) {
|
|
2659
|
+
scan(fullPath, depth + 1);
|
|
2660
|
+
}
|
|
2661
|
+
continue;
|
|
2662
|
+
}
|
|
2663
|
+
let size = 0;
|
|
2664
|
+
let mtime = (/* @__PURE__ */ new Date()).toISOString();
|
|
2665
|
+
try {
|
|
2666
|
+
const s = statSync(fullPath);
|
|
2667
|
+
size = isDir ? 0 : s.size;
|
|
2668
|
+
mtime = new Date(s.mtimeMs).toISOString();
|
|
2669
|
+
} catch {
|
|
2670
|
+
}
|
|
2671
|
+
entries.push({
|
|
2672
|
+
name: d.name,
|
|
2673
|
+
path: relative(dirPath, fullPath),
|
|
2674
|
+
type: fileType(isDir, d.isSymbolicLink()),
|
|
2675
|
+
size,
|
|
2676
|
+
modified_at: mtime,
|
|
2677
|
+
is_hidden: d.name.startsWith(".")
|
|
2678
|
+
});
|
|
2679
|
+
if (isDir && effectiveDepth > 1) {
|
|
2680
|
+
scan(fullPath, depth + 1);
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
scan(dirPath, 0);
|
|
2685
|
+
return ok({
|
|
2686
|
+
path: dirPath,
|
|
2687
|
+
entries,
|
|
2688
|
+
total_count: entries.length
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
function handleExists(args) {
|
|
2692
|
+
const targetPath = resolvePath(args.path);
|
|
2693
|
+
const pathExists = existsSync4(targetPath);
|
|
2694
|
+
let type = null;
|
|
2695
|
+
if (pathExists) {
|
|
2696
|
+
const stat = statSync(targetPath, { throwIfNoEntry: false });
|
|
2697
|
+
if (stat) {
|
|
2698
|
+
type = fileType(stat.isDirectory(), stat.isSymbolicLink());
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
return ok({ exists: pathExists, path: targetPath, type });
|
|
2702
|
+
}
|
|
2703
|
+
function handleGetFileInfo(args) {
|
|
2704
|
+
const filePath = resolvePath(args.path);
|
|
2705
|
+
if (!existsSync4(filePath)) throw new Error("Path not found.");
|
|
2706
|
+
const stat = statSync(filePath, { throwIfNoEntry: false });
|
|
2707
|
+
if (!stat) throw new Error("Path not found.");
|
|
2708
|
+
const isDir = stat.isDirectory();
|
|
2709
|
+
const isSymlink = stat.isSymbolicLink();
|
|
2710
|
+
const name = basename(filePath);
|
|
2711
|
+
const ext = isDir ? null : extname(name) || null;
|
|
2712
|
+
const binary = !isDir && !isSymlink ? isBinaryFile(filePath) : false;
|
|
2713
|
+
return ok({
|
|
2714
|
+
name,
|
|
2715
|
+
path: filePath,
|
|
2716
|
+
type: fileType(isDir, isSymlink),
|
|
2717
|
+
size: isDir ? 0 : stat.size,
|
|
2718
|
+
modified_at: new Date(stat.mtimeMs).toISOString(),
|
|
2719
|
+
created_at: stat.birthtimeMs ? new Date(stat.birthtimeMs).toISOString() : null,
|
|
2720
|
+
extension: ext,
|
|
2721
|
+
is_hidden: name.startsWith("."),
|
|
2722
|
+
is_binary: binary
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2725
|
+
function handleSearchFiles(args) {
|
|
2726
|
+
const searchPath = resolvePath(args.path);
|
|
2727
|
+
const pattern = args.pattern || "*";
|
|
2728
|
+
const recursive = args.recursive !== false;
|
|
2729
|
+
const includeHidden = args.include_hidden || false;
|
|
2730
|
+
const maxResults = args.max_results || 1e3;
|
|
2731
|
+
if (!existsSync4(searchPath)) throw new Error("Directory not found.");
|
|
2732
|
+
if (!statSync(searchPath).isDirectory()) throw new Error("Path is not a directory.");
|
|
2733
|
+
const patternRe = globToRegex(pattern);
|
|
2734
|
+
const matches = [];
|
|
2735
|
+
let totalMatches = 0;
|
|
2736
|
+
function scan(dir) {
|
|
2737
|
+
let dirents;
|
|
2738
|
+
try {
|
|
2739
|
+
dirents = readdirSync(dir, { withFileTypes: true });
|
|
2740
|
+
} catch {
|
|
2741
|
+
return;
|
|
2742
|
+
}
|
|
2743
|
+
for (const d of dirents) {
|
|
2744
|
+
if (!includeHidden) {
|
|
2745
|
+
if (d.name.startsWith(".")) continue;
|
|
2746
|
+
}
|
|
2747
|
+
const fullPath = join4(dir, d.name);
|
|
2748
|
+
if (d.isDirectory()) {
|
|
2749
|
+
if (recursive) scan(fullPath);
|
|
2750
|
+
continue;
|
|
2751
|
+
}
|
|
2752
|
+
if (patternRe.test(d.name)) {
|
|
2753
|
+
totalMatches++;
|
|
2754
|
+
if (matches.length < maxResults) {
|
|
2755
|
+
matches.push(relative(searchPath, fullPath));
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
scan(searchPath);
|
|
2761
|
+
return ok({
|
|
2762
|
+
matches,
|
|
2763
|
+
total_matches: totalMatches,
|
|
2764
|
+
truncated: totalMatches > maxResults,
|
|
2765
|
+
search_path: searchPath,
|
|
2766
|
+
pattern
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
function handleFindInFiles(args) {
|
|
2770
|
+
const searchPath = resolvePath(args.path);
|
|
2771
|
+
const query = args.query;
|
|
2772
|
+
const isRegex = args.is_regex || false;
|
|
2773
|
+
const caseSensitive = args.case_sensitive !== false;
|
|
2774
|
+
const filePattern = args.pattern;
|
|
2775
|
+
const contextLines = args.context_lines || 0;
|
|
2776
|
+
const maxResults = args.max_results || 500;
|
|
2777
|
+
const includeHidden = args.include_hidden || false;
|
|
2778
|
+
if (!existsSync4(searchPath)) throw new Error("Directory not found.");
|
|
2779
|
+
if (!statSync(searchPath).isDirectory()) throw new Error("Path is not a directory.");
|
|
2780
|
+
const flags = caseSensitive ? "" : "i";
|
|
2781
|
+
const re = isRegex ? new RegExp(query, flags) : new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), flags);
|
|
2782
|
+
const patternRe = filePattern ? globToRegex(filePattern) : null;
|
|
2783
|
+
const results = [];
|
|
2784
|
+
let totalMatches = 0;
|
|
2785
|
+
let filesSearched = 0;
|
|
2786
|
+
let filesWithMatches = 0;
|
|
2787
|
+
function scan(dir) {
|
|
2788
|
+
let dirents;
|
|
2789
|
+
try {
|
|
2790
|
+
dirents = readdirSync(dir, { withFileTypes: true });
|
|
2791
|
+
} catch {
|
|
2792
|
+
return;
|
|
2793
|
+
}
|
|
2794
|
+
for (const d of dirents) {
|
|
2795
|
+
if (!includeHidden && d.name.startsWith(".")) continue;
|
|
2796
|
+
const fullPath = join4(dir, d.name);
|
|
2797
|
+
if (d.isDirectory()) {
|
|
2798
|
+
scan(fullPath);
|
|
2799
|
+
continue;
|
|
2800
|
+
}
|
|
2801
|
+
if (patternRe && !patternRe.test(d.name)) continue;
|
|
2802
|
+
if (isBinaryFile(fullPath)) continue;
|
|
2803
|
+
filesSearched++;
|
|
2804
|
+
let fileHasMatch = false;
|
|
2805
|
+
let lines;
|
|
2806
|
+
try {
|
|
2807
|
+
const text = readFileSync4(fullPath, "utf-8");
|
|
2808
|
+
lines = text.split("\n");
|
|
2809
|
+
} catch {
|
|
2810
|
+
continue;
|
|
2811
|
+
}
|
|
2812
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2813
|
+
if (re.test(lines[i])) {
|
|
2814
|
+
totalMatches++;
|
|
2815
|
+
fileHasMatch = true;
|
|
2816
|
+
if (results.length < maxResults) {
|
|
2817
|
+
const ctxStart = Math.max(0, i - contextLines);
|
|
2818
|
+
const ctxEnd = Math.min(lines.length, i + contextLines + 1);
|
|
2819
|
+
results.push({
|
|
2820
|
+
file: relative(searchPath, fullPath),
|
|
2821
|
+
line: i + 1,
|
|
2822
|
+
content: lines[i],
|
|
2823
|
+
context_before: lines.slice(ctxStart, i),
|
|
2824
|
+
context_after: lines.slice(i + 1, ctxEnd)
|
|
2825
|
+
});
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
if (fileHasMatch) filesWithMatches++;
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
scan(searchPath);
|
|
2833
|
+
return ok({
|
|
2834
|
+
results,
|
|
2835
|
+
total_matches: totalMatches,
|
|
2836
|
+
files_searched: filesSearched,
|
|
2837
|
+
files_with_matches: filesWithMatches,
|
|
2838
|
+
truncated: totalMatches > maxResults,
|
|
2839
|
+
query
|
|
2840
|
+
});
|
|
2841
|
+
}
|
|
2842
|
+
function handleGetTree(args) {
|
|
2843
|
+
const rootPath = resolvePath(args.path);
|
|
2844
|
+
const maxDepth = args.max_depth || 3;
|
|
2845
|
+
const includeHidden = args.include_hidden || false;
|
|
2846
|
+
const maxEntries = args.max_entries || 500;
|
|
2847
|
+
if (!existsSync4(rootPath)) throw new Error("Directory not found.");
|
|
2848
|
+
if (!statSync(rootPath).isDirectory()) throw new Error("Path is not a directory.");
|
|
2849
|
+
const lines = [];
|
|
2850
|
+
let entryCount = 0;
|
|
2851
|
+
let truncated = false;
|
|
2852
|
+
const rootName = basename(rootPath) || rootPath;
|
|
2853
|
+
lines.push(rootName + "/");
|
|
2854
|
+
function buildTree(dirPath, prefix, depth) {
|
|
2855
|
+
if (truncated || depth >= maxDepth) return;
|
|
2856
|
+
let dirents;
|
|
2857
|
+
try {
|
|
2858
|
+
dirents = readdirSync(dirPath, { withFileTypes: true });
|
|
2859
|
+
} catch {
|
|
2860
|
+
return;
|
|
2861
|
+
}
|
|
2862
|
+
if (!includeHidden) {
|
|
2863
|
+
dirents = dirents.filter((d) => !d.name.startsWith("."));
|
|
2864
|
+
}
|
|
2865
|
+
dirents.sort((a, b) => a.name.localeCompare(b.name));
|
|
2866
|
+
for (let i = 0; i < dirents.length; i++) {
|
|
2867
|
+
if (truncated) return;
|
|
2868
|
+
entryCount++;
|
|
2869
|
+
if (entryCount > maxEntries) {
|
|
2870
|
+
truncated = true;
|
|
2871
|
+
lines.push(prefix + "... (truncated)");
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2874
|
+
const d = dirents[i];
|
|
2875
|
+
const isLast = i === dirents.length - 1;
|
|
2876
|
+
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
2877
|
+
const childPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
2878
|
+
const fullPath = join4(dirPath, d.name);
|
|
2879
|
+
if (d.isDirectory()) {
|
|
2880
|
+
lines.push(prefix + connector + d.name + "/");
|
|
2881
|
+
buildTree(fullPath, childPrefix, depth + 1);
|
|
2882
|
+
} else {
|
|
2883
|
+
lines.push(prefix + connector + d.name);
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
buildTree(rootPath, "", 0);
|
|
2888
|
+
return ok({
|
|
2889
|
+
tree: lines.join("\n"),
|
|
2890
|
+
path: rootPath,
|
|
2891
|
+
entry_count: entryCount,
|
|
2892
|
+
truncated,
|
|
2893
|
+
max_depth: maxDepth
|
|
2894
|
+
});
|
|
2895
|
+
}
|
|
2896
|
+
var HANDLERS = {
|
|
2897
|
+
read_file: handleReadFile,
|
|
2898
|
+
read_file_lines: handleReadFileLines,
|
|
2899
|
+
write_file: handleWriteFile,
|
|
2900
|
+
append_file: handleAppendFile,
|
|
2901
|
+
create_directory: handleCreateDirectory,
|
|
2902
|
+
delete: handleDelete,
|
|
2903
|
+
move: handleMove,
|
|
2904
|
+
copy: handleCopy,
|
|
2905
|
+
list_directory: handleListDirectory,
|
|
2906
|
+
exists: handleExists,
|
|
2907
|
+
get_file_info: handleGetFileInfo,
|
|
2908
|
+
search_files: handleSearchFiles,
|
|
2909
|
+
find_in_files: handleFindInFiles,
|
|
2910
|
+
get_tree: handleGetTree
|
|
2911
|
+
};
|
|
2912
|
+
function handleLocalFilesystemTool(_toolName, baseName, args) {
|
|
2913
|
+
console.error(`[cortex-mcp] filesystem.${baseName}: executing locally`);
|
|
2914
|
+
const handler = HANDLERS[baseName];
|
|
2915
|
+
if (!handler) {
|
|
2916
|
+
return err(`Unknown filesystem tool: ${baseName}`);
|
|
2917
|
+
}
|
|
2918
|
+
try {
|
|
2919
|
+
return handler(args);
|
|
2920
|
+
} catch (e) {
|
|
2921
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
2922
|
+
console.error(`[cortex-mcp] filesystem.${baseName} error: ${message}`);
|
|
2923
|
+
return err(message);
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2299
2927
|
// src/proxy/stdio-server.ts
|
|
2300
2928
|
var UPLOAD_TOOLS = /* @__PURE__ */ new Set(["upload_file", "upload_file_to_sharepoint"]);
|
|
2301
2929
|
var INLINE_UPLOAD_MAX = 3 * 1024 * 1024;
|
|
@@ -2360,7 +2988,7 @@ async function handleLocalFileUpload(cortex, toolName, args) {
|
|
|
2360
2988
|
const filePath = args.file_path;
|
|
2361
2989
|
let fileSize;
|
|
2362
2990
|
try {
|
|
2363
|
-
fileSize =
|
|
2991
|
+
fileSize = statSync2(filePath).size;
|
|
2364
2992
|
} catch {
|
|
2365
2993
|
return {
|
|
2366
2994
|
content: [{ type: "text", text: JSON.stringify({
|
|
@@ -2371,7 +2999,7 @@ async function handleLocalFileUpload(cortex, toolName, args) {
|
|
|
2371
2999
|
};
|
|
2372
3000
|
}
|
|
2373
3001
|
if (fileSize <= INLINE_UPLOAD_MAX) {
|
|
2374
|
-
const fileBuffer2 =
|
|
3002
|
+
const fileBuffer2 = readFileSync5(filePath);
|
|
2375
3003
|
const base64Content = fileBuffer2.toString("base64");
|
|
2376
3004
|
const forwardArgs = { ...args, content: base64Content };
|
|
2377
3005
|
delete forwardArgs.file_path;
|
|
@@ -2423,7 +3051,7 @@ async function handleLocalFileUpload(cortex, toolName, args) {
|
|
|
2423
3051
|
isError: true
|
|
2424
3052
|
};
|
|
2425
3053
|
}
|
|
2426
|
-
const fileBuffer =
|
|
3054
|
+
const fileBuffer = readFileSync5(filePath);
|
|
2427
3055
|
const chunkSize = 2.5 * 1024 * 1024;
|
|
2428
3056
|
const total = fileBuffer.length;
|
|
2429
3057
|
let driveItem = {};
|
|
@@ -2493,8 +3121,8 @@ async function startStdioServer(options) {
|
|
|
2493
3121
|
console.error("[cortex-mcp] Initializing backend session...");
|
|
2494
3122
|
await cortex.initialize();
|
|
2495
3123
|
console.error("[cortex-mcp] Backend session established.");
|
|
2496
|
-
} catch (
|
|
2497
|
-
const msg =
|
|
3124
|
+
} catch (err2) {
|
|
3125
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
2498
3126
|
console.error(`[cortex-mcp] Backend initialization failed: ${msg}`);
|
|
2499
3127
|
}
|
|
2500
3128
|
initialized = true;
|
|
@@ -2517,6 +3145,9 @@ async function startStdioServer(options) {
|
|
|
2517
3145
|
if (UPLOAD_TOOLS.has(baseName) && typedArgs.file_path) {
|
|
2518
3146
|
return handleLocalFileUpload(cortex, name, typedArgs);
|
|
2519
3147
|
}
|
|
3148
|
+
if (FILESYSTEM_TOOLS.has(baseName)) {
|
|
3149
|
+
return handleLocalFilesystemTool(name, baseName, typedArgs);
|
|
3150
|
+
}
|
|
2520
3151
|
const response = await cortex.callTool(name, typedArgs);
|
|
2521
3152
|
if (response.error) {
|
|
2522
3153
|
return {
|
|
@@ -2587,7 +3218,7 @@ function runStatus() {
|
|
|
2587
3218
|
}
|
|
2588
3219
|
|
|
2589
3220
|
// src/cli/reset.ts
|
|
2590
|
-
import { existsSync as
|
|
3221
|
+
import { existsSync as existsSync5, unlinkSync as unlinkSync3, rmdirSync } from "fs";
|
|
2591
3222
|
function runReset() {
|
|
2592
3223
|
console.log("");
|
|
2593
3224
|
console.log(" Resetting Cortex MCP configuration...");
|
|
@@ -2608,8 +3239,8 @@ function runReset() {
|
|
|
2608
3239
|
` Codex: ${codexReset ? "entries removed" : "no entries found"}`
|
|
2609
3240
|
);
|
|
2610
3241
|
const configPath = getConfigPath();
|
|
2611
|
-
if (
|
|
2612
|
-
|
|
3242
|
+
if (existsSync5(configPath)) {
|
|
3243
|
+
unlinkSync3(configPath);
|
|
2613
3244
|
console.log(` Config file: removed`);
|
|
2614
3245
|
}
|
|
2615
3246
|
const configDir = getConfigDir();
|
|
@@ -2631,15 +3262,15 @@ function log2(msg) {
|
|
|
2631
3262
|
process.stderr.write(msg + "\n");
|
|
2632
3263
|
}
|
|
2633
3264
|
function sleep(ms) {
|
|
2634
|
-
return new Promise((
|
|
3265
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
2635
3266
|
}
|
|
2636
3267
|
function waitForEnter() {
|
|
2637
|
-
return new Promise((
|
|
3268
|
+
return new Promise((resolve2) => {
|
|
2638
3269
|
process.stdin.setRawMode?.(false);
|
|
2639
3270
|
process.stdin.resume();
|
|
2640
3271
|
process.stdin.once("data", () => {
|
|
2641
3272
|
process.stdin.pause();
|
|
2642
|
-
|
|
3273
|
+
resolve2();
|
|
2643
3274
|
});
|
|
2644
3275
|
});
|
|
2645
3276
|
}
|
|
@@ -2663,16 +3294,16 @@ async function connectProvider(providerName, displayName, apiKey, serverUrl, ins
|
|
|
2663
3294
|
log2(" Error: Your session has expired. Run 'cortex-mcp login' to re-authenticate.");
|
|
2664
3295
|
return false;
|
|
2665
3296
|
}
|
|
2666
|
-
const
|
|
2667
|
-
log2(` Error: ${
|
|
3297
|
+
const err2 = await resp.json().catch(() => ({}));
|
|
3298
|
+
log2(` Error: ${err2.detail || `HTTP ${resp.status}`}`);
|
|
2668
3299
|
return false;
|
|
2669
3300
|
}
|
|
2670
3301
|
const data = await resp.json();
|
|
2671
3302
|
sessionId = data.session_id;
|
|
2672
3303
|
authUrl = data.authorization_url;
|
|
2673
3304
|
expiresIn = data.expires_in;
|
|
2674
|
-
} catch (
|
|
2675
|
-
const msg =
|
|
3305
|
+
} catch (err2) {
|
|
3306
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
2676
3307
|
log2(` Error: Could not reach Cortex server at ${serverUrl}`);
|
|
2677
3308
|
log2(` ${msg}`);
|
|
2678
3309
|
return false;
|
|
@@ -2777,7 +3408,7 @@ function log3(msg) {
|
|
|
2777
3408
|
process.stderr.write(msg + "\n");
|
|
2778
3409
|
}
|
|
2779
3410
|
function sleep2(ms) {
|
|
2780
|
-
return new Promise((
|
|
3411
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
2781
3412
|
}
|
|
2782
3413
|
async function loginWithSSO(serverUrl, emailHint) {
|
|
2783
3414
|
let sessionId;
|
|
@@ -2801,8 +3432,8 @@ async function loginWithSSO(serverUrl, emailHint) {
|
|
|
2801
3432
|
sessionId = data.session_id;
|
|
2802
3433
|
authUrl = data.auth_url;
|
|
2803
3434
|
expiresIn = data.expires_in;
|
|
2804
|
-
} catch (
|
|
2805
|
-
const msg =
|
|
3435
|
+
} catch (err2) {
|
|
3436
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
2806
3437
|
log3(` Error: Could not reach Cortex server at ${serverUrl}`);
|
|
2807
3438
|
log3(` ${msg}`);
|
|
2808
3439
|
return { status: "failed" };
|
|
@@ -2906,8 +3537,8 @@ async function showConnectionsAndAutoConnect(apiKey, serverUrl) {
|
|
|
2906
3537
|
input: process.stdin,
|
|
2907
3538
|
output: process.stderr
|
|
2908
3539
|
});
|
|
2909
|
-
const ask = (question) => new Promise((
|
|
2910
|
-
rl.question(question, (answer) =>
|
|
3540
|
+
const ask = (question) => new Promise((resolve2) => {
|
|
3541
|
+
rl.question(question, (answer) => resolve2(answer.trim().toLowerCase()));
|
|
2911
3542
|
});
|
|
2912
3543
|
for (const mcp of personalMcps) {
|
|
2913
3544
|
const answer = await ask(
|
|
@@ -2951,10 +3582,10 @@ async function promptForEmailHint(ssoEmail) {
|
|
|
2951
3582
|
input: process.stdin,
|
|
2952
3583
|
output: process.stderr
|
|
2953
3584
|
});
|
|
2954
|
-
const answer = await new Promise((
|
|
3585
|
+
const answer = await new Promise((resolve2) => {
|
|
2955
3586
|
rl.question(
|
|
2956
3587
|
" Enter your company email address: ",
|
|
2957
|
-
(a) =>
|
|
3588
|
+
(a) => resolve2(a.trim())
|
|
2958
3589
|
);
|
|
2959
3590
|
});
|
|
2960
3591
|
rl.close();
|
|
@@ -3215,11 +3846,11 @@ program.name("cortex-mcp").description(
|
|
|
3215
3846
|
program.command("setup").description("Interactive setup wizard \u2014 configure MCPs and AI clients").action(async () => {
|
|
3216
3847
|
try {
|
|
3217
3848
|
await runSetup();
|
|
3218
|
-
} catch (
|
|
3219
|
-
if (
|
|
3849
|
+
} catch (err2) {
|
|
3850
|
+
if (err2.code === "ERR_USE_AFTER_CLOSE") {
|
|
3220
3851
|
process.exit(0);
|
|
3221
3852
|
}
|
|
3222
|
-
console.error("Setup failed:",
|
|
3853
|
+
console.error("Setup failed:", err2);
|
|
3223
3854
|
process.exit(1);
|
|
3224
3855
|
}
|
|
3225
3856
|
});
|
|
@@ -3249,11 +3880,11 @@ program.command("login").description("Sign in with your company Okta SSO account
|
|
|
3249
3880
|
).action(async (options) => {
|
|
3250
3881
|
try {
|
|
3251
3882
|
await runLogin(options.email);
|
|
3252
|
-
} catch (
|
|
3253
|
-
if (
|
|
3883
|
+
} catch (err2) {
|
|
3884
|
+
if (err2.code === "ERR_USE_AFTER_CLOSE") {
|
|
3254
3885
|
process.exit(0);
|
|
3255
3886
|
}
|
|
3256
|
-
console.error("Login failed:",
|
|
3887
|
+
console.error("Login failed:", err2);
|
|
3257
3888
|
process.exit(1);
|
|
3258
3889
|
}
|
|
3259
3890
|
});
|
|
@@ -3266,27 +3897,27 @@ program.command("whoami").description("Show current authenticated user").action(
|
|
|
3266
3897
|
program.command("connect <provider>").description("Connect your personal account to an MCP service (e.g., asana)").action(async (provider) => {
|
|
3267
3898
|
try {
|
|
3268
3899
|
await runConnect(provider);
|
|
3269
|
-
} catch (
|
|
3270
|
-
if (
|
|
3900
|
+
} catch (err2) {
|
|
3901
|
+
if (err2.code === "ERR_USE_AFTER_CLOSE") {
|
|
3271
3902
|
process.exit(0);
|
|
3272
3903
|
}
|
|
3273
|
-
console.error("Connect failed:",
|
|
3904
|
+
console.error("Connect failed:", err2);
|
|
3274
3905
|
process.exit(1);
|
|
3275
3906
|
}
|
|
3276
3907
|
});
|
|
3277
3908
|
program.command("connections").description("List your OAuth connections to MCP services").action(async () => {
|
|
3278
3909
|
try {
|
|
3279
3910
|
await runConnections();
|
|
3280
|
-
} catch (
|
|
3281
|
-
console.error("Failed:",
|
|
3911
|
+
} catch (err2) {
|
|
3912
|
+
console.error("Failed:", err2);
|
|
3282
3913
|
process.exit(1);
|
|
3283
3914
|
}
|
|
3284
3915
|
});
|
|
3285
3916
|
program.command("disconnect <provider>").description("Remove your personal OAuth connection to an MCP service").action(async (provider) => {
|
|
3286
3917
|
try {
|
|
3287
3918
|
await runDisconnect(provider);
|
|
3288
|
-
} catch (
|
|
3289
|
-
console.error("Disconnect failed:",
|
|
3919
|
+
} catch (err2) {
|
|
3920
|
+
console.error("Disconnect failed:", err2);
|
|
3290
3921
|
process.exit(1);
|
|
3291
3922
|
}
|
|
3292
3923
|
});
|