@solongate/proxy 0.5.4 → 0.5.6
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 +32 -64
- package/dist/init.js +28 -60
- 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) {
|
|
@@ -610,10 +610,7 @@ 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]) {
|
|
@@ -629,25 +626,12 @@ function parseInitArgs(argv) {
|
|
|
629
626
|
case "--all":
|
|
630
627
|
options.all = true;
|
|
631
628
|
break;
|
|
632
|
-
case "--dry-run":
|
|
633
|
-
options.dryRun = true;
|
|
634
|
-
break;
|
|
635
|
-
case "--restore":
|
|
636
|
-
options.restore = true;
|
|
637
|
-
break;
|
|
638
629
|
case "--help":
|
|
639
630
|
case "-h":
|
|
640
631
|
printHelp();
|
|
641
632
|
process.exit(0);
|
|
642
633
|
}
|
|
643
634
|
}
|
|
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
635
|
return options;
|
|
652
636
|
}
|
|
653
637
|
function printHelp() {
|
|
@@ -655,30 +639,19 @@ function printHelp() {
|
|
|
655
639
|
SolonGate Init \u2014 Protect your MCP servers in seconds
|
|
656
640
|
|
|
657
641
|
USAGE
|
|
658
|
-
solongate
|
|
642
|
+
npx @solongate/proxy init --all
|
|
659
643
|
|
|
660
644
|
OPTIONS
|
|
661
645
|
--config <path> Path to MCP config file (default: auto-detect)
|
|
662
|
-
--policy <
|
|
663
|
-
|
|
646
|
+
--policy <file> Custom policy JSON file (default: restricted)
|
|
647
|
+
Auto-detects policy.json in current directory
|
|
664
648
|
--api-key <key> SolonGate API key (sg_live_... or sg_test_...)
|
|
665
649
|
--all Protect all servers without prompting
|
|
666
|
-
--dry-run Preview changes without writing
|
|
667
|
-
--restore Restore original config from backup
|
|
668
650
|
-h, --help Show this help message
|
|
669
651
|
|
|
670
652
|
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
|
|
653
|
+
npx @solongate/proxy init --all # Protect everything
|
|
654
|
+
npx @solongate/proxy init --all --policy policy.json # With custom policy
|
|
682
655
|
`;
|
|
683
656
|
console.log(help);
|
|
684
657
|
}
|
|
@@ -776,16 +749,6 @@ async function main() {
|
|
|
776
749
|
console.log(` Config: ${configInfo.path}`);
|
|
777
750
|
console.log(` Type: ${configInfo.type === "claude-desktop" ? "Claude Desktop" : "MCP JSON"}`);
|
|
778
751
|
console.log("");
|
|
779
|
-
const backupPath = configInfo.path + ".solongate-backup";
|
|
780
|
-
if (options.restore) {
|
|
781
|
-
if (!existsSync3(backupPath)) {
|
|
782
|
-
console.log(" No backup found. Nothing to restore.");
|
|
783
|
-
process.exit(1);
|
|
784
|
-
}
|
|
785
|
-
copyFileSync(backupPath, configInfo.path);
|
|
786
|
-
console.log(" Restored original config from backup.");
|
|
787
|
-
process.exit(0);
|
|
788
|
-
}
|
|
789
752
|
const config = readConfig(configInfo.path);
|
|
790
753
|
const serverNames = Object.keys(config.mcpServers);
|
|
791
754
|
if (serverNames.length === 0) {
|
|
@@ -864,8 +827,26 @@ async function main() {
|
|
|
864
827
|
console.log(" Invalid API key format. Must start with sg_live_ or sg_test_");
|
|
865
828
|
process.exit(1);
|
|
866
829
|
}
|
|
830
|
+
let policyValue = "restricted";
|
|
831
|
+
if (options.policy) {
|
|
832
|
+
const policyPath = resolve2(options.policy);
|
|
833
|
+
if (existsSync3(policyPath)) {
|
|
834
|
+
policyValue = `./${options.policy}`;
|
|
835
|
+
console.log(` Policy: ${policyPath}`);
|
|
836
|
+
} else {
|
|
837
|
+
console.log(` Policy file not found: ${options.policy}`);
|
|
838
|
+
process.exit(1);
|
|
839
|
+
}
|
|
840
|
+
} else {
|
|
841
|
+
const defaultPolicy = resolve2("policy.json");
|
|
842
|
+
if (existsSync3(defaultPolicy)) {
|
|
843
|
+
policyValue = "./policy.json";
|
|
844
|
+
console.log(` Policy: ${defaultPolicy} (auto-detected)`);
|
|
845
|
+
} else {
|
|
846
|
+
console.log(` Policy: restricted (default)`);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
867
849
|
await sleep(300);
|
|
868
|
-
console.log(` Policy: ${options.policy}`);
|
|
869
850
|
await sleep(150);
|
|
870
851
|
console.log(` API Key: ${apiKey.slice(0, 12)}...${apiKey.slice(-4)}`);
|
|
871
852
|
await sleep(150);
|
|
@@ -874,23 +855,12 @@ async function main() {
|
|
|
874
855
|
const newConfig = { mcpServers: {} };
|
|
875
856
|
for (const name of serverNames) {
|
|
876
857
|
if (toProtect.includes(name)) {
|
|
877
|
-
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name],
|
|
858
|
+
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name], policyValue);
|
|
878
859
|
} else {
|
|
879
860
|
newConfig.mcpServers[name] = config.mcpServers[name];
|
|
880
861
|
}
|
|
881
862
|
}
|
|
882
|
-
if (options.dryRun) {
|
|
883
|
-
console.log(" --- DRY RUN (no changes written) ---");
|
|
884
|
-
console.log("");
|
|
885
|
-
console.log(" New config:");
|
|
886
|
-
console.log(JSON.stringify(newConfig, null, 2));
|
|
887
|
-
process.exit(0);
|
|
888
|
-
}
|
|
889
863
|
await sleep(400);
|
|
890
|
-
if (!configInfo.created && !existsSync3(backupPath)) {
|
|
891
|
-
copyFileSync(configInfo.path, backupPath);
|
|
892
|
-
console.log(` Backup: ${backupPath}`);
|
|
893
|
-
}
|
|
894
864
|
if (configInfo.type === "claude-desktop") {
|
|
895
865
|
const original = JSON.parse(readFileSync3(configInfo.path, "utf-8"));
|
|
896
866
|
original.mcpServers = newConfig.mcpServers;
|
|
@@ -909,7 +879,7 @@ async function main() {
|
|
|
909
879
|
console.log("");
|
|
910
880
|
for (const name of toProtect) {
|
|
911
881
|
await sleep(200);
|
|
912
|
-
console.log(` \u2713 ${name} \u2014 protected
|
|
882
|
+
console.log(` \u2713 ${name} \u2014 protected`);
|
|
913
883
|
}
|
|
914
884
|
for (const name of alreadyProtected) {
|
|
915
885
|
await sleep(200);
|
|
@@ -929,17 +899,15 @@ async function main() {
|
|
|
929
899
|
console.log(" \u2502 API key \u2192 Set in .env \u2502");
|
|
930
900
|
console.log(" \u2502 \u2502");
|
|
931
901
|
console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
|
|
932
|
-
console.log(" \u2502 To undo: npx @solongate/proxy init --restore \u2502");
|
|
933
902
|
console.log(" \u2502 \u2502");
|
|
934
903
|
console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
|
|
935
904
|
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");
|
|
936
905
|
console.log("");
|
|
937
906
|
}
|
|
938
|
-
var
|
|
907
|
+
var SEARCH_PATHS, CLAUDE_DESKTOP_PATHS, sleep, GUARD_SCRIPT, AUDIT_SCRIPT;
|
|
939
908
|
var init_init = __esm({
|
|
940
909
|
"src/init.ts"() {
|
|
941
910
|
"use strict";
|
|
942
|
-
POLICY_PRESETS = ["restricted", "read-only", "permissive", "deny-all"];
|
|
943
911
|
SEARCH_PATHS = [
|
|
944
912
|
".mcp.json",
|
|
945
913
|
"mcp.json",
|
|
@@ -1162,7 +1130,7 @@ process.stdin.on('end', async () => {
|
|
|
1162
1130
|
|
|
1163
1131
|
// src/inject.ts
|
|
1164
1132
|
var inject_exports = {};
|
|
1165
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, copyFileSync
|
|
1133
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, copyFileSync } from "fs";
|
|
1166
1134
|
import { resolve as resolve3 } from "path";
|
|
1167
1135
|
import { execSync } from "child_process";
|
|
1168
1136
|
function parseInjectArgs(argv) {
|
|
@@ -1454,7 +1422,7 @@ async function main2() {
|
|
|
1454
1422
|
log3(" No backup found. Nothing to restore.");
|
|
1455
1423
|
process.exit(1);
|
|
1456
1424
|
}
|
|
1457
|
-
|
|
1425
|
+
copyFileSync(backupPath, entryFile);
|
|
1458
1426
|
log3(` Restored original file from backup.`);
|
|
1459
1427
|
log3(` Backup: ${backupPath}`);
|
|
1460
1428
|
process.exit(0);
|
|
@@ -1487,7 +1455,7 @@ async function main2() {
|
|
|
1487
1455
|
process.exit(0);
|
|
1488
1456
|
}
|
|
1489
1457
|
if (!existsSync4(backupPath)) {
|
|
1490
|
-
|
|
1458
|
+
copyFileSync(entryFile, backupPath);
|
|
1491
1459
|
log3("");
|
|
1492
1460
|
log3(` Backup: ${backupPath}`);
|
|
1493
1461
|
}
|
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",
|
|
@@ -95,10 +94,7 @@ 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]) {
|
|
@@ -114,25 +110,12 @@ function parseInitArgs(argv) {
|
|
|
114
110
|
case "--all":
|
|
115
111
|
options.all = true;
|
|
116
112
|
break;
|
|
117
|
-
case "--dry-run":
|
|
118
|
-
options.dryRun = true;
|
|
119
|
-
break;
|
|
120
|
-
case "--restore":
|
|
121
|
-
options.restore = true;
|
|
122
|
-
break;
|
|
123
113
|
case "--help":
|
|
124
114
|
case "-h":
|
|
125
115
|
printHelp();
|
|
126
116
|
process.exit(0);
|
|
127
117
|
}
|
|
128
118
|
}
|
|
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
119
|
return options;
|
|
137
120
|
}
|
|
138
121
|
function printHelp() {
|
|
@@ -140,30 +123,19 @@ function printHelp() {
|
|
|
140
123
|
SolonGate Init \u2014 Protect your MCP servers in seconds
|
|
141
124
|
|
|
142
125
|
USAGE
|
|
143
|
-
solongate
|
|
126
|
+
npx @solongate/proxy init --all
|
|
144
127
|
|
|
145
128
|
OPTIONS
|
|
146
129
|
--config <path> Path to MCP config file (default: auto-detect)
|
|
147
|
-
--policy <
|
|
148
|
-
|
|
130
|
+
--policy <file> Custom policy JSON file (default: restricted)
|
|
131
|
+
Auto-detects policy.json in current directory
|
|
149
132
|
--api-key <key> SolonGate API key (sg_live_... or sg_test_...)
|
|
150
133
|
--all Protect all servers without prompting
|
|
151
|
-
--dry-run Preview changes without writing
|
|
152
|
-
--restore Restore original config from backup
|
|
153
134
|
-h, --help Show this help message
|
|
154
135
|
|
|
155
136
|
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
|
|
137
|
+
npx @solongate/proxy init --all # Protect everything
|
|
138
|
+
npx @solongate/proxy init --all --policy policy.json # With custom policy
|
|
167
139
|
`;
|
|
168
140
|
console.log(help);
|
|
169
141
|
}
|
|
@@ -467,16 +439,6 @@ async function main() {
|
|
|
467
439
|
console.log(` Config: ${configInfo.path}`);
|
|
468
440
|
console.log(` Type: ${configInfo.type === "claude-desktop" ? "Claude Desktop" : "MCP JSON"}`);
|
|
469
441
|
console.log("");
|
|
470
|
-
const backupPath = configInfo.path + ".solongate-backup";
|
|
471
|
-
if (options.restore) {
|
|
472
|
-
if (!existsSync(backupPath)) {
|
|
473
|
-
console.log(" No backup found. Nothing to restore.");
|
|
474
|
-
process.exit(1);
|
|
475
|
-
}
|
|
476
|
-
copyFileSync(backupPath, configInfo.path);
|
|
477
|
-
console.log(" Restored original config from backup.");
|
|
478
|
-
process.exit(0);
|
|
479
|
-
}
|
|
480
442
|
const config = readConfig(configInfo.path);
|
|
481
443
|
const serverNames = Object.keys(config.mcpServers);
|
|
482
444
|
if (serverNames.length === 0) {
|
|
@@ -555,8 +517,26 @@ async function main() {
|
|
|
555
517
|
console.log(" Invalid API key format. Must start with sg_live_ or sg_test_");
|
|
556
518
|
process.exit(1);
|
|
557
519
|
}
|
|
520
|
+
let policyValue = "restricted";
|
|
521
|
+
if (options.policy) {
|
|
522
|
+
const policyPath = resolve(options.policy);
|
|
523
|
+
if (existsSync(policyPath)) {
|
|
524
|
+
policyValue = `./${options.policy}`;
|
|
525
|
+
console.log(` Policy: ${policyPath}`);
|
|
526
|
+
} else {
|
|
527
|
+
console.log(` Policy file not found: ${options.policy}`);
|
|
528
|
+
process.exit(1);
|
|
529
|
+
}
|
|
530
|
+
} else {
|
|
531
|
+
const defaultPolicy = resolve("policy.json");
|
|
532
|
+
if (existsSync(defaultPolicy)) {
|
|
533
|
+
policyValue = "./policy.json";
|
|
534
|
+
console.log(` Policy: ${defaultPolicy} (auto-detected)`);
|
|
535
|
+
} else {
|
|
536
|
+
console.log(` Policy: restricted (default)`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
558
539
|
await sleep(300);
|
|
559
|
-
console.log(` Policy: ${options.policy}`);
|
|
560
540
|
await sleep(150);
|
|
561
541
|
console.log(` API Key: ${apiKey.slice(0, 12)}...${apiKey.slice(-4)}`);
|
|
562
542
|
await sleep(150);
|
|
@@ -565,23 +545,12 @@ async function main() {
|
|
|
565
545
|
const newConfig = { mcpServers: {} };
|
|
566
546
|
for (const name of serverNames) {
|
|
567
547
|
if (toProtect.includes(name)) {
|
|
568
|
-
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name],
|
|
548
|
+
newConfig.mcpServers[name] = wrapServer(config.mcpServers[name], policyValue);
|
|
569
549
|
} else {
|
|
570
550
|
newConfig.mcpServers[name] = config.mcpServers[name];
|
|
571
551
|
}
|
|
572
552
|
}
|
|
573
|
-
if (options.dryRun) {
|
|
574
|
-
console.log(" --- DRY RUN (no changes written) ---");
|
|
575
|
-
console.log("");
|
|
576
|
-
console.log(" New config:");
|
|
577
|
-
console.log(JSON.stringify(newConfig, null, 2));
|
|
578
|
-
process.exit(0);
|
|
579
|
-
}
|
|
580
553
|
await sleep(400);
|
|
581
|
-
if (!configInfo.created && !existsSync(backupPath)) {
|
|
582
|
-
copyFileSync(configInfo.path, backupPath);
|
|
583
|
-
console.log(` Backup: ${backupPath}`);
|
|
584
|
-
}
|
|
585
554
|
if (configInfo.type === "claude-desktop") {
|
|
586
555
|
const original = JSON.parse(readFileSync(configInfo.path, "utf-8"));
|
|
587
556
|
original.mcpServers = newConfig.mcpServers;
|
|
@@ -600,7 +569,7 @@ async function main() {
|
|
|
600
569
|
console.log("");
|
|
601
570
|
for (const name of toProtect) {
|
|
602
571
|
await sleep(200);
|
|
603
|
-
console.log(` \u2713 ${name} \u2014 protected
|
|
572
|
+
console.log(` \u2713 ${name} \u2014 protected`);
|
|
604
573
|
}
|
|
605
574
|
for (const name of alreadyProtected) {
|
|
606
575
|
await sleep(200);
|
|
@@ -620,7 +589,6 @@ async function main() {
|
|
|
620
589
|
console.log(" \u2502 API key \u2192 Set in .env \u2502");
|
|
621
590
|
console.log(" \u2502 \u2502");
|
|
622
591
|
console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
|
|
623
|
-
console.log(" \u2502 To undo: npx @solongate/proxy init --restore \u2502");
|
|
624
592
|
console.log(" \u2502 \u2502");
|
|
625
593
|
console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
|
|
626
594
|
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.6",
|
|
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": {
|