@solongate/proxy 0.1.21 → 0.1.22

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
@@ -181,13 +181,14 @@ console.log = (...args: unknown[]) => {
181
181
  process.stderr.write(args.map(String).join(' ') + '\\n');
182
182
  };
183
183
 
184
- import { SecureMcpServer, createPermissivePolicySet } from '@solongate/sdk';
184
+ import { SecureMcpServer } from '@solongate/sdk';
185
185
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
186
186
  import { z } from 'zod';
187
187
 
188
+ // Policy is managed from the SolonGate Dashboard (https://solongate.com)
189
+ // No local policySet needed \u2014 it's fetched from the cloud via your API key.
188
190
  const server = new SecureMcpServer(
189
191
  { name: '${name}', version: '0.1.0' },
190
- { policySet: createPermissivePolicySet() },
191
192
  );
192
193
 
193
194
  server.tool(
@@ -213,7 +214,7 @@ console.log('${name} is running');
213
214
  command: "node",
214
215
  args: ["dist/index.js"],
215
216
  env: {
216
- SOLONGATE_API_KEY: "sg_test_YOUR_KEY_HERE"
217
+ SOLONGATE_API_KEY: "sg_live_YOUR_KEY_HERE"
217
218
  }
218
219
  }
219
220
  }
@@ -293,11 +294,16 @@ async function main() {
293
294
  bEmpty();
294
295
  log(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
295
296
  bEmpty();
296
- bLine(`${c.yellow}Use with Claude Code:${c.reset}`);
297
+ bLine(`${c.yellow}Use with Claude Code / Cursor / MCP client:${c.reset}`);
297
298
  bEmpty();
298
- bLine(` ${c.dim}1.${c.reset} Open the project folder in Claude Code`);
299
- bLine(` ${c.dim}2.${c.reset} .mcp.json is auto-detected on startup`);
300
- bLine(` ${c.dim}3.${c.reset} Restart Claude Code if already open`);
299
+ bLine(` ${c.dim}1.${c.reset} Replace ${c.blue3}sg_live_YOUR_KEY_HERE${c.reset} in .mcp.json`);
300
+ bLine(` ${c.dim}2.${c.reset} Open this folder in your MCP client`);
301
+ bLine(` ${c.dim}3.${c.reset} .mcp.json is auto-detected on startup`);
302
+ bEmpty();
303
+ bLine(`${c.yellow}Direct test (without MCP client):${c.reset}`);
304
+ bEmpty();
305
+ bLine(` ${c.dim}1.${c.reset} Replace ${c.blue3}sg_live_YOUR_KEY_HERE${c.reset} in .env`);
306
+ bLine(` ${c.dim}2.${c.reset} ${c.cyan}$${c.reset} npm run build && npm start`);
301
307
  bEmpty();
302
308
  log(` ${c.dim}\u2570${hr}\u256F${c.reset}`);
303
309
  log("");
package/dist/index.js CHANGED
@@ -893,13 +893,14 @@ console.log = (...args: unknown[]) => {
893
893
  process.stderr.write(args.map(String).join(' ') + '\\n');
894
894
  };
895
895
 
896
- import { SecureMcpServer, createPermissivePolicySet } from '@solongate/sdk';
896
+ import { SecureMcpServer } from '@solongate/sdk';
897
897
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
898
898
  import { z } from 'zod';
899
899
 
900
+ // Policy is managed from the SolonGate Dashboard (https://solongate.com)
901
+ // No local policySet needed \u2014 it's fetched from the cloud via your API key.
900
902
  const server = new SecureMcpServer(
901
903
  { name: '${name}', version: '0.1.0' },
902
- { policySet: createPermissivePolicySet() },
903
904
  );
904
905
 
905
906
  server.tool(
@@ -925,7 +926,7 @@ console.log('${name} is running');
925
926
  command: "node",
926
927
  args: ["dist/index.js"],
927
928
  env: {
928
- SOLONGATE_API_KEY: "sg_test_YOUR_KEY_HERE"
929
+ SOLONGATE_API_KEY: "sg_live_YOUR_KEY_HERE"
929
930
  }
930
931
  }
931
932
  }
@@ -1005,11 +1006,16 @@ async function main3() {
1005
1006
  bEmpty();
1006
1007
  log3(` ${c2.dim}\u251C${hr}\u2524${c2.reset}`);
1007
1008
  bEmpty();
1008
- bLine(`${c2.yellow}Use with Claude Code:${c2.reset}`);
1009
+ bLine(`${c2.yellow}Use with Claude Code / Cursor / MCP client:${c2.reset}`);
1009
1010
  bEmpty();
1010
- bLine(` ${c2.dim}1.${c2.reset} Open the project folder in Claude Code`);
1011
- bLine(` ${c2.dim}2.${c2.reset} .mcp.json is auto-detected on startup`);
1012
- bLine(` ${c2.dim}3.${c2.reset} Restart Claude Code if already open`);
1011
+ bLine(` ${c2.dim}1.${c2.reset} Replace ${c2.blue3}sg_live_YOUR_KEY_HERE${c2.reset} in .mcp.json`);
1012
+ bLine(` ${c2.dim}2.${c2.reset} Open this folder in your MCP client`);
1013
+ bLine(` ${c2.dim}3.${c2.reset} .mcp.json is auto-detected on startup`);
1014
+ bEmpty();
1015
+ bLine(`${c2.yellow}Direct test (without MCP client):${c2.reset}`);
1016
+ bEmpty();
1017
+ bLine(` ${c2.dim}1.${c2.reset} Replace ${c2.blue3}sg_live_YOUR_KEY_HERE${c2.reset} in .env`);
1018
+ bLine(` ${c2.dim}2.${c2.reset} ${c2.cyan}$${c2.reset} npm run build && npm start`);
1013
1019
  bEmpty();
1014
1020
  log3(` ${c2.dim}\u2570${hr}\u256F${c2.reset}`);
1015
1021
  log3("");
@@ -3063,6 +3069,9 @@ var SolonGate = class {
3063
3069
  timeoutMs: config.evaluationTimeoutMs,
3064
3070
  store
3065
3071
  });
3072
+ if (!options.policySet && !config.policySet && apiKey.startsWith("sg_live_")) {
3073
+ this.fetchCloudPolicyOnce();
3074
+ }
3066
3075
  this.tokenIssuer = config.tokenSecret ? new TokenIssuer({
3067
3076
  secret: config.tokenSecret,
3068
3077
  ttlSeconds: config.tokenTtlSeconds,
@@ -3106,6 +3115,47 @@ var SolonGate = class {
3106
3115
  );
3107
3116
  }
3108
3117
  }
3118
+ /**
3119
+ * Fetch policy from SolonGate Cloud API (fire once, non-blocking).
3120
+ */
3121
+ fetchCloudPolicyOnce() {
3122
+ const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
3123
+ fetch(`${apiUrl}/api/v1/policies/default`, {
3124
+ headers: { "Authorization": `Bearer ${this.apiKey}` },
3125
+ signal: AbortSignal.timeout(1e4)
3126
+ }).then(async (res) => {
3127
+ if (!res.ok) return;
3128
+ const data = await res.json();
3129
+ const policySet = {
3130
+ id: String(data.id ?? "cloud"),
3131
+ name: String(data.name ?? "Cloud Policy"),
3132
+ description: String(data.description ?? ""),
3133
+ version: Number(data._version ?? 1),
3134
+ rules: data.rules ?? [],
3135
+ createdAt: String(data._created_at ?? ""),
3136
+ updatedAt: ""
3137
+ };
3138
+ this.policyEngine.loadPolicySet(policySet);
3139
+ console.warn(`[SolonGate] Loaded cloud policy: ${policySet.name} (${policySet.rules.length} rules)`);
3140
+ }).catch(() => {
3141
+ });
3142
+ }
3143
+ /**
3144
+ * Send audit log to SolonGate Cloud API (fire-and-forget).
3145
+ */
3146
+ sendAuditLog(entry) {
3147
+ if (!this.apiKey.startsWith("sg_live_")) return;
3148
+ const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
3149
+ fetch(`${apiUrl}/api/v1/audit-logs`, {
3150
+ method: "POST",
3151
+ headers: {
3152
+ "Authorization": `Bearer ${this.apiKey}`,
3153
+ "Content-Type": "application/json"
3154
+ },
3155
+ body: JSON.stringify(entry)
3156
+ }).catch(() => {
3157
+ });
3158
+ }
3109
3159
  /**
3110
3160
  * Intercept and evaluate a tool call against the full security pipeline.
3111
3161
  * If denied at any stage, returns an error result without calling upstream.
@@ -3113,11 +3163,32 @@ var SolonGate = class {
3113
3163
  */
3114
3164
  async executeToolCall(params, upstreamCall) {
3115
3165
  await this.validateLicense();
3166
+ const startTime = performance.now();
3116
3167
  return interceptToolCall(params, upstreamCall, {
3117
3168
  policyEngine: this.policyEngine,
3118
3169
  validateSchemas: this.config.validateSchemas,
3119
3170
  verboseErrors: this.config.verboseErrors,
3120
- onDecision: (result) => this.logger.logDecision(result),
3171
+ onDecision: (result) => {
3172
+ this.logger.logDecision(result);
3173
+ if (result.status === "ALLOWED" || result.status === "DENIED") {
3174
+ this.sendAuditLog({
3175
+ tool: params.name,
3176
+ arguments: params.arguments ?? {},
3177
+ decision: result.decision.effect === "ALLOW" ? "ALLOW" : "DENY",
3178
+ reason: result.decision.reason,
3179
+ matchedRule: result.decision.matchedRule?.id,
3180
+ evaluationTimeMs: performance.now() - startTime
3181
+ });
3182
+ } else if (result.status === "ERROR") {
3183
+ this.sendAuditLog({
3184
+ tool: params.name,
3185
+ arguments: params.arguments ?? {},
3186
+ decision: "DENY",
3187
+ reason: result.error.message,
3188
+ evaluationTimeMs: performance.now() - startTime
3189
+ });
3190
+ }
3191
+ },
3121
3192
  tokenIssuer: this.tokenIssuer ?? void 0,
3122
3193
  serverVerifier: this.serverVerifier ?? void 0,
3123
3194
  rateLimiter: this.rateLimiter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
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": {