@mcp-guardian/server 0.4.0 → 0.7.0

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.
Files changed (58) hide show
  1. package/README.md +119 -8
  2. package/dist/auth/auth-types.d.ts +40 -0
  3. package/dist/auth/auth-types.d.ts.map +1 -0
  4. package/dist/auth/auth-types.js +5 -0
  5. package/dist/auth/auth-types.js.map +1 -0
  6. package/dist/auth/oauth.d.ts +25 -0
  7. package/dist/auth/oauth.d.ts.map +1 -0
  8. package/dist/auth/oauth.js +96 -0
  9. package/dist/auth/oauth.js.map +1 -0
  10. package/dist/auth/redis-session-cache.d.ts +21 -0
  11. package/dist/auth/redis-session-cache.d.ts.map +1 -0
  12. package/dist/auth/redis-session-cache.js +74 -0
  13. package/dist/auth/redis-session-cache.js.map +1 -0
  14. package/dist/auth/session-cache.d.ts +47 -0
  15. package/dist/auth/session-cache.d.ts.map +1 -0
  16. package/dist/auth/session-cache.js +91 -0
  17. package/dist/auth/session-cache.js.map +1 -0
  18. package/dist/cli.js +27 -5
  19. package/dist/cli.js.map +1 -1
  20. package/dist/database/database-interface.d.ts +17 -0
  21. package/dist/database/database-interface.d.ts.map +1 -0
  22. package/dist/database/database-interface.js +2 -0
  23. package/dist/database/database-interface.js.map +1 -0
  24. package/dist/database/history-db.d.ts.map +1 -1
  25. package/dist/database/history-db.js.map +1 -1
  26. package/dist/database/postgres-db.d.ts +18 -0
  27. package/dist/database/postgres-db.d.ts.map +1 -0
  28. package/dist/database/postgres-db.js +118 -0
  29. package/dist/database/postgres-db.js.map +1 -0
  30. package/dist/index.js +1 -1
  31. package/dist/policy/policy-engine.d.ts.map +1 -1
  32. package/dist/policy/policy-engine.js +21 -0
  33. package/dist/policy/policy-engine.js.map +1 -1
  34. package/dist/policy/policy-types.d.ts +9 -0
  35. package/dist/policy/policy-types.d.ts.map +1 -1
  36. package/dist/policy/policy-watcher.d.ts +24 -0
  37. package/dist/policy/policy-watcher.d.ts.map +1 -0
  38. package/dist/policy/policy-watcher.js +68 -0
  39. package/dist/policy/policy-watcher.js.map +1 -0
  40. package/dist/proxy/proxy-manager.d.ts +3 -1
  41. package/dist/proxy/proxy-manager.d.ts.map +1 -1
  42. package/dist/proxy/proxy-manager.js +10 -3
  43. package/dist/proxy/proxy-manager.js.map +1 -1
  44. package/dist/proxy/proxy-server.d.ts +20 -8
  45. package/dist/proxy/proxy-server.d.ts.map +1 -1
  46. package/dist/proxy/proxy-server.js +209 -37
  47. package/dist/proxy/proxy-server.js.map +1 -1
  48. package/dist/utils/circuit-breaker.d.ts +29 -0
  49. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  50. package/dist/utils/circuit-breaker.js +81 -0
  51. package/dist/utils/circuit-breaker.js.map +1 -0
  52. package/dist/utils/metrics.d.ts +10 -0
  53. package/dist/utils/metrics.d.ts.map +1 -0
  54. package/dist/utils/metrics.js +77 -0
  55. package/dist/utils/metrics.js.map +1 -0
  56. package/dist/utils/structured-logger.d.ts +1 -1
  57. package/dist/utils/structured-logger.d.ts.map +1 -1
  58. package/package.json +9 -1
@@ -1 +1 @@
1
- {"version":3,"file":"proxy-manager.js","sourceRoot":"","sources":["../../src/proxy/proxy-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,MAAM,OAAO,YAAY;IAIb;IACA;IAJF,OAAO,GAAqB,EAAE,CAAC;IAEvC,YACU,EAAmB,EACnB,YAA2B;QAD3B,OAAE,GAAF,EAAE,CAAiB;QACnB,iBAAY,GAAZ,YAAY,CAAe;IAClC,CAAC;IAEJ,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAA0B;QACvC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,SAAS,KAAK,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnD,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,IAAI,cAAc,CAC9B,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,IAAI,IAAI,EAAE,EACjB,MAAM,CAAC,GAAG,IAAI,EAAE,EAChB,IAAI,CAAC,EAAE,EACP,MAAM,CAAC,IAAI,EACX,IAAI,CAAC,YAAY,CAClB,CAAC;oBACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,MAAM,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC7I,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,MAAM,CAAC,KAAK,CAAC,6BAA6B,MAAM,CAAC,IAAI,KAAK,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC5E,CAAC;YACH,CAAC;iBAAM,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,IAAI,+BAA+B,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;CACF"}
1
+ {"version":3,"file":"proxy-manager.js","sourceRoot":"","sources":["../../src/proxy/proxy-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAI5C,MAAM,OAAO,YAAY;IAIb;IACA;IACA;IALF,OAAO,GAAqB,EAAE,CAAC;IAEvC,YACU,EAAmB,EACnB,YAA2B,EAC3B,aAA8B;QAF9B,OAAE,GAAF,EAAE,CAAiB;QACnB,iBAAY,GAAZ,YAAY,CAAe;QAC3B,kBAAa,GAAb,aAAa,CAAiB;IACrC,CAAC;IAEJ,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAA0B;QACvC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,SAAS,KAAK,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnD,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,IAAI,cAAc,CAC9B,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,IAAI,IAAI,EAAE,EACjB,MAAM,CAAC,GAAG,IAAI,EAAE,EAChB,IAAI,CAAC,EAAE,EACP,MAAM,CAAC,IAAI,EACX,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,aAAa,CACnB,CAAC;oBACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACzB,MAAM,MAAM,GAAa,EAAE,CAAC;oBAC5B,IAAI,IAAI,CAAC,YAAY;wBAAE,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;oBAC7E,IAAI,IAAI,CAAC,aAAa;wBAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;oBACvD,MAAM,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvH,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,MAAM,CAAC,KAAK,CAAC,6BAA6B,MAAM,CAAC,IAAI,KAAK,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC5E,CAAC;YACH,CAAC;iBAAM,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,IAAI,+BAA+B,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;CACF"}
@@ -1,12 +1,14 @@
1
1
  import { HistoryDatabase } from '../database/history-db.js';
2
2
  import { PolicyEngine } from '../policy/policy-engine.js';
3
+ import { OAuthValidator } from '../auth/oauth.js';
3
4
  /**
4
- * MCP Proxy Interceptor — sits between the AI client and an MCP server,
5
- * capturing every JSON-RPC call's token usage for real cost auditing.
5
+ * MCP Proxy Interceptor — sits between the AI client and an MCP server.
6
6
  *
7
7
  * v0.4: Integrated PolicyEngine for active blocking of malicious tool calls.
8
- * If policyEngine is provided, every tools/call is evaluated before forwarding.
9
- * Blocked calls return a JSON-RPC error to the client instead of reaching the server.
8
+ * v0.5: OAuth 2.1 JWT validation validates bearer tokens before policy evaluation.
9
+ * v0.5.2: Circuit breaker for upstream MCP server failures.
10
+ * v0.5.2: Per-client rate limiting (keyed by agent sub + tool name).
11
+ * v0.5.2: Consistent SIEM fields (request_id, proxy_latency_ms, authn_success, authz_allowed).
10
12
  */
11
13
  export declare class McpProxyServer {
12
14
  private child;
@@ -19,16 +21,26 @@ export declare class McpProxyServer {
19
21
  private requestArguments;
20
22
  private serverName;
21
23
  private policyEngine;
22
- constructor(command: string, args: string[], env: Record<string, string>, db: HistoryDatabase, serverName?: string, policyEngine?: PolicyEngine);
24
+ private authValidator;
25
+ private sessionCache;
26
+ private circuitBreaker;
27
+ /** v0.5.2: Per-client rate limit counters (key: agentSub:toolName) */
28
+ private clientRateCounters;
29
+ constructor(command: string, args: string[], env: Record<string, string>, db: HistoryDatabase, serverName?: string, policyEngine?: PolicyEngine, authValidator?: OAuthValidator);
23
30
  get stdin(): NodeJS.WritableStream | null;
24
31
  private setupStdout;
25
32
  private setupStderr;
33
+ private sendError;
26
34
  /**
27
35
  * Called when the AI client writes a request to be proxied.
28
- * Evaluates tools/call against policy engine before forwarding.
29
- * Blocked calls receive a JSON-RPC error response.
36
+ * Pipeline: Auth Circuit Breaker Policy + RBAC → Forward.
30
37
  */
31
- handleClientInput(raw: string): void;
38
+ handleClientInput(raw: string): Promise<void>;
39
+ /**
40
+ * Check per-client rate limits against RBAC rules.
41
+ * Returns block reason string or null.
42
+ */
43
+ private checkPerClientRateLimit;
32
44
  kill(): void;
33
45
  }
34
46
  //# sourceMappingURL=proxy-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy-server.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy-server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAI1D;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,gBAAgB,CAAsC;IAC9D,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAsB;gBAGxC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,EAAE,EAAE,eAAe,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,YAAY;IAoB7B,IAAI,KAAK,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI,CAExC;IAED,OAAO,CAAC,WAAW;IAoCnB,OAAO,CAAC,WAAW;IAMnB;;;;OAIG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAuEpC,IAAI,IAAI,IAAI;CAOb"}
1
+ {"version":3,"file":"proxy-server.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy-server.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMlD;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,gBAAgB,CAAsC;IAC9D,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,cAAc,CAAiB;IACvC,sEAAsE;IACtE,OAAO,CAAC,kBAAkB,CAA8D;gBAGtF,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,EAAE,EAAE,eAAe,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,YAAY,EAC3B,aAAa,CAAC,EAAE,cAAc;IA0BhC,IAAI,KAAK,IAAI,MAAM,CAAC,cAAc,GAAG,IAAI,CAExC;IAED,OAAO,CAAC,WAAW;IAuCnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,SAAS;IASjB;;;OAGG;IACG,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8MnD;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAY/B,IAAI,IAAI,IAAI;CAOb"}
@@ -1,15 +1,21 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { createInterface } from 'readline';
3
+ import { randomUUID } from 'crypto';
3
4
  import { TokenCounter } from '../utils/token-counter.js';
4
5
  import { Logger } from '../utils/logger.js';
5
6
  import { StructuredLogger } from '../utils/structured-logger.js';
7
+ import { OAuthValidator } from '../auth/oauth.js';
8
+ import { SessionCache } from '../auth/session-cache.js';
9
+ import { CircuitBreaker } from '../utils/circuit-breaker.js';
10
+ import * as Metrics from '../utils/metrics.js';
6
11
  /**
7
- * MCP Proxy Interceptor — sits between the AI client and an MCP server,
8
- * capturing every JSON-RPC call's token usage for real cost auditing.
12
+ * MCP Proxy Interceptor — sits between the AI client and an MCP server.
9
13
  *
10
14
  * v0.4: Integrated PolicyEngine for active blocking of malicious tool calls.
11
- * If policyEngine is provided, every tools/call is evaluated before forwarding.
12
- * Blocked calls return a JSON-RPC error to the client instead of reaching the server.
15
+ * v0.5: OAuth 2.1 JWT validation validates bearer tokens before policy evaluation.
16
+ * v0.5.2: Circuit breaker for upstream MCP server failures.
17
+ * v0.5.2: Per-client rate limiting (keyed by agent sub + tool name).
18
+ * v0.5.2: Consistent SIEM fields (request_id, proxy_latency_ms, authn_success, authz_allowed).
13
19
  */
14
20
  export class McpProxyServer {
15
21
  child;
@@ -22,9 +28,18 @@ export class McpProxyServer {
22
28
  requestArguments;
23
29
  serverName;
24
30
  policyEngine;
25
- constructor(command, args, env, db, serverName, policyEngine) {
31
+ authValidator;
32
+ sessionCache;
33
+ circuitBreaker;
34
+ /** v0.5.2: Per-client rate limit counters (key: agentSub:toolName) */
35
+ clientRateCounters = new Map();
36
+ constructor(command, args, env, db, serverName, policyEngine, authValidator) {
26
37
  this.serverName = serverName || command.split('/').pop() || command;
27
38
  this.policyEngine = policyEngine || null;
39
+ this.authValidator = authValidator || null;
40
+ this.sessionCache = authValidator ? new SessionCache() : null;
41
+ this.circuitBreaker = new CircuitBreaker(this.serverName);
42
+ Metrics.circuitBreakerState.set({ server_name: this.serverName }, 0);
28
43
  this.child = spawn(command, args, {
29
44
  env: { ...process.env, ...env },
30
45
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -37,6 +52,8 @@ export class McpProxyServer {
37
52
  event: 'proxy_started',
38
53
  serverName: this.serverName,
39
54
  blockingMode: this.policyEngine ? this.policyEngine.getMode() : 'audit',
55
+ authEnabled: this.authValidator ? this.authValidator.getConfig().required : false,
56
+ circuitBreaker: this.circuitBreaker.getState(),
40
57
  });
41
58
  }
42
59
  get stdin() {
@@ -48,7 +65,7 @@ export class McpProxyServer {
48
65
  try {
49
66
  const msg = JSON.parse(line);
50
67
  if (msg.id && msg.id === this.currentRequestId) {
51
- // Response to our tracked tools/call request
68
+ const proxyLatencyMs = Date.now() - this.requestStartTime;
52
69
  const responseTokens = this.tokenCounter.count(line);
53
70
  const record = {
54
71
  serverName: this.serverName,
@@ -56,18 +73,22 @@ export class McpProxyServer {
56
73
  requestTokens: this.requestTokens,
57
74
  responseTokens,
58
75
  totalTokens: this.requestTokens + responseTokens,
59
- durationMs: Date.now() - this.requestStartTime,
76
+ durationMs: proxyLatencyMs,
60
77
  timestamp: new Date().toISOString(),
61
78
  };
62
79
  this.db.addCallRecord(record).then(() => this.db.flush()).catch((err) => Logger.debug(`Proxy: failed to store call record: ${err?.message}`));
80
+ this.circuitBreaker.recordSuccess();
81
+ Metrics.circuitBreakerState.set({ server_name: this.serverName }, this.circuitBreaker.getState() === 'CLOSED' ? 0 : this.circuitBreaker.getState() === 'OPEN' ? 1 : 2);
82
+ Metrics.proxyLatencyMs.observe({ server_name: this.serverName }, proxyLatencyMs);
83
+ Metrics.requestsTotal.inc({ server_name: this.serverName, decision: 'pass', authn_success: 'true' });
84
+ if (this.sessionCache)
85
+ Metrics.activeSessions.set(this.sessionCache.size);
63
86
  this.currentRequestId = null;
64
87
  this.requestToolName = null;
65
88
  }
66
- // Forward response to client
67
89
  process.stdout.write(line + '\n');
68
90
  }
69
91
  catch {
70
- // Non-JSON line — forward as-is
71
92
  process.stdout.write(line + '\n');
72
93
  }
73
94
  });
@@ -80,76 +101,227 @@ export class McpProxyServer {
80
101
  process.stderr.write(data);
81
102
  });
82
103
  }
104
+ sendError(id, code, message, data) {
105
+ const errorResponse = JSON.stringify({
106
+ jsonrpc: '2.0',
107
+ id,
108
+ error: { code, message, data },
109
+ });
110
+ process.stdout.write(errorResponse + '\n');
111
+ }
83
112
  /**
84
113
  * Called when the AI client writes a request to be proxied.
85
- * Evaluates tools/call against policy engine before forwarding.
86
- * Blocked calls receive a JSON-RPC error response.
114
+ * Pipeline: Auth Circuit Breaker Policy + RBAC → Forward.
87
115
  */
88
- handleClientInput(raw) {
116
+ async handleClientInput(raw) {
117
+ const requestId = randomUUID();
118
+ const proxyStartTime = Date.now();
89
119
  try {
90
120
  const msg = JSON.parse(raw);
91
121
  if (msg.method === 'tools/call' && msg.id) {
92
- this.requestStartTime = Date.now();
93
- this.currentRequestId = msg.id;
122
+ this.requestStartTime = proxyStartTime;
123
+ this.currentRequestId = msg.id; // Original msg ID for response matching
94
124
  this.requestToolName = msg.params?.name || 'unknown';
95
125
  this.requestTokens = this.tokenCounter.count(raw);
96
126
  this.requestArguments = msg.params?.arguments;
97
- // ── v0.4: Active policy enforcement ──────────────────
127
+ const toolName = this.requestToolName || 'unknown';
128
+ let agentIdentity;
129
+ let authnSuccess = false;
130
+ // ── v0.5: OAuth 2.1 JWT validation ──────────────────
131
+ if (this.authValidator) {
132
+ const authHeader = msg.params?._meta?.auth?.Authorization
133
+ || msg.Authorization
134
+ || msg.params?.Authorization
135
+ || undefined;
136
+ const token = OAuthValidator.extractToken(authHeader);
137
+ if (!token) {
138
+ if (this.authValidator.getConfig().required) {
139
+ StructuredLogger.info({
140
+ event: 'auth_required',
141
+ requestId,
142
+ serverName: this.serverName,
143
+ toolName,
144
+ authnSuccess: false,
145
+ });
146
+ this.sendError(msg.id, -32002, 'Authentication required. Provide a valid Bearer token in the Authorization header.');
147
+ return;
148
+ }
149
+ }
150
+ else {
151
+ const result = await this.authValidator.validate(token);
152
+ authnSuccess = result.valid;
153
+ if (result.identity)
154
+ agentIdentity = result.identity;
155
+ if (!result.valid) {
156
+ StructuredLogger.logError({
157
+ event: 'oidc_auth_error',
158
+ serverName: this.serverName,
159
+ requestId,
160
+ error: `JWT validation failed: ${result.error}`,
161
+ });
162
+ if (this.authValidator.getConfig().required) {
163
+ this.sendError(msg.id, -32003, `Authentication failed: ${result.error}`);
164
+ return;
165
+ }
166
+ }
167
+ else {
168
+ // v0.6.0: Session cache — issue short-lived session to prevent JWT replay
169
+ if (this.sessionCache && result.identity) {
170
+ const session = this.sessionCache.createSession(result.identity);
171
+ StructuredLogger.info({
172
+ event: 'auth_success',
173
+ requestId,
174
+ serverName: this.serverName,
175
+ toolName,
176
+ agent: result.identity.sub,
177
+ clientId: result.identity.clientId,
178
+ sessionToken: session.token,
179
+ sessionExpiry: new Date(session.expiresAt).toISOString(),
180
+ authnSuccess: true,
181
+ });
182
+ }
183
+ else {
184
+ StructuredLogger.info({
185
+ event: 'auth_success',
186
+ requestId,
187
+ serverName: this.serverName,
188
+ toolName,
189
+ agent: result.identity?.sub,
190
+ clientId: result.identity?.clientId,
191
+ authnSuccess: true,
192
+ });
193
+ }
194
+ }
195
+ }
196
+ }
197
+ // ── v0.5.2: Circuit breaker check ──────────────────
198
+ if (!this.circuitBreaker.allowRequest()) {
199
+ StructuredLogger.info({
200
+ event: 'circuit_open',
201
+ requestId,
202
+ serverName: this.serverName,
203
+ toolName,
204
+ state: this.circuitBreaker.getState(),
205
+ });
206
+ this.sendError(msg.id, -32005, `Upstream MCP server '${this.serverName}' unavailable — circuit breaker open`);
207
+ this.circuitBreaker.recordFailure();
208
+ return;
209
+ }
210
+ // ── v0.5.1: RBAC + policy evaluation ────────────────
211
+ let authzAllowed = true;
212
+ let blockReason;
98
213
  if (this.policyEngine) {
99
- const toolName = this.requestToolName || 'unknown';
100
214
  const context = {
101
215
  serverName: this.serverName,
102
216
  toolName,
103
217
  arguments: this.requestArguments,
104
- requestId: msg.id,
218
+ requestId,
105
219
  requestTokens: this.requestTokens,
106
220
  timestamp: new Date().toISOString(),
221
+ agentIdentity,
107
222
  };
108
223
  const decision = this.policyEngine.evaluate(context);
109
- // Log every decision for SIEM audit trail
110
224
  StructuredLogger.logPolicyDecision({
111
225
  event: 'policy_decision',
112
- requestId: msg.id,
226
+ requestId,
113
227
  serverName: this.serverName,
114
228
  toolName,
115
229
  decision,
116
230
  context,
117
231
  });
118
232
  if (decision.action === 'block') {
233
+ authzAllowed = false;
234
+ blockReason = `policy:${decision.rule}:${decision.reason}`;
119
235
  StructuredLogger.logBlocked({
120
236
  event: 'tool_blocked',
121
- requestId: msg.id,
237
+ requestId,
122
238
  serverName: this.serverName,
123
239
  toolName,
124
- reason: decision.reason,
240
+ reason: `policy_rule=${decision.rule} | reason=${decision.reason}`,
125
241
  rule: decision.rule,
126
242
  });
127
- // Return JSON-RPC 2.0 error to client — do NOT forward to server
128
- const errorResponse = JSON.stringify({
129
- jsonrpc: '2.0',
130
- id: msg.id,
131
- error: {
132
- code: -32001,
133
- message: `Blocked by MCP Guardian policy: ${decision.reason}`,
134
- data: { rule: decision.rule, policy: this.policyEngine.getMode() },
135
- },
243
+ StructuredLogger.info({
244
+ event: 'request_denied',
245
+ requestId,
246
+ serverName: this.serverName,
247
+ toolName,
248
+ authnSuccess,
249
+ authzAllowed,
250
+ blockReason,
251
+ proxyLatencyMs: Date.now() - proxyStartTime,
136
252
  });
137
- process.stdout.write(errorResponse + '\n');
138
- // Reset state
139
- this.currentRequestId = null;
140
- this.requestToolName = null;
141
- this.requestArguments = undefined;
142
- return; // ← CRITICAL: do not forward to child
253
+ Metrics.blockedRequestsTotal.inc({ server_name: this.serverName, block_reason: blockReason || 'policy', rule: decision.rule });
254
+ Metrics.requestsTotal.inc({ server_name: this.serverName, decision: 'block', authn_success: String(authnSuccess) });
255
+ this.sendError(msg.id, -32001, `Blocked by MCP Guardian policy: ${decision.reason}`, {
256
+ rule: decision.rule,
257
+ policy: this.policyEngine.getMode(),
258
+ });
259
+ return;
260
+ }
261
+ // v0.5.2: Per-client rate limiting
262
+ if (agentIdentity) {
263
+ const rateKey = `${agentIdentity.sub}:${toolName}`;
264
+ const now = Date.now();
265
+ let counter = this.clientRateCounters.get(rateKey);
266
+ if (!counter || now > counter.resetAt) {
267
+ counter = { count: 1, resetAt: now + 60000 };
268
+ this.clientRateCounters.set(rateKey, counter);
269
+ }
270
+ else {
271
+ counter.count++;
272
+ }
273
+ // Check if any RBAC rule with per-client rate limit fires
274
+ const perClientLimit = this.checkPerClientRateLimit(agentIdentity, toolName, counter.count);
275
+ if (perClientLimit) {
276
+ StructuredLogger.info({
277
+ event: 'request_denied',
278
+ requestId,
279
+ serverName: this.serverName,
280
+ toolName,
281
+ authnSuccess,
282
+ authzAllowed: false,
283
+ blockReason: perClientLimit,
284
+ proxyLatencyMs: Date.now() - proxyStartTime,
285
+ });
286
+ this.sendError(msg.id, -32004, `Rate limit exceeded for agent '${agentIdentity.sub}': ${perClientLimit}`);
287
+ return;
288
+ }
143
289
  }
144
290
  }
291
+ // ── Log successful forwarding ───────────────────────
292
+ StructuredLogger.info({
293
+ event: 'request_forwarded',
294
+ requestId,
295
+ serverName: this.serverName,
296
+ toolName,
297
+ authnSuccess,
298
+ authzAllowed,
299
+ proxyLatencyMs: Date.now() - proxyStartTime,
300
+ agent: agentIdentity?.sub,
301
+ });
145
302
  }
146
303
  }
147
304
  catch {
148
305
  // Non-JSON input — forward as-is
149
306
  }
150
- // Forward to the underlying MCP server
151
307
  this.child.stdin?.write(raw + '\n');
152
308
  }
309
+ /**
310
+ * Check per-client rate limits against RBAC rules.
311
+ * Returns block reason string or null.
312
+ */
313
+ checkPerClientRateLimit(identity, toolName, currentCount) {
314
+ if (!this.policyEngine)
315
+ return null;
316
+ // Per-client limits are tracked via RBAC scopes — if agent has "basic" scope, check against "basic" rate limit rule
317
+ const scopes = identity.scopes || [];
318
+ // Simple: if the agent has no special scopes and we've hit a hard limit
319
+ // In a full implementation, this would check per-scope/per-client limits from policy
320
+ if (scopes.length === 0 && currentCount > 100) {
321
+ return `Per-client rate limit exceeded: ${currentCount}/100 calls per minute (agent: ${identity.sub})`;
322
+ }
323
+ return null;
324
+ }
153
325
  kill() {
154
326
  try {
155
327
  this.child.kill();
@@ -1 +1 @@
1
- {"version":3,"file":"proxy-server.js","sourceRoot":"","sources":["../../src/proxy/proxy-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"proxy-server.js","sourceRoot":"","sources":["../../src/proxy/proxy-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,OAAO,cAAc;IACjB,KAAK,CAAe;IACpB,YAAY,CAAe;IAC3B,EAAE,CAAkB;IACpB,gBAAgB,GAAkB,IAAI,CAAC;IACvC,gBAAgB,GAAW,CAAC,CAAC;IAC7B,eAAe,GAAkB,IAAI,CAAC;IACtC,aAAa,GAAW,CAAC,CAAC;IAC1B,gBAAgB,CAAsC;IACtD,UAAU,CAAS;IACnB,YAAY,CAAsB;IAClC,aAAa,CAAwB;IACrC,YAAY,CAAsB;IAClC,cAAc,CAAiB;IACvC,sEAAsE;IAC9D,kBAAkB,GAAoD,IAAI,GAAG,EAAE,CAAC;IAExF,YACE,OAAe,EACf,IAAc,EACd,GAA2B,EAC3B,EAAmB,EACnB,UAAmB,EACnB,YAA2B,EAC3B,aAA8B;QAE9B,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,OAAO,CAAC;QACpE,IAAI,CAAC,YAAY,GAAG,YAAY,IAAI,IAAI,CAAC;QACzC,IAAI,CAAC,aAAa,GAAG,aAAa,IAAI,IAAI,CAAC;QAC3C,IAAI,CAAC,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,IAAI,CAAC,cAAc,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YAChC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE;YAC/B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QACvC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,gBAAgB,CAAC,IAAI,CAAC;YACpB,KAAK,EAAE,eAAe;YACtB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO;YACvE,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK;YACjF,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEO,WAAW;QACjB,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAO,EAAE,CAAC,CAAC;QAC1D,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC7B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7B,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBAC/C,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC;oBAC1D,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACrD,MAAM,MAAM,GAAoB;wBAC9B,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,QAAQ,EAAE,IAAI,CAAC,eAAe,IAAI,SAAS;wBAC3C,aAAa,EAAE,IAAI,CAAC,aAAa;wBACjC,cAAc;wBACd,WAAW,EAAE,IAAI,CAAC,aAAa,GAAG,cAAc;wBAChD,UAAU,EAAE,cAAc;wBAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACpC,CAAC;oBACF,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACtE,MAAM,CAAC,KAAK,CAAC,uCAAuC,GAAG,EAAE,OAAO,EAAE,CAAC,CACpE,CAAC;oBACF,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC;oBACpC,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACvK,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,cAAc,CAAC,CAAC;oBACjF,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;oBACrG,IAAI,IAAI,CAAC,YAAY;wBAAE,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;oBAC1E,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;oBAC7B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;gBAC9B,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;YACpC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAClB,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,UAAU,iBAAiB,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,SAAS,CAAC,EAAmB,EAAE,IAAY,EAAE,OAAe,EAAE,IAA8B;QAClG,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC;YACnC,OAAO,EAAE,KAAK;YACd,EAAE;YACF,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;SAC/B,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,GAAW;QACjC,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;QAC/B,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAElC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,GAAG,CAAC,MAAM,KAAK,YAAY,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBAC9C,IAAI,CAAC,gBAAgB,GAAG,cAAc,CAAC;gBACvC,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,wCAAwC;gBACpE,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,IAAI,SAAS,CAAC;gBACrD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClD,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;gBAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,IAAI,SAAS,CAAC;gBAEnD,IAAI,aAAwC,CAAC;gBAC7C,IAAI,YAAY,GAAG,KAAK,CAAC;gBAEzB,uDAAuD;gBACvD,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACvB,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa;2BACpD,GAAG,CAAC,aAAa;2BACjB,GAAG,CAAC,MAAM,EAAE,aAAa;2BACzB,SAAS,CAAC;oBAEf,MAAM,KAAK,GAAG,cAAc,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;oBAEtD,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC;4BAC5C,gBAAgB,CAAC,IAAI,CAAC;gCACpB,KAAK,EAAE,eAAe;gCACtB,SAAS;gCACT,UAAU,EAAE,IAAI,CAAC,UAAU;gCAC3B,QAAQ;gCACR,YAAY,EAAE,KAAK;6BACpB,CAAC,CAAC;4BACH,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,oFAAoF,CAAC,CAAC;4BACrH,OAAO;wBACT,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,MAAM,MAAM,GAAyB,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;wBAC9E,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC;wBAC5B,IAAI,MAAM,CAAC,QAAQ;4BAAE,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC;wBAErD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;4BAClB,gBAAgB,CAAC,QAAQ,CAAC;gCACxB,KAAK,EAAE,iBAAiB;gCACxB,UAAU,EAAE,IAAI,CAAC,UAAU;gCAC3B,SAAS;gCACT,KAAK,EAAE,0BAA0B,MAAM,CAAC,KAAK,EAAE;6BAChD,CAAC,CAAC;4BAEH,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC;gCAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,0BAA0B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;gCACzE,OAAO;4BACT,CAAC;wBACH,CAAC;6BAAM,CAAC;4BACN,0EAA0E;4BAC1E,IAAI,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gCACzC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gCACjE,gBAAgB,CAAC,IAAI,CAAC;oCACpB,KAAK,EAAE,cAAc;oCACrB,SAAS;oCACT,UAAU,EAAE,IAAI,CAAC,UAAU;oCAC3B,QAAQ;oCACR,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;oCAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;oCAClC,YAAY,EAAE,OAAO,CAAC,KAAK;oCAC3B,aAAa,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;oCACxD,YAAY,EAAE,IAAI;iCACnB,CAAC,CAAC;4BACL,CAAC;iCAAM,CAAC;gCACN,gBAAgB,CAAC,IAAI,CAAC;oCACpB,KAAK,EAAE,cAAc;oCACrB,SAAS;oCACT,UAAU,EAAE,IAAI,CAAC,UAAU;oCAC3B,QAAQ;oCACR,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG;oCAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ;oCACnC,YAAY,EAAE,IAAI;iCACnB,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,sDAAsD;gBACtD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,EAAE,CAAC;oBACxC,gBAAgB,CAAC,IAAI,CAAC;wBACpB,KAAK,EAAE,cAAc;wBACrB,SAAS;wBACT,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,QAAQ;wBACR,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE;qBACtC,CAAC,CAAC;oBACH,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,wBAAwB,IAAI,CAAC,UAAU,sCAAsC,CAAC,CAAC;oBAC9G,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC;oBACpC,OAAO;gBACT,CAAC;gBAED,uDAAuD;gBACvD,IAAI,YAAY,GAAG,IAAI,CAAC;gBACxB,IAAI,WAA+B,CAAC;gBAEpC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBACtB,MAAM,OAAO,GAAgB;wBAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,QAAQ;wBACR,SAAS,EAAE,IAAI,CAAC,gBAAgB;wBAChC,SAAS;wBACT,aAAa,EAAE,IAAI,CAAC,aAAa;wBACjC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,aAAa;qBACd,CAAC;oBAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAErD,gBAAgB,CAAC,iBAAiB,CAAC;wBACjC,KAAK,EAAE,iBAAiB;wBACxB,SAAS;wBACT,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,QAAQ;wBACR,QAAQ;wBACR,OAAO;qBACR,CAAC,CAAC;oBAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;wBAChC,YAAY,GAAG,KAAK,CAAC;wBACrB,WAAW,GAAG,UAAU,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;wBAE3D,gBAAgB,CAAC,UAAU,CAAC;4BAC1B,KAAK,EAAE,cAAc;4BACrB,SAAS;4BACT,UAAU,EAAE,IAAI,CAAC,UAAU;4BAC3B,QAAQ;4BACR,MAAM,EAAE,eAAe,QAAQ,CAAC,IAAI,aAAa,QAAQ,CAAC,MAAM,EAAE;4BAClE,IAAI,EAAE,QAAQ,CAAC,IAAI;yBACpB,CAAC,CAAC;wBAEH,gBAAgB,CAAC,IAAI,CAAC;4BACpB,KAAK,EAAE,gBAAgB;4BACvB,SAAS;4BACT,UAAU,EAAE,IAAI,CAAC,UAAU;4BAC3B,QAAQ;4BACR,YAAY;4BACZ,YAAY;4BACZ,WAAW;4BACX,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc;yBAC5C,CAAC,CAAC;wBAEH,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,EAAE,WAAW,IAAI,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;wBAC/H,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;wBACpH,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,mCAAmC,QAAQ,CAAC,MAAM,EAAE,EAAE;4BACnF,IAAI,EAAE,QAAQ,CAAC,IAAI;4BACnB,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;yBACpC,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;oBAED,mCAAmC;oBACnC,IAAI,aAAa,EAAE,CAAC;wBAClB,MAAM,OAAO,GAAG,GAAG,aAAa,CAAC,GAAG,IAAI,QAAQ,EAAE,CAAC;wBACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;wBACvB,IAAI,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;wBACnD,IAAI,CAAC,OAAO,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;4BACtC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,KAAK,EAAE,CAAC;4BAC7C,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBAChD,CAAC;6BAAM,CAAC;4BACN,OAAO,CAAC,KAAK,EAAE,CAAC;wBAClB,CAAC;wBACD,0DAA0D;wBAC1D,MAAM,cAAc,GAAG,IAAI,CAAC,uBAAuB,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;wBAC5F,IAAI,cAAc,EAAE,CAAC;4BACnB,gBAAgB,CAAC,IAAI,CAAC;gCACpB,KAAK,EAAE,gBAAgB;gCACvB,SAAS;gCACT,UAAU,EAAE,IAAI,CAAC,UAAU;gCAC3B,QAAQ;gCACR,YAAY;gCACZ,YAAY,EAAE,KAAK;gCACnB,WAAW,EAAE,cAAc;gCAC3B,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc;6BAC5C,CAAC,CAAC;4BACH,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,kCAAkC,aAAa,CAAC,GAAG,MAAM,cAAc,EAAE,CAAC,CAAC;4BAC1G,OAAO;wBACT,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,uDAAuD;gBACvD,gBAAgB,CAAC,IAAI,CAAC;oBACpB,KAAK,EAAE,mBAAmB;oBAC1B,SAAS;oBACT,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,QAAQ;oBACR,YAAY;oBACZ,YAAY;oBACZ,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc;oBAC3C,KAAK,EAAE,aAAa,EAAE,GAAG;iBAC1B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACK,uBAAuB,CAAC,QAAuB,EAAE,QAAgB,EAAE,YAAoB;QAC7F,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QACpC,oHAAoH;QACpH,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC;QACrC,wEAAwE;QACxE,qFAAqF;QACrF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;YAC9C,OAAO,mCAAmC,YAAY,iCAAiC,QAAQ,CAAC,GAAG,GAAG,CAAC;QACzG,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI;QACF,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ export type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
2
+ export declare class CircuitBreaker {
3
+ private state;
4
+ private failureCount;
5
+ private successCount;
6
+ private lastFailureTime;
7
+ private readonly resetTimeout;
8
+ private readonly failureThreshold;
9
+ private readonly successThreshold;
10
+ private readonly name;
11
+ constructor(name: string, options?: {
12
+ failureThreshold?: number;
13
+ successThreshold?: number;
14
+ resetTimeoutMs?: number;
15
+ });
16
+ /** Check if the circuit allows a request through */
17
+ allowRequest(): boolean;
18
+ /** Record a successful request */
19
+ recordSuccess(): void;
20
+ /** Record a failed request */
21
+ recordFailure(): void;
22
+ getState(): CircuitState;
23
+ getStats(): {
24
+ state: CircuitState;
25
+ failureCount: number;
26
+ successCount: number;
27
+ };
28
+ }
29
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/utils/circuit-breaker.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAG5B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAO;IAQjG,oDAAoD;IACpD,YAAY,IAAI,OAAO;IAcvB,kCAAkC;IAClC,aAAa,IAAI,IAAI;IAcrB,8BAA8B;IAC9B,aAAa,IAAI,IAAI;IAerB,QAAQ,IAAI,YAAY;IAIxB,QAAQ,IAAI;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;CAOhF"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Circuit Breaker for MCP Proxy Server.
3
+ * Implements the classic 3-state circuit breaker pattern:
4
+ * CLOSED → OPEN → HALF_OPEN → CLOSED (or OPEN again).
5
+ *
6
+ * Used to protect upstream MCP servers from cascading failures.
7
+ */
8
+ import { Logger } from './logger.js';
9
+ export class CircuitBreaker {
10
+ state = 'CLOSED';
11
+ failureCount = 0;
12
+ successCount = 0;
13
+ lastFailureTime = 0;
14
+ resetTimeout;
15
+ failureThreshold;
16
+ successThreshold;
17
+ name;
18
+ constructor(name, options = {}) {
19
+ this.name = name;
20
+ this.failureThreshold = options.failureThreshold || 5;
21
+ this.successThreshold = options.successThreshold || 2;
22
+ this.resetTimeout = options.resetTimeoutMs || 30000;
23
+ }
24
+ /** Check if the circuit allows a request through */
25
+ allowRequest() {
26
+ if (this.state === 'CLOSED')
27
+ return true;
28
+ if (this.state === 'OPEN') {
29
+ if (Date.now() - this.lastFailureTime >= this.resetTimeout) {
30
+ this.state = 'HALF_OPEN';
31
+ Logger.debug(`[circuit-breaker:${this.name}] Transitioned to HALF_OPEN`);
32
+ return true;
33
+ }
34
+ return false;
35
+ }
36
+ // HALF_OPEN: allow probes
37
+ return true;
38
+ }
39
+ /** Record a successful request */
40
+ recordSuccess() {
41
+ if (this.state === 'HALF_OPEN') {
42
+ this.successCount++;
43
+ if (this.successCount >= this.successThreshold) {
44
+ this.state = 'CLOSED';
45
+ this.failureCount = 0;
46
+ this.successCount = 0;
47
+ Logger.info(`[circuit-breaker:${this.name}] Circuit CLOSED — service healthy`);
48
+ }
49
+ }
50
+ else if (this.state === 'CLOSED') {
51
+ this.failureCount = 0;
52
+ }
53
+ }
54
+ /** Record a failed request */
55
+ recordFailure() {
56
+ this.lastFailureTime = Date.now();
57
+ if (this.state === 'HALF_OPEN') {
58
+ this.state = 'OPEN';
59
+ this.successCount = 0;
60
+ Logger.warn(`[circuit-breaker:${this.name}] Circuit OPEN — half-open probe failed`);
61
+ }
62
+ else if (this.state === 'CLOSED') {
63
+ this.failureCount++;
64
+ if (this.failureCount >= this.failureThreshold) {
65
+ this.state = 'OPEN';
66
+ Logger.warn(`[circuit-breaker:${this.name}] Circuit OPEN — ${this.failureCount} consecutive failures`);
67
+ }
68
+ }
69
+ }
70
+ getState() {
71
+ return this.state;
72
+ }
73
+ getStats() {
74
+ return {
75
+ state: this.state,
76
+ failureCount: this.failureCount,
77
+ successCount: this.successCount,
78
+ };
79
+ }
80
+ }
81
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/utils/circuit-breaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Counter, Gauge, Histogram } from 'prom-client';
2
+ export declare const requestsTotal: Counter<"server_name" | "decision" | "authn_success">;
3
+ export declare const blockedRequestsTotal: Counter<"rule" | "server_name" | "block_reason">;
4
+ export declare const authFailuresTotal: Counter<"reason" | "server_name">;
5
+ export declare const circuitBreakerState: Gauge<"server_name">;
6
+ export declare const activeSessions: Gauge<string>;
7
+ export declare const proxyLatencyMs: Histogram<"server_name">;
8
+ export declare const authLatencyMs: Histogram<"server_name">;
9
+ export declare function startMetricsServer(port?: number): Promise<void>;
10
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/utils/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,OAAO,EAAE,KAAK,EAAE,SAAS,EAAyB,MAAM,aAAa,CAAC;AAazF,eAAO,MAAM,aAAa,uDAKxB,CAAC;AAEH,eAAO,MAAM,oBAAoB,kDAK/B,CAAC;AAEH,eAAO,MAAM,iBAAiB,mCAK5B,CAAC;AAGH,eAAO,MAAM,mBAAmB,sBAK9B,CAAC;AAEH,eAAO,MAAM,cAAc,eAIzB,CAAC;AAGH,eAAO,MAAM,cAAc,0BAMzB,CAAC;AAEH,eAAO,MAAM,aAAa,0BAMxB,CAAC;AAGH,wBAAsB,kBAAkB,CAAC,IAAI,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB3E"}