@solongate/proxy 0.5.3 → 0.5.5
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 +28 -117
- package/dist/init.js +24 -113
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -524,7 +524,7 @@ var init_config = __esm({
|
|
|
524
524
|
|
|
525
525
|
// src/init.ts
|
|
526
526
|
var init_exports = {};
|
|
527
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3,
|
|
527
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync } from "fs";
|
|
528
528
|
import { resolve as resolve2, join } from "path";
|
|
529
529
|
import { createInterface } from "readline";
|
|
530
530
|
function findConfigFile(explicitPath, createIfMissing = false) {
|
|
@@ -580,7 +580,7 @@ function isAlreadyProtected(server) {
|
|
|
580
580
|
}
|
|
581
581
|
return false;
|
|
582
582
|
}
|
|
583
|
-
function wrapServer(server
|
|
583
|
+
function wrapServer(server) {
|
|
584
584
|
const env = { ...server.env ?? {} };
|
|
585
585
|
env.SOLONGATE_API_KEY = "${SOLONGATE_API_KEY}";
|
|
586
586
|
return {
|
|
@@ -589,7 +589,7 @@ function wrapServer(server, policy) {
|
|
|
589
589
|
"-y",
|
|
590
590
|
"@solongate/proxy",
|
|
591
591
|
"--policy",
|
|
592
|
-
|
|
592
|
+
"restricted",
|
|
593
593
|
"--verbose",
|
|
594
594
|
"--",
|
|
595
595
|
server.command,
|
|
@@ -610,44 +610,25 @@ async function prompt(question) {
|
|
|
610
610
|
function parseInitArgs(argv) {
|
|
611
611
|
const args = argv.slice(2);
|
|
612
612
|
const options = {
|
|
613
|
-
|
|
614
|
-
all: false,
|
|
615
|
-
dryRun: false,
|
|
616
|
-
restore: false
|
|
613
|
+
all: false
|
|
617
614
|
};
|
|
618
615
|
for (let i = 0; i < args.length; i++) {
|
|
619
616
|
switch (args[i]) {
|
|
620
617
|
case "--config":
|
|
621
618
|
options.configPath = args[++i];
|
|
622
619
|
break;
|
|
623
|
-
case "--policy":
|
|
624
|
-
options.policy = args[++i];
|
|
625
|
-
break;
|
|
626
620
|
case "--api-key":
|
|
627
621
|
options.apiKey = args[++i];
|
|
628
622
|
break;
|
|
629
623
|
case "--all":
|
|
630
624
|
options.all = true;
|
|
631
625
|
break;
|
|
632
|
-
case "--dry-run":
|
|
633
|
-
options.dryRun = true;
|
|
634
|
-
break;
|
|
635
|
-
case "--restore":
|
|
636
|
-
options.restore = true;
|
|
637
|
-
break;
|
|
638
626
|
case "--help":
|
|
639
627
|
case "-h":
|
|
640
628
|
printHelp();
|
|
641
629
|
process.exit(0);
|
|
642
630
|
}
|
|
643
631
|
}
|
|
644
|
-
if (!POLICY_PRESETS.includes(options.policy)) {
|
|
645
|
-
if (!existsSync3(resolve2(options.policy))) {
|
|
646
|
-
console.log(`Unknown policy: ${options.policy}`);
|
|
647
|
-
console.log(`Available presets: ${POLICY_PRESETS.join(", ")}`);
|
|
648
|
-
process.exit(1);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
632
|
return options;
|
|
652
633
|
}
|
|
653
634
|
function printHelp() {
|
|
@@ -655,35 +636,22 @@ function printHelp() {
|
|
|
655
636
|
SolonGate Init \u2014 Protect your MCP servers in seconds
|
|
656
637
|
|
|
657
638
|
USAGE
|
|
658
|
-
solongate
|
|
639
|
+
npx @solongate/proxy init --all
|
|
659
640
|
|
|
660
641
|
OPTIONS
|
|
661
642
|
--config <path> Path to MCP config file (default: auto-detect)
|
|
662
|
-
--policy <preset> Policy preset or JSON file (default: restricted)
|
|
663
|
-
Presets: ${POLICY_PRESETS.join(", ")}
|
|
664
643
|
--api-key <key> SolonGate API key (sg_live_... or sg_test_...)
|
|
665
644
|
--all Protect all servers without prompting
|
|
666
|
-
--dry-run Preview changes without writing
|
|
667
|
-
--restore Restore original config from backup
|
|
668
645
|
-h, --help Show this help message
|
|
669
646
|
|
|
670
647
|
EXAMPLES
|
|
671
|
-
solongate
|
|
672
|
-
solongate
|
|
673
|
-
solongate-init --policy read-only # Use read-only policy
|
|
674
|
-
solongate-init --dry-run # Preview changes
|
|
675
|
-
solongate-init --restore # Undo protection
|
|
676
|
-
|
|
677
|
-
POLICY PRESETS
|
|
678
|
-
restricted Block shell/exec/eval, allow reads and writes (recommended)
|
|
679
|
-
read-only Only allow read/list/get/search/query operations
|
|
680
|
-
permissive Allow everything (monitoring + audit only)
|
|
681
|
-
deny-all Block all tool calls
|
|
648
|
+
npx @solongate/proxy init --all # Protect everything
|
|
649
|
+
npx @solongate/proxy init --api-key sg_live_xxx # With API key
|
|
682
650
|
`;
|
|
683
651
|
console.log(help);
|
|
684
652
|
}
|
|
685
|
-
function
|
|
686
|
-
const hooksDir = resolve2(".
|
|
653
|
+
function installHooks() {
|
|
654
|
+
const hooksDir = resolve2(".solongate", "hooks");
|
|
687
655
|
mkdirSync(hooksDir, { recursive: true });
|
|
688
656
|
const guardPath = join(hooksDir, "guard.mjs");
|
|
689
657
|
writeFileSync2(guardPath, GUARD_SCRIPT);
|
|
@@ -691,50 +659,15 @@ function installClaudeCodeHooks(apiKey) {
|
|
|
691
659
|
const auditPath = join(hooksDir, "audit.mjs");
|
|
692
660
|
writeFileSync2(auditPath, AUDIT_SCRIPT);
|
|
693
661
|
console.log(` Created ${auditPath}`);
|
|
694
|
-
const settingsPath = resolve2(".claude", "settings.json");
|
|
695
|
-
let settings = {};
|
|
696
|
-
if (existsSync3(settingsPath)) {
|
|
697
|
-
try {
|
|
698
|
-
settings = JSON.parse(readFileSync3(settingsPath, "utf-8"));
|
|
699
|
-
} catch {
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
settings.hooks = {
|
|
703
|
-
PreToolUse: [
|
|
704
|
-
{
|
|
705
|
-
matcher: ".*",
|
|
706
|
-
hooks: [
|
|
707
|
-
{
|
|
708
|
-
type: "command",
|
|
709
|
-
command: "node .claude/hooks/guard.mjs",
|
|
710
|
-
timeout: 5
|
|
711
|
-
}
|
|
712
|
-
]
|
|
713
|
-
}
|
|
714
|
-
],
|
|
715
|
-
PostToolUse: [
|
|
716
|
-
{
|
|
717
|
-
matcher: ".*",
|
|
718
|
-
hooks: [
|
|
719
|
-
{
|
|
720
|
-
type: "command",
|
|
721
|
-
command: "node .claude/hooks/audit.mjs",
|
|
722
|
-
timeout: 10,
|
|
723
|
-
async: true
|
|
724
|
-
}
|
|
725
|
-
]
|
|
726
|
-
}
|
|
727
|
-
]
|
|
728
|
-
};
|
|
729
|
-
const envObj = settings.env || {};
|
|
730
|
-
envObj.SOLONGATE_API_KEY = apiKey;
|
|
731
|
-
settings.env = envObj;
|
|
732
|
-
writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
733
|
-
console.log(` Created ${settingsPath}`);
|
|
734
662
|
console.log("");
|
|
735
|
-
console.log("
|
|
736
|
-
console.log("
|
|
737
|
-
console.log("
|
|
663
|
+
console.log(" Hooks installed in .solongate/hooks/");
|
|
664
|
+
console.log(" guard.mjs \u2192 blocks dangerous calls (pre-execution)");
|
|
665
|
+
console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
|
|
666
|
+
console.log("");
|
|
667
|
+
console.log(" To activate hooks in your MCP client:");
|
|
668
|
+
console.log(" Claude Code \u2192 .claude/settings.json");
|
|
669
|
+
console.log(" Cursor \u2192 .cursor/settings.json");
|
|
670
|
+
console.log(" Or run: node .solongate/hooks/guard.mjs (stdin: JSON)");
|
|
738
671
|
}
|
|
739
672
|
function ensureEnvFile() {
|
|
740
673
|
const envPath = resolve2(".env");
|
|
@@ -811,16 +744,6 @@ async function main() {
|
|
|
811
744
|
console.log(` Config: ${configInfo.path}`);
|
|
812
745
|
console.log(` Type: ${configInfo.type === "claude-desktop" ? "Claude Desktop" : "MCP JSON"}`);
|
|
813
746
|
console.log("");
|
|
814
|
-
const backupPath = configInfo.path + ".solongate-backup";
|
|
815
|
-
if (options.restore) {
|
|
816
|
-
if (!existsSync3(backupPath)) {
|
|
817
|
-
console.log(" No backup found. Nothing to restore.");
|
|
818
|
-
process.exit(1);
|
|
819
|
-
}
|
|
820
|
-
copyFileSync(backupPath, configInfo.path);
|
|
821
|
-
console.log(" Restored original config from backup.");
|
|
822
|
-
process.exit(0);
|
|
823
|
-
}
|
|
824
747
|
const config = readConfig(configInfo.path);
|
|
825
748
|
const serverNames = Object.keys(config.mcpServers);
|
|
826
749
|
if (serverNames.length === 0) {
|
|
@@ -900,7 +823,7 @@ async function main() {
|
|
|
900
823
|
process.exit(1);
|
|
901
824
|
}
|
|
902
825
|
await sleep(300);
|
|
903
|
-
console.log(` Policy:
|
|
826
|
+
console.log(` Policy: restricted`);
|
|
904
827
|
await sleep(150);
|
|
905
828
|
console.log(` API Key: ${apiKey.slice(0, 12)}...${apiKey.slice(-4)}`);
|
|
906
829
|
await sleep(150);
|
|
@@ -909,23 +832,12 @@ async function main() {
|
|
|
909
832
|
const newConfig = { mcpServers: {} };
|
|
910
833
|
for (const name of serverNames) {
|
|
911
834
|
if (toProtect.includes(name)) {
|
|
912
|
-
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name]
|
|
835
|
+
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name]);
|
|
913
836
|
} else {
|
|
914
837
|
newConfig.mcpServers[name] = config.mcpServers[name];
|
|
915
838
|
}
|
|
916
839
|
}
|
|
917
|
-
if (options.dryRun) {
|
|
918
|
-
console.log(" --- DRY RUN (no changes written) ---");
|
|
919
|
-
console.log("");
|
|
920
|
-
console.log(" New config:");
|
|
921
|
-
console.log(JSON.stringify(newConfig, null, 2));
|
|
922
|
-
process.exit(0);
|
|
923
|
-
}
|
|
924
840
|
await sleep(400);
|
|
925
|
-
if (!configInfo.created && !existsSync3(backupPath)) {
|
|
926
|
-
copyFileSync(configInfo.path, backupPath);
|
|
927
|
-
console.log(` Backup: ${backupPath}`);
|
|
928
|
-
}
|
|
929
841
|
if (configInfo.type === "claude-desktop") {
|
|
930
842
|
const original = JSON.parse(readFileSync3(configInfo.path, "utf-8"));
|
|
931
843
|
original.mcpServers = newConfig.mcpServers;
|
|
@@ -937,14 +849,14 @@ async function main() {
|
|
|
937
849
|
console.log(" Config updated!");
|
|
938
850
|
console.log("");
|
|
939
851
|
await sleep(500);
|
|
940
|
-
|
|
852
|
+
installHooks();
|
|
941
853
|
console.log("");
|
|
942
854
|
await sleep(400);
|
|
943
855
|
console.log(" \u2500\u2500 Summary \u2500\u2500");
|
|
944
856
|
console.log("");
|
|
945
857
|
for (const name of toProtect) {
|
|
946
858
|
await sleep(200);
|
|
947
|
-
console.log(` \u2713 ${name} \u2014 protected
|
|
859
|
+
console.log(` \u2713 ${name} \u2014 protected`);
|
|
948
860
|
}
|
|
949
861
|
for (const name of alreadyProtected) {
|
|
950
862
|
await sleep(200);
|
|
@@ -959,21 +871,20 @@ async function main() {
|
|
|
959
871
|
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");
|
|
960
872
|
console.log(" \u2502 Setup complete! \u2502");
|
|
961
873
|
console.log(" \u2502 \u2502");
|
|
962
|
-
console.log(" \u2502 MCP
|
|
963
|
-
console.log(" \u2502
|
|
874
|
+
console.log(" \u2502 MCP servers \u2192 Protected via proxy \u2502");
|
|
875
|
+
console.log(" \u2502 AI tools \u2192 Guarded via hooks \u2502");
|
|
876
|
+
console.log(" \u2502 API key \u2192 Set in .env \u2502");
|
|
964
877
|
console.log(" \u2502 \u2502");
|
|
965
878
|
console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
|
|
966
|
-
console.log(" \u2502 To undo: solongate-init --restore \u2502");
|
|
967
879
|
console.log(" \u2502 \u2502");
|
|
968
880
|
console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
|
|
969
881
|
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");
|
|
970
882
|
console.log("");
|
|
971
883
|
}
|
|
972
|
-
var
|
|
884
|
+
var SEARCH_PATHS, CLAUDE_DESKTOP_PATHS, sleep, GUARD_SCRIPT, AUDIT_SCRIPT;
|
|
973
885
|
var init_init = __esm({
|
|
974
886
|
"src/init.ts"() {
|
|
975
887
|
"use strict";
|
|
976
|
-
POLICY_PRESETS = ["restricted", "read-only", "permissive", "deny-all"];
|
|
977
888
|
SEARCH_PATHS = [
|
|
978
889
|
".mcp.json",
|
|
979
890
|
"mcp.json",
|
|
@@ -1196,7 +1107,7 @@ process.stdin.on('end', async () => {
|
|
|
1196
1107
|
|
|
1197
1108
|
// src/inject.ts
|
|
1198
1109
|
var inject_exports = {};
|
|
1199
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, copyFileSync
|
|
1110
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, copyFileSync } from "fs";
|
|
1200
1111
|
import { resolve as resolve3 } from "path";
|
|
1201
1112
|
import { execSync } from "child_process";
|
|
1202
1113
|
function parseInjectArgs(argv) {
|
|
@@ -1488,7 +1399,7 @@ async function main2() {
|
|
|
1488
1399
|
log3(" No backup found. Nothing to restore.");
|
|
1489
1400
|
process.exit(1);
|
|
1490
1401
|
}
|
|
1491
|
-
|
|
1402
|
+
copyFileSync(backupPath, entryFile);
|
|
1492
1403
|
log3(` Restored original file from backup.`);
|
|
1493
1404
|
log3(` Backup: ${backupPath}`);
|
|
1494
1405
|
process.exit(0);
|
|
@@ -1521,7 +1432,7 @@ async function main2() {
|
|
|
1521
1432
|
process.exit(0);
|
|
1522
1433
|
}
|
|
1523
1434
|
if (!existsSync4(backupPath)) {
|
|
1524
|
-
|
|
1435
|
+
copyFileSync(entryFile, backupPath);
|
|
1525
1436
|
log3("");
|
|
1526
1437
|
log3(` Backup: ${backupPath}`);
|
|
1527
1438
|
}
|
package/dist/init.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/init.ts
|
|
4
|
-
import { readFileSync, writeFileSync, existsSync,
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
5
5
|
import { resolve, join } from "path";
|
|
6
6
|
import { createInterface } from "readline";
|
|
7
|
-
var POLICY_PRESETS = ["restricted", "read-only", "permissive", "deny-all"];
|
|
8
7
|
var SEARCH_PATHS = [
|
|
9
8
|
".mcp.json",
|
|
10
9
|
"mcp.json",
|
|
@@ -65,7 +64,7 @@ function isAlreadyProtected(server) {
|
|
|
65
64
|
}
|
|
66
65
|
return false;
|
|
67
66
|
}
|
|
68
|
-
function wrapServer(server
|
|
67
|
+
function wrapServer(server) {
|
|
69
68
|
const env = { ...server.env ?? {} };
|
|
70
69
|
env.SOLONGATE_API_KEY = "${SOLONGATE_API_KEY}";
|
|
71
70
|
return {
|
|
@@ -74,7 +73,7 @@ function wrapServer(server, policy) {
|
|
|
74
73
|
"-y",
|
|
75
74
|
"@solongate/proxy",
|
|
76
75
|
"--policy",
|
|
77
|
-
|
|
76
|
+
"restricted",
|
|
78
77
|
"--verbose",
|
|
79
78
|
"--",
|
|
80
79
|
server.command,
|
|
@@ -95,44 +94,25 @@ async function prompt(question) {
|
|
|
95
94
|
function parseInitArgs(argv) {
|
|
96
95
|
const args = argv.slice(2);
|
|
97
96
|
const options = {
|
|
98
|
-
|
|
99
|
-
all: false,
|
|
100
|
-
dryRun: false,
|
|
101
|
-
restore: false
|
|
97
|
+
all: false
|
|
102
98
|
};
|
|
103
99
|
for (let i = 0; i < args.length; i++) {
|
|
104
100
|
switch (args[i]) {
|
|
105
101
|
case "--config":
|
|
106
102
|
options.configPath = args[++i];
|
|
107
103
|
break;
|
|
108
|
-
case "--policy":
|
|
109
|
-
options.policy = args[++i];
|
|
110
|
-
break;
|
|
111
104
|
case "--api-key":
|
|
112
105
|
options.apiKey = args[++i];
|
|
113
106
|
break;
|
|
114
107
|
case "--all":
|
|
115
108
|
options.all = true;
|
|
116
109
|
break;
|
|
117
|
-
case "--dry-run":
|
|
118
|
-
options.dryRun = true;
|
|
119
|
-
break;
|
|
120
|
-
case "--restore":
|
|
121
|
-
options.restore = true;
|
|
122
|
-
break;
|
|
123
110
|
case "--help":
|
|
124
111
|
case "-h":
|
|
125
112
|
printHelp();
|
|
126
113
|
process.exit(0);
|
|
127
114
|
}
|
|
128
115
|
}
|
|
129
|
-
if (!POLICY_PRESETS.includes(options.policy)) {
|
|
130
|
-
if (!existsSync(resolve(options.policy))) {
|
|
131
|
-
console.log(`Unknown policy: ${options.policy}`);
|
|
132
|
-
console.log(`Available presets: ${POLICY_PRESETS.join(", ")}`);
|
|
133
|
-
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
116
|
return options;
|
|
137
117
|
}
|
|
138
118
|
function printHelp() {
|
|
@@ -140,30 +120,17 @@ function printHelp() {
|
|
|
140
120
|
SolonGate Init \u2014 Protect your MCP servers in seconds
|
|
141
121
|
|
|
142
122
|
USAGE
|
|
143
|
-
solongate
|
|
123
|
+
npx @solongate/proxy init --all
|
|
144
124
|
|
|
145
125
|
OPTIONS
|
|
146
126
|
--config <path> Path to MCP config file (default: auto-detect)
|
|
147
|
-
--policy <preset> Policy preset or JSON file (default: restricted)
|
|
148
|
-
Presets: ${POLICY_PRESETS.join(", ")}
|
|
149
127
|
--api-key <key> SolonGate API key (sg_live_... or sg_test_...)
|
|
150
128
|
--all Protect all servers without prompting
|
|
151
|
-
--dry-run Preview changes without writing
|
|
152
|
-
--restore Restore original config from backup
|
|
153
129
|
-h, --help Show this help message
|
|
154
130
|
|
|
155
131
|
EXAMPLES
|
|
156
|
-
solongate
|
|
157
|
-
solongate
|
|
158
|
-
solongate-init --policy read-only # Use read-only policy
|
|
159
|
-
solongate-init --dry-run # Preview changes
|
|
160
|
-
solongate-init --restore # Undo protection
|
|
161
|
-
|
|
162
|
-
POLICY PRESETS
|
|
163
|
-
restricted Block shell/exec/eval, allow reads and writes (recommended)
|
|
164
|
-
read-only Only allow read/list/get/search/query operations
|
|
165
|
-
permissive Allow everything (monitoring + audit only)
|
|
166
|
-
deny-all Block all tool calls
|
|
132
|
+
npx @solongate/proxy init --all # Protect everything
|
|
133
|
+
npx @solongate/proxy init --api-key sg_live_xxx # With API key
|
|
167
134
|
`;
|
|
168
135
|
console.log(help);
|
|
169
136
|
}
|
|
@@ -373,8 +340,8 @@ process.stdin.on('end', async () => {
|
|
|
373
340
|
process.exit(0);
|
|
374
341
|
});
|
|
375
342
|
`;
|
|
376
|
-
function
|
|
377
|
-
const hooksDir = resolve(".
|
|
343
|
+
function installHooks() {
|
|
344
|
+
const hooksDir = resolve(".solongate", "hooks");
|
|
378
345
|
mkdirSync(hooksDir, { recursive: true });
|
|
379
346
|
const guardPath = join(hooksDir, "guard.mjs");
|
|
380
347
|
writeFileSync(guardPath, GUARD_SCRIPT);
|
|
@@ -382,50 +349,15 @@ function installClaudeCodeHooks(apiKey) {
|
|
|
382
349
|
const auditPath = join(hooksDir, "audit.mjs");
|
|
383
350
|
writeFileSync(auditPath, AUDIT_SCRIPT);
|
|
384
351
|
console.log(` Created ${auditPath}`);
|
|
385
|
-
const settingsPath = resolve(".claude", "settings.json");
|
|
386
|
-
let settings = {};
|
|
387
|
-
if (existsSync(settingsPath)) {
|
|
388
|
-
try {
|
|
389
|
-
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
390
|
-
} catch {
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
settings.hooks = {
|
|
394
|
-
PreToolUse: [
|
|
395
|
-
{
|
|
396
|
-
matcher: ".*",
|
|
397
|
-
hooks: [
|
|
398
|
-
{
|
|
399
|
-
type: "command",
|
|
400
|
-
command: "node .claude/hooks/guard.mjs",
|
|
401
|
-
timeout: 5
|
|
402
|
-
}
|
|
403
|
-
]
|
|
404
|
-
}
|
|
405
|
-
],
|
|
406
|
-
PostToolUse: [
|
|
407
|
-
{
|
|
408
|
-
matcher: ".*",
|
|
409
|
-
hooks: [
|
|
410
|
-
{
|
|
411
|
-
type: "command",
|
|
412
|
-
command: "node .claude/hooks/audit.mjs",
|
|
413
|
-
timeout: 10,
|
|
414
|
-
async: true
|
|
415
|
-
}
|
|
416
|
-
]
|
|
417
|
-
}
|
|
418
|
-
]
|
|
419
|
-
};
|
|
420
|
-
const envObj = settings.env || {};
|
|
421
|
-
envObj.SOLONGATE_API_KEY = apiKey;
|
|
422
|
-
settings.env = envObj;
|
|
423
|
-
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
424
|
-
console.log(` Created ${settingsPath}`);
|
|
425
352
|
console.log("");
|
|
426
|
-
console.log("
|
|
427
|
-
console.log("
|
|
428
|
-
console.log("
|
|
353
|
+
console.log(" Hooks installed in .solongate/hooks/");
|
|
354
|
+
console.log(" guard.mjs \u2192 blocks dangerous calls (pre-execution)");
|
|
355
|
+
console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
|
|
356
|
+
console.log("");
|
|
357
|
+
console.log(" To activate hooks in your MCP client:");
|
|
358
|
+
console.log(" Claude Code \u2192 .claude/settings.json");
|
|
359
|
+
console.log(" Cursor \u2192 .cursor/settings.json");
|
|
360
|
+
console.log(" Or run: node .solongate/hooks/guard.mjs (stdin: JSON)");
|
|
429
361
|
}
|
|
430
362
|
function ensureEnvFile() {
|
|
431
363
|
const envPath = resolve(".env");
|
|
@@ -502,16 +434,6 @@ async function main() {
|
|
|
502
434
|
console.log(` Config: ${configInfo.path}`);
|
|
503
435
|
console.log(` Type: ${configInfo.type === "claude-desktop" ? "Claude Desktop" : "MCP JSON"}`);
|
|
504
436
|
console.log("");
|
|
505
|
-
const backupPath = configInfo.path + ".solongate-backup";
|
|
506
|
-
if (options.restore) {
|
|
507
|
-
if (!existsSync(backupPath)) {
|
|
508
|
-
console.log(" No backup found. Nothing to restore.");
|
|
509
|
-
process.exit(1);
|
|
510
|
-
}
|
|
511
|
-
copyFileSync(backupPath, configInfo.path);
|
|
512
|
-
console.log(" Restored original config from backup.");
|
|
513
|
-
process.exit(0);
|
|
514
|
-
}
|
|
515
437
|
const config = readConfig(configInfo.path);
|
|
516
438
|
const serverNames = Object.keys(config.mcpServers);
|
|
517
439
|
if (serverNames.length === 0) {
|
|
@@ -591,7 +513,7 @@ async function main() {
|
|
|
591
513
|
process.exit(1);
|
|
592
514
|
}
|
|
593
515
|
await sleep(300);
|
|
594
|
-
console.log(` Policy:
|
|
516
|
+
console.log(` Policy: restricted`);
|
|
595
517
|
await sleep(150);
|
|
596
518
|
console.log(` API Key: ${apiKey.slice(0, 12)}...${apiKey.slice(-4)}`);
|
|
597
519
|
await sleep(150);
|
|
@@ -600,23 +522,12 @@ async function main() {
|
|
|
600
522
|
const newConfig = { mcpServers: {} };
|
|
601
523
|
for (const name of serverNames) {
|
|
602
524
|
if (toProtect.includes(name)) {
|
|
603
|
-
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name]
|
|
525
|
+
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name]);
|
|
604
526
|
} else {
|
|
605
527
|
newConfig.mcpServers[name] = config.mcpServers[name];
|
|
606
528
|
}
|
|
607
529
|
}
|
|
608
|
-
if (options.dryRun) {
|
|
609
|
-
console.log(" --- DRY RUN (no changes written) ---");
|
|
610
|
-
console.log("");
|
|
611
|
-
console.log(" New config:");
|
|
612
|
-
console.log(JSON.stringify(newConfig, null, 2));
|
|
613
|
-
process.exit(0);
|
|
614
|
-
}
|
|
615
530
|
await sleep(400);
|
|
616
|
-
if (!configInfo.created && !existsSync(backupPath)) {
|
|
617
|
-
copyFileSync(configInfo.path, backupPath);
|
|
618
|
-
console.log(` Backup: ${backupPath}`);
|
|
619
|
-
}
|
|
620
531
|
if (configInfo.type === "claude-desktop") {
|
|
621
532
|
const original = JSON.parse(readFileSync(configInfo.path, "utf-8"));
|
|
622
533
|
original.mcpServers = newConfig.mcpServers;
|
|
@@ -628,14 +539,14 @@ async function main() {
|
|
|
628
539
|
console.log(" Config updated!");
|
|
629
540
|
console.log("");
|
|
630
541
|
await sleep(500);
|
|
631
|
-
|
|
542
|
+
installHooks();
|
|
632
543
|
console.log("");
|
|
633
544
|
await sleep(400);
|
|
634
545
|
console.log(" \u2500\u2500 Summary \u2500\u2500");
|
|
635
546
|
console.log("");
|
|
636
547
|
for (const name of toProtect) {
|
|
637
548
|
await sleep(200);
|
|
638
|
-
console.log(` \u2713 ${name} \u2014 protected
|
|
549
|
+
console.log(` \u2713 ${name} \u2014 protected`);
|
|
639
550
|
}
|
|
640
551
|
for (const name of alreadyProtected) {
|
|
641
552
|
await sleep(200);
|
|
@@ -650,11 +561,11 @@ async function main() {
|
|
|
650
561
|
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");
|
|
651
562
|
console.log(" \u2502 Setup complete! \u2502");
|
|
652
563
|
console.log(" \u2502 \u2502");
|
|
653
|
-
console.log(" \u2502 MCP
|
|
654
|
-
console.log(" \u2502
|
|
564
|
+
console.log(" \u2502 MCP servers \u2192 Protected via proxy \u2502");
|
|
565
|
+
console.log(" \u2502 AI tools \u2192 Guarded via hooks \u2502");
|
|
566
|
+
console.log(" \u2502 API key \u2192 Set in .env \u2502");
|
|
655
567
|
console.log(" \u2502 \u2502");
|
|
656
568
|
console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
|
|
657
|
-
console.log(" \u2502 To undo: solongate-init --restore \u2502");
|
|
658
569
|
console.log(" \u2502 \u2502");
|
|
659
570
|
console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
|
|
660
571
|
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");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
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": {
|