@solongate/proxy 0.28.7 → 0.28.9

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.
Files changed (3) hide show
  1. package/dist/index.js +97 -41
  2. package/dist/init.js +97 -41
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -672,15 +672,29 @@ function installHooks(selectedTools = []) {
672
672
  unlockProtectedDirs();
673
673
  const hooksDir = resolve3(".solongate", "hooks");
674
674
  mkdirSync2(hooksDir, { recursive: true });
675
- const guardPath = join(hooksDir, "guard.mjs");
676
- writeFileSync2(guardPath, readHookScript("guard.mjs"));
677
- console.log(` Created ${guardPath}`);
678
- const auditPath = join(hooksDir, "audit.mjs");
679
- writeFileSync2(auditPath, readHookScript("audit.mjs"));
680
- console.log(` Created ${auditPath}`);
681
- const stopPath = join(hooksDir, "stop.mjs");
682
- writeFileSync2(stopPath, readHookScript("stop.mjs"));
683
- console.log(` Created ${stopPath}`);
675
+ const hookFiles = ["guard.mjs", "audit.mjs", "stop.mjs"];
676
+ let hooksUpdated = 0;
677
+ let hooksSkipped = 0;
678
+ for (const filename of hookFiles) {
679
+ const hookPath = join(hooksDir, filename);
680
+ const latest = readHookScript(filename);
681
+ let needsWrite = true;
682
+ if (existsSync4(hookPath)) {
683
+ const current = readFileSync4(hookPath, "utf-8");
684
+ if (current === latest) {
685
+ needsWrite = false;
686
+ hooksSkipped++;
687
+ }
688
+ }
689
+ if (needsWrite) {
690
+ writeFileSync2(hookPath, latest);
691
+ hooksUpdated++;
692
+ console.log(` ${existsSync4(hookPath) ? "Updated" : "Created"} ${hookPath}`);
693
+ }
694
+ }
695
+ if (hooksSkipped > 0 && hooksUpdated === 0) {
696
+ console.log(` Hook files already up to date`);
697
+ }
684
698
  const allClients = [
685
699
  { name: "Claude Code", dir: ".claude", key: "claude", agentId: "claude-code", agentName: "Claude Code" },
686
700
  { name: "Cursor", dir: ".cursor", key: "cursor", agentId: "cursor", agentName: "Cursor" },
@@ -691,6 +705,7 @@ function installHooks(selectedTools = []) {
691
705
  ];
692
706
  const clients = selectedTools.length > 0 ? allClients.filter((c3) => selectedTools.includes(c3.key)) : allClients;
693
707
  const activatedNames = [];
708
+ const skippedNames = [];
694
709
  for (const client of clients) {
695
710
  const clientDir = resolve3(client.dir);
696
711
  mkdirSync2(clientDir, { recursive: true });
@@ -715,18 +730,31 @@ function installHooks(selectedTools = []) {
715
730
  } catch {
716
731
  }
717
732
  const merged = { ...existing, hooks: hookSettings };
718
- writeFileSync2(settingsPath, JSON.stringify(merged, null, 2) + "\n");
719
- console.log(` Created ${settingsPath}`);
720
- activatedNames.push(client.name);
733
+ const mergedStr = JSON.stringify(merged, null, 2) + "\n";
734
+ const existingStr = existsSync4(settingsPath) ? readFileSync4(settingsPath, "utf-8") : "";
735
+ if (mergedStr === existingStr) {
736
+ skippedNames.push(client.name);
737
+ } else {
738
+ writeFileSync2(settingsPath, mergedStr);
739
+ console.log(` ${existingStr ? "Updated" : "Created"} ${settingsPath}`);
740
+ activatedNames.push(client.name);
741
+ }
721
742
  }
722
743
  console.log("");
723
- console.log(" Hooks installed:");
724
- console.log(" guard.mjs \u2192 blocks policy-violating calls (pre-execution)");
725
- console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
726
- console.log(" stop.mjs \u2192 tracks text-only responses (no tool calls)");
727
- console.log(` Activated for: ${activatedNames.join(", ")}`);
744
+ if (activatedNames.length > 0) {
745
+ console.log(" Hooks installed:");
746
+ console.log(" guard.mjs \u2192 blocks policy-violating calls (pre-execution)");
747
+ console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
748
+ console.log(" stop.mjs \u2192 tracks text-only responses (no tool calls)");
749
+ console.log(` Activated for: ${activatedNames.join(", ")}`);
750
+ }
751
+ if (skippedNames.length > 0) {
752
+ console.log(` Already configured: ${skippedNames.join(", ")}`);
753
+ }
728
754
  }
729
755
  function ensureEnvFile() {
756
+ let envChanged = false;
757
+ let gitignoreChanged = false;
730
758
  const envPath = resolve3(".env");
731
759
  if (!existsSync4(envPath)) {
732
760
  const envContent = `# SolonGate Configuration
@@ -742,7 +770,7 @@ GROQ_API_KEY=gsk_your_groq_key_here
742
770
  writeFileSync2(envPath, envContent);
743
771
  console.log(` Created .env`);
744
772
  console.log(` \u2192 Set your API key in .env (get one at https://dashboard.solongate.com)`);
745
- console.log("");
773
+ envChanged = true;
746
774
  } else {
747
775
  const existingEnv = readFileSync4(envPath, "utf-8");
748
776
  if (!existingEnv.includes("SOLONGATE_API_KEY")) {
@@ -754,14 +782,20 @@ SOLONGATE_API_KEY=sg_live_your_key_here
754
782
  writeFileSync2(envPath, existingEnv + appendContent);
755
783
  console.log(` Updated .env (added SOLONGATE_API_KEY)`);
756
784
  console.log(` \u2192 Set your API key in .env (get one at https://dashboard.solongate.com)`);
757
- console.log("");
785
+ envChanged = true;
758
786
  }
759
787
  }
760
788
  const gitignorePath = resolve3(".gitignore");
761
789
  const requiredEntries = [
762
790
  { pattern: ".env", lines: ".env\n.env.local" },
763
791
  { pattern: ".mcp.json", lines: ".mcp.json" },
764
- { pattern: ".solongate", lines: ".solongate/" }
792
+ { pattern: ".solongate", lines: ".solongate/" },
793
+ { pattern: ".claude", lines: ".claude/" },
794
+ { pattern: ".cursor", lines: ".cursor/" },
795
+ { pattern: ".gemini", lines: ".gemini/" },
796
+ { pattern: ".antigravity", lines: ".antigravity/" },
797
+ { pattern: ".openclaw", lines: ".openclaw/" },
798
+ { pattern: ".perplexity", lines: ".perplexity/" }
765
799
  ];
766
800
  if (existsSync4(gitignorePath)) {
767
801
  let gitignore = readFileSync4(gitignorePath, "utf-8");
@@ -775,11 +809,17 @@ SOLONGATE_API_KEY=sg_live_your_key_here
775
809
  if (added.length > 0) {
776
810
  writeFileSync2(gitignorePath, gitignore);
777
811
  console.log(` Updated .gitignore (added ${added.join(", ")})`);
812
+ gitignoreChanged = true;
778
813
  }
779
814
  } else {
780
- writeFileSync2(gitignorePath, ".env\n.env.local\n.mcp.json\n.solongate/\nnode_modules/\n");
781
- console.log(` Created .gitignore (with .env, .mcp.json, .solongate/ excluded)`);
815
+ writeFileSync2(gitignorePath, ".env\n.env.local\n.mcp.json\n.solongate/\n.claude/\n.cursor/\n.gemini/\n.antigravity/\n.openclaw/\n.perplexity/\nnode_modules/\n");
816
+ console.log(` Created .gitignore`);
817
+ gitignoreChanged = true;
818
+ }
819
+ if (!envChanged && !gitignoreChanged) {
820
+ console.log(` .env and .gitignore already up to date`);
782
821
  }
822
+ return { envChanged, gitignoreChanged };
783
823
  }
784
824
  async function main() {
785
825
  const options = parseInitArgs(process.argv);
@@ -940,21 +980,28 @@ async function main() {
940
980
  newConfig.mcpServers[name] = config.mcpServers[name];
941
981
  }
942
982
  }
943
- await sleep(400);
983
+ const currentContent = readFileSync4(configInfo.path, "utf-8");
984
+ let newContent;
944
985
  if (configInfo.type === "claude-desktop") {
945
- const original = JSON.parse(readFileSync4(configInfo.path, "utf-8"));
986
+ const original = JSON.parse(currentContent);
946
987
  original.mcpServers = newConfig.mcpServers;
947
- writeFileSync2(configInfo.path, JSON.stringify(original, null, 2) + "\n");
988
+ newContent = JSON.stringify(original, null, 2) + "\n";
948
989
  } else {
949
- writeFileSync2(configInfo.path, JSON.stringify(newConfig, null, 2) + "\n");
990
+ newContent = JSON.stringify(newConfig, null, 2) + "\n";
991
+ }
992
+ await sleep(400);
993
+ if (newContent === currentContent) {
994
+ console.log(" Config already up to date");
995
+ } else {
996
+ writeFileSync2(configInfo.path, newContent);
997
+ console.log(" Config updated!");
950
998
  }
951
- await sleep(300);
952
- console.log(" Config updated!");
953
999
  console.log("");
954
1000
  await sleep(500);
955
1001
  installHooks(options.tools);
956
1002
  console.log("");
957
1003
  await sleep(400);
1004
+ const allUpToDate = toProtect.length === 0 && alreadyProtected.length === serverNames.length;
958
1005
  console.log(" \u2500\u2500 Summary \u2500\u2500");
959
1006
  console.log("");
960
1007
  for (const name of toProtect) {
@@ -971,19 +1018,28 @@ async function main() {
971
1018
  }
972
1019
  console.log("");
973
1020
  await sleep(500);
974
- console.log(" \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\u2500\u2500\u2500\u2510");
975
- console.log(" \u2502 Setup complete! \u2502");
976
- console.log(" \u2502 \u2502");
977
- console.log(" \u2502 MCP servers \u2192 Protected via proxy \u2502");
978
- console.log(" \u2502 AI tools \u2192 Guarded via hooks \u2502");
979
- console.log(" \u2502 Claude, Cursor, Gemini, Antigravity, \u2502");
980
- console.log(" \u2502 OpenClaw, Perplexity \u2502");
981
- console.log(" \u2502 API key \u2192 Set in .env \u2502");
982
- console.log(" \u2502 \u2502");
983
- console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
984
- console.log(" \u2502 \u2502");
985
- console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
986
- console.log(" \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\u2500\u2500\u2500\u2518");
1021
+ if (allUpToDate) {
1022
+ console.log(" \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\u2500\u2500\u2500\u2510");
1023
+ console.log(" \u2502 Everything is already up to date! \u2502");
1024
+ console.log(" \u2502 \u2502");
1025
+ console.log(" \u2502 All MCP servers protected, hooks configured. \u2502");
1026
+ console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
1027
+ console.log(" \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\u2500\u2500\u2500\u2518");
1028
+ } else {
1029
+ console.log(" \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\u2500\u2500\u2500\u2510");
1030
+ console.log(" \u2502 Setup complete! \u2502");
1031
+ console.log(" \u2502 \u2502");
1032
+ console.log(" \u2502 MCP servers \u2192 Protected via proxy \u2502");
1033
+ console.log(" \u2502 AI tools \u2192 Guarded via hooks \u2502");
1034
+ console.log(" \u2502 Claude, Cursor, Gemini, Antigravity, \u2502");
1035
+ console.log(" \u2502 OpenClaw, Perplexity \u2502");
1036
+ console.log(" \u2502 API key \u2192 Set in .env \u2502");
1037
+ console.log(" \u2502 \u2502");
1038
+ console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
1039
+ console.log(" \u2502 \u2502");
1040
+ console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
1041
+ console.log(" \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\u2500\u2500\u2500\u2518");
1042
+ }
987
1043
  console.log("");
988
1044
  }
989
1045
  var SEARCH_PATHS, CLAUDE_DESKTOP_PATHS, sleep, __dirname, HOOKS_DIR;
package/dist/init.js CHANGED
@@ -255,15 +255,29 @@ function installHooks(selectedTools = []) {
255
255
  unlockProtectedDirs();
256
256
  const hooksDir = resolve(".solongate", "hooks");
257
257
  mkdirSync(hooksDir, { recursive: true });
258
- const guardPath = join(hooksDir, "guard.mjs");
259
- writeFileSync(guardPath, readHookScript("guard.mjs"));
260
- console.log(` Created ${guardPath}`);
261
- const auditPath = join(hooksDir, "audit.mjs");
262
- writeFileSync(auditPath, readHookScript("audit.mjs"));
263
- console.log(` Created ${auditPath}`);
264
- const stopPath = join(hooksDir, "stop.mjs");
265
- writeFileSync(stopPath, readHookScript("stop.mjs"));
266
- console.log(` Created ${stopPath}`);
258
+ const hookFiles = ["guard.mjs", "audit.mjs", "stop.mjs"];
259
+ let hooksUpdated = 0;
260
+ let hooksSkipped = 0;
261
+ for (const filename of hookFiles) {
262
+ const hookPath = join(hooksDir, filename);
263
+ const latest = readHookScript(filename);
264
+ let needsWrite = true;
265
+ if (existsSync(hookPath)) {
266
+ const current = readFileSync(hookPath, "utf-8");
267
+ if (current === latest) {
268
+ needsWrite = false;
269
+ hooksSkipped++;
270
+ }
271
+ }
272
+ if (needsWrite) {
273
+ writeFileSync(hookPath, latest);
274
+ hooksUpdated++;
275
+ console.log(` ${existsSync(hookPath) ? "Updated" : "Created"} ${hookPath}`);
276
+ }
277
+ }
278
+ if (hooksSkipped > 0 && hooksUpdated === 0) {
279
+ console.log(` Hook files already up to date`);
280
+ }
267
281
  const allClients = [
268
282
  { name: "Claude Code", dir: ".claude", key: "claude", agentId: "claude-code", agentName: "Claude Code" },
269
283
  { name: "Cursor", dir: ".cursor", key: "cursor", agentId: "cursor", agentName: "Cursor" },
@@ -274,6 +288,7 @@ function installHooks(selectedTools = []) {
274
288
  ];
275
289
  const clients = selectedTools.length > 0 ? allClients.filter((c2) => selectedTools.includes(c2.key)) : allClients;
276
290
  const activatedNames = [];
291
+ const skippedNames = [];
277
292
  for (const client of clients) {
278
293
  const clientDir = resolve(client.dir);
279
294
  mkdirSync(clientDir, { recursive: true });
@@ -298,18 +313,31 @@ function installHooks(selectedTools = []) {
298
313
  } catch {
299
314
  }
300
315
  const merged = { ...existing, hooks: hookSettings };
301
- writeFileSync(settingsPath, JSON.stringify(merged, null, 2) + "\n");
302
- console.log(` Created ${settingsPath}`);
303
- activatedNames.push(client.name);
316
+ const mergedStr = JSON.stringify(merged, null, 2) + "\n";
317
+ const existingStr = existsSync(settingsPath) ? readFileSync(settingsPath, "utf-8") : "";
318
+ if (mergedStr === existingStr) {
319
+ skippedNames.push(client.name);
320
+ } else {
321
+ writeFileSync(settingsPath, mergedStr);
322
+ console.log(` ${existingStr ? "Updated" : "Created"} ${settingsPath}`);
323
+ activatedNames.push(client.name);
324
+ }
304
325
  }
305
326
  console.log("");
306
- console.log(" Hooks installed:");
307
- console.log(" guard.mjs \u2192 blocks policy-violating calls (pre-execution)");
308
- console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
309
- console.log(" stop.mjs \u2192 tracks text-only responses (no tool calls)");
310
- console.log(` Activated for: ${activatedNames.join(", ")}`);
327
+ if (activatedNames.length > 0) {
328
+ console.log(" Hooks installed:");
329
+ console.log(" guard.mjs \u2192 blocks policy-violating calls (pre-execution)");
330
+ console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
331
+ console.log(" stop.mjs \u2192 tracks text-only responses (no tool calls)");
332
+ console.log(` Activated for: ${activatedNames.join(", ")}`);
333
+ }
334
+ if (skippedNames.length > 0) {
335
+ console.log(` Already configured: ${skippedNames.join(", ")}`);
336
+ }
311
337
  }
312
338
  function ensureEnvFile() {
339
+ let envChanged = false;
340
+ let gitignoreChanged = false;
313
341
  const envPath = resolve(".env");
314
342
  if (!existsSync(envPath)) {
315
343
  const envContent = `# SolonGate Configuration
@@ -325,7 +353,7 @@ GROQ_API_KEY=gsk_your_groq_key_here
325
353
  writeFileSync(envPath, envContent);
326
354
  console.log(` Created .env`);
327
355
  console.log(` \u2192 Set your API key in .env (get one at https://dashboard.solongate.com)`);
328
- console.log("");
356
+ envChanged = true;
329
357
  } else {
330
358
  const existingEnv = readFileSync(envPath, "utf-8");
331
359
  if (!existingEnv.includes("SOLONGATE_API_KEY")) {
@@ -337,14 +365,20 @@ SOLONGATE_API_KEY=sg_live_your_key_here
337
365
  writeFileSync(envPath, existingEnv + appendContent);
338
366
  console.log(` Updated .env (added SOLONGATE_API_KEY)`);
339
367
  console.log(` \u2192 Set your API key in .env (get one at https://dashboard.solongate.com)`);
340
- console.log("");
368
+ envChanged = true;
341
369
  }
342
370
  }
343
371
  const gitignorePath = resolve(".gitignore");
344
372
  const requiredEntries = [
345
373
  { pattern: ".env", lines: ".env\n.env.local" },
346
374
  { pattern: ".mcp.json", lines: ".mcp.json" },
347
- { pattern: ".solongate", lines: ".solongate/" }
375
+ { pattern: ".solongate", lines: ".solongate/" },
376
+ { pattern: ".claude", lines: ".claude/" },
377
+ { pattern: ".cursor", lines: ".cursor/" },
378
+ { pattern: ".gemini", lines: ".gemini/" },
379
+ { pattern: ".antigravity", lines: ".antigravity/" },
380
+ { pattern: ".openclaw", lines: ".openclaw/" },
381
+ { pattern: ".perplexity", lines: ".perplexity/" }
348
382
  ];
349
383
  if (existsSync(gitignorePath)) {
350
384
  let gitignore = readFileSync(gitignorePath, "utf-8");
@@ -358,11 +392,17 @@ SOLONGATE_API_KEY=sg_live_your_key_here
358
392
  if (added.length > 0) {
359
393
  writeFileSync(gitignorePath, gitignore);
360
394
  console.log(` Updated .gitignore (added ${added.join(", ")})`);
395
+ gitignoreChanged = true;
361
396
  }
362
397
  } else {
363
- writeFileSync(gitignorePath, ".env\n.env.local\n.mcp.json\n.solongate/\nnode_modules/\n");
364
- console.log(` Created .gitignore (with .env, .mcp.json, .solongate/ excluded)`);
398
+ writeFileSync(gitignorePath, ".env\n.env.local\n.mcp.json\n.solongate/\n.claude/\n.cursor/\n.gemini/\n.antigravity/\n.openclaw/\n.perplexity/\nnode_modules/\n");
399
+ console.log(` Created .gitignore`);
400
+ gitignoreChanged = true;
401
+ }
402
+ if (!envChanged && !gitignoreChanged) {
403
+ console.log(` .env and .gitignore already up to date`);
365
404
  }
405
+ return { envChanged, gitignoreChanged };
366
406
  }
367
407
  async function main() {
368
408
  const options = parseInitArgs(process.argv);
@@ -523,21 +563,28 @@ async function main() {
523
563
  newConfig.mcpServers[name] = config.mcpServers[name];
524
564
  }
525
565
  }
526
- await sleep(400);
566
+ const currentContent = readFileSync(configInfo.path, "utf-8");
567
+ let newContent;
527
568
  if (configInfo.type === "claude-desktop") {
528
- const original = JSON.parse(readFileSync(configInfo.path, "utf-8"));
569
+ const original = JSON.parse(currentContent);
529
570
  original.mcpServers = newConfig.mcpServers;
530
- writeFileSync(configInfo.path, JSON.stringify(original, null, 2) + "\n");
571
+ newContent = JSON.stringify(original, null, 2) + "\n";
531
572
  } else {
532
- writeFileSync(configInfo.path, JSON.stringify(newConfig, null, 2) + "\n");
573
+ newContent = JSON.stringify(newConfig, null, 2) + "\n";
574
+ }
575
+ await sleep(400);
576
+ if (newContent === currentContent) {
577
+ console.log(" Config already up to date");
578
+ } else {
579
+ writeFileSync(configInfo.path, newContent);
580
+ console.log(" Config updated!");
533
581
  }
534
- await sleep(300);
535
- console.log(" Config updated!");
536
582
  console.log("");
537
583
  await sleep(500);
538
584
  installHooks(options.tools);
539
585
  console.log("");
540
586
  await sleep(400);
587
+ const allUpToDate = toProtect.length === 0 && alreadyProtected.length === serverNames.length;
541
588
  console.log(" \u2500\u2500 Summary \u2500\u2500");
542
589
  console.log("");
543
590
  for (const name of toProtect) {
@@ -554,19 +601,28 @@ async function main() {
554
601
  }
555
602
  console.log("");
556
603
  await sleep(500);
557
- console.log(" \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\u2500\u2500\u2500\u2510");
558
- console.log(" \u2502 Setup complete! \u2502");
559
- console.log(" \u2502 \u2502");
560
- console.log(" \u2502 MCP servers \u2192 Protected via proxy \u2502");
561
- console.log(" \u2502 AI tools \u2192 Guarded via hooks \u2502");
562
- console.log(" \u2502 Claude, Cursor, Gemini, Antigravity, \u2502");
563
- console.log(" \u2502 OpenClaw, Perplexity \u2502");
564
- console.log(" \u2502 API key \u2192 Set in .env \u2502");
565
- console.log(" \u2502 \u2502");
566
- console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
567
- console.log(" \u2502 \u2502");
568
- console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
569
- console.log(" \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\u2500\u2500\u2500\u2518");
604
+ if (allUpToDate) {
605
+ console.log(" \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\u2500\u2500\u2500\u2510");
606
+ console.log(" \u2502 Everything is already up to date! \u2502");
607
+ console.log(" \u2502 \u2502");
608
+ console.log(" \u2502 All MCP servers protected, hooks configured. \u2502");
609
+ console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
610
+ console.log(" \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\u2500\u2500\u2500\u2518");
611
+ } else {
612
+ console.log(" \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\u2500\u2500\u2500\u2510");
613
+ console.log(" \u2502 Setup complete! \u2502");
614
+ console.log(" \u2502 \u2502");
615
+ console.log(" \u2502 MCP servers \u2192 Protected via proxy \u2502");
616
+ console.log(" \u2502 AI tools \u2192 Guarded via hooks \u2502");
617
+ console.log(" \u2502 Claude, Cursor, Gemini, Antigravity, \u2502");
618
+ console.log(" \u2502 OpenClaw, Perplexity \u2502");
619
+ console.log(" \u2502 API key \u2192 Set in .env \u2502");
620
+ console.log(" \u2502 \u2502");
621
+ console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
622
+ console.log(" \u2502 \u2502");
623
+ console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
624
+ console.log(" \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\u2500\u2500\u2500\u2518");
625
+ }
570
626
  console.log("");
571
627
  }
572
628
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.28.7",
3
+ "version": "0.28.9",
4
4
  "description": "MCP security proxy — protect any MCP server with customizable policies, path/command constraints, rate limiting, and audit logging. Zero code changes required.",
5
5
  "type": "module",
6
6
  "bin": {