@solongate/proxy 0.82.21 → 0.82.23

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/index.js CHANGED
@@ -3398,12 +3398,12 @@ ${ctx.indent}`;
3398
3398
  for (const {
3399
3399
  format,
3400
3400
  test,
3401
- resolve: resolve9
3401
+ resolve: resolve7
3402
3402
  } of tags) {
3403
3403
  if (test) {
3404
3404
  const match = str.match(test);
3405
3405
  if (match) {
3406
- let res = resolve9.apply(null, match);
3406
+ let res = resolve7.apply(null, match);
3407
3407
  if (!(res instanceof Scalar)) res = new Scalar(res);
3408
3408
  if (format) res.format = format;
3409
3409
  return res;
@@ -6507,18 +6507,6 @@ var init_src = __esm({
6507
6507
  });
6508
6508
 
6509
6509
  // src/cli-utils.ts
6510
- function log3(msg) {
6511
- process.stderr.write(msg + "\n");
6512
- }
6513
- function printBanner(subtitle) {
6514
- log3("");
6515
- for (let i = 0; i < BANNER_FULL.length; i++) {
6516
- log3(`${c.bold}${BANNER_COLORS[i]}${BANNER_FULL[i]}${c.reset}`);
6517
- }
6518
- log3("");
6519
- log3(` ${c.dim}${c.italic}${subtitle}${c.reset}`);
6520
- log3("");
6521
- }
6522
6510
  var c, BANNER_FULL, BANNER_COLORS;
6523
6511
  var init_cli_utils = __esm({
6524
6512
  "src/cli-utils.ts"() {
@@ -6622,9 +6610,9 @@ async function fetchLatest() {
6622
6610
  function spawnGlobalInstall(version) {
6623
6611
  try {
6624
6612
  mkdirSync3(join4(homedir2(), ".solongate"), { recursive: true });
6625
- const log5 = openSync(LOG_FILE, "a");
6613
+ const log4 = openSync(LOG_FILE, "a");
6626
6614
  const p = spawn("npm", ["install", "-g", `${PKG}@${version}`], {
6627
- stdio: ["ignore", log5, log5],
6615
+ stdio: ["ignore", log4, log4],
6628
6616
  detached: true,
6629
6617
  windowsHide: true,
6630
6618
  shell: process.platform === "win32"
@@ -6638,7 +6626,7 @@ function spawnGlobalInstall(version) {
6638
6626
  }
6639
6627
  }
6640
6628
  function runGlobalInstall(version) {
6641
- return new Promise((resolve9) => {
6629
+ return new Promise((resolve7) => {
6642
6630
  try {
6643
6631
  mkdirSync3(join4(homedir2(), ".solongate"), { recursive: true });
6644
6632
  execFile(
@@ -6653,11 +6641,11 @@ ${stderr}
6653
6641
  `, { flag: "a" });
6654
6642
  } catch {
6655
6643
  }
6656
- resolve9(!err2);
6644
+ resolve7(!err2);
6657
6645
  }
6658
6646
  );
6659
6647
  } catch {
6660
- resolve9(false);
6648
+ resolve7(false);
6661
6649
  }
6662
6650
  });
6663
6651
  }
@@ -6772,11 +6760,11 @@ function startLogsServerDaemon() {
6772
6760
  }
6773
6761
  try {
6774
6762
  mkdirSync4(DIR, { recursive: true });
6775
- const log5 = openSync2(LOG_FILE2, "a");
6763
+ const log4 = openSync2(LOG_FILE2, "a");
6776
6764
  const cli = join5(dirname2(fileURLToPath2(import.meta.url)), "index.js");
6777
6765
  const p = spawn2(process.execPath, [cli, "logs-server"], {
6778
6766
  detached: true,
6779
- stdio: ["ignore", log5, log5],
6767
+ stdio: ["ignore", log4, log4],
6780
6768
  windowsHide: true
6781
6769
  });
6782
6770
  p.on("error", () => {
@@ -7854,7 +7842,7 @@ function LivePanel({ active: active2 }) {
7854
7842
  const [localBuf, setLocalBuf] = useState2([]);
7855
7843
  const [localOn, setLocalOn] = useState2(null);
7856
7844
  const [ring, setRing] = useState2(null);
7857
- const [log5, setLog] = useState2([]);
7845
+ const [log4, setLog] = useState2([]);
7858
7846
  const [filter, setFilter] = useState2("all");
7859
7847
  const [signal, setSignal] = useState2("none");
7860
7848
  const [search, setSearch] = useState2("");
@@ -8698,7 +8686,7 @@ function LivePanel({ active: active2 }) {
8698
8686
  ] }),
8699
8687
  /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, overflow: "hidden", children: [
8700
8688
  /* @__PURE__ */ jsx2(PaneTitle, { label: "EVENT LOG", extra: "system heartbeat", width: colW }),
8701
- log5.slice(-(colH - 1)).map((l, i) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
8689
+ log4.slice(-(colH - 1)).map((l, i) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
8702
8690
  /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
8703
8691
  hhmmss(l.ts),
8704
8692
  " "
@@ -11511,32 +11499,6 @@ async function run(argv) {
11511
11499
  err(green(` \u2713 Revoked ${ruleId}`) + dim(` \u2192 v${res.policy_version}`));
11512
11500
  return 0;
11513
11501
  }
11514
- case "versions": {
11515
- const id = positionals[1];
11516
- if (!id) return err(" Usage: policy versions <id>"), 1;
11517
- const { versions: versions2 } = await api.policies.versions(id, { limit: flagNum(flags, "limit") });
11518
- if (json) return printJson(versions2), 0;
11519
- table(
11520
- ["VER", "RULES", "REASON", "BY", "WHEN"],
11521
- versions2.map((v) => [
11522
- `v${v.version}`,
11523
- String(v.rules_count),
11524
- truncate3(v.reason || "\u2014", 40),
11525
- dim(truncate3(v.created_by || "\u2014", 18)),
11526
- dim(v.created_at)
11527
- ])
11528
- );
11529
- return 0;
11530
- }
11531
- case "rollback": {
11532
- const id = positionals[1];
11533
- const version = Number(positionals[2]);
11534
- if (!id || !Number.isFinite(version)) return err(" Usage: policy rollback <id> <version>"), 1;
11535
- const res = await api.policies.rollback(id, version);
11536
- if (json) return printJson(res), 0;
11537
- err(green(` \u2713 Rolled back ${res.policy_id} from v${res.rolled_back_from} \u2192 v${res.version}`));
11538
- return 0;
11539
- }
11540
11502
  case "active": {
11541
11503
  const a = await api.policies.active();
11542
11504
  if (json) return printJson(a), 0;
@@ -11628,8 +11590,6 @@ var init_policy = __esm({
11628
11590
  policy allow <id> --tool <p> [--command|--path|--url <val>]
11629
11591
  Append an ALLOW rule
11630
11592
  policy revoke <id> <ruleId> Remove a rule
11631
- policy versions <id> List version history
11632
- policy rollback <id> <version> Roll back to a version
11633
11593
  policy active Show the resolved active policy
11634
11594
  policy activate <id> | --clear Pin / unpin the active policy
11635
11595
  policy dry-run <id|file.json> [--limit N] [--mode denylist|whitelist]
@@ -12605,644 +12565,16 @@ var init_logs_server = __esm({
12605
12565
  }
12606
12566
  });
12607
12567
 
12608
- // src/inject.ts
12609
- var inject_exports = {};
12610
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, existsSync as existsSync7, copyFileSync } from "fs";
12611
- import { resolve as resolve6 } from "path";
12612
- import { execSync } from "child_process";
12613
- function parseInjectArgs(argv) {
12614
- const args = argv.slice(2);
12615
- const opts = {
12616
- dryRun: false,
12617
- restore: false,
12618
- skipInstall: false
12619
- };
12620
- for (let i = 0; i < args.length; i++) {
12621
- switch (args[i]) {
12622
- case "--file":
12623
- opts.file = args[++i];
12624
- break;
12625
- case "--dry-run":
12626
- opts.dryRun = true;
12627
- break;
12628
- case "--restore":
12629
- opts.restore = true;
12630
- break;
12631
- case "--skip-install":
12632
- opts.skipInstall = true;
12633
- break;
12634
- case "--help":
12635
- case "-h":
12636
- printHelp();
12637
- process.exit(0);
12638
- }
12639
- }
12640
- return opts;
12641
- }
12642
- function printHelp() {
12643
- log3(`
12644
- SolonGate Inject \u2014 Add security to your MCP server in seconds
12645
-
12646
- USAGE
12647
- npx @solongate/proxy inject [options]
12648
-
12649
- OPTIONS
12650
- --file <path> Entry file to modify (default: auto-detect)
12651
- --dry-run Preview changes without writing
12652
- --restore Restore original file from backup
12653
- --skip-install Don't install SDK package
12654
- -h, --help Show this help message
12655
-
12656
- EXAMPLES
12657
- npx @solongate/proxy inject # Auto-detect and inject
12658
- npx @solongate/proxy inject --file src/main.ts # Specify entry file
12659
- npx @solongate/proxy inject --dry-run # Preview changes
12660
- npx @solongate/proxy inject --restore # Undo injection
12661
-
12662
- WHAT IT DOES
12663
- Replaces McpServer with SecureMcpServer (2 lines changed)
12664
- All tool() calls are automatically protected by SolonGate.
12665
- `);
12666
- }
12667
- function detectProject() {
12668
- if (!existsSync7(resolve6("package.json"))) return false;
12669
- try {
12670
- const pkg = JSON.parse(readFileSync12(resolve6("package.json"), "utf-8"));
12671
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
12672
- return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
12673
- } catch {
12674
- return false;
12675
- }
12676
- }
12677
- function findTsEntryFile() {
12678
- try {
12679
- const pkg = JSON.parse(readFileSync12(resolve6("package.json"), "utf-8"));
12680
- if (pkg.bin) {
12681
- const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
12682
- if (typeof binPath === "string") {
12683
- const srcPath = binPath.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
12684
- if (existsSync7(resolve6(srcPath))) return resolve6(srcPath);
12685
- if (existsSync7(resolve6(binPath))) return resolve6(binPath);
12686
- }
12687
- }
12688
- if (pkg.main) {
12689
- const srcPath = pkg.main.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
12690
- if (existsSync7(resolve6(srcPath))) return resolve6(srcPath);
12691
- }
12692
- } catch {
12693
- }
12694
- const candidates = [
12695
- "src/index.ts",
12696
- "src/server.ts",
12697
- "src/main.ts",
12698
- "index.ts",
12699
- "server.ts",
12700
- "main.ts"
12701
- ];
12702
- for (const c2 of candidates) {
12703
- const full = resolve6(c2);
12704
- if (existsSync7(full)) {
12705
- try {
12706
- const content = readFileSync12(full, "utf-8");
12707
- if (content.includes("McpServer") || content.includes("McpServer")) {
12708
- return full;
12709
- }
12710
- } catch {
12711
- }
12712
- }
12713
- }
12714
- for (const c2 of candidates) {
12715
- if (existsSync7(resolve6(c2))) return resolve6(c2);
12716
- }
12717
- return null;
12718
- }
12719
- function detectPackageManager() {
12720
- if (existsSync7(resolve6("pnpm-lock.yaml"))) return "pnpm";
12721
- if (existsSync7(resolve6("yarn.lock"))) return "yarn";
12722
- return "npm";
12723
- }
12724
- function installSdk() {
12725
- try {
12726
- const pkg = JSON.parse(readFileSync12(resolve6("package.json"), "utf-8"));
12727
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
12728
- if (allDeps["@solongate/proxy"]) {
12729
- log3(" @solongate/proxy already installed");
12730
- return true;
12731
- }
12732
- } catch {
12733
- }
12734
- const pm = detectPackageManager();
12735
- const cmd = pm === "yarn" ? "yarn add @solongate/proxy" : `${pm} install @solongate/proxy`;
12736
- log3(` Installing @solongate/proxy via ${pm}...`);
12737
- try {
12738
- execSync(cmd, { stdio: "pipe", cwd: process.cwd() });
12739
- return true;
12740
- } catch (err2) {
12741
- log3(` Failed to install: ${err2 instanceof Error ? err2.message : String(err2)}`);
12742
- log3(" You can install manually: npm install @solongate/proxy");
12743
- return false;
12744
- }
12745
- }
12746
- function injectTypeScript(filePath) {
12747
- const original = readFileSync12(filePath, "utf-8");
12748
- const changes = [];
12749
- let modified = original;
12750
- if (modified.includes("SecureMcpServer")) {
12751
- return { file: filePath, changes: ["Already injected \u2014 skipping"], original, modified };
12752
- }
12753
- const mcpImportPatterns = [
12754
- // Solo import: import { McpServer } from '...'
12755
- /import\s*\{\s*McpServer\s*\}\s*from\s*['"][^'"]+['"]/,
12756
- // Import with others: import { McpServer, ... } from '...'
12757
- /import\s*\{[^}]*McpServer[^}]*\}\s*from\s*['"][^'"]+['"]/
12758
- ];
12759
- let importReplaced = false;
12760
- for (const pattern of mcpImportPatterns) {
12761
- const match = modified.match(pattern);
12762
- if (match) {
12763
- const importLine = match[0];
12764
- const namedImports = importLine.match(/\{([^}]+)\}/)?.[1] ?? "";
12765
- const importNames = namedImports.split(",").map((s) => s.trim()).filter(Boolean);
12766
- if (importNames.length === 1 && importNames[0] === "McpServer") {
12767
- modified = modified.replace(
12768
- importLine,
12769
- `import { SecureMcpServer } from '@solongate/proxy'`
12770
- );
12771
- changes.push("Replaced McpServer import with SecureMcpServer from @solongate/proxy");
12772
- } else {
12773
- const otherImports = importNames.filter((n) => n !== "McpServer");
12774
- const fromModule = importLine.match(/from\s*['"]([^'"]+)['"]/)?.[1] ?? "";
12775
- modified = modified.replace(
12776
- importLine,
12777
- `import { ${otherImports.join(", ")} } from '${fromModule}';
12778
- import { SecureMcpServer } from '@solongate/proxy'`
12779
- );
12780
- changes.push("Removed McpServer from existing import, added SecureMcpServer import from @solongate/proxy");
12781
- }
12782
- importReplaced = true;
12783
- break;
12784
- }
12785
- }
12786
- if (!importReplaced) {
12787
- const insertPos = findImportInsertPosition(modified);
12788
- modified = modified.slice(0, insertPos) + `import { SecureMcpServer } from '@solongate/proxy';
12789
- ` + modified.slice(insertPos);
12790
- changes.push("Added SecureMcpServer import from @solongate/proxy");
12791
- }
12792
- const constructorPattern = /new\s+McpServer\s*\(/g;
12793
- const constructorCount = (modified.match(constructorPattern) || []).length;
12794
- if (constructorCount > 0) {
12795
- modified = modified.replace(constructorPattern, "new SecureMcpServer(");
12796
- changes.push(`Replaced ${constructorCount} McpServer constructor(s) with SecureMcpServer`);
12797
- }
12798
- return { file: filePath, changes, original, modified };
12799
- }
12800
- function findImportInsertPosition(content) {
12801
- let pos = 0;
12802
- if (content.startsWith("#!")) {
12803
- pos = content.indexOf("\n") + 1;
12804
- }
12805
- const lines = content.slice(pos).split("\n");
12806
- let offset = pos;
12807
- for (const line of lines) {
12808
- const trimmed = line.trim();
12809
- if (trimmed === "" || trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*") || trimmed.startsWith("*/")) {
12810
- offset += line.length + 1;
12811
- } else {
12812
- break;
12813
- }
12814
- }
12815
- const importRegex = /^import\s+.+$/gm;
12816
- let lastImportEnd = offset;
12817
- let importMatch;
12818
- while ((importMatch = importRegex.exec(content)) !== null) {
12819
- lastImportEnd = importMatch.index + importMatch[0].length + 1;
12820
- }
12821
- return lastImportEnd > offset ? lastImportEnd : offset;
12822
- }
12823
- function showDiff(result) {
12824
- if (result.original === result.modified) {
12825
- log3(" No changes needed.");
12826
- return;
12827
- }
12828
- const origLines = result.original.split("\n");
12829
- const modLines = result.modified.split("\n");
12830
- log3("");
12831
- log3(` File: ${result.file}`);
12832
- log3(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
12833
- const maxLines = Math.max(origLines.length, modLines.length);
12834
- let diffCount = 0;
12835
- for (let i = 0; i < maxLines; i++) {
12836
- const orig = origLines[i];
12837
- const mod = modLines[i];
12838
- if (orig !== mod) {
12839
- if (diffCount < 30) {
12840
- if (orig !== void 0) log3(` - ${orig}`);
12841
- if (mod !== void 0) log3(` + ${mod}`);
12842
- }
12843
- diffCount++;
12844
- }
12845
- }
12846
- if (diffCount > 30) {
12847
- log3(` ... and ${diffCount - 30} more line changes`);
12848
- }
12849
- log3("");
12850
- }
12851
- async function main() {
12852
- const opts = parseInjectArgs(process.argv);
12853
- printBanner("Inject SDK");
12854
- if (!detectProject()) {
12855
- log3(" Could not detect a TypeScript MCP server project.");
12856
- log3(" Make sure you are in a project directory with:");
12857
- log3(" package.json + @modelcontextprotocol/sdk in dependencies");
12858
- log3("");
12859
- log3(" To create a new MCP server: npx @solongate/proxy create <name>");
12860
- process.exit(1);
12861
- }
12862
- log3(" Language: TypeScript");
12863
- const entryFile = opts.file ? resolve6(opts.file) : findTsEntryFile();
12864
- if (!entryFile || !existsSync7(entryFile)) {
12865
- log3(` Could not find entry file.${opts.file ? ` File not found: ${opts.file}` : ""}`);
12866
- log3("");
12867
- log3(" Specify it manually: --file <path>");
12868
- log3("");
12869
- log3(" Common entry points:");
12870
- log3(" src/index.ts, src/server.ts, index.ts");
12871
- process.exit(1);
12872
- }
12873
- log3(` Entry: ${entryFile}`);
12874
- log3("");
12875
- const backupPath = entryFile + ".solongate-backup";
12876
- if (opts.restore) {
12877
- if (!existsSync7(backupPath)) {
12878
- log3(" No backup found. Nothing to restore.");
12879
- process.exit(1);
12880
- }
12881
- copyFileSync(backupPath, entryFile);
12882
- log3(` Restored original file from backup.`);
12883
- log3(` Backup: ${backupPath}`);
12884
- process.exit(0);
12885
- }
12886
- if (!opts.skipInstall && !opts.dryRun) {
12887
- installSdk();
12888
- log3("");
12889
- }
12890
- const result = injectTypeScript(entryFile);
12891
- log3(` Changes (${result.changes.length}):`);
12892
- for (const change of result.changes) {
12893
- log3(` - ${change}`);
12894
- }
12895
- if (result.changes.length === 1 && result.changes[0].includes("Already injected")) {
12896
- log3("");
12897
- log3(" Your MCP server is already protected by SolonGate!");
12898
- process.exit(0);
12899
- }
12900
- if (result.original === result.modified) {
12901
- log3("");
12902
- log3(" No changes were made. The file may not contain recognizable MCP patterns.");
12903
- log3(" See docs: https://solongate.com/docs/integration");
12904
- process.exit(0);
12905
- }
12906
- if (opts.dryRun) {
12907
- log3("");
12908
- log3(" --- DRY RUN (no changes written) ---");
12909
- showDiff(result);
12910
- log3(" To apply: npx @solongate/proxy inject");
12911
- process.exit(0);
12912
- }
12913
- if (!existsSync7(backupPath)) {
12914
- copyFileSync(entryFile, backupPath);
12915
- log3("");
12916
- log3(` Backup: ${backupPath}`);
12917
- }
12918
- writeFileSync10(entryFile, result.modified);
12919
- log3("");
12920
- log3(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
12921
- log3(" \u2502 SolonGate SDK injected successfully! \u2502");
12922
- log3(" \u2502 \u2502");
12923
- log3(" \u2502 McpServer \u2192 SecureMcpServer \u2502");
12924
- log3(" \u2502 All tool() calls are now auto-protected. \u2502");
12925
- log3(" \u2502 \u2502");
12926
- log3(" \u2502 Set your API key: \u2502");
12927
- log3(" \u2502 export SOLONGATE_API_KEY=sg_live_xxx \u2502");
12928
- log3(" \u2502 \u2502");
12929
- log3(" \u2502 To undo: \u2502");
12930
- log3(" \u2502 npx @solongate/proxy inject --restore \u2502");
12931
- log3(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
12932
- log3("");
12933
- }
12934
- var init_inject = __esm({
12935
- "src/inject.ts"() {
12936
- "use strict";
12937
- init_cli_utils();
12938
- main().catch((err2) => {
12939
- log3(`Fatal: ${err2 instanceof Error ? err2.message : String(err2)}`);
12940
- process.exit(1);
12941
- });
12942
- }
12943
- });
12944
-
12945
- // src/create.ts
12946
- var create_exports = {};
12947
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, existsSync as existsSync8 } from "fs";
12948
- import { resolve as resolve7, join as join16 } from "path";
12949
- import { execSync as execSync2 } from "child_process";
12950
- function withSpinner(message, fn) {
12951
- const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
12952
- let i = 0;
12953
- const id = setInterval(() => {
12954
- const color = i % 2 === 0 ? c.blue3 : c.blue5;
12955
- process.stderr.write(`\r ${color}${frames[i++ % frames.length]}${c.reset} ${c.dim}${message}${c.reset}`);
12956
- }, 80);
12957
- try {
12958
- const result = fn();
12959
- clearInterval(id);
12960
- process.stderr.write(`\r ${c.green}\u2713${c.reset} ${message}${" ".repeat(20)}
12961
- `);
12962
- return result;
12963
- } catch (err2) {
12964
- clearInterval(id);
12965
- process.stderr.write(`\r ${c.red}\u2717${c.reset} ${message} \u2014 failed${" ".repeat(10)}
12966
- `);
12967
- throw err2;
12968
- }
12969
- }
12970
- function parseCreateArgs(argv) {
12971
- const args = argv.slice(2);
12972
- const opts = {
12973
- name: "",
12974
- policy: "",
12975
- noInstall: false
12976
- };
12977
- for (let i = 0; i < args.length; i++) {
12978
- switch (args[i]) {
12979
- case "--policy":
12980
- opts.policy = args[++i];
12981
- break;
12982
- case "--no-install":
12983
- opts.noInstall = true;
12984
- break;
12985
- case "--help":
12986
- case "-h":
12987
- printHelp2();
12988
- process.exit(0);
12989
- break;
12990
- default:
12991
- if (!args[i].startsWith("-") && !opts.name) {
12992
- opts.name = args[i];
12993
- }
12994
- }
12995
- }
12996
- if (!opts.name) {
12997
- log3("");
12998
- log3(" Error: Project name required.");
12999
- log3("");
13000
- log3(" Usage: npx @solongate/proxy create <name>");
13001
- log3("");
13002
- log3(" Examples:");
13003
- log3(" npx @solongate/proxy create my-mcp-server");
13004
- log3(" npx @solongate/proxy create weather-api");
13005
- process.exit(1);
13006
- }
13007
- return opts;
13008
- }
13009
- function printHelp2() {
13010
- log3(`
13011
- SolonGate Create \u2014 Scaffold a secure MCP server in seconds
13012
-
13013
- USAGE
13014
- npx @solongate/proxy create <name> [options]
13015
-
13016
- OPTIONS
13017
- --policy <file> Policy JSON file (default: cloud-managed)
13018
- --no-install Skip dependency installation
13019
- -h, --help Show this help message
13020
-
13021
- EXAMPLES
13022
- npx @solongate/proxy create my-server
13023
- npx @solongate/proxy create db-tools --policy ./policy.json
13024
- `);
13025
- }
13026
- function createProject(dir, name, _policy) {
13027
- writeFileSync11(
13028
- join16(dir, "package.json"),
13029
- JSON.stringify(
13030
- {
13031
- name,
13032
- version: "0.1.0",
13033
- type: "module",
13034
- private: true,
13035
- bin: { [name]: "./dist/index.js" },
13036
- scripts: {
13037
- build: "tsup src/index.ts --format esm",
13038
- dev: "tsx --env-file=.env src/index.ts",
13039
- start: "node --env-file=.env dist/index.js"
13040
- },
13041
- dependencies: {
13042
- "@modelcontextprotocol/sdk": "^1.26.0",
13043
- "@solongate/proxy": "latest",
13044
- zod: "^3.25.0"
13045
- },
13046
- devDependencies: {
13047
- "@types/node": "^22.0.0",
13048
- tsup: "^8.3.0",
13049
- tsx: "^4.19.0",
13050
- typescript: "^5.7.0"
13051
- }
13052
- },
13053
- null,
13054
- 2
13055
- ) + "\n"
13056
- );
13057
- writeFileSync11(
13058
- join16(dir, "tsconfig.json"),
13059
- JSON.stringify(
13060
- {
13061
- compilerOptions: {
13062
- target: "ES2022",
13063
- module: "ESNext",
13064
- moduleResolution: "bundler",
13065
- esModuleInterop: true,
13066
- strict: true,
13067
- outDir: "dist",
13068
- rootDir: "src",
13069
- declaration: true,
13070
- skipLibCheck: true
13071
- },
13072
- include: ["src"]
13073
- },
13074
- null,
13075
- 2
13076
- ) + "\n"
13077
- );
13078
- mkdirSync10(join16(dir, "src"), { recursive: true });
13079
- writeFileSync11(
13080
- join16(dir, "src", "index.ts"),
13081
- `#!/usr/bin/env node
13082
-
13083
- console.log = (...args: unknown[]) => {
13084
- process.stderr.write(args.map(String).join(' ') + '\\n');
13085
- };
13086
-
13087
- import { SecureMcpServer } from '@solongate/proxy';
13088
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13089
- import { z } from 'zod';
13090
-
13091
- // Policy is managed from the SolonGate Dashboard (https://solongate.com)
13092
- // No local policySet needed \u2014 it's fetched from the cloud via your API key.
13093
- const server = new SecureMcpServer(
13094
- { name: '${name}', version: '0.1.0' },
13095
- );
13096
-
13097
- server.tool(
13098
- 'hello',
13099
- 'Say hello to someone',
13100
- { name: z.string().describe('Name of the person to greet') },
13101
- async ({ name }: { name: string }) => ({
13102
- content: [{ type: 'text', text: \`Hello, \${name}! Welcome to ${name}.\` }],
13103
- }),
13104
- );
13105
-
13106
- const transport = new StdioServerTransport();
13107
- await server.connect(transport);
13108
- console.log('');
13109
- console.log('${name} is running (stdio mode)');
13110
- console.log('');
13111
- console.log('MCP servers communicate over stdin/stdout \u2014 not HTTP.');
13112
- console.log('You need an MCP client to connect:');
13113
- console.log('');
13114
- console.log(' Claude Code Open this folder, .mcp.json is auto-detected');
13115
- console.log(' Antigravity .agents/mcp_config.json (or ~/.gemini/config/mcp_config.json)');
13116
- console.log(' OpenClaw Uses openclaw.plugin.json config');
13117
- console.log('');
13118
- console.log('Press Ctrl+C to stop.');
13119
- `
13120
- );
13121
- writeFileSync11(
13122
- join16(dir, ".mcp.json"),
13123
- JSON.stringify(
13124
- {
13125
- mcpServers: {
13126
- [name]: {
13127
- command: "node",
13128
- args: ["dist/index.js"],
13129
- env: {
13130
- SOLONGATE_API_KEY: "sg_live_YOUR_KEY_HERE"
13131
- }
13132
- }
13133
- }
13134
- },
13135
- null,
13136
- 2
13137
- ) + "\n"
13138
- );
13139
- writeFileSync11(
13140
- join16(dir, ".env"),
13141
- `SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
13142
- `
13143
- );
13144
- writeFileSync11(
13145
- join16(dir, ".gitignore"),
13146
- `node_modules/
13147
- dist/
13148
- *.solongate-backup
13149
- .env
13150
- .env.local
13151
- .mcp.json
13152
- `
13153
- );
13154
- }
13155
- async function main2() {
13156
- const opts = parseCreateArgs(process.argv);
13157
- const dir = resolve7(opts.name);
13158
- printBanner("Create MCP Server");
13159
- if (existsSync8(dir)) {
13160
- log3(` ${c.red}Error:${c.reset} Directory "${opts.name}" already exists.`);
13161
- process.exit(1);
13162
- }
13163
- withSpinner(`Setting up ${opts.name}...`, () => {
13164
- mkdirSync10(dir, { recursive: true });
13165
- createProject(dir, opts.name, opts.policy);
13166
- });
13167
- if (!opts.noInstall) {
13168
- withSpinner("Installing dependencies...", () => {
13169
- execSync2("npm install", { cwd: dir, stdio: "pipe" });
13170
- });
13171
- }
13172
- log3("");
13173
- const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
13174
- const W = 52;
13175
- const hr = "\u2500".repeat(W + 2);
13176
- const bLine = (text) => {
13177
- const visible = stripAnsi(text);
13178
- const padding = W - visible.length;
13179
- log3(` ${c.dim}\u2502${c.reset} ${text}${" ".repeat(Math.max(0, padding))} ${c.dim}\u2502${c.reset}`);
13180
- };
13181
- const bEmpty = () => log3(` ${c.dim}\u2502${c.reset} ${" ".repeat(W)} ${c.dim}\u2502${c.reset}`);
13182
- log3(` ${c.dim}\u256D${hr}\u256E${c.reset}`);
13183
- log3(` ${c.dim}\u2502${c.reset} ${c.green}${c.bold}\u2714 MCP Server created successfully!${c.reset}${" ".repeat(W - 35)} ${c.dim}\u2502${c.reset}`);
13184
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13185
- bEmpty();
13186
- bLine(`${c.yellow}Next steps:${c.reset}`);
13187
- bEmpty();
13188
- bLine(` ${c.cyan}$${c.reset} cd ${c.bold}${opts.name}${c.reset}`);
13189
- bLine(` ${c.cyan}$${c.reset} npm run build`);
13190
- bLine(` ${c.cyan}$${c.reset} npm run dev ${c.dim}# dev mode${c.reset}`);
13191
- bLine(` ${c.cyan}$${c.reset} npm start ${c.dim}# production${c.reset}`);
13192
- bEmpty();
13193
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13194
- bEmpty();
13195
- bLine(`${c.yellow}Set your API key:${c.reset}`);
13196
- bEmpty();
13197
- bLine(` ${c.cyan}$${c.reset} export SOLONGATE_API_KEY=${c.blue3}sg_live_xxx${c.reset}`);
13198
- bEmpty();
13199
- bLine(`${c.dim}https://dashboard.solongate.com/api-keys/${c.reset}`);
13200
- bEmpty();
13201
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13202
- bEmpty();
13203
- bLine(`${c.yellow}Use with any MCP server:${c.reset}`);
13204
- bEmpty();
13205
- bLine(` ${c.cyan}$${c.reset} solongate-proxy -- npx @modelcontextprotocol/server-filesystem .`);
13206
- bLine(` ${c.cyan}$${c.reset} solongate-proxy -- npx @playwright/mcp@latest`);
13207
- bLine(` ${c.dim}Wraps any MCP server or AI tool with SolonGate protection${c.reset}`);
13208
- bEmpty();
13209
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13210
- bEmpty();
13211
- bLine(`${c.yellow}Use with Claude Code / MCP client:${c.reset}`);
13212
- bEmpty();
13213
- bLine(` ${c.dim}1.${c.reset} Replace ${c.blue3}sg_live_YOUR_KEY_HERE${c.reset} in .mcp.json`);
13214
- bLine(` ${c.dim}2.${c.reset} Open this folder in your MCP client`);
13215
- bLine(` ${c.dim}3.${c.reset} .mcp.json is auto-detected on startup`);
13216
- bEmpty();
13217
- bLine(`${c.yellow}Direct test (without MCP client):${c.reset}`);
13218
- bEmpty();
13219
- bLine(` ${c.dim}1.${c.reset} Replace ${c.blue3}sg_live_YOUR_KEY_HERE${c.reset} in .env`);
13220
- bLine(` ${c.dim}2.${c.reset} ${c.cyan}$${c.reset} npm run build && npm start`);
13221
- bEmpty();
13222
- log3(` ${c.dim}\u2570${hr}\u256F${c.reset}`);
13223
- log3("");
13224
- }
13225
- var init_create = __esm({
13226
- "src/create.ts"() {
13227
- "use strict";
13228
- init_cli_utils();
13229
- main2().catch((err2) => {
13230
- log3(`Fatal: ${err2 instanceof Error ? err2.message : String(err2)}`);
13231
- process.exit(1);
13232
- });
13233
- }
13234
- });
13235
-
13236
12568
  // src/pull-push.ts
13237
12569
  var pull_push_exports = {};
13238
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync12, existsSync as existsSync9 } from "fs";
13239
- import { resolve as resolve8 } from "path";
12570
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, existsSync as existsSync7 } from "fs";
12571
+ import { resolve as resolve6 } from "path";
13240
12572
  function loadEnv() {
13241
12573
  if (process.env.SOLONGATE_API_KEY) return;
13242
- const envPath = resolve8(".env");
13243
- if (!existsSync9(envPath)) return;
12574
+ const envPath = resolve6(".env");
12575
+ if (!existsSync7(envPath)) return;
13244
12576
  try {
13245
- const content = readFileSync13(envPath, "utf-8");
12577
+ const content = readFileSync12(envPath, "utf-8");
13246
12578
  for (const line of content.split("\n")) {
13247
12579
  const trimmed = line.trim();
13248
12580
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -13284,20 +12616,20 @@ function parseCliArgs() {
13284
12616
  }
13285
12617
  }
13286
12618
  if (!apiKey) {
13287
- log4(red2("ERROR: API key not found."));
13288
- log4("");
13289
- log4("Set it in .env file:");
13290
- log4(" SOLONGATE_API_KEY=sg_live_...");
13291
- log4("");
13292
- log4("Or pass via environment:");
13293
- log4(` SOLONGATE_API_KEY=sg_live_... solongate-proxy ${command}`);
12619
+ log3(red2("ERROR: API key not found."));
12620
+ log3("");
12621
+ log3("Set it in .env file:");
12622
+ log3(" SOLONGATE_API_KEY=sg_live_...");
12623
+ log3("");
12624
+ log3("Or pass via environment:");
12625
+ log3(` SOLONGATE_API_KEY=sg_live_... solongate-proxy ${command}`);
13294
12626
  process.exit(1);
13295
12627
  }
13296
12628
  if (!apiKey.startsWith("sg_live_")) {
13297
- log4(red2("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
12629
+ log3(red2("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
13298
12630
  process.exit(1);
13299
12631
  }
13300
- return { command, apiKey, file: resolve8(file), policyId };
12632
+ return { command, apiKey, file: resolve6(file), policyId };
13301
12633
  }
13302
12634
  async function listPolicies(apiKey) {
13303
12635
  const res = await fetch(`${API_URL}/api/v1/policies`, {
@@ -13310,18 +12642,18 @@ async function listPolicies(apiKey) {
13310
12642
  async function list5(apiKey, policyId) {
13311
12643
  const policies = await listPolicies(apiKey);
13312
12644
  if (policies.length === 0) {
13313
- log4(yellow2("No policies found. Create one in the dashboard first."));
13314
- log4(dim2(" https://dashboard.solongate.com/policies"));
12645
+ log3(yellow2("No policies found. Create one in the dashboard first."));
12646
+ log3(dim2(" https://dashboard.solongate.com/policies"));
13315
12647
  return;
13316
12648
  }
13317
12649
  if (policyId) {
13318
12650
  const match = policies.find((p) => p.id === policyId);
13319
12651
  if (!match) {
13320
- log4(red2(`Policy not found: ${policyId}`));
13321
- log4("");
13322
- log4("Available policies:");
12652
+ log3(red2(`Policy not found: ${policyId}`));
12653
+ log3("");
12654
+ log3("Available policies:");
13323
12655
  for (const p of policies) {
13324
- log4(` ${dim2("\u2022")} ${p.id}`);
12656
+ log3(` ${dim2("\u2022")} ${p.id}`);
13325
12657
  }
13326
12658
  process.exit(1);
13327
12659
  }
@@ -13329,10 +12661,10 @@ async function list5(apiKey, policyId) {
13329
12661
  printPolicyDetail(full);
13330
12662
  return;
13331
12663
  }
13332
- log4("");
13333
- log4(bold2(` Policies (${policies.length})`));
13334
- log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13335
- log4("");
12664
+ log3("");
12665
+ log3(bold2(` Policies (${policies.length})`));
12666
+ log3(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
12667
+ log3("");
13336
12668
  const fullPolicies = await Promise.all(
13337
12669
  policies.map(
13338
12670
  (p) => fetchCloudPolicy(apiKey, API_URL, p.id).then((full) => ({ policy: p, rules: full.rules })).catch(() => ({ policy: p, rules: [] }))
@@ -13341,136 +12673,136 @@ async function list5(apiKey, policyId) {
13341
12673
  for (const { policy, rules } of fullPolicies) {
13342
12674
  printPolicySummary(policy, [...rules]);
13343
12675
  }
13344
- log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13345
- log4("");
13346
- log4(` ${dim2("View details:")} solongate-proxy list --policy-id <ID>`);
13347
- log4(` ${dim2("Pull policy:")} solongate-proxy pull --policy-id <ID>`);
13348
- log4(` ${dim2("Push policy:")} solongate-proxy push --policy-id <ID>`);
13349
- log4("");
12676
+ log3(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
12677
+ log3("");
12678
+ log3(` ${dim2("View details:")} solongate-proxy list --policy-id <ID>`);
12679
+ log3(` ${dim2("Pull policy:")} solongate-proxy pull --policy-id <ID>`);
12680
+ log3(` ${dim2("Push policy:")} solongate-proxy push --policy-id <ID>`);
12681
+ log3("");
13350
12682
  }
13351
12683
  function printPolicySummary(p, rules) {
13352
12684
  const ruleCount = rules.length;
13353
12685
  const allowCount = rules.filter((r) => r.effect === "ALLOW").length;
13354
12686
  const denyCount = rules.filter((r) => r.effect === "DENY").length;
13355
- log4(` ${cyan2(p.id)}`);
13356
- log4(` ${bold2(p.name)} ${dim2(`v${p.version ?? "?"}`)}`);
13357
- log4(` ${dim2("Rules:")} ${ruleCount} ${green2(`${allowCount} ALLOW`)} ${red2(`${denyCount} DENY`)}`);
12687
+ log3(` ${cyan2(p.id)}`);
12688
+ log3(` ${bold2(p.name)} ${dim2(`v${p.version ?? "?"}`)}`);
12689
+ log3(` ${dim2("Rules:")} ${ruleCount} ${green2(`${allowCount} ALLOW`)} ${red2(`${denyCount} DENY`)}`);
13358
12690
  if (p.created_at) {
13359
- log4(` ${dim2("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
12691
+ log3(` ${dim2("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
13360
12692
  }
13361
- log4("");
12693
+ log3("");
13362
12694
  }
13363
12695
  function printPolicyDetail(policy) {
13364
- log4("");
13365
- log4(bold2(` ${policy.name}`));
13366
- log4(` ${dim2("ID:")} ${cyan2(policy.id)} ${dim2("Version:")} ${policy.version} ${dim2("Rules:")} ${policy.rules.length}`);
13367
- log4("");
12696
+ log3("");
12697
+ log3(bold2(` ${policy.name}`));
12698
+ log3(` ${dim2("ID:")} ${cyan2(policy.id)} ${dim2("Version:")} ${policy.version} ${dim2("Rules:")} ${policy.rules.length}`);
12699
+ log3("");
13368
12700
  if (policy.rules.length === 0) {
13369
- log4(yellow2(" No rules defined."));
13370
- log4("");
12701
+ log3(yellow2(" No rules defined."));
12702
+ log3("");
13371
12703
  return;
13372
12704
  }
13373
- log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
12705
+ log3(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13374
12706
  for (const rule of policy.rules) {
13375
12707
  const effectColor = rule.effect === "ALLOW" ? green2 : red2;
13376
- log4("");
13377
- log4(` ${effectColor(rule.effect.padEnd(5))} ${bold2(rule.toolPattern)} ${dim2(`P:${rule.priority}`)}`);
12708
+ log3("");
12709
+ log3(` ${effectColor(rule.effect.padEnd(5))} ${bold2(rule.toolPattern)} ${dim2(`P:${rule.priority}`)}`);
13378
12710
  if (rule.description) {
13379
- log4(` ${dim2(rule.description)}`);
12711
+ log3(` ${dim2(rule.description)}`);
13380
12712
  }
13381
- log4(` ${dim2(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
12713
+ log3(` ${dim2(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
13382
12714
  if (rule.pathConstraints) {
13383
12715
  const pc = rule.pathConstraints;
13384
- if (pc.rootDirectory) log4(` ${magenta("ROOT")} ${pc.rootDirectory}`);
13385
- if (pc.allowed?.length) log4(` ${green2("PATHS")} ${pc.allowed.join(", ")}`);
13386
- if (pc.denied?.length) log4(` ${red2("DENY")} ${pc.denied.join(", ")}`);
12716
+ if (pc.rootDirectory) log3(` ${magenta("ROOT")} ${pc.rootDirectory}`);
12717
+ if (pc.allowed?.length) log3(` ${green2("PATHS")} ${pc.allowed.join(", ")}`);
12718
+ if (pc.denied?.length) log3(` ${red2("DENY")} ${pc.denied.join(", ")}`);
13387
12719
  }
13388
12720
  if (rule.commandConstraints) {
13389
12721
  const cc = rule.commandConstraints;
13390
- if (cc.allowed?.length) log4(` ${green2("CMDS")} ${cc.allowed.join(", ")}`);
13391
- if (cc.denied?.length) log4(` ${red2("DENY")} ${cc.denied.join(", ")}`);
12722
+ if (cc.allowed?.length) log3(` ${green2("CMDS")} ${cc.allowed.join(", ")}`);
12723
+ if (cc.denied?.length) log3(` ${red2("DENY")} ${cc.denied.join(", ")}`);
13392
12724
  }
13393
12725
  if (rule.filenameConstraints) {
13394
12726
  const fc = rule.filenameConstraints;
13395
- if (fc.allowed?.length) log4(` ${green2("FILES")} ${fc.allowed.join(", ")}`);
13396
- if (fc.denied?.length) log4(` ${red2("DENY")} ${fc.denied.join(", ")}`);
12727
+ if (fc.allowed?.length) log3(` ${green2("FILES")} ${fc.allowed.join(", ")}`);
12728
+ if (fc.denied?.length) log3(` ${red2("DENY")} ${fc.denied.join(", ")}`);
13397
12729
  }
13398
12730
  if (rule.urlConstraints) {
13399
12731
  const uc = rule.urlConstraints;
13400
- if (uc.allowed?.length) log4(` ${green2("URLS")} ${uc.allowed.join(", ")}`);
13401
- if (uc.denied?.length) log4(` ${red2("DENY")} ${uc.denied.join(", ")}`);
12732
+ if (uc.allowed?.length) log3(` ${green2("URLS")} ${uc.allowed.join(", ")}`);
12733
+ if (uc.denied?.length) log3(` ${red2("DENY")} ${uc.denied.join(", ")}`);
13402
12734
  }
13403
12735
  }
13404
- log4("");
13405
- log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13406
- log4("");
12736
+ log3("");
12737
+ log3(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
12738
+ log3("");
13407
12739
  }
13408
12740
  async function pull(apiKey, file, policyId) {
13409
12741
  if (!policyId) {
13410
12742
  const policies = await listPolicies(apiKey);
13411
12743
  if (policies.length === 0) {
13412
- log4(red2("No policies found. Create one in the dashboard first."));
12744
+ log3(red2("No policies found. Create one in the dashboard first."));
13413
12745
  process.exit(1);
13414
12746
  }
13415
12747
  if (policies.length === 1) {
13416
12748
  policyId = policies[0].id;
13417
- log4(dim2(`Auto-selecting only policy: ${policyId}`));
12749
+ log3(dim2(`Auto-selecting only policy: ${policyId}`));
13418
12750
  } else {
13419
- log4(yellow2(`Found ${policies.length} policies:`));
13420
- log4("");
12751
+ log3(yellow2(`Found ${policies.length} policies:`));
12752
+ log3("");
13421
12753
  for (const p of policies) {
13422
- log4(` ${cyan2(p.id)} ${p.name} ${dim2(`v${p.version ?? "?"}`)}`);
12754
+ log3(` ${cyan2(p.id)} ${p.name} ${dim2(`v${p.version ?? "?"}`)}`);
13423
12755
  }
13424
- log4("");
13425
- log4("Use --policy-id <ID> to specify which one to pull.");
12756
+ log3("");
12757
+ log3("Use --policy-id <ID> to specify which one to pull.");
13426
12758
  process.exit(1);
13427
12759
  }
13428
12760
  }
13429
- log4(`Pulling ${cyan2(policyId)} from dashboard...`);
12761
+ log3(`Pulling ${cyan2(policyId)} from dashboard...`);
13430
12762
  const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
13431
12763
  const { id: _id, ...policyWithoutId } = policy;
13432
12764
  const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
13433
- writeFileSync12(file, json, "utf-8");
13434
- log4("");
13435
- log4(green2(" Saved to: ") + file);
13436
- log4(` ${dim2("Name:")} ${policy.name}`);
13437
- log4(` ${dim2("Version:")} ${policy.version}`);
13438
- log4(` ${dim2("Rules:")} ${policy.rules.length}`);
13439
- log4("");
13440
- log4(dim2("The policy file does not contain an ID."));
13441
- log4(dim2("Use --policy-id to specify the target when pushing/pulling."));
13442
- log4("");
12765
+ writeFileSync10(file, json, "utf-8");
12766
+ log3("");
12767
+ log3(green2(" Saved to: ") + file);
12768
+ log3(` ${dim2("Name:")} ${policy.name}`);
12769
+ log3(` ${dim2("Version:")} ${policy.version}`);
12770
+ log3(` ${dim2("Rules:")} ${policy.rules.length}`);
12771
+ log3("");
12772
+ log3(dim2("The policy file does not contain an ID."));
12773
+ log3(dim2("Use --policy-id to specify the target when pushing/pulling."));
12774
+ log3("");
13443
12775
  }
13444
12776
  async function push(apiKey, file, policyId) {
13445
- if (!existsSync9(file)) {
13446
- log4(red2(`ERROR: File not found: ${file}`));
12777
+ if (!existsSync7(file)) {
12778
+ log3(red2(`ERROR: File not found: ${file}`));
13447
12779
  process.exit(1);
13448
12780
  }
13449
12781
  if (!policyId) {
13450
- log4(red2("ERROR: --policy-id is required for push."));
13451
- log4("");
13452
- log4("This determines which cloud policy to update.");
13453
- log4("");
13454
- log4("Usage:");
13455
- log4(" solongate-proxy push --policy-id my-policy");
13456
- log4(" solongate-proxy push --policy-id my-policy --file custom.json");
13457
- log4("");
13458
- log4("List your policies:");
13459
- log4(" solongate-proxy list");
12782
+ log3(red2("ERROR: --policy-id is required for push."));
12783
+ log3("");
12784
+ log3("This determines which cloud policy to update.");
12785
+ log3("");
12786
+ log3("Usage:");
12787
+ log3(" solongate-proxy push --policy-id my-policy");
12788
+ log3(" solongate-proxy push --policy-id my-policy --file custom.json");
12789
+ log3("");
12790
+ log3("List your policies:");
12791
+ log3(" solongate-proxy list");
13460
12792
  process.exit(1);
13461
12793
  }
13462
- const content = readFileSync13(file, "utf-8");
12794
+ const content = readFileSync12(file, "utf-8");
13463
12795
  let policy;
13464
12796
  try {
13465
12797
  policy = JSON.parse(content);
13466
12798
  } catch {
13467
- log4(red2(`ERROR: Invalid JSON in ${file}`));
12799
+ log3(red2(`ERROR: Invalid JSON in ${file}`));
13468
12800
  process.exit(1);
13469
12801
  }
13470
- log4(`Pushing to ${cyan2(policyId)}...`);
13471
- log4(` ${dim2("File:")} ${file}`);
13472
- log4(` ${dim2("Name:")} ${policy.name || "Unnamed"}`);
13473
- log4(` ${dim2("Rules:")} ${(policy.rules || []).length}`);
12802
+ log3(`Pushing to ${cyan2(policyId)}...`);
12803
+ log3(` ${dim2("File:")} ${file}`);
12804
+ log3(` ${dim2("Name:")} ${policy.name || "Unnamed"}`);
12805
+ log3(` ${dim2("Rules:")} ${(policy.rules || []).length}`);
13474
12806
  const checkRes = await fetch(`${API_URL}/api/v1/policies/${policyId}`, {
13475
12807
  headers: { "Authorization": `Bearer ${apiKey}` }
13476
12808
  });
@@ -13492,17 +12824,17 @@ async function push(apiKey, file, policyId) {
13492
12824
  });
13493
12825
  if (!res.ok) {
13494
12826
  const body = await res.text().catch(() => "");
13495
- log4(red2(`ERROR: Push failed (${res.status}): ${body}`));
12827
+ log3(red2(`ERROR: Push failed (${res.status}): ${body}`));
13496
12828
  process.exit(1);
13497
12829
  }
13498
12830
  const data = await res.json();
13499
- log4("");
13500
- log4(green2(` Pushed to cloud: v${data._version ?? "created"}`));
13501
- log4(` ${dim2("Policy ID:")} ${policyId}`);
13502
- log4(` ${dim2("Method:")} ${method === "PUT" ? "Updated existing" : "Created new"}`);
13503
- log4("");
12831
+ log3("");
12832
+ log3(green2(` Pushed to cloud: v${data._version ?? "created"}`));
12833
+ log3(` ${dim2("Policy ID:")} ${policyId}`);
12834
+ log3(` ${dim2("Method:")} ${method === "PUT" ? "Updated existing" : "Created new"}`);
12835
+ log3("");
13504
12836
  }
13505
- async function main3() {
12837
+ async function main() {
13506
12838
  const { command, apiKey, file, policyId } = parseCliArgs();
13507
12839
  try {
13508
12840
  if (command === "pull") {
@@ -13512,32 +12844,32 @@ async function main3() {
13512
12844
  } else if (command === "list" || command === "ls") {
13513
12845
  await list5(apiKey, policyId);
13514
12846
  } else {
13515
- log4(red2(`Unknown command: ${command}`));
13516
- log4("");
13517
- log4(bold2("Usage:"));
13518
- log4(" solongate-proxy list List all policies");
13519
- log4(" solongate-proxy list --policy-id <ID> Show policy details");
13520
- log4(" solongate-proxy pull --policy-id <ID> Pull policy to local file");
13521
- log4(" solongate-proxy push --policy-id <ID> Push local file to cloud");
13522
- log4("");
13523
- log4(bold2("Flags:"));
13524
- log4(" --policy-id, --id <ID> Cloud policy ID (required for push)");
13525
- log4(" --file, -f <path> Local file path (default: policy.json)");
13526
- log4(" --api-key <key> API key (or set SOLONGATE_API_KEY)");
13527
- log4("");
12847
+ log3(red2(`Unknown command: ${command}`));
12848
+ log3("");
12849
+ log3(bold2("Usage:"));
12850
+ log3(" solongate-proxy list List all policies");
12851
+ log3(" solongate-proxy list --policy-id <ID> Show policy details");
12852
+ log3(" solongate-proxy pull --policy-id <ID> Pull policy to local file");
12853
+ log3(" solongate-proxy push --policy-id <ID> Push local file to cloud");
12854
+ log3("");
12855
+ log3(bold2("Flags:"));
12856
+ log3(" --policy-id, --id <ID> Cloud policy ID (required for push)");
12857
+ log3(" --file, -f <path> Local file path (default: policy.json)");
12858
+ log3(" --api-key <key> API key (or set SOLONGATE_API_KEY)");
12859
+ log3("");
13528
12860
  process.exit(1);
13529
12861
  }
13530
12862
  } catch (err2) {
13531
- log4(red2(`ERROR: ${err2 instanceof Error ? err2.message : String(err2)}`));
12863
+ log3(red2(`ERROR: ${err2 instanceof Error ? err2.message : String(err2)}`));
13532
12864
  process.exit(1);
13533
12865
  }
13534
12866
  }
13535
- var log4, dim2, bold2, green2, red2, yellow2, cyan2, magenta, API_URL;
12867
+ var log3, dim2, bold2, green2, red2, yellow2, cyan2, magenta, API_URL;
13536
12868
  var init_pull_push = __esm({
13537
12869
  "src/pull-push.ts"() {
13538
12870
  "use strict";
13539
12871
  init_config();
13540
- log4 = (...args) => process.stderr.write(`${args.map(String).join(" ")}
12872
+ log3 = (...args) => process.stderr.write(`${args.map(String).join(" ")}
13541
12873
  `);
13542
12874
  dim2 = (s) => `\x1B[2m${s}\x1B[0m`;
13543
12875
  bold2 = (s) => `\x1B[1m${s}\x1B[0m`;
@@ -13547,15 +12879,15 @@ var init_pull_push = __esm({
13547
12879
  cyan2 = (s) => `\x1B[36m${s}\x1B[0m`;
13548
12880
  magenta = (s) => `\x1B[35m${s}\x1B[0m`;
13549
12881
  API_URL = "https://api.solongate.com";
13550
- main3();
12882
+ main();
13551
12883
  }
13552
12884
  });
13553
12885
 
13554
12886
  // src/index.ts
13555
12887
  init_config();
13556
- import { readFileSync as readFileSync14 } from "fs";
12888
+ import { readFileSync as readFileSync13 } from "fs";
13557
12889
  import { fileURLToPath as fileURLToPath4 } from "url";
13558
- import { dirname as dirname4, join as join17 } from "path";
12890
+ import { dirname as dirname4, join as join16 } from "path";
13559
12891
 
13560
12892
  // src/proxy.ts
13561
12893
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -15979,7 +15311,7 @@ var Mutex = class {
15979
15311
  this.locked = true;
15980
15312
  return;
15981
15313
  }
15982
- return new Promise((resolve9, reject) => {
15314
+ return new Promise((resolve7, reject) => {
15983
15315
  const timer = setTimeout(() => {
15984
15316
  const idx = this.queue.indexOf(onReady);
15985
15317
  if (idx !== -1) this.queue.splice(idx, 1);
@@ -15987,7 +15319,7 @@ var Mutex = class {
15987
15319
  }, timeoutMs);
15988
15320
  const onReady = () => {
15989
15321
  clearTimeout(timer);
15990
- resolve9();
15322
+ resolve7();
15991
15323
  };
15992
15324
  this.queue.push(onReady);
15993
15325
  });
@@ -16578,7 +15910,7 @@ ${msg.content.text}`;
16578
15910
 
16579
15911
  // src/index.ts
16580
15912
  init_cli_utils();
16581
- var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["create", "inject", "pull", "push", "list", "ls", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
15913
+ var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["pull", "push", "list", "ls", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
16582
15914
  var CLI_INFO_ARGS = /* @__PURE__ */ new Set(["login", "help", "--help", "-h", "--version", "-v", "version"]);
16583
15915
  var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "") || CLI_INFO_ARGS.has(process.argv[2] ?? "");
16584
15916
  if (!IS_HUMAN_CLI) {
@@ -16597,8 +15929,8 @@ if (!IS_HUMAN_CLI) {
16597
15929
  }
16598
15930
  var PKG_VERSION = (() => {
16599
15931
  try {
16600
- const p = join17(dirname4(fileURLToPath4(import.meta.url)), "..", "package.json");
16601
- return JSON.parse(readFileSync14(p, "utf-8")).version || "unknown";
15932
+ const p = join16(dirname4(fileURLToPath4(import.meta.url)), "..", "package.json");
15933
+ return JSON.parse(readFileSync13(p, "utf-8")).version || "unknown";
16602
15934
  } catch {
16603
15935
  return "unknown";
16604
15936
  }
@@ -16617,7 +15949,7 @@ function printWelcome() {
16617
15949
  console.log(` ${c.dim}Manage it at ${c.reset}${c.cyan}https://dashboard.solongate.com${c.reset}`);
16618
15950
  console.log("");
16619
15951
  }
16620
- function printHelp3() {
15952
+ function printHelp() {
16621
15953
  const W = 46;
16622
15954
  const head = (t) => console.log(`
16623
15955
  ${c.bold}${t}${c.reset}`);
@@ -16640,7 +15972,6 @@ function printHelp3() {
16640
15972
  head("Setup & status");
16641
15973
  cmd("solongate", "open the dataroom UI (login, policies, audit, settings)");
16642
15974
  cmd("doctor [--json]", "health check: login, policy, guard, local logs");
16643
- cmd("create", "scaffold a guarded MCP server in this folder");
16644
15975
  cmd("logs-server", "serve local audit logs to the dashboard");
16645
15976
  head("Policies");
16646
15977
  cmd("policy list", "list all policies");
@@ -16649,8 +15980,6 @@ function printHelp3() {
16649
15980
  cmd("policy allow <id> --tool <p> [--command|--path|--url <val>]", "add an ALLOW rule");
16650
15981
  cmd("policy revoke <id> <ruleId>", "remove a rule");
16651
15982
  cmd("policy activate <id> | --clear", "pin / unpin the active policy");
16652
- cmd("policy rollback <id> <version>", "roll back to a version");
16653
- cmd("policy versions <id>", "version history");
16654
15983
  cmd("policy active", "show the resolved active policy");
16655
15984
  cmd("policy dry-run <id|file.json> [--mode denylist|whitelist]", "replay recent traffic against rules");
16656
15985
  head("Rate limits");
@@ -16687,10 +16016,10 @@ function printHelp3() {
16687
16016
  console.log(` ${c.dim}Details for a command: ${c.reset}${c.cyan}solongate <command> help${c.reset}${c.dim} \xB7 Dashboard: ${c.reset}${c.cyan}https://dashboard.solongate.com${c.reset}`);
16688
16017
  console.log("");
16689
16018
  }
16690
- async function main4() {
16019
+ async function main2() {
16691
16020
  const subcommand = process.argv[2];
16692
16021
  if (subcommand === "--help" || subcommand === "-h" || subcommand === "help") {
16693
- printHelp3();
16022
+ printHelp();
16694
16023
  return;
16695
16024
  }
16696
16025
  if (subcommand === "--version" || subcommand === "-v" || subcommand === "version") {
@@ -16740,16 +16069,6 @@ async function main4() {
16740
16069
  await runLogsServer2();
16741
16070
  return;
16742
16071
  }
16743
- if (subcommand === "inject") {
16744
- process.argv.splice(2, 1);
16745
- await Promise.resolve().then(() => (init_inject(), inject_exports));
16746
- return;
16747
- }
16748
- if (subcommand === "create") {
16749
- process.argv.splice(2, 1);
16750
- await Promise.resolve().then(() => (init_create(), create_exports));
16751
- return;
16752
- }
16753
16072
  if (subcommand === "pull" || subcommand === "push" || subcommand === "list" || subcommand === "ls") {
16754
16073
  await Promise.resolve().then(() => (init_pull_push(), pull_push_exports));
16755
16074
  return;
@@ -16776,4 +16095,4 @@ async function main4() {
16776
16095
  process.exit(1);
16777
16096
  }
16778
16097
  }
16779
- main4();
16098
+ main2();