@solongate/sdk 0.1.1

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.
@@ -0,0 +1,511 @@
1
+ import * as _solongate_policy_engine from '@solongate/policy-engine';
2
+ import { PolicyEngine } from '@solongate/policy-engine';
3
+ export { PolicyDiff, PolicyEngine, PolicyStore, PolicyVersion, createDefaultDenyPolicySet, createReadOnlyPolicySet } from '@solongate/policy-engine';
4
+ import { PolicySet, InputGuardConfig, TokenConfig, Permission, TokenVerificationResult, McpCallToolParams, McpCallToolResult, ExecutionResult, TrustLevel, PolicyDecision } from '@solongate/core';
5
+ export { CapabilityToken, RateLimitError as CoreRateLimitError, DetectedThreat, ExecutionRequest, ExecutionResult, InputGuardConfig, InputGuardError, McpCallToolParams, McpCallToolResult, NetworkError, Permission, PolicyDecision, PolicyDeniedError, PolicyEffect, PolicyRule, PolicySet, SanitizationResult, SchemaValidationError, SecurityContext, SolonGateError, ThreatType, TokenConfig, ToolCapability, TrustLevel, checkEntropyLimits, checkLengthLimits, createDeniedToolResult, createSecurityContext, detectPathTraversal, detectSQLInjection, detectSSRF, detectShellInjection, detectWildcardAbuse, sanitizeInput, validateToolInput } from '@solongate/core';
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ import { Implementation } from '@modelcontextprotocol/sdk/types.js';
8
+
9
+ /**
10
+ * Configuration for the SolonGate SDK.
11
+ * All fields have secure defaults. Weakening requires explicit opt-in.
12
+ */
13
+ interface SolonGateConfig {
14
+ readonly policySet?: PolicySet;
15
+ readonly validateSchemas: boolean;
16
+ readonly enableLogging: boolean;
17
+ readonly logLevel: 'debug' | 'info' | 'warn' | 'error';
18
+ readonly evaluationTimeoutMs: number;
19
+ readonly verboseErrors: boolean;
20
+ readonly globalRateLimitPerMinute: number;
21
+ readonly rateLimitPerTool: number;
22
+ readonly tokenSecret?: string;
23
+ readonly tokenTtlSeconds: number;
24
+ readonly tokenIssuer?: string;
25
+ readonly gatewaySecret?: string;
26
+ readonly inputGuardConfig: InputGuardConfig;
27
+ readonly enableVersionedPolicies: boolean;
28
+ readonly apiUrl?: string;
29
+ }
30
+ declare const DEFAULT_CONFIG: Readonly<SolonGateConfig>;
31
+ declare function resolveConfig(userConfig?: Partial<SolonGateConfig>): {
32
+ config: SolonGateConfig;
33
+ warnings: string[];
34
+ };
35
+
36
+ /**
37
+ * Issues and verifies capability tokens using HMAC-SHA256.
38
+ *
39
+ * Security properties:
40
+ * - Short-lived TTL (default 30 seconds)
41
+ * - Single-use nonces (replay prevention)
42
+ * - Revocation support
43
+ * - No external JWT library dependency
44
+ */
45
+ declare class TokenIssuer {
46
+ private readonly secret;
47
+ private readonly ttlSeconds;
48
+ private readonly issuer;
49
+ private readonly usedNonces;
50
+ private readonly revokedTokens;
51
+ constructor(config: TokenConfig);
52
+ /**
53
+ * Issues a signed capability token.
54
+ */
55
+ issue(requestId: string, permissions: readonly Permission[], toolScope: readonly string[], serverScope?: readonly string[], pathScope?: readonly string[]): string;
56
+ /**
57
+ * Verifies a capability token and consumes the nonce (single-use).
58
+ */
59
+ verify(token: string): TokenVerificationResult;
60
+ /**
61
+ * Revokes a token by its ID.
62
+ */
63
+ revoke(jti: string): void;
64
+ /**
65
+ * Checks if a token ID has been revoked.
66
+ */
67
+ isRevoked(jti: string): boolean;
68
+ private sign;
69
+ private parseAndVerify;
70
+ private computeSignature;
71
+ }
72
+
73
+ /**
74
+ * Result of a rate limit check.
75
+ */
76
+ interface RateLimitResult {
77
+ readonly allowed: boolean;
78
+ readonly remaining: number;
79
+ readonly resetAt: number;
80
+ }
81
+ /**
82
+ * Sliding window rate limiter for tool calls.
83
+ *
84
+ * Tracks per-tool and global call rates using an in-memory sliding window.
85
+ * Window size defaults to 1 minute.
86
+ */
87
+ declare class RateLimiter {
88
+ private readonly windowMs;
89
+ private readonly records;
90
+ private globalRecords;
91
+ constructor(options?: {
92
+ windowMs?: number;
93
+ });
94
+ /**
95
+ * Checks if a tool call is within the rate limit.
96
+ * Does NOT record the call - use recordCall() after successful execution.
97
+ */
98
+ checkLimit(toolName: string, limitPerWindow: number): RateLimitResult;
99
+ /**
100
+ * Checks the global rate limit across all tools.
101
+ */
102
+ checkGlobalLimit(limitPerWindow: number): RateLimitResult;
103
+ /**
104
+ * Atomically checks and records a tool call.
105
+ * Prevents TOCTOU race conditions between check and record.
106
+ * Returns the rate limit result; if allowed, the call is already recorded.
107
+ */
108
+ checkAndRecord(toolName: string, limitPerWindow: number, globalLimit?: number): RateLimitResult;
109
+ /**
110
+ * Records a tool call for rate limiting.
111
+ * Call this after successful execution.
112
+ */
113
+ recordCall(toolName: string): void;
114
+ /**
115
+ * Gets usage stats for a tool.
116
+ */
117
+ getUsage(toolName: string): {
118
+ count: number;
119
+ windowStart: number;
120
+ };
121
+ /**
122
+ * Resets rate tracking for a specific tool.
123
+ */
124
+ resetTool(toolName: string): void;
125
+ /**
126
+ * Resets all rate tracking.
127
+ */
128
+ resetAll(): void;
129
+ private getActiveRecords;
130
+ }
131
+
132
+ /**
133
+ * Error thrown when a valid SolonGate license (API key) is missing or invalid.
134
+ */
135
+ declare class LicenseError extends Error {
136
+ constructor(message: string);
137
+ }
138
+ /**
139
+ * SolonGate - Security Gateway for MCP Tool Servers.
140
+ *
141
+ * Requires a valid API key. Get one at https://solongate.com
142
+ *
143
+ * Usage:
144
+ * ```typescript
145
+ * const gate = new SolonGate({ name: 'my-gateway', apiKey: 'sg_live_xxx' });
146
+ *
147
+ * // Intercept a tool call
148
+ * const result = await gate.executeToolCall(
149
+ * { name: 'file.read', arguments: { path: '/etc/passwd' } },
150
+ * async (params) => upstreamMcpServer.callTool(params),
151
+ * );
152
+ * ```
153
+ *
154
+ * Architecture:
155
+ * [LLM] -> [SolonGate.executeToolCall] -> [Security Pipeline] -> [Upstream MCP Server]
156
+ *
157
+ * Pipeline:
158
+ * Rate Limit → Input Guard → Policy Eval → Token Issue → Sign → Call → Audit
159
+ */
160
+ declare class SolonGate {
161
+ private readonly policyEngine;
162
+ private readonly config;
163
+ private readonly logger;
164
+ private readonly configWarnings;
165
+ private readonly tokenIssuer;
166
+ private readonly serverVerifier;
167
+ private readonly rateLimiter;
168
+ private readonly apiKey;
169
+ private licenseValidated;
170
+ constructor(options: {
171
+ name: string;
172
+ version?: string;
173
+ apiKey?: string;
174
+ config?: Partial<SolonGateConfig>;
175
+ policySet?: PolicySet;
176
+ });
177
+ /**
178
+ * Validate the API key against the SolonGate cloud API.
179
+ * Called once on first executeToolCall. Throws LicenseError if invalid.
180
+ * Test keys (sg_test_) skip online validation.
181
+ */
182
+ private validateLicense;
183
+ /**
184
+ * Intercept and evaluate a tool call against the full security pipeline.
185
+ * If denied at any stage, returns an error result without calling upstream.
186
+ * If allowed, calls upstream and returns the result.
187
+ */
188
+ executeToolCall(params: McpCallToolParams, upstreamCall: (params: McpCallToolParams) => Promise<McpCallToolResult>): Promise<McpCallToolResult>;
189
+ /** Load a new policy set at runtime. */
190
+ loadPolicy(policySet: PolicySet, options?: {
191
+ reason?: string;
192
+ createdBy?: string;
193
+ }): _solongate_policy_engine.ValidationResult;
194
+ /** Get current security warnings. */
195
+ getWarnings(): readonly string[];
196
+ /** Get the policy engine for direct access. */
197
+ getPolicyEngine(): PolicyEngine;
198
+ /** Get the rate limiter for direct access. */
199
+ getRateLimiter(): RateLimiter;
200
+ /** Get the token issuer (null if not configured). */
201
+ getTokenIssuer(): TokenIssuer | null;
202
+ }
203
+
204
+ /**
205
+ * SecureMcpServer — Drop-in replacement for McpServer with SolonGate protection.
206
+ *
207
+ * Extends the standard McpServer and automatically wraps every tool handler
208
+ * with SolonGate's security pipeline (rate limiting, input guard, policy eval,
209
+ * audit logging). No manual wrapping of individual tool handlers needed.
210
+ *
211
+ * Usage:
212
+ * ```typescript
213
+ * import { SecureMcpServer } from '@solongate/sdk';
214
+ *
215
+ * // Just replace `new McpServer(...)` with `new SecureMcpServer(...)`
216
+ * const server = new SecureMcpServer({
217
+ * name: 'my-server',
218
+ * version: '1.0.0',
219
+ * });
220
+ *
221
+ * // Register tools as normal — they're automatically protected
222
+ * server.tool('file_read', { path: z.string() }, async ({ path }) => {
223
+ * return { content: [{ type: 'text', text: readFileSync(path, 'utf-8') }] };
224
+ * });
225
+ *
226
+ * // API key comes from env: SOLONGATE_API_KEY=sg_live_xxx
227
+ * ```
228
+ */
229
+
230
+ /**
231
+ * Options for SecureMcpServer that control SolonGate behavior.
232
+ */
233
+ interface SecureMcpServerOptions {
234
+ /** SolonGate Cloud API key. Defaults to process.env.SOLONGATE_API_KEY */
235
+ apiKey?: string;
236
+ /** Policy set to enforce. If omitted, uses cloud policy or default. */
237
+ policySet?: PolicySet;
238
+ /** SolonGate configuration overrides. */
239
+ config?: Partial<SolonGateConfig>;
240
+ }
241
+ declare class SecureMcpServer extends McpServer {
242
+ private readonly gate;
243
+ /**
244
+ * Create a secure MCP server.
245
+ *
246
+ * @param serverInfo - MCP server info (name, version)
247
+ * @param solongateOptions - SolonGate security options
248
+ * @param mcpOptions - Standard McpServer options (capabilities, etc.)
249
+ */
250
+ constructor(serverInfo: Implementation, solongateOptions?: SecureMcpServerOptions, mcpOptions?: ConstructorParameters<typeof McpServer>[1]);
251
+ /**
252
+ * Override tool() to auto-wrap handlers with SolonGate security pipeline.
253
+ *
254
+ * Supports all McpServer.tool() overloads — the handler (always the last
255
+ * argument) is transparently wrapped. Tool name, description, schema, and
256
+ * annotations pass through unchanged.
257
+ */
258
+ tool(name: string, ...rest: unknown[]): ReturnType<McpServer['tool']>;
259
+ /**
260
+ * Override registerTool() to auto-wrap handlers with SolonGate security pipeline.
261
+ *
262
+ * This is the modern (non-deprecated) API for registering tools.
263
+ */
264
+ registerTool(name: string, config: Parameters<McpServer['registerTool']>[1], cb: unknown): ReturnType<McpServer['registerTool']>;
265
+ /** Get the underlying SolonGate instance for direct access. */
266
+ getSolonGate(): SolonGate;
267
+ }
268
+
269
+ /**
270
+ * A signed MCP request that includes capability token and integrity signature.
271
+ * Requests without valid gateway signature should be rejected by MCP servers.
272
+ */
273
+ interface SignedMcpRequest {
274
+ readonly params: McpCallToolParams;
275
+ readonly capabilityToken: string;
276
+ readonly signature: string;
277
+ readonly timestamp: string;
278
+ readonly nonce: string;
279
+ }
280
+ /**
281
+ * Result of validating a signed request.
282
+ */
283
+ interface SignatureValidationResult {
284
+ readonly valid: boolean;
285
+ readonly reason?: string;
286
+ }
287
+ /**
288
+ * Signs and verifies MCP requests to ensure they originate from the gateway.
289
+ *
290
+ * Security properties:
291
+ * - HMAC-SHA256 signature of request params + token
292
+ * - Timestamp to prevent old request replays
293
+ * - Nonce for uniqueness
294
+ * - Configurable max age for timestamp validation
295
+ */
296
+ declare class ServerVerifier {
297
+ private readonly gatewaySecret;
298
+ private readonly maxAgeMs;
299
+ private readonly usedNonces;
300
+ constructor(config: {
301
+ gatewaySecret: string;
302
+ maxAgeMs?: number;
303
+ });
304
+ /**
305
+ * Computes HMAC signature for request data.
306
+ */
307
+ signRequest(params: McpCallToolParams, capabilityToken: string): string;
308
+ /**
309
+ * Verifies the HMAC signature of request data.
310
+ */
311
+ verifySignature(params: McpCallToolParams, capabilityToken: string, signature: string): boolean;
312
+ /**
313
+ * Creates a complete signed request including timestamp and nonce.
314
+ */
315
+ createSignedRequest(params: McpCallToolParams, capabilityToken: string): SignedMcpRequest;
316
+ /**
317
+ * Validates a complete signed request including timestamp, nonce, and signature.
318
+ */
319
+ validateSignedRequest(request: SignedMcpRequest): SignatureValidationResult;
320
+ }
321
+
322
+ interface InterceptorOptions {
323
+ readonly policyEngine: PolicyEngine;
324
+ readonly validateSchemas: boolean;
325
+ readonly verboseErrors: boolean;
326
+ readonly onDecision?: (result: ExecutionResult) => void;
327
+ readonly tokenIssuer?: TokenIssuer;
328
+ readonly serverVerifier?: ServerVerifier;
329
+ readonly rateLimiter?: RateLimiter;
330
+ readonly inputGuardConfig?: InputGuardConfig;
331
+ readonly rateLimitPerTool?: number;
332
+ readonly globalRateLimitPerMinute?: number;
333
+ }
334
+ /**
335
+ * Intercepts an MCP tool call and runs the full security pipeline:
336
+ *
337
+ * 1. Rate limit check → RateLimitError if exceeded
338
+ * 2. Input guard (sanitization) → SchemaValidationError if dangerous
339
+ * 3. Policy evaluation → PolicyDeniedError if denied
340
+ * 4. Issue capability token (if TokenIssuer configured)
341
+ * 5. Sign request (if ServerVerifier configured)
342
+ * 6. Call upstream
343
+ * 7. Record rate limit usage
344
+ * 8. Log to audit trail
345
+ * 9. Return result
346
+ */
347
+ declare function interceptToolCall(params: McpCallToolParams, upstreamCall: (params: McpCallToolParams) => Promise<McpCallToolResult>, options: InterceptorOptions): Promise<McpCallToolResult>;
348
+
349
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error';
350
+ /**
351
+ * Structured security event logger.
352
+ * Outputs JSON-formatted log entries for machine consumption.
353
+ */
354
+ declare class SecurityLogger {
355
+ private readonly minLevel;
356
+ private readonly enabled;
357
+ constructor(options: {
358
+ level: LogLevel;
359
+ enabled: boolean;
360
+ });
361
+ logDecision(result: ExecutionResult): void;
362
+ private log;
363
+ }
364
+
365
+ /**
366
+ * SolonGate API Client for TypeScript/JavaScript
367
+ *
368
+ * Provides cloud-based security management with API keys.
369
+ *
370
+ * @example
371
+ * ```typescript
372
+ * import { SolonGateAPI } from '@solongate/sdk';
373
+ *
374
+ * const api = new SolonGateAPI({ apiKey: 'sg_live_xxx' });
375
+ *
376
+ * const result = await api.validate('file.read', { path: '/home/user/doc.txt' });
377
+ * if (result.allowed) {
378
+ * console.log('Allowed! Token:', result.token);
379
+ * }
380
+ * ```
381
+ */
382
+
383
+ interface APIConfig {
384
+ apiKey: string;
385
+ apiUrl?: string;
386
+ timeout?: number;
387
+ maxRetries?: number;
388
+ }
389
+ interface ValidationRequest {
390
+ tool: string;
391
+ arguments: Record<string, unknown>;
392
+ trustLevel?: TrustLevel;
393
+ includeToken?: boolean;
394
+ }
395
+ interface ValidationResult {
396
+ allowed: boolean;
397
+ tool: string;
398
+ decision?: PolicyDecision;
399
+ token?: string;
400
+ tokenExpiresAt?: number;
401
+ requestId?: string;
402
+ latencyMs?: number;
403
+ }
404
+ interface TokenResult {
405
+ token: string;
406
+ tool: string;
407
+ scope: string;
408
+ expiresAt: string;
409
+ nonce: string;
410
+ }
411
+ interface Tool {
412
+ id: string;
413
+ name: string;
414
+ description: string;
415
+ inputSchema?: Record<string, unknown>;
416
+ permissions: string[];
417
+ enabled: boolean;
418
+ createdAt: string;
419
+ updatedAt: string;
420
+ }
421
+ declare class APIError extends Error {
422
+ readonly statusCode?: number | undefined;
423
+ readonly requestId?: string | undefined;
424
+ readonly code: string;
425
+ constructor(message: string, statusCode?: number | undefined, requestId?: string | undefined, code?: string);
426
+ }
427
+ declare class AuthenticationError extends APIError {
428
+ constructor(message?: string);
429
+ }
430
+ declare class RateLimitError extends APIError {
431
+ readonly retryAfter?: number | undefined;
432
+ constructor(message: string, retryAfter?: number | undefined);
433
+ }
434
+ declare class PoliciesResource {
435
+ private client;
436
+ constructor(client: SolonGateAPI);
437
+ get(policyId?: string, version?: number): Promise<PolicySet>;
438
+ list(): Promise<{
439
+ policies: Array<{
440
+ id: string;
441
+ name: string;
442
+ version: number;
443
+ }>;
444
+ }>;
445
+ create(policy: PolicySet): Promise<PolicySet>;
446
+ update(policyId: string, policy: PolicySet): Promise<PolicySet>;
447
+ }
448
+ declare class TokensResource {
449
+ private client;
450
+ constructor(client: SolonGateAPI);
451
+ create(tool: string, scope?: string, ttlSeconds?: number): Promise<TokenResult>;
452
+ verify(token: string): Promise<{
453
+ valid: boolean;
454
+ error?: string;
455
+ tool?: string;
456
+ scope?: string;
457
+ }>;
458
+ }
459
+ declare class ToolsResource {
460
+ private client;
461
+ constructor(client: SolonGateAPI);
462
+ list(): Promise<{
463
+ tools: Tool[];
464
+ }>;
465
+ get(name: string): Promise<Tool>;
466
+ register(name: string, description: string, inputSchema?: Record<string, unknown>, permissions?: string[]): Promise<Tool>;
467
+ update(name: string, data: Partial<Tool>): Promise<Tool>;
468
+ delete(name: string): Promise<{
469
+ deleted: boolean;
470
+ }>;
471
+ }
472
+ declare class SolonGateAPI {
473
+ private readonly apiKey;
474
+ private readonly apiUrl;
475
+ private readonly timeout;
476
+ private readonly maxRetries;
477
+ readonly policies: PoliciesResource;
478
+ readonly tokens: TokensResource;
479
+ readonly tools: ToolsResource;
480
+ constructor(config: APIConfig | string);
481
+ /**
482
+ * Make an API request.
483
+ * @internal
484
+ */
485
+ request<T>(method: string, path: string, body?: unknown): Promise<T>;
486
+ /**
487
+ * Validate a tool call against policies.
488
+ *
489
+ * @example
490
+ * ```typescript
491
+ * const result = await api.validate('file.read', { path: '/home/user/doc.txt' });
492
+ * if (result.allowed) {
493
+ * // Proceed with the tool call
494
+ * }
495
+ * ```
496
+ */
497
+ validate(tool: string, args: Record<string, unknown>, options?: {
498
+ trustLevel?: TrustLevel;
499
+ includeToken?: boolean;
500
+ }): Promise<ValidationResult>;
501
+ /**
502
+ * Check if using live (production) API key.
503
+ */
504
+ isLiveMode(): boolean;
505
+ /**
506
+ * Check if using test (development) API key.
507
+ */
508
+ isTestMode(): boolean;
509
+ }
510
+
511
+ export { type APIConfig, APIError, AuthenticationError, DEFAULT_CONFIG, type InterceptorOptions, LicenseError, RateLimitError, type RateLimitResult, RateLimiter, SecureMcpServer, type SecureMcpServerOptions, SecurityLogger, ServerVerifier, type SignatureValidationResult, type SignedMcpRequest, SolonGate, SolonGateAPI, type SolonGateConfig, TokenIssuer, type TokenResult, type Tool, type ValidationRequest, type ValidationResult, interceptToolCall, resolveConfig };