@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/commands/index.js +0 -28
- package/dist/index.js +140 -821
- package/package.json +1 -1
- package/dist/create.d.ts +0 -13
- package/dist/create.js +0 -329
- package/dist/inject.d.ts +0 -19
- package/dist/inject.js +0 -375
package/dist/index.js
CHANGED
|
@@ -3398,12 +3398,12 @@ ${ctx.indent}`;
|
|
|
3398
3398
|
for (const {
|
|
3399
3399
|
format,
|
|
3400
3400
|
test,
|
|
3401
|
-
resolve:
|
|
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 =
|
|
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
|
|
6613
|
+
const log4 = openSync(LOG_FILE, "a");
|
|
6626
6614
|
const p = spawn("npm", ["install", "-g", `${PKG}@${version}`], {
|
|
6627
|
-
stdio: ["ignore",
|
|
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((
|
|
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
|
-
|
|
6644
|
+
resolve7(!err2);
|
|
6657
6645
|
}
|
|
6658
6646
|
);
|
|
6659
6647
|
} catch {
|
|
6660
|
-
|
|
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
|
|
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",
|
|
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 [
|
|
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
|
-
|
|
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
|
|
13239
|
-
import { resolve as
|
|
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 =
|
|
13243
|
-
if (!
|
|
12574
|
+
const envPath = resolve6(".env");
|
|
12575
|
+
if (!existsSync7(envPath)) return;
|
|
13244
12576
|
try {
|
|
13245
|
-
const content =
|
|
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
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
13314
|
-
|
|
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
|
-
|
|
13321
|
-
|
|
13322
|
-
|
|
12652
|
+
log3(red2(`Policy not found: ${policyId}`));
|
|
12653
|
+
log3("");
|
|
12654
|
+
log3("Available policies:");
|
|
13323
12655
|
for (const p of policies) {
|
|
13324
|
-
|
|
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
|
-
|
|
13333
|
-
|
|
13334
|
-
|
|
13335
|
-
|
|
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
|
-
|
|
13345
|
-
|
|
13346
|
-
|
|
13347
|
-
|
|
13348
|
-
|
|
13349
|
-
|
|
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
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
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
|
-
|
|
12691
|
+
log3(` ${dim2("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
|
|
13360
12692
|
}
|
|
13361
|
-
|
|
12693
|
+
log3("");
|
|
13362
12694
|
}
|
|
13363
12695
|
function printPolicyDetail(policy) {
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
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
|
-
|
|
13370
|
-
|
|
12701
|
+
log3(yellow2(" No rules defined."));
|
|
12702
|
+
log3("");
|
|
13371
12703
|
return;
|
|
13372
12704
|
}
|
|
13373
|
-
|
|
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
|
-
|
|
13377
|
-
|
|
12708
|
+
log3("");
|
|
12709
|
+
log3(` ${effectColor(rule.effect.padEnd(5))} ${bold2(rule.toolPattern)} ${dim2(`P:${rule.priority}`)}`);
|
|
13378
12710
|
if (rule.description) {
|
|
13379
|
-
|
|
12711
|
+
log3(` ${dim2(rule.description)}`);
|
|
13380
12712
|
}
|
|
13381
|
-
|
|
12713
|
+
log3(` ${dim2(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
|
|
13382
12714
|
if (rule.pathConstraints) {
|
|
13383
12715
|
const pc = rule.pathConstraints;
|
|
13384
|
-
if (pc.rootDirectory)
|
|
13385
|
-
if (pc.allowed?.length)
|
|
13386
|
-
if (pc.denied?.length)
|
|
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)
|
|
13391
|
-
if (cc.denied?.length)
|
|
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)
|
|
13396
|
-
if (fc.denied?.length)
|
|
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)
|
|
13401
|
-
if (uc.denied?.length)
|
|
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
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
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
|
-
|
|
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
|
-
|
|
12749
|
+
log3(dim2(`Auto-selecting only policy: ${policyId}`));
|
|
13418
12750
|
} else {
|
|
13419
|
-
|
|
13420
|
-
|
|
12751
|
+
log3(yellow2(`Found ${policies.length} policies:`));
|
|
12752
|
+
log3("");
|
|
13421
12753
|
for (const p of policies) {
|
|
13422
|
-
|
|
12754
|
+
log3(` ${cyan2(p.id)} ${p.name} ${dim2(`v${p.version ?? "?"}`)}`);
|
|
13423
12755
|
}
|
|
13424
|
-
|
|
13425
|
-
|
|
12756
|
+
log3("");
|
|
12757
|
+
log3("Use --policy-id <ID> to specify which one to pull.");
|
|
13426
12758
|
process.exit(1);
|
|
13427
12759
|
}
|
|
13428
12760
|
}
|
|
13429
|
-
|
|
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
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
|
|
13441
|
-
|
|
13442
|
-
|
|
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 (!
|
|
13446
|
-
|
|
12777
|
+
if (!existsSync7(file)) {
|
|
12778
|
+
log3(red2(`ERROR: File not found: ${file}`));
|
|
13447
12779
|
process.exit(1);
|
|
13448
12780
|
}
|
|
13449
12781
|
if (!policyId) {
|
|
13450
|
-
|
|
13451
|
-
|
|
13452
|
-
|
|
13453
|
-
|
|
13454
|
-
|
|
13455
|
-
|
|
13456
|
-
|
|
13457
|
-
|
|
13458
|
-
|
|
13459
|
-
|
|
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 =
|
|
12794
|
+
const content = readFileSync12(file, "utf-8");
|
|
13463
12795
|
let policy;
|
|
13464
12796
|
try {
|
|
13465
12797
|
policy = JSON.parse(content);
|
|
13466
12798
|
} catch {
|
|
13467
|
-
|
|
12799
|
+
log3(red2(`ERROR: Invalid JSON in ${file}`));
|
|
13468
12800
|
process.exit(1);
|
|
13469
12801
|
}
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
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
|
-
|
|
12827
|
+
log3(red2(`ERROR: Push failed (${res.status}): ${body}`));
|
|
13496
12828
|
process.exit(1);
|
|
13497
12829
|
}
|
|
13498
12830
|
const data = await res.json();
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
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
|
|
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
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
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
|
-
|
|
12863
|
+
log3(red2(`ERROR: ${err2 instanceof Error ? err2.message : String(err2)}`));
|
|
13532
12864
|
process.exit(1);
|
|
13533
12865
|
}
|
|
13534
12866
|
}
|
|
13535
|
-
var
|
|
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
|
-
|
|
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
|
-
|
|
12882
|
+
main();
|
|
13551
12883
|
}
|
|
13552
12884
|
});
|
|
13553
12885
|
|
|
13554
12886
|
// src/index.ts
|
|
13555
12887
|
init_config();
|
|
13556
|
-
import { readFileSync as
|
|
12888
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
13557
12889
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
13558
|
-
import { dirname as dirname4, join as
|
|
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((
|
|
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
|
-
|
|
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(["
|
|
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 =
|
|
16601
|
-
return JSON.parse(
|
|
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
|
|
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
|
|
16019
|
+
async function main2() {
|
|
16691
16020
|
const subcommand = process.argv[2];
|
|
16692
16021
|
if (subcommand === "--help" || subcommand === "-h" || subcommand === "help") {
|
|
16693
|
-
|
|
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
|
-
|
|
16098
|
+
main2();
|