@danainnovations/cortex-mcp 1.0.69 → 1.0.71

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 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((resolve) => {
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
- resolve(JSON.parse(Buffer.concat(chunks).toString()));
1860
+ resolve2(JSON.parse(Buffer.concat(chunks).toString()));
1860
1861
  } catch {
1861
- resolve({});
1862
+ resolve2({});
1862
1863
  }
1863
1864
  });
1864
- req.on("error", () => resolve({}));
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 (err) {
1908
- const msg = err instanceof Error ? err.message : String(err);
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 (err) {
1957
- const msg = err instanceof Error ? err.message : String(err);
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 err = await resp.json().catch(() => ({}));
2007
- json(res, { error: err.detail || `HTTP ${resp.status}` }, resp.status);
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 (err) {
2013
- const msg = err instanceof Error ? err.message : String(err);
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;
@@ -2038,6 +2039,17 @@ async function handleApiRoute(path, searchParams, req, res, options, onComplete)
2038
2039
  const body = await parseBody(req);
2039
2040
  const mcps = body.mcps || [...DEFAULT_MCPS];
2040
2041
  const configuredClients = body.configuredClients || [];
2042
+ const apiKey = getState().apiKey;
2043
+ try {
2044
+ await fetch(`${options.serverUrl}/api/v1/setup/complete`, {
2045
+ method: "POST",
2046
+ headers: {
2047
+ "Content-Type": "application/json",
2048
+ "x-api-key": apiKey
2049
+ }
2050
+ });
2051
+ } catch {
2052
+ }
2041
2053
  const config = createConfig(getState().apiKey, mcps);
2042
2054
  config.configuredClients = configuredClients;
2043
2055
  writeConfig(config);
@@ -2050,7 +2062,7 @@ async function handleApiRoute(path, searchParams, req, res, options, onComplete)
2050
2062
 
2051
2063
  // src/wizard/server.ts
2052
2064
  function startWizardServer(options) {
2053
- return new Promise((resolve, reject) => {
2065
+ return new Promise((resolve2, reject) => {
2054
2066
  let completionResolve;
2055
2067
  const completionPromise = new Promise((r) => {
2056
2068
  completionResolve = r;
@@ -2075,8 +2087,8 @@ function startWizardServer(options) {
2075
2087
  res.writeHead(404, { "Content-Type": "application/json" });
2076
2088
  res.end(JSON.stringify({ error: "Not found" }));
2077
2089
  }
2078
- } catch (err) {
2079
- const msg = err instanceof Error ? err.message : String(err);
2090
+ } catch (err2) {
2091
+ const msg = err2 instanceof Error ? err2.message : String(err2);
2080
2092
  res.writeHead(500, { "Content-Type": "application/json" });
2081
2093
  res.end(JSON.stringify({ error: msg }));
2082
2094
  }
@@ -2087,7 +2099,7 @@ function startWizardServer(options) {
2087
2099
  });
2088
2100
  server.listen(0, "127.0.0.1", () => {
2089
2101
  const addr = server.address();
2090
- resolve({
2102
+ resolve2({
2091
2103
  port: addr.port,
2092
2104
  close: () => new Promise((r) => {
2093
2105
  server.close(() => r());
@@ -2172,8 +2184,8 @@ async function runConfigure(options) {
2172
2184
  selectedMcps
2173
2185
  );
2174
2186
  console.log(result);
2175
- } catch (err) {
2176
- const msg = err instanceof Error ? err.message : String(err);
2187
+ } catch (err2) {
2188
+ const msg = err2 instanceof Error ? err2.message : String(err2);
2177
2189
  console.error(`Failed to configure ${client}: ${msg}`);
2178
2190
  process.exit(1);
2179
2191
  }
@@ -2184,7 +2196,7 @@ async function runConfigure(options) {
2184
2196
  }
2185
2197
 
2186
2198
  // src/proxy/stdio-server.ts
2187
- import { readFileSync as readFileSync4, statSync } from "fs";
2199
+ import { readFileSync as readFileSync5, statSync as statSync2 } from "fs";
2188
2200
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2189
2201
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2190
2202
  import {
@@ -2296,6 +2308,633 @@ var CortexHttpClient = class {
2296
2308
  }
2297
2309
  };
2298
2310
 
2311
+ // src/proxy/local-filesystem.ts
2312
+ import {
2313
+ copyFileSync,
2314
+ cpSync,
2315
+ existsSync as existsSync4,
2316
+ mkdirSync as mkdirSync4,
2317
+ readFileSync as readFileSync4,
2318
+ readdirSync,
2319
+ rmSync,
2320
+ statSync,
2321
+ unlinkSync as unlinkSync2,
2322
+ writeFileSync as writeFileSync4,
2323
+ appendFileSync,
2324
+ renameSync
2325
+ } from "fs";
2326
+ import { basename, dirname as dirname2, extname, join as join4, relative, resolve } from "path";
2327
+ var FILESYSTEM_TOOLS = /* @__PURE__ */ new Set([
2328
+ "read_file",
2329
+ "read_file_lines",
2330
+ "write_file",
2331
+ "append_file",
2332
+ "create_directory",
2333
+ "delete",
2334
+ "move",
2335
+ "copy",
2336
+ "list_directory",
2337
+ "exists",
2338
+ "get_file_info",
2339
+ "search_files",
2340
+ "find_in_files",
2341
+ "get_tree"
2342
+ ]);
2343
+ var MAX_READ_SIZE = 50 * 1024 * 1024;
2344
+ var BINARY_CHECK_SIZE = 8192;
2345
+ var BINARY_SIGNATURES = [
2346
+ Buffer.from([137, 80, 78, 71]),
2347
+ // PNG
2348
+ Buffer.from([255, 216, 255]),
2349
+ // JPEG
2350
+ Buffer.from("GIF8"),
2351
+ // GIF
2352
+ Buffer.from([80, 75, 3, 4]),
2353
+ // ZIP / DOCX / XLSX
2354
+ Buffer.from("%PDF"),
2355
+ // PDF
2356
+ Buffer.from([127, 69, 76, 70]),
2357
+ // ELF
2358
+ Buffer.from([254, 237, 250]),
2359
+ // Mach-O
2360
+ Buffer.from([207, 250, 237, 254]),
2361
+ // Mach-O (reversed)
2362
+ Buffer.from("MZ")
2363
+ // Windows executable
2364
+ ];
2365
+ function resolvePath(p) {
2366
+ return resolve(p);
2367
+ }
2368
+ function isBinaryFile(filePath) {
2369
+ try {
2370
+ const fd = readFileSync4(filePath, { flag: "r" });
2371
+ const chunk = fd.subarray(0, BINARY_CHECK_SIZE);
2372
+ if (chunk.length === 0) return false;
2373
+ for (const sig of BINARY_SIGNATURES) {
2374
+ if (chunk.length >= sig.length && chunk.subarray(0, sig.length).equals(sig)) {
2375
+ return true;
2376
+ }
2377
+ }
2378
+ return chunk.includes(0);
2379
+ } catch {
2380
+ return false;
2381
+ }
2382
+ }
2383
+ function globToRegex(pattern) {
2384
+ let re = "^";
2385
+ for (let i = 0; i < pattern.length; i++) {
2386
+ const c = pattern[i];
2387
+ if (c === "*") {
2388
+ re += ".*";
2389
+ } else if (c === "?") {
2390
+ re += ".";
2391
+ } else if (c === "[") {
2392
+ const close = pattern.indexOf("]", i + 1);
2393
+ if (close !== -1) {
2394
+ re += "[" + pattern.slice(i + 1, close) + "]";
2395
+ i = close;
2396
+ } else {
2397
+ re += "\\[";
2398
+ }
2399
+ } else if (".+^${}()|\\".includes(c)) {
2400
+ re += "\\" + c;
2401
+ } else {
2402
+ re += c;
2403
+ }
2404
+ }
2405
+ re += "$";
2406
+ return new RegExp(re);
2407
+ }
2408
+ function fileType(isDir, isSymlink) {
2409
+ if (isSymlink) return "symlink";
2410
+ if (isDir) return "directory";
2411
+ return "file";
2412
+ }
2413
+ function countDirectoryContents(dirPath) {
2414
+ let files = 0;
2415
+ let bytes = 0;
2416
+ try {
2417
+ const entries = readdirSync(dirPath, { withFileTypes: true });
2418
+ for (const entry of entries) {
2419
+ const full = join4(dirPath, entry.name);
2420
+ if (entry.isDirectory()) {
2421
+ const sub = countDirectoryContents(full);
2422
+ files += sub.files;
2423
+ bytes += sub.bytes;
2424
+ } else {
2425
+ files += 1;
2426
+ try {
2427
+ bytes += statSync(full).size;
2428
+ } catch {
2429
+ }
2430
+ }
2431
+ }
2432
+ } catch {
2433
+ }
2434
+ return { files, bytes };
2435
+ }
2436
+ function ok(data) {
2437
+ return {
2438
+ content: [{ type: "text", text: JSON.stringify(data) }],
2439
+ isError: false
2440
+ };
2441
+ }
2442
+ function err(message) {
2443
+ return {
2444
+ content: [{ type: "text", text: JSON.stringify({ success: false, error: message }) }],
2445
+ isError: true
2446
+ };
2447
+ }
2448
+ function handleReadFile(args) {
2449
+ const filePath = resolvePath(args.path);
2450
+ const encoding = args.encoding || "utf-8";
2451
+ const stat = statSync(filePath);
2452
+ if (!stat.isFile()) throw new Error("Not a file.");
2453
+ if (stat.size > MAX_READ_SIZE) {
2454
+ throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size (${MAX_READ_SIZE} bytes).`);
2455
+ }
2456
+ if (isBinaryFile(filePath)) {
2457
+ const raw = readFileSync4(filePath);
2458
+ return ok({
2459
+ content: raw.toString("base64"),
2460
+ is_binary: true,
2461
+ size: stat.size,
2462
+ encoding: "base64",
2463
+ path: filePath
2464
+ });
2465
+ }
2466
+ const text = readFileSync4(filePath, encoding);
2467
+ return ok({
2468
+ content: text,
2469
+ is_binary: false,
2470
+ size: stat.size,
2471
+ encoding,
2472
+ path: filePath
2473
+ });
2474
+ }
2475
+ function handleReadFileLines(args) {
2476
+ const filePath = resolvePath(args.path);
2477
+ const encoding = args.encoding || "utf-8";
2478
+ const startLine = args.start_line || 1;
2479
+ const endLine = args.end_line;
2480
+ const stat = statSync(filePath);
2481
+ if (!stat.isFile()) throw new Error("Not a file.");
2482
+ if (stat.size > MAX_READ_SIZE) {
2483
+ throw new Error(`File size (${stat.size} bytes) exceeds maximum allowed size.`);
2484
+ }
2485
+ if (startLine < 1) throw new Error("start_line must be >= 1.");
2486
+ if (endLine !== void 0 && endLine < startLine) throw new Error("end_line must be >= start_line.");
2487
+ const text = readFileSync4(filePath, encoding);
2488
+ const allLines = text.split(/\n/);
2489
+ const totalLines = allLines.length;
2490
+ const startIdx = startLine - 1;
2491
+ const endIdx = endLine !== void 0 ? endLine : totalLines;
2492
+ const selected = allLines.slice(startIdx, endIdx);
2493
+ const actualEnd = Math.min(endIdx, totalLines);
2494
+ return ok({
2495
+ content: selected.join("\n"),
2496
+ start_line: startLine,
2497
+ end_line: actualEnd,
2498
+ total_lines: totalLines,
2499
+ size: stat.size,
2500
+ path: filePath
2501
+ });
2502
+ }
2503
+ function handleWriteFile(args) {
2504
+ const filePath = resolvePath(args.path);
2505
+ const content = args.content;
2506
+ const encoding = args.encoding || "utf-8";
2507
+ const isBinary = args.is_binary || false;
2508
+ const overwrite = args.overwrite !== false;
2509
+ const createParents = args.create_parents || false;
2510
+ const created = !existsSync4(filePath);
2511
+ if (!overwrite && !created) {
2512
+ throw new Error("File already exists.");
2513
+ }
2514
+ if (createParents) {
2515
+ mkdirSync4(dirname2(filePath), { recursive: true });
2516
+ }
2517
+ let bytesWritten;
2518
+ let usedEncoding;
2519
+ if (isBinary) {
2520
+ const raw = Buffer.from(content, "base64");
2521
+ writeFileSync4(filePath, raw);
2522
+ bytesWritten = raw.length;
2523
+ usedEncoding = "base64";
2524
+ } else {
2525
+ const encoded = Buffer.from(content, encoding);
2526
+ writeFileSync4(filePath, content, encoding);
2527
+ bytesWritten = encoded.length;
2528
+ usedEncoding = encoding;
2529
+ }
2530
+ return ok({
2531
+ path: filePath,
2532
+ bytes_written: bytesWritten,
2533
+ created,
2534
+ encoding: usedEncoding
2535
+ });
2536
+ }
2537
+ function handleAppendFile(args) {
2538
+ const filePath = resolvePath(args.path);
2539
+ const content = args.content;
2540
+ const encoding = args.encoding || "utf-8";
2541
+ if (!existsSync4(filePath)) throw new Error("File not found.");
2542
+ const encoded = Buffer.from(content, encoding);
2543
+ appendFileSync(filePath, content, encoding);
2544
+ const newSize = statSync(filePath).size;
2545
+ return ok({
2546
+ path: filePath,
2547
+ bytes_written: encoded.length,
2548
+ new_size: newSize
2549
+ });
2550
+ }
2551
+ function handleCreateDirectory(args) {
2552
+ const dirPath = resolvePath(args.path);
2553
+ const parents = args.parents !== false;
2554
+ if (existsSync4(dirPath)) {
2555
+ return ok({ path: dirPath, created: false });
2556
+ }
2557
+ if (parents) {
2558
+ mkdirSync4(dirPath, { recursive: true });
2559
+ } else {
2560
+ mkdirSync4(dirPath);
2561
+ }
2562
+ return ok({ path: dirPath, created: true });
2563
+ }
2564
+ function handleDelete(args) {
2565
+ const targetPath = resolvePath(args.path);
2566
+ const recursive = args.recursive || false;
2567
+ if (!existsSync4(targetPath)) throw new Error("Path not found.");
2568
+ const stat = statSync(targetPath, { throwIfNoEntry: false });
2569
+ if (!stat) throw new Error("Path not found.");
2570
+ if (stat.isDirectory()) {
2571
+ const { files: filesDeleted, bytes: bytesFreed } = countDirectoryContents(targetPath);
2572
+ if (recursive) {
2573
+ rmSync(targetPath, { recursive: true });
2574
+ } else {
2575
+ rmSync(targetPath);
2576
+ }
2577
+ return ok({
2578
+ path: targetPath,
2579
+ type: "directory",
2580
+ files_deleted: recursive ? filesDeleted : 0,
2581
+ bytes_freed: recursive ? bytesFreed : 0
2582
+ });
2583
+ }
2584
+ const size = stat.size;
2585
+ unlinkSync2(targetPath);
2586
+ return ok({
2587
+ path: targetPath,
2588
+ type: "file",
2589
+ files_deleted: 1,
2590
+ bytes_freed: size
2591
+ });
2592
+ }
2593
+ function handleMove(args) {
2594
+ const source = resolvePath(args.source);
2595
+ const destination = resolvePath(args.destination);
2596
+ const overwrite = args.overwrite || false;
2597
+ if (!existsSync4(source)) throw new Error("Source path not found.");
2598
+ if (existsSync4(destination) && !overwrite) throw new Error("Destination already exists.");
2599
+ const stat = statSync(source);
2600
+ const type = stat.isDirectory() ? "directory" : "file";
2601
+ const bytesMoved = stat.isDirectory() ? countDirectoryContents(source).bytes : stat.size;
2602
+ try {
2603
+ renameSync(source, destination);
2604
+ } catch (e) {
2605
+ if (e.code === "EXDEV") {
2606
+ if (stat.isDirectory()) {
2607
+ cpSync(source, destination, { recursive: true });
2608
+ rmSync(source, { recursive: true });
2609
+ } else {
2610
+ copyFileSync(source, destination);
2611
+ unlinkSync2(source);
2612
+ }
2613
+ } else {
2614
+ throw e;
2615
+ }
2616
+ }
2617
+ return ok({
2618
+ source,
2619
+ destination,
2620
+ type,
2621
+ bytes_moved: bytesMoved
2622
+ });
2623
+ }
2624
+ function handleCopy(args) {
2625
+ const source = resolvePath(args.source);
2626
+ const destination = resolvePath(args.destination);
2627
+ const overwrite = args.overwrite || false;
2628
+ if (!existsSync4(source)) throw new Error("Source path not found.");
2629
+ if (existsSync4(destination) && !overwrite) throw new Error("Destination already exists.");
2630
+ const stat = statSync(source);
2631
+ if (stat.isDirectory()) {
2632
+ if (existsSync4(destination) && overwrite) {
2633
+ rmSync(destination, { recursive: true });
2634
+ }
2635
+ cpSync(source, destination, { recursive: true });
2636
+ const { bytes } = countDirectoryContents(destination);
2637
+ return ok({ source, destination, type: "directory", bytes_copied: bytes });
2638
+ }
2639
+ copyFileSync(source, destination);
2640
+ const bytesCopied = statSync(destination).size;
2641
+ return ok({ source, destination, type: "file", bytes_copied: bytesCopied });
2642
+ }
2643
+ function handleListDirectory(args) {
2644
+ const dirPath = resolvePath(args.path);
2645
+ const recursive = args.recursive || false;
2646
+ const maxDepth = args.max_depth || 1;
2647
+ const pattern = args.pattern;
2648
+ const includeHidden = args.include_hidden || false;
2649
+ if (!existsSync4(dirPath)) throw new Error("Directory not found.");
2650
+ const stat = statSync(dirPath);
2651
+ if (!stat.isDirectory()) throw new Error("Path is not a directory.");
2652
+ const effectiveDepth = recursive ? maxDepth : 1;
2653
+ const patternRe = pattern ? globToRegex(pattern) : null;
2654
+ const entries = [];
2655
+ function scan(dir, depth) {
2656
+ if (depth >= effectiveDepth) return;
2657
+ let dirents;
2658
+ try {
2659
+ dirents = readdirSync(dir, { withFileTypes: true });
2660
+ } catch {
2661
+ return;
2662
+ }
2663
+ dirents.sort((a, b) => a.name.localeCompare(b.name));
2664
+ for (const d of dirents) {
2665
+ if (!includeHidden && d.name.startsWith(".")) continue;
2666
+ const fullPath = join4(dir, d.name);
2667
+ const isDir = d.isDirectory();
2668
+ if (patternRe && !patternRe.test(d.name)) {
2669
+ if (isDir && effectiveDepth > 1) {
2670
+ scan(fullPath, depth + 1);
2671
+ }
2672
+ continue;
2673
+ }
2674
+ let size = 0;
2675
+ let mtime = (/* @__PURE__ */ new Date()).toISOString();
2676
+ try {
2677
+ const s = statSync(fullPath);
2678
+ size = isDir ? 0 : s.size;
2679
+ mtime = new Date(s.mtimeMs).toISOString();
2680
+ } catch {
2681
+ }
2682
+ entries.push({
2683
+ name: d.name,
2684
+ path: relative(dirPath, fullPath),
2685
+ type: fileType(isDir, d.isSymbolicLink()),
2686
+ size,
2687
+ modified_at: mtime,
2688
+ is_hidden: d.name.startsWith(".")
2689
+ });
2690
+ if (isDir && effectiveDepth > 1) {
2691
+ scan(fullPath, depth + 1);
2692
+ }
2693
+ }
2694
+ }
2695
+ scan(dirPath, 0);
2696
+ return ok({
2697
+ path: dirPath,
2698
+ entries,
2699
+ total_count: entries.length
2700
+ });
2701
+ }
2702
+ function handleExists(args) {
2703
+ const targetPath = resolvePath(args.path);
2704
+ const pathExists = existsSync4(targetPath);
2705
+ let type = null;
2706
+ if (pathExists) {
2707
+ const stat = statSync(targetPath, { throwIfNoEntry: false });
2708
+ if (stat) {
2709
+ type = fileType(stat.isDirectory(), stat.isSymbolicLink());
2710
+ }
2711
+ }
2712
+ return ok({ exists: pathExists, path: targetPath, type });
2713
+ }
2714
+ function handleGetFileInfo(args) {
2715
+ const filePath = resolvePath(args.path);
2716
+ if (!existsSync4(filePath)) throw new Error("Path not found.");
2717
+ const stat = statSync(filePath, { throwIfNoEntry: false });
2718
+ if (!stat) throw new Error("Path not found.");
2719
+ const isDir = stat.isDirectory();
2720
+ const isSymlink = stat.isSymbolicLink();
2721
+ const name = basename(filePath);
2722
+ const ext = isDir ? null : extname(name) || null;
2723
+ const binary = !isDir && !isSymlink ? isBinaryFile(filePath) : false;
2724
+ return ok({
2725
+ name,
2726
+ path: filePath,
2727
+ type: fileType(isDir, isSymlink),
2728
+ size: isDir ? 0 : stat.size,
2729
+ modified_at: new Date(stat.mtimeMs).toISOString(),
2730
+ created_at: stat.birthtimeMs ? new Date(stat.birthtimeMs).toISOString() : null,
2731
+ extension: ext,
2732
+ is_hidden: name.startsWith("."),
2733
+ is_binary: binary
2734
+ });
2735
+ }
2736
+ function handleSearchFiles(args) {
2737
+ const searchPath = resolvePath(args.path);
2738
+ const pattern = args.pattern || "*";
2739
+ const recursive = args.recursive !== false;
2740
+ const includeHidden = args.include_hidden || false;
2741
+ const maxResults = args.max_results || 1e3;
2742
+ if (!existsSync4(searchPath)) throw new Error("Directory not found.");
2743
+ if (!statSync(searchPath).isDirectory()) throw new Error("Path is not a directory.");
2744
+ const patternRe = globToRegex(pattern);
2745
+ const matches = [];
2746
+ let totalMatches = 0;
2747
+ function scan(dir) {
2748
+ let dirents;
2749
+ try {
2750
+ dirents = readdirSync(dir, { withFileTypes: true });
2751
+ } catch {
2752
+ return;
2753
+ }
2754
+ for (const d of dirents) {
2755
+ if (!includeHidden) {
2756
+ if (d.name.startsWith(".")) continue;
2757
+ }
2758
+ const fullPath = join4(dir, d.name);
2759
+ if (d.isDirectory()) {
2760
+ if (recursive) scan(fullPath);
2761
+ continue;
2762
+ }
2763
+ if (patternRe.test(d.name)) {
2764
+ totalMatches++;
2765
+ if (matches.length < maxResults) {
2766
+ matches.push(relative(searchPath, fullPath));
2767
+ }
2768
+ }
2769
+ }
2770
+ }
2771
+ scan(searchPath);
2772
+ return ok({
2773
+ matches,
2774
+ total_matches: totalMatches,
2775
+ truncated: totalMatches > maxResults,
2776
+ search_path: searchPath,
2777
+ pattern
2778
+ });
2779
+ }
2780
+ function handleFindInFiles(args) {
2781
+ const searchPath = resolvePath(args.path);
2782
+ const query = args.query;
2783
+ const isRegex = args.is_regex || false;
2784
+ const caseSensitive = args.case_sensitive !== false;
2785
+ const filePattern = args.pattern;
2786
+ const contextLines = args.context_lines || 0;
2787
+ const maxResults = args.max_results || 500;
2788
+ const includeHidden = args.include_hidden || false;
2789
+ if (!existsSync4(searchPath)) throw new Error("Directory not found.");
2790
+ if (!statSync(searchPath).isDirectory()) throw new Error("Path is not a directory.");
2791
+ const flags = caseSensitive ? "" : "i";
2792
+ const re = isRegex ? new RegExp(query, flags) : new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), flags);
2793
+ const patternRe = filePattern ? globToRegex(filePattern) : null;
2794
+ const results = [];
2795
+ let totalMatches = 0;
2796
+ let filesSearched = 0;
2797
+ let filesWithMatches = 0;
2798
+ function scan(dir) {
2799
+ let dirents;
2800
+ try {
2801
+ dirents = readdirSync(dir, { withFileTypes: true });
2802
+ } catch {
2803
+ return;
2804
+ }
2805
+ for (const d of dirents) {
2806
+ if (!includeHidden && d.name.startsWith(".")) continue;
2807
+ const fullPath = join4(dir, d.name);
2808
+ if (d.isDirectory()) {
2809
+ scan(fullPath);
2810
+ continue;
2811
+ }
2812
+ if (patternRe && !patternRe.test(d.name)) continue;
2813
+ if (isBinaryFile(fullPath)) continue;
2814
+ filesSearched++;
2815
+ let fileHasMatch = false;
2816
+ let lines;
2817
+ try {
2818
+ const text = readFileSync4(fullPath, "utf-8");
2819
+ lines = text.split("\n");
2820
+ } catch {
2821
+ continue;
2822
+ }
2823
+ for (let i = 0; i < lines.length; i++) {
2824
+ if (re.test(lines[i])) {
2825
+ totalMatches++;
2826
+ fileHasMatch = true;
2827
+ if (results.length < maxResults) {
2828
+ const ctxStart = Math.max(0, i - contextLines);
2829
+ const ctxEnd = Math.min(lines.length, i + contextLines + 1);
2830
+ results.push({
2831
+ file: relative(searchPath, fullPath),
2832
+ line: i + 1,
2833
+ content: lines[i],
2834
+ context_before: lines.slice(ctxStart, i),
2835
+ context_after: lines.slice(i + 1, ctxEnd)
2836
+ });
2837
+ }
2838
+ }
2839
+ }
2840
+ if (fileHasMatch) filesWithMatches++;
2841
+ }
2842
+ }
2843
+ scan(searchPath);
2844
+ return ok({
2845
+ results,
2846
+ total_matches: totalMatches,
2847
+ files_searched: filesSearched,
2848
+ files_with_matches: filesWithMatches,
2849
+ truncated: totalMatches > maxResults,
2850
+ query
2851
+ });
2852
+ }
2853
+ function handleGetTree(args) {
2854
+ const rootPath = resolvePath(args.path);
2855
+ const maxDepth = args.max_depth || 3;
2856
+ const includeHidden = args.include_hidden || false;
2857
+ const maxEntries = args.max_entries || 500;
2858
+ if (!existsSync4(rootPath)) throw new Error("Directory not found.");
2859
+ if (!statSync(rootPath).isDirectory()) throw new Error("Path is not a directory.");
2860
+ const lines = [];
2861
+ let entryCount = 0;
2862
+ let truncated = false;
2863
+ const rootName = basename(rootPath) || rootPath;
2864
+ lines.push(rootName + "/");
2865
+ function buildTree(dirPath, prefix, depth) {
2866
+ if (truncated || depth >= maxDepth) return;
2867
+ let dirents;
2868
+ try {
2869
+ dirents = readdirSync(dirPath, { withFileTypes: true });
2870
+ } catch {
2871
+ return;
2872
+ }
2873
+ if (!includeHidden) {
2874
+ dirents = dirents.filter((d) => !d.name.startsWith("."));
2875
+ }
2876
+ dirents.sort((a, b) => a.name.localeCompare(b.name));
2877
+ for (let i = 0; i < dirents.length; i++) {
2878
+ if (truncated) return;
2879
+ entryCount++;
2880
+ if (entryCount > maxEntries) {
2881
+ truncated = true;
2882
+ lines.push(prefix + "... (truncated)");
2883
+ return;
2884
+ }
2885
+ const d = dirents[i];
2886
+ const isLast = i === dirents.length - 1;
2887
+ const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
2888
+ const childPrefix = prefix + (isLast ? " " : "\u2502 ");
2889
+ const fullPath = join4(dirPath, d.name);
2890
+ if (d.isDirectory()) {
2891
+ lines.push(prefix + connector + d.name + "/");
2892
+ buildTree(fullPath, childPrefix, depth + 1);
2893
+ } else {
2894
+ lines.push(prefix + connector + d.name);
2895
+ }
2896
+ }
2897
+ }
2898
+ buildTree(rootPath, "", 0);
2899
+ return ok({
2900
+ tree: lines.join("\n"),
2901
+ path: rootPath,
2902
+ entry_count: entryCount,
2903
+ truncated,
2904
+ max_depth: maxDepth
2905
+ });
2906
+ }
2907
+ var HANDLERS = {
2908
+ read_file: handleReadFile,
2909
+ read_file_lines: handleReadFileLines,
2910
+ write_file: handleWriteFile,
2911
+ append_file: handleAppendFile,
2912
+ create_directory: handleCreateDirectory,
2913
+ delete: handleDelete,
2914
+ move: handleMove,
2915
+ copy: handleCopy,
2916
+ list_directory: handleListDirectory,
2917
+ exists: handleExists,
2918
+ get_file_info: handleGetFileInfo,
2919
+ search_files: handleSearchFiles,
2920
+ find_in_files: handleFindInFiles,
2921
+ get_tree: handleGetTree
2922
+ };
2923
+ function handleLocalFilesystemTool(_toolName, baseName, args) {
2924
+ console.error(`[cortex-mcp] filesystem.${baseName}: executing locally`);
2925
+ const handler = HANDLERS[baseName];
2926
+ if (!handler) {
2927
+ return err(`Unknown filesystem tool: ${baseName}`);
2928
+ }
2929
+ try {
2930
+ return handler(args);
2931
+ } catch (e) {
2932
+ const message = e instanceof Error ? e.message : String(e);
2933
+ console.error(`[cortex-mcp] filesystem.${baseName} error: ${message}`);
2934
+ return err(message);
2935
+ }
2936
+ }
2937
+
2299
2938
  // src/proxy/stdio-server.ts
2300
2939
  var UPLOAD_TOOLS = /* @__PURE__ */ new Set(["upload_file", "upload_file_to_sharepoint"]);
2301
2940
  var INLINE_UPLOAD_MAX = 3 * 1024 * 1024;
@@ -2360,7 +2999,7 @@ async function handleLocalFileUpload(cortex, toolName, args) {
2360
2999
  const filePath = args.file_path;
2361
3000
  let fileSize;
2362
3001
  try {
2363
- fileSize = statSync(filePath).size;
3002
+ fileSize = statSync2(filePath).size;
2364
3003
  } catch {
2365
3004
  return {
2366
3005
  content: [{ type: "text", text: JSON.stringify({
@@ -2371,7 +3010,7 @@ async function handleLocalFileUpload(cortex, toolName, args) {
2371
3010
  };
2372
3011
  }
2373
3012
  if (fileSize <= INLINE_UPLOAD_MAX) {
2374
- const fileBuffer2 = readFileSync4(filePath);
3013
+ const fileBuffer2 = readFileSync5(filePath);
2375
3014
  const base64Content = fileBuffer2.toString("base64");
2376
3015
  const forwardArgs = { ...args, content: base64Content };
2377
3016
  delete forwardArgs.file_path;
@@ -2423,7 +3062,7 @@ async function handleLocalFileUpload(cortex, toolName, args) {
2423
3062
  isError: true
2424
3063
  };
2425
3064
  }
2426
- const fileBuffer = readFileSync4(filePath);
3065
+ const fileBuffer = readFileSync5(filePath);
2427
3066
  const chunkSize = 2.5 * 1024 * 1024;
2428
3067
  const total = fileBuffer.length;
2429
3068
  let driveItem = {};
@@ -2493,8 +3132,8 @@ async function startStdioServer(options) {
2493
3132
  console.error("[cortex-mcp] Initializing backend session...");
2494
3133
  await cortex.initialize();
2495
3134
  console.error("[cortex-mcp] Backend session established.");
2496
- } catch (err) {
2497
- const msg = err instanceof Error ? err.message : String(err);
3135
+ } catch (err2) {
3136
+ const msg = err2 instanceof Error ? err2.message : String(err2);
2498
3137
  console.error(`[cortex-mcp] Backend initialization failed: ${msg}`);
2499
3138
  }
2500
3139
  initialized = true;
@@ -2517,6 +3156,9 @@ async function startStdioServer(options) {
2517
3156
  if (UPLOAD_TOOLS.has(baseName) && typedArgs.file_path) {
2518
3157
  return handleLocalFileUpload(cortex, name, typedArgs);
2519
3158
  }
3159
+ if (FILESYSTEM_TOOLS.has(baseName)) {
3160
+ return handleLocalFilesystemTool(name, baseName, typedArgs);
3161
+ }
2520
3162
  const response = await cortex.callTool(name, typedArgs);
2521
3163
  if (response.error) {
2522
3164
  return {
@@ -2587,7 +3229,7 @@ function runStatus() {
2587
3229
  }
2588
3230
 
2589
3231
  // src/cli/reset.ts
2590
- import { existsSync as existsSync4, unlinkSync as unlinkSync2, rmdirSync } from "fs";
3232
+ import { existsSync as existsSync5, unlinkSync as unlinkSync3, rmdirSync } from "fs";
2591
3233
  function runReset() {
2592
3234
  console.log("");
2593
3235
  console.log(" Resetting Cortex MCP configuration...");
@@ -2608,8 +3250,8 @@ function runReset() {
2608
3250
  ` Codex: ${codexReset ? "entries removed" : "no entries found"}`
2609
3251
  );
2610
3252
  const configPath = getConfigPath();
2611
- if (existsSync4(configPath)) {
2612
- unlinkSync2(configPath);
3253
+ if (existsSync5(configPath)) {
3254
+ unlinkSync3(configPath);
2613
3255
  console.log(` Config file: removed`);
2614
3256
  }
2615
3257
  const configDir = getConfigDir();
@@ -2631,15 +3273,15 @@ function log2(msg) {
2631
3273
  process.stderr.write(msg + "\n");
2632
3274
  }
2633
3275
  function sleep(ms) {
2634
- return new Promise((resolve) => setTimeout(resolve, ms));
3276
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
2635
3277
  }
2636
3278
  function waitForEnter() {
2637
- return new Promise((resolve) => {
3279
+ return new Promise((resolve2) => {
2638
3280
  process.stdin.setRawMode?.(false);
2639
3281
  process.stdin.resume();
2640
3282
  process.stdin.once("data", () => {
2641
3283
  process.stdin.pause();
2642
- resolve();
3284
+ resolve2();
2643
3285
  });
2644
3286
  });
2645
3287
  }
@@ -2663,16 +3305,16 @@ async function connectProvider(providerName, displayName, apiKey, serverUrl, ins
2663
3305
  log2(" Error: Your session has expired. Run 'cortex-mcp login' to re-authenticate.");
2664
3306
  return false;
2665
3307
  }
2666
- const err = await resp.json().catch(() => ({}));
2667
- log2(` Error: ${err.detail || `HTTP ${resp.status}`}`);
3308
+ const err2 = await resp.json().catch(() => ({}));
3309
+ log2(` Error: ${err2.detail || `HTTP ${resp.status}`}`);
2668
3310
  return false;
2669
3311
  }
2670
3312
  const data = await resp.json();
2671
3313
  sessionId = data.session_id;
2672
3314
  authUrl = data.authorization_url;
2673
3315
  expiresIn = data.expires_in;
2674
- } catch (err) {
2675
- const msg = err instanceof Error ? err.message : String(err);
3316
+ } catch (err2) {
3317
+ const msg = err2 instanceof Error ? err2.message : String(err2);
2676
3318
  log2(` Error: Could not reach Cortex server at ${serverUrl}`);
2677
3319
  log2(` ${msg}`);
2678
3320
  return false;
@@ -2777,7 +3419,7 @@ function log3(msg) {
2777
3419
  process.stderr.write(msg + "\n");
2778
3420
  }
2779
3421
  function sleep2(ms) {
2780
- return new Promise((resolve) => setTimeout(resolve, ms));
3422
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
2781
3423
  }
2782
3424
  async function loginWithSSO(serverUrl, emailHint) {
2783
3425
  let sessionId;
@@ -2801,8 +3443,8 @@ async function loginWithSSO(serverUrl, emailHint) {
2801
3443
  sessionId = data.session_id;
2802
3444
  authUrl = data.auth_url;
2803
3445
  expiresIn = data.expires_in;
2804
- } catch (err) {
2805
- const msg = err instanceof Error ? err.message : String(err);
3446
+ } catch (err2) {
3447
+ const msg = err2 instanceof Error ? err2.message : String(err2);
2806
3448
  log3(` Error: Could not reach Cortex server at ${serverUrl}`);
2807
3449
  log3(` ${msg}`);
2808
3450
  return { status: "failed" };
@@ -2906,8 +3548,8 @@ async function showConnectionsAndAutoConnect(apiKey, serverUrl) {
2906
3548
  input: process.stdin,
2907
3549
  output: process.stderr
2908
3550
  });
2909
- const ask = (question) => new Promise((resolve) => {
2910
- rl.question(question, (answer) => resolve(answer.trim().toLowerCase()));
3551
+ const ask = (question) => new Promise((resolve2) => {
3552
+ rl.question(question, (answer) => resolve2(answer.trim().toLowerCase()));
2911
3553
  });
2912
3554
  for (const mcp of personalMcps) {
2913
3555
  const answer = await ask(
@@ -2951,10 +3593,10 @@ async function promptForEmailHint(ssoEmail) {
2951
3593
  input: process.stdin,
2952
3594
  output: process.stderr
2953
3595
  });
2954
- const answer = await new Promise((resolve) => {
3596
+ const answer = await new Promise((resolve2) => {
2955
3597
  rl.question(
2956
3598
  " Enter your company email address: ",
2957
- (a) => resolve(a.trim())
3599
+ (a) => resolve2(a.trim())
2958
3600
  );
2959
3601
  });
2960
3602
  rl.close();
@@ -3036,6 +3678,16 @@ async function runLogin(emailHint) {
3036
3678
  writeConfig(existingConfig);
3037
3679
  }
3038
3680
  await showConnectionsAndAutoConnect(apiKey, serverUrl);
3681
+ try {
3682
+ await fetch(`${serverUrl}/api/v1/setup/complete`, {
3683
+ method: "POST",
3684
+ headers: {
3685
+ "Content-Type": "application/json",
3686
+ "x-api-key": apiKey
3687
+ }
3688
+ });
3689
+ } catch {
3690
+ }
3039
3691
  log3(" Done! Restart your AI clients to apply.");
3040
3692
  log3("");
3041
3693
  }
@@ -3215,11 +3867,11 @@ program.name("cortex-mcp").description(
3215
3867
  program.command("setup").description("Interactive setup wizard \u2014 configure MCPs and AI clients").action(async () => {
3216
3868
  try {
3217
3869
  await runSetup();
3218
- } catch (err) {
3219
- if (err.code === "ERR_USE_AFTER_CLOSE") {
3870
+ } catch (err2) {
3871
+ if (err2.code === "ERR_USE_AFTER_CLOSE") {
3220
3872
  process.exit(0);
3221
3873
  }
3222
- console.error("Setup failed:", err);
3874
+ console.error("Setup failed:", err2);
3223
3875
  process.exit(1);
3224
3876
  }
3225
3877
  });
@@ -3249,11 +3901,11 @@ program.command("login").description("Sign in with your company Okta SSO account
3249
3901
  ).action(async (options) => {
3250
3902
  try {
3251
3903
  await runLogin(options.email);
3252
- } catch (err) {
3253
- if (err.code === "ERR_USE_AFTER_CLOSE") {
3904
+ } catch (err2) {
3905
+ if (err2.code === "ERR_USE_AFTER_CLOSE") {
3254
3906
  process.exit(0);
3255
3907
  }
3256
- console.error("Login failed:", err);
3908
+ console.error("Login failed:", err2);
3257
3909
  process.exit(1);
3258
3910
  }
3259
3911
  });
@@ -3266,27 +3918,27 @@ program.command("whoami").description("Show current authenticated user").action(
3266
3918
  program.command("connect <provider>").description("Connect your personal account to an MCP service (e.g., asana)").action(async (provider) => {
3267
3919
  try {
3268
3920
  await runConnect(provider);
3269
- } catch (err) {
3270
- if (err.code === "ERR_USE_AFTER_CLOSE") {
3921
+ } catch (err2) {
3922
+ if (err2.code === "ERR_USE_AFTER_CLOSE") {
3271
3923
  process.exit(0);
3272
3924
  }
3273
- console.error("Connect failed:", err);
3925
+ console.error("Connect failed:", err2);
3274
3926
  process.exit(1);
3275
3927
  }
3276
3928
  });
3277
3929
  program.command("connections").description("List your OAuth connections to MCP services").action(async () => {
3278
3930
  try {
3279
3931
  await runConnections();
3280
- } catch (err) {
3281
- console.error("Failed:", err);
3932
+ } catch (err2) {
3933
+ console.error("Failed:", err2);
3282
3934
  process.exit(1);
3283
3935
  }
3284
3936
  });
3285
3937
  program.command("disconnect <provider>").description("Remove your personal OAuth connection to an MCP service").action(async (provider) => {
3286
3938
  try {
3287
3939
  await runDisconnect(provider);
3288
- } catch (err) {
3289
- console.error("Disconnect failed:", err);
3940
+ } catch (err2) {
3941
+ console.error("Disconnect failed:", err2);
3290
3942
  process.exit(1);
3291
3943
  }
3292
3944
  });