@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 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;
@@ -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((resolve, reject) => {
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 (err) {
2079
- const msg = err instanceof Error ? err.message : String(err);
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
- resolve({
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 (err) {
2176
- const msg = err instanceof Error ? err.message : String(err);
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 readFileSync4, statSync } from "fs";
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 = statSync(filePath).size;
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 = readFileSync4(filePath);
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 = readFileSync4(filePath);
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 (err) {
2497
- const msg = err instanceof Error ? err.message : String(err);
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 existsSync4, unlinkSync as unlinkSync2, rmdirSync } from "fs";
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 (existsSync4(configPath)) {
2612
- unlinkSync2(configPath);
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((resolve) => setTimeout(resolve, ms));
3265
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
2635
3266
  }
2636
3267
  function waitForEnter() {
2637
- return new Promise((resolve) => {
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
- resolve();
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 err = await resp.json().catch(() => ({}));
2667
- log2(` Error: ${err.detail || `HTTP ${resp.status}`}`);
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 (err) {
2675
- const msg = err instanceof Error ? err.message : String(err);
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((resolve) => setTimeout(resolve, ms));
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 (err) {
2805
- const msg = err instanceof Error ? err.message : String(err);
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((resolve) => {
2910
- rl.question(question, (answer) => resolve(answer.trim().toLowerCase()));
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((resolve) => {
3585
+ const answer = await new Promise((resolve2) => {
2955
3586
  rl.question(
2956
3587
  " Enter your company email address: ",
2957
- (a) => resolve(a.trim())
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 (err) {
3219
- if (err.code === "ERR_USE_AFTER_CLOSE") {
3849
+ } catch (err2) {
3850
+ if (err2.code === "ERR_USE_AFTER_CLOSE") {
3220
3851
  process.exit(0);
3221
3852
  }
3222
- console.error("Setup failed:", err);
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 (err) {
3253
- if (err.code === "ERR_USE_AFTER_CLOSE") {
3883
+ } catch (err2) {
3884
+ if (err2.code === "ERR_USE_AFTER_CLOSE") {
3254
3885
  process.exit(0);
3255
3886
  }
3256
- console.error("Login failed:", err);
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 (err) {
3270
- if (err.code === "ERR_USE_AFTER_CLOSE") {
3900
+ } catch (err2) {
3901
+ if (err2.code === "ERR_USE_AFTER_CLOSE") {
3271
3902
  process.exit(0);
3272
3903
  }
3273
- console.error("Connect failed:", err);
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 (err) {
3281
- console.error("Failed:", err);
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 (err) {
3289
- console.error("Disconnect failed:", err);
3919
+ } catch (err2) {
3920
+ console.error("Disconnect failed:", err2);
3290
3921
  process.exit(1);
3291
3922
  }
3292
3923
  });