@mcp-guardian/server 0.3.0 → 0.6.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 (55) hide show
  1. package/README.md +373 -136
  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/session-cache.d.ts +47 -0
  11. package/dist/auth/session-cache.d.ts.map +1 -0
  12. package/dist/auth/session-cache.js +91 -0
  13. package/dist/auth/session-cache.js.map +1 -0
  14. package/dist/cli.js +48 -3
  15. package/dist/cli.js.map +1 -1
  16. package/dist/database/database-interface.d.ts +17 -0
  17. package/dist/database/database-interface.d.ts.map +1 -0
  18. package/dist/database/database-interface.js +2 -0
  19. package/dist/database/database-interface.js.map +1 -0
  20. package/dist/database/history-db.d.ts.map +1 -1
  21. package/dist/database/history-db.js.map +1 -1
  22. package/dist/database/postgres-db.d.ts +18 -0
  23. package/dist/database/postgres-db.d.ts.map +1 -0
  24. package/dist/database/postgres-db.js +118 -0
  25. package/dist/database/postgres-db.js.map +1 -0
  26. package/dist/index.js +1 -1
  27. package/dist/policy/policy-engine.d.ts +19 -0
  28. package/dist/policy/policy-engine.d.ts.map +1 -0
  29. package/dist/policy/policy-engine.js +108 -0
  30. package/dist/policy/policy-engine.js.map +1 -0
  31. package/dist/policy/policy-types.d.ts +51 -0
  32. package/dist/policy/policy-types.d.ts.map +1 -0
  33. package/dist/policy/policy-types.js +5 -0
  34. package/dist/policy/policy-types.js.map +1 -0
  35. package/dist/policy/policy-watcher.d.ts +24 -0
  36. package/dist/policy/policy-watcher.d.ts.map +1 -0
  37. package/dist/policy/policy-watcher.js +68 -0
  38. package/dist/policy/policy-watcher.js.map +1 -0
  39. package/dist/proxy/proxy-manager.d.ts +5 -1
  40. package/dist/proxy/proxy-manager.d.ts.map +1 -1
  41. package/dist/proxy/proxy-manager.js +12 -3
  42. package/dist/proxy/proxy-manager.js.map +1 -1
  43. package/dist/proxy/proxy-server.d.ts +25 -5
  44. package/dist/proxy/proxy-server.d.ts.map +1 -1
  45. package/dist/proxy/proxy-server.js +239 -12
  46. package/dist/proxy/proxy-server.js.map +1 -1
  47. package/dist/utils/circuit-breaker.d.ts +29 -0
  48. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  49. package/dist/utils/circuit-breaker.js +81 -0
  50. package/dist/utils/circuit-breaker.js.map +1 -0
  51. package/dist/utils/structured-logger.d.ts +47 -0
  52. package/dist/utils/structured-logger.d.ts.map +1 -0
  53. package/dist/utils/structured-logger.js +48 -0
  54. package/dist/utils/structured-logger.js.map +1 -0
  55. package/package.json +18 -8
@@ -1,10 +1,20 @@
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';
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';
5
10
  /**
6
- * MCP Proxy Interceptor — sits between the AI client and an MCP server,
7
- * capturing every JSON-RPC call's token usage for real cost auditing.
11
+ * MCP Proxy Interceptor — sits between the AI client and an MCP server.
12
+ *
13
+ * v0.4: Integrated PolicyEngine for active blocking of malicious tool calls.
14
+ * v0.5: OAuth 2.1 JWT validation — validates bearer tokens before policy evaluation.
15
+ * v0.5.2: Circuit breaker for upstream MCP server failures.
16
+ * v0.5.2: Per-client rate limiting (keyed by agent sub + tool name).
17
+ * v0.5.2: Consistent SIEM fields (request_id, proxy_latency_ms, authn_success, authz_allowed).
8
18
  */
9
19
  export class McpProxyServer {
10
20
  child;
@@ -14,9 +24,20 @@ export class McpProxyServer {
14
24
  requestStartTime = 0;
15
25
  requestToolName = null;
16
26
  requestTokens = 0;
27
+ requestArguments;
17
28
  serverName;
18
- constructor(command, args, env, db, serverName) {
29
+ policyEngine;
30
+ authValidator;
31
+ sessionCache;
32
+ circuitBreaker;
33
+ /** v0.5.2: Per-client rate limit counters (key: agentSub:toolName) */
34
+ clientRateCounters = new Map();
35
+ constructor(command, args, env, db, serverName, policyEngine, authValidator) {
19
36
  this.serverName = serverName || command.split('/').pop() || command;
37
+ this.policyEngine = policyEngine || null;
38
+ this.authValidator = authValidator || null;
39
+ this.sessionCache = authValidator ? new SessionCache() : null;
40
+ this.circuitBreaker = new CircuitBreaker(this.serverName);
20
41
  this.child = spawn(command, args, {
21
42
  env: { ...process.env, ...env },
22
43
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -25,6 +46,13 @@ export class McpProxyServer {
25
46
  this.db = db;
26
47
  this.setupStdout();
27
48
  this.setupStderr();
49
+ StructuredLogger.info({
50
+ event: 'proxy_started',
51
+ serverName: this.serverName,
52
+ blockingMode: this.policyEngine ? this.policyEngine.getMode() : 'audit',
53
+ authEnabled: this.authValidator ? this.authValidator.getConfig().required : false,
54
+ circuitBreaker: this.circuitBreaker.getState(),
55
+ });
28
56
  }
29
57
  get stdin() {
30
58
  return this.child.stdin;
@@ -35,7 +63,7 @@ export class McpProxyServer {
35
63
  try {
36
64
  const msg = JSON.parse(line);
37
65
  if (msg.id && msg.id === this.currentRequestId) {
38
- // Response to our tracked tools/call request
66
+ const proxyLatencyMs = Date.now() - this.requestStartTime;
39
67
  const responseTokens = this.tokenCounter.count(line);
40
68
  const record = {
41
69
  serverName: this.serverName,
@@ -43,19 +71,18 @@ export class McpProxyServer {
43
71
  requestTokens: this.requestTokens,
44
72
  responseTokens,
45
73
  totalTokens: this.requestTokens + responseTokens,
46
- durationMs: Date.now() - this.requestStartTime,
74
+ durationMs: proxyLatencyMs,
47
75
  timestamp: new Date().toISOString(),
48
76
  };
49
- // Await the DB write so tests can read immediately
50
77
  this.db.addCallRecord(record).then(() => this.db.flush()).catch((err) => Logger.debug(`Proxy: failed to store call record: ${err?.message}`));
78
+ // Circuit breaker: success
79
+ this.circuitBreaker.recordSuccess();
51
80
  this.currentRequestId = null;
52
81
  this.requestToolName = null;
53
82
  }
54
- // Forward response to client
55
83
  process.stdout.write(line + '\n');
56
84
  }
57
85
  catch {
58
- // Non-JSON line — forward as-is
59
86
  process.stdout.write(line + '\n');
60
87
  }
61
88
  });
@@ -68,18 +95,202 @@ export class McpProxyServer {
68
95
  process.stderr.write(data);
69
96
  });
70
97
  }
98
+ sendError(id, code, message, data) {
99
+ const errorResponse = JSON.stringify({
100
+ jsonrpc: '2.0',
101
+ id,
102
+ error: { code, message, data },
103
+ });
104
+ process.stdout.write(errorResponse + '\n');
105
+ }
71
106
  /**
72
107
  * Called when the AI client writes a request to be proxied.
73
- * Tracks tools/call requests for token counting.
108
+ * Pipeline: Auth Circuit Breaker → Policy + RBAC → Forward.
74
109
  */
75
- handleClientInput(raw) {
110
+ async handleClientInput(raw) {
111
+ const requestId = randomUUID();
112
+ const proxyStartTime = Date.now();
76
113
  try {
77
114
  const msg = JSON.parse(raw);
78
115
  if (msg.method === 'tools/call' && msg.id) {
79
- this.requestStartTime = Date.now();
80
- this.currentRequestId = msg.id;
116
+ this.requestStartTime = proxyStartTime;
117
+ this.currentRequestId = msg.id; // Original msg ID for response matching
81
118
  this.requestToolName = msg.params?.name || 'unknown';
82
119
  this.requestTokens = this.tokenCounter.count(raw);
120
+ this.requestArguments = msg.params?.arguments;
121
+ const toolName = this.requestToolName || 'unknown';
122
+ let agentIdentity;
123
+ let authnSuccess = false;
124
+ // ── v0.5: OAuth 2.1 JWT validation ──────────────────
125
+ if (this.authValidator) {
126
+ const authHeader = msg.params?._meta?.auth?.Authorization
127
+ || msg.Authorization
128
+ || msg.params?.Authorization
129
+ || undefined;
130
+ const token = OAuthValidator.extractToken(authHeader);
131
+ if (!token) {
132
+ if (this.authValidator.getConfig().required) {
133
+ StructuredLogger.info({
134
+ event: 'auth_required',
135
+ requestId,
136
+ serverName: this.serverName,
137
+ toolName,
138
+ authnSuccess: false,
139
+ });
140
+ this.sendError(msg.id, -32002, 'Authentication required. Provide a valid Bearer token in the Authorization header.');
141
+ return;
142
+ }
143
+ }
144
+ else {
145
+ const result = await this.authValidator.validate(token);
146
+ authnSuccess = result.valid;
147
+ if (result.identity)
148
+ agentIdentity = result.identity;
149
+ if (!result.valid) {
150
+ StructuredLogger.logError({
151
+ event: 'oidc_auth_error',
152
+ serverName: this.serverName,
153
+ requestId,
154
+ error: `JWT validation failed: ${result.error}`,
155
+ });
156
+ if (this.authValidator.getConfig().required) {
157
+ this.sendError(msg.id, -32003, `Authentication failed: ${result.error}`);
158
+ return;
159
+ }
160
+ }
161
+ else {
162
+ // v0.6.0: Session cache — issue short-lived session to prevent JWT replay
163
+ if (this.sessionCache && result.identity) {
164
+ const session = this.sessionCache.createSession(result.identity);
165
+ StructuredLogger.info({
166
+ event: 'auth_success',
167
+ requestId,
168
+ serverName: this.serverName,
169
+ toolName,
170
+ agent: result.identity.sub,
171
+ clientId: result.identity.clientId,
172
+ sessionToken: session.token,
173
+ sessionExpiry: new Date(session.expiresAt).toISOString(),
174
+ authnSuccess: true,
175
+ });
176
+ }
177
+ else {
178
+ StructuredLogger.info({
179
+ event: 'auth_success',
180
+ requestId,
181
+ serverName: this.serverName,
182
+ toolName,
183
+ agent: result.identity?.sub,
184
+ clientId: result.identity?.clientId,
185
+ authnSuccess: true,
186
+ });
187
+ }
188
+ }
189
+ }
190
+ }
191
+ // ── v0.5.2: Circuit breaker check ──────────────────
192
+ if (!this.circuitBreaker.allowRequest()) {
193
+ StructuredLogger.info({
194
+ event: 'circuit_open',
195
+ requestId,
196
+ serverName: this.serverName,
197
+ toolName,
198
+ state: this.circuitBreaker.getState(),
199
+ });
200
+ this.sendError(msg.id, -32005, `Upstream MCP server '${this.serverName}' unavailable — circuit breaker open`);
201
+ this.circuitBreaker.recordFailure();
202
+ return;
203
+ }
204
+ // ── v0.5.1: RBAC + policy evaluation ────────────────
205
+ let authzAllowed = true;
206
+ let blockReason;
207
+ if (this.policyEngine) {
208
+ const context = {
209
+ serverName: this.serverName,
210
+ toolName,
211
+ arguments: this.requestArguments,
212
+ requestId,
213
+ requestTokens: this.requestTokens,
214
+ timestamp: new Date().toISOString(),
215
+ agentIdentity,
216
+ };
217
+ const decision = this.policyEngine.evaluate(context);
218
+ StructuredLogger.logPolicyDecision({
219
+ event: 'policy_decision',
220
+ requestId,
221
+ serverName: this.serverName,
222
+ toolName,
223
+ decision,
224
+ context,
225
+ });
226
+ if (decision.action === 'block') {
227
+ authzAllowed = false;
228
+ blockReason = `policy:${decision.rule}:${decision.reason}`;
229
+ StructuredLogger.logBlocked({
230
+ event: 'tool_blocked',
231
+ requestId,
232
+ serverName: this.serverName,
233
+ toolName,
234
+ reason: `policy_rule=${decision.rule} | reason=${decision.reason}`,
235
+ rule: decision.rule,
236
+ });
237
+ StructuredLogger.info({
238
+ event: 'request_denied',
239
+ requestId,
240
+ serverName: this.serverName,
241
+ toolName,
242
+ authnSuccess,
243
+ authzAllowed,
244
+ blockReason,
245
+ proxyLatencyMs: Date.now() - proxyStartTime,
246
+ });
247
+ this.sendError(msg.id, -32001, `Blocked by MCP Guardian policy: ${decision.reason}`, {
248
+ rule: decision.rule,
249
+ policy: this.policyEngine.getMode(),
250
+ });
251
+ return;
252
+ }
253
+ // v0.5.2: Per-client rate limiting
254
+ if (agentIdentity) {
255
+ const rateKey = `${agentIdentity.sub}:${toolName}`;
256
+ const now = Date.now();
257
+ let counter = this.clientRateCounters.get(rateKey);
258
+ if (!counter || now > counter.resetAt) {
259
+ counter = { count: 1, resetAt: now + 60000 };
260
+ this.clientRateCounters.set(rateKey, counter);
261
+ }
262
+ else {
263
+ counter.count++;
264
+ }
265
+ // Check if any RBAC rule with per-client rate limit fires
266
+ const perClientLimit = this.checkPerClientRateLimit(agentIdentity, toolName, counter.count);
267
+ if (perClientLimit) {
268
+ StructuredLogger.info({
269
+ event: 'request_denied',
270
+ requestId,
271
+ serverName: this.serverName,
272
+ toolName,
273
+ authnSuccess,
274
+ authzAllowed: false,
275
+ blockReason: perClientLimit,
276
+ proxyLatencyMs: Date.now() - proxyStartTime,
277
+ });
278
+ this.sendError(msg.id, -32004, `Rate limit exceeded for agent '${agentIdentity.sub}': ${perClientLimit}`);
279
+ return;
280
+ }
281
+ }
282
+ }
283
+ // ── Log successful forwarding ───────────────────────
284
+ StructuredLogger.info({
285
+ event: 'request_forwarded',
286
+ requestId,
287
+ serverName: this.serverName,
288
+ toolName,
289
+ authnSuccess,
290
+ authzAllowed,
291
+ proxyLatencyMs: Date.now() - proxyStartTime,
292
+ agent: agentIdentity?.sub,
293
+ });
83
294
  }
84
295
  }
85
296
  catch {
@@ -87,6 +298,22 @@ export class McpProxyServer {
87
298
  }
88
299
  this.child.stdin?.write(raw + '\n');
89
300
  }
301
+ /**
302
+ * Check per-client rate limits against RBAC rules.
303
+ * Returns block reason string or null.
304
+ */
305
+ checkPerClientRateLimit(identity, toolName, currentCount) {
306
+ if (!this.policyEngine)
307
+ return null;
308
+ // Per-client limits are tracked via RBAC scopes — if agent has "basic" scope, check against "basic" rate limit rule
309
+ const scopes = identity.scopes || [];
310
+ // Simple: if the agent has no special scopes and we've hit a hard limit
311
+ // In a full implementation, this would check per-scope/per-client limits from policy
312
+ if (scopes.length === 0 && currentCount > 100) {
313
+ return `Per-client rate limit exceeded: ${currentCount}/100 calls per minute (agent: ${identity.sub})`;
314
+ }
315
+ return null;
316
+ }
90
317
  kill() {
91
318
  try {
92
319
  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":"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"}
@@ -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,47 @@
1
+ import { PolicyDecision, CallContext } from '../policy/policy-types.js';
2
+ export interface AuditLogEntry {
3
+ event: 'policy_decision';
4
+ requestId: string | number;
5
+ serverName: string;
6
+ toolName: string;
7
+ decision: PolicyDecision;
8
+ context: CallContext;
9
+ }
10
+ export interface BlockLogEntry {
11
+ event: 'tool_blocked';
12
+ requestId: string | number;
13
+ serverName: string;
14
+ toolName: string;
15
+ reason: string;
16
+ rule: string;
17
+ }
18
+ export interface ErrorLogEntry {
19
+ event: 'proxy_error' | 'oidc_discovery_error' | 'oidc_auth_error';
20
+ requestId?: string | number;
21
+ serverName: string;
22
+ error: string;
23
+ stack?: string;
24
+ }
25
+ export declare class StructuredLogger {
26
+ /**
27
+ * Log a policy decision (pass, flag, or block).
28
+ */
29
+ static logPolicyDecision(entry: AuditLogEntry): void;
30
+ /**
31
+ * Log a blocked tool call — always at WARN level for SIEM alerting.
32
+ */
33
+ static logBlocked(entry: BlockLogEntry): void;
34
+ /**
35
+ * Log proxy internal errors.
36
+ */
37
+ static logError(entry: ErrorLogEntry): void;
38
+ /**
39
+ * Log general proxy lifecycle events.
40
+ */
41
+ static info(msg: object | string): void;
42
+ /**
43
+ * Debug-level log for development.
44
+ */
45
+ static debug(msg: object | string): void;
46
+ }
47
+ //# sourceMappingURL=structured-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-logger.d.ts","sourceRoot":"","sources":["../../src/utils/structured-logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAkBxE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,iBAAiB,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,aAAa,GAAG,sBAAsB,GAAG,iBAAiB,CAAC;IAClE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAIpD;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAI7C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAI3C;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAGzC"}
@@ -0,0 +1,48 @@
1
+ import pino from 'pino';
2
+ /**
3
+ * Structured JSON logger for enterprise SIEM ingestion.
4
+ * Uses pino for high-performance structured logging with request-ID tracing.
5
+ */
6
+ const level = process.env.LOG_LEVEL || 'info';
7
+ const logger = pino({
8
+ level: level.toLowerCase(),
9
+ formatters: {
10
+ level(label) {
11
+ return { level: label };
12
+ },
13
+ },
14
+ timestamp: pino.stdTimeFunctions.isoTime,
15
+ });
16
+ export class StructuredLogger {
17
+ /**
18
+ * Log a policy decision (pass, flag, or block).
19
+ */
20
+ static logPolicyDecision(entry) {
21
+ logger.info(entry);
22
+ }
23
+ /**
24
+ * Log a blocked tool call — always at WARN level for SIEM alerting.
25
+ */
26
+ static logBlocked(entry) {
27
+ logger.warn(entry);
28
+ }
29
+ /**
30
+ * Log proxy internal errors.
31
+ */
32
+ static logError(entry) {
33
+ logger.error(entry);
34
+ }
35
+ /**
36
+ * Log general proxy lifecycle events.
37
+ */
38
+ static info(msg) {
39
+ logger.info(msg);
40
+ }
41
+ /**
42
+ * Debug-level log for development.
43
+ */
44
+ static debug(msg) {
45
+ logger.debug(msg);
46
+ }
47
+ }
48
+ //# sourceMappingURL=structured-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-logger.js","sourceRoot":"","sources":["../../src/utils/structured-logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;;GAGG;AACH,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC;AAE9C,MAAM,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE;IAC1B,UAAU,EAAE;QACV,KAAK,CAAC,KAAK;YACT,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC1B,CAAC;KACF;IACD,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC,OAAO;CACzC,CAAC,CAAC;AA4BH,MAAM,OAAO,gBAAgB;IAC3B;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,KAAoB;QAC3C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,KAAoB;QACpC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAoB;QAClC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,GAAoB;QAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,GAAoB;QAC/B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;CACF"}
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@mcp-guardian/server",
3
- "version": "0.3.0",
3
+ "version": "0.6.0",
4
4
  "description": "Security, cost, and health audit for MCP infrastructure",
5
5
  "type": "module",
6
- "files": ["dist"],
6
+ "files": [
7
+ "dist"
8
+ ],
7
9
  "main": "./dist/index.js",
8
10
  "bin": {
9
11
  "mcp-guardian": "./dist/cli.js"
@@ -13,7 +15,7 @@
13
15
  },
14
16
  "repository": "github:rudraneel93/mcp-guardian",
15
17
  "bugs": "https://github.com/rudraneel93/mcp-guardian/issues",
16
- "homepage": "https://github.com/rudraneel93/mcp-guardian#readme",
18
+ "homepage": "https://www.npmjs.com/package/@mcp-guardian/server",
17
19
  "keywords": [
18
20
  "mcp",
19
21
  "model-context-protocol",
@@ -36,17 +38,25 @@
36
38
  },
37
39
  "dependencies": {
38
40
  "@modelcontextprotocol/sdk": "^1.0.0",
39
- "tiktoken": "^1.0.15",
40
- "sql.js": "^1.11.0",
41
41
  "axios": "^1.7.0",
42
- "commander": "^12.0.0",
43
42
  "chalk": "^5.3.0",
43
+ "chokidar": "^5.0.0",
44
+ "commander": "^12.0.0",
45
+ "jose": "^6.2.3",
46
+ "js-yaml": "^4.1.1",
47
+ "pg": "^8.20.0",
48
+ "pino": "^10.3.1",
49
+ "sql.js": "^1.11.0",
50
+ "tiktoken": "^1.0.15",
44
51
  "zod": "^3.23.0"
45
52
  },
46
53
  "devDependencies": {
54
+ "@types/chokidar": "^1.7.5",
55
+ "@types/js-yaml": "^4.0.9",
47
56
  "@types/node": "^20.0.0",
48
- "typescript": "^5.4.0",
57
+ "@types/pg": "^8.20.0",
49
58
  "tsx": "^4.7.0",
59
+ "typescript": "^5.4.0",
50
60
  "vitest": "^1.6.0"
51
61
  }
52
- }
62
+ }