@solongate/proxy 0.1.23 → 0.1.25

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/create.js CHANGED
@@ -205,13 +205,15 @@ await server.connect(transport);
205
205
  console.log('');
206
206
  console.log('${name} is running (stdio mode)');
207
207
  console.log('');
208
- console.log('This server communicates over stdin/stdout (MCP protocol).');
209
- console.log('It does NOT open a URL or port \u2014 it is used by MCP clients.');
208
+ console.log('MCP servers communicate over stdin/stdout \u2014 not HTTP.');
209
+ console.log('You need an MCP client to connect:');
210
210
  console.log('');
211
- console.log('To connect:');
212
- console.log(' 1. Open this folder in Claude Code, Cursor, or another MCP client');
213
- console.log(' 2. .mcp.json is auto-detected \u2014 your tools are ready to use');
214
- console.log(' 3. Try asking: "Use the hello tool to greet Alice"');
211
+ console.log(' Claude Code Open this folder, .mcp.json is auto-detected');
212
+ console.log(' Claude Desktop Add to Settings > MCP Servers');
213
+ console.log(' Cursor Open this folder, .mcp.json is auto-detected');
214
+ console.log(' Windsurf Open this folder, .mcp.json is auto-detected');
215
+ console.log(' Cline VS Code extension, add server in settings');
216
+ console.log(' Zed Add to settings.json under mcp_servers');
215
217
  console.log('');
216
218
  console.log('Press Ctrl+C to stop.');
217
219
  `
package/dist/index.js CHANGED
@@ -917,13 +917,15 @@ await server.connect(transport);
917
917
  console.log('');
918
918
  console.log('${name} is running (stdio mode)');
919
919
  console.log('');
920
- console.log('This server communicates over stdin/stdout (MCP protocol).');
921
- console.log('It does NOT open a URL or port \u2014 it is used by MCP clients.');
920
+ console.log('MCP servers communicate over stdin/stdout \u2014 not HTTP.');
921
+ console.log('You need an MCP client to connect:');
922
922
  console.log('');
923
- console.log('To connect:');
924
- console.log(' 1. Open this folder in Claude Code, Cursor, or another MCP client');
925
- console.log(' 2. .mcp.json is auto-detected \u2014 your tools are ready to use');
926
- console.log(' 3. Try asking: "Use the hello tool to greet Alice"');
923
+ console.log(' Claude Code Open this folder, .mcp.json is auto-detected');
924
+ console.log(' Claude Desktop Add to Settings > MCP Servers');
925
+ console.log(' Cursor Open this folder, .mcp.json is auto-detected');
926
+ console.log(' Windsurf Open this folder, .mcp.json is auto-detected');
927
+ console.log(' Cline VS Code extension, add server in settings');
928
+ console.log(' Zed Add to settings.json under mcp_servers');
927
929
  console.log('');
928
930
  console.log('Press Ctrl+C to stop.');
929
931
  `
@@ -3082,6 +3084,7 @@ var SolonGate = class {
3082
3084
  });
3083
3085
  if (!options.policySet && !config.policySet && apiKey.startsWith("sg_live_")) {
3084
3086
  this.fetchCloudPolicyOnce();
3087
+ this.startPolicyPolling();
3085
3088
  }
3086
3089
  this.tokenIssuer = config.tokenSecret ? new TokenIssuer({
3087
3090
  secret: config.tokenSecret,
@@ -3151,6 +3154,40 @@ var SolonGate = class {
3151
3154
  }).catch(() => {
3152
3155
  });
3153
3156
  }
3157
+ /**
3158
+ * Poll for policy updates from dashboard every 60 seconds.
3159
+ */
3160
+ startPolicyPolling() {
3161
+ const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
3162
+ let currentVersion = 0;
3163
+ setInterval(async () => {
3164
+ try {
3165
+ const res = await fetch(`${apiUrl}/api/v1/policies/default`, {
3166
+ headers: { "Authorization": `Bearer ${this.apiKey}` },
3167
+ signal: AbortSignal.timeout(1e4)
3168
+ });
3169
+ if (!res.ok) return;
3170
+ const data = await res.json();
3171
+ const version = Number(data._version ?? 0);
3172
+ const rulesCount = Array.isArray(data.rules) ? data.rules.length : 0;
3173
+ if (version !== currentVersion && version > 0) {
3174
+ const policySet = {
3175
+ id: String(data.id ?? "cloud"),
3176
+ name: String(data.name ?? "Cloud Policy"),
3177
+ description: String(data.description ?? ""),
3178
+ version,
3179
+ rules: data.rules ?? [],
3180
+ createdAt: String(data._created_at ?? ""),
3181
+ updatedAt: ""
3182
+ };
3183
+ this.policyEngine.loadPolicySet(policySet);
3184
+ currentVersion = version;
3185
+ console.warn(`[SolonGate] Policy updated from dashboard: ${policySet.name} v${version} (${rulesCount} rules)`);
3186
+ }
3187
+ } catch {
3188
+ }
3189
+ }, 6e4);
3190
+ }
3154
3191
  /**
3155
3192
  * Send audit log to SolonGate Cloud API (fire-and-forget).
3156
3193
  */
@@ -3325,6 +3362,7 @@ var SolonGateProxy = class {
3325
3362
  }
3326
3363
  }
3327
3364
  }
3365
+ this.gate.loadPolicy(this.config.policy);
3328
3366
  log(`Policy: ${this.config.policy.name} (${this.config.policy.rules.length} rules)`);
3329
3367
  const transport = this.config.upstream.transport ?? "stdio";
3330
3368
  if (transport === "stdio") {
@@ -3334,8 +3372,10 @@ var SolonGateProxy = class {
3334
3372
  }
3335
3373
  await this.connectUpstream();
3336
3374
  await this.discoverTools();
3375
+ this.registerToolsToCloud();
3337
3376
  this.createServer();
3338
3377
  await this.serve();
3378
+ this.startPolicyPolling();
3339
3379
  }
3340
3380
  /**
3341
3381
  * Connect to the upstream MCP server.
@@ -3495,6 +3535,65 @@ var SolonGateProxy = class {
3495
3535
  });
3496
3536
  });
3497
3537
  }
3538
+ /**
3539
+ * Register discovered tools to the SolonGate Cloud API.
3540
+ * This makes tools visible on the Dashboard (/tools page).
3541
+ */
3542
+ registerToolsToCloud() {
3543
+ if (!this.config.apiKey || this.config.apiKey.startsWith("sg_test_")) return;
3544
+ const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
3545
+ for (const tool of this.upstreamTools) {
3546
+ fetch(`${apiUrl}/api/v1/tools`, {
3547
+ method: "POST",
3548
+ headers: {
3549
+ "Authorization": `Bearer ${this.config.apiKey}`,
3550
+ "Content-Type": "application/json"
3551
+ },
3552
+ body: JSON.stringify({
3553
+ name: tool.name,
3554
+ description: tool.description ?? "",
3555
+ input_schema: tool.inputSchema,
3556
+ permissions: this.guessPermissions(tool.name),
3557
+ enabled: true
3558
+ })
3559
+ }).catch(() => {
3560
+ });
3561
+ }
3562
+ log(`Registered ${this.upstreamTools.length} tools to dashboard`);
3563
+ }
3564
+ /**
3565
+ * Guess tool permissions from tool name.
3566
+ */
3567
+ guessPermissions(toolName) {
3568
+ const name = toolName.toLowerCase();
3569
+ if (name.includes("exec") || name.includes("shell") || name.includes("run") || name.includes("eval")) {
3570
+ return ["EXECUTE"];
3571
+ }
3572
+ if (name.includes("write") || name.includes("create") || name.includes("delete") || name.includes("update") || name.includes("set")) {
3573
+ return ["WRITE"];
3574
+ }
3575
+ return ["READ"];
3576
+ }
3577
+ /**
3578
+ * Poll for policy updates from dashboard every 60 seconds.
3579
+ * When user changes policy in dashboard, proxy picks it up automatically.
3580
+ */
3581
+ startPolicyPolling() {
3582
+ if (!this.config.apiKey || this.config.apiKey.startsWith("sg_test_")) return;
3583
+ const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
3584
+ const POLL_INTERVAL = 6e4;
3585
+ setInterval(async () => {
3586
+ try {
3587
+ const newPolicy = await fetchCloudPolicy(this.config.apiKey, apiUrl);
3588
+ if (newPolicy.version !== this.config.policy.version || newPolicy.rules.length !== this.config.policy.rules.length) {
3589
+ this.config.policy = newPolicy;
3590
+ this.gate.loadPolicy(newPolicy);
3591
+ log(`Policy updated from dashboard: ${newPolicy.name} v${newPolicy.version} (${newPolicy.rules.length} rules)`);
3592
+ }
3593
+ } catch {
3594
+ }
3595
+ }, POLL_INTERVAL);
3596
+ }
3498
3597
  /**
3499
3598
  * Start serving downstream.
3500
3599
  * If --port is set, serves via StreamableHTTP on that port.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "MCP security proxy \u00e2\u20ac\u201d protect any MCP server with policies, input validation, rate limiting, and audit logging. Zero code changes required.",
5
5
  "type": "module",
6
6
  "bin": {