@mcp-audit-gateway/core 0.1.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 (145) hide show
  1. package/.github/workflows/npm-publish.yml +21 -0
  2. package/CONTRIBUTING.md +41 -0
  3. package/LICENSE +21 -0
  4. package/README.md +156 -0
  5. package/dist/attestation/audit-log.d.ts +25 -0
  6. package/dist/attestation/audit-log.d.ts.map +1 -0
  7. package/dist/attestation/audit-log.js +95 -0
  8. package/dist/attestation/audit-log.js.map +1 -0
  9. package/dist/attestation/bugfix.test.d.ts +2 -0
  10. package/dist/attestation/bugfix.test.d.ts.map +1 -0
  11. package/dist/attestation/bugfix.test.js +103 -0
  12. package/dist/attestation/bugfix.test.js.map +1 -0
  13. package/dist/attestation/chain.test.d.ts +2 -0
  14. package/dist/attestation/chain.test.d.ts.map +1 -0
  15. package/dist/attestation/chain.test.js +153 -0
  16. package/dist/attestation/chain.test.js.map +1 -0
  17. package/dist/attestation/keygen.d.ts +5 -0
  18. package/dist/attestation/keygen.d.ts.map +1 -0
  19. package/dist/attestation/keygen.js +12 -0
  20. package/dist/attestation/keygen.js.map +1 -0
  21. package/dist/attestation/signer.d.ts +25 -0
  22. package/dist/attestation/signer.d.ts.map +1 -0
  23. package/dist/attestation/signer.js +93 -0
  24. package/dist/attestation/signer.js.map +1 -0
  25. package/dist/attestation/signer.test.d.ts +2 -0
  26. package/dist/attestation/signer.test.d.ts.map +1 -0
  27. package/dist/attestation/signer.test.js +62 -0
  28. package/dist/attestation/signer.test.js.map +1 -0
  29. package/dist/attestation/verify.d.ts +26 -0
  30. package/dist/attestation/verify.d.ts.map +1 -0
  31. package/dist/attestation/verify.js +104 -0
  32. package/dist/attestation/verify.js.map +1 -0
  33. package/dist/attestation/verify.test.d.ts +2 -0
  34. package/dist/attestation/verify.test.d.ts.map +1 -0
  35. package/dist/attestation/verify.test.js +79 -0
  36. package/dist/attestation/verify.test.js.map +1 -0
  37. package/dist/cli.d.ts +3 -0
  38. package/dist/cli.d.ts.map +1 -0
  39. package/dist/cli.js +364 -0
  40. package/dist/cli.js.map +1 -0
  41. package/dist/index.d.ts +12 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +12 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/integration.test.d.ts +2 -0
  46. package/dist/integration.test.d.ts.map +1 -0
  47. package/dist/integration.test.js +88 -0
  48. package/dist/integration.test.js.map +1 -0
  49. package/dist/policy/engine.d.ts +24 -0
  50. package/dist/policy/engine.d.ts.map +1 -0
  51. package/dist/policy/engine.js +130 -0
  52. package/dist/policy/engine.js.map +1 -0
  53. package/dist/policy/engine.test.d.ts +2 -0
  54. package/dist/policy/engine.test.d.ts.map +1 -0
  55. package/dist/policy/engine.test.js +80 -0
  56. package/dist/policy/engine.test.js.map +1 -0
  57. package/dist/proxy/gateway.d.ts +54 -0
  58. package/dist/proxy/gateway.d.ts.map +1 -0
  59. package/dist/proxy/gateway.js +245 -0
  60. package/dist/proxy/gateway.js.map +1 -0
  61. package/dist/proxy/gateway.test.d.ts +2 -0
  62. package/dist/proxy/gateway.test.d.ts.map +1 -0
  63. package/dist/proxy/gateway.test.js +93 -0
  64. package/dist/proxy/gateway.test.js.map +1 -0
  65. package/dist/proxy/mcp-server-adapter.d.ts +21 -0
  66. package/dist/proxy/mcp-server-adapter.d.ts.map +1 -0
  67. package/dist/proxy/mcp-server-adapter.js +98 -0
  68. package/dist/proxy/mcp-server-adapter.js.map +1 -0
  69. package/dist/proxy/mcp-server-adapter.test.d.ts +2 -0
  70. package/dist/proxy/mcp-server-adapter.test.d.ts.map +1 -0
  71. package/dist/proxy/mcp-server-adapter.test.js +160 -0
  72. package/dist/proxy/mcp-server-adapter.test.js.map +1 -0
  73. package/dist/proxy/upstream-manager.d.ts +49 -0
  74. package/dist/proxy/upstream-manager.d.ts.map +1 -0
  75. package/dist/proxy/upstream-manager.js +246 -0
  76. package/dist/proxy/upstream-manager.js.map +1 -0
  77. package/dist/proxy/upstream-manager.test.d.ts +2 -0
  78. package/dist/proxy/upstream-manager.test.d.ts.map +1 -0
  79. package/dist/proxy/upstream-manager.test.js +413 -0
  80. package/dist/proxy/upstream-manager.test.js.map +1 -0
  81. package/dist/telemetry/logger.d.ts +26 -0
  82. package/dist/telemetry/logger.d.ts.map +1 -0
  83. package/dist/telemetry/logger.js +48 -0
  84. package/dist/telemetry/logger.js.map +1 -0
  85. package/dist/telemetry/logger.test.d.ts +2 -0
  86. package/dist/telemetry/logger.test.d.ts.map +1 -0
  87. package/dist/telemetry/logger.test.js +124 -0
  88. package/dist/telemetry/logger.test.js.map +1 -0
  89. package/dist/telemetry/metrics.d.ts +41 -0
  90. package/dist/telemetry/metrics.d.ts.map +1 -0
  91. package/dist/telemetry/metrics.js +64 -0
  92. package/dist/telemetry/metrics.js.map +1 -0
  93. package/dist/telemetry/metrics.test.d.ts +2 -0
  94. package/dist/telemetry/metrics.test.d.ts.map +1 -0
  95. package/dist/telemetry/metrics.test.js +93 -0
  96. package/dist/telemetry/metrics.test.js.map +1 -0
  97. package/dist/telemetry/tracer.d.ts +16 -0
  98. package/dist/telemetry/tracer.d.ts.map +1 -0
  99. package/dist/telemetry/tracer.js +71 -0
  100. package/dist/telemetry/tracer.js.map +1 -0
  101. package/dist/types.d.ts +477 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/types.js +68 -0
  104. package/dist/types.js.map +1 -0
  105. package/dist/wrap/proxy.d.ts +2 -0
  106. package/dist/wrap/proxy.d.ts.map +1 -0
  107. package/dist/wrap/proxy.js +152 -0
  108. package/dist/wrap/proxy.js.map +1 -0
  109. package/dist/wrap/proxy.test.d.ts +2 -0
  110. package/dist/wrap/proxy.test.d.ts.map +1 -0
  111. package/dist/wrap/proxy.test.js +155 -0
  112. package/dist/wrap/proxy.test.js.map +1 -0
  113. package/examples/README.md +33 -0
  114. package/examples/claude-desktop.json +50 -0
  115. package/examples/multi-agent-production.json +72 -0
  116. package/gateway.config.example.json +61 -0
  117. package/package.json +49 -0
  118. package/src/attestation/audit-log.ts +126 -0
  119. package/src/attestation/bugfix.test.ts +113 -0
  120. package/src/attestation/chain.test.ts +188 -0
  121. package/src/attestation/keygen.ts +18 -0
  122. package/src/attestation/signer.test.ts +75 -0
  123. package/src/attestation/signer.ts +105 -0
  124. package/src/attestation/verify.test.ts +86 -0
  125. package/src/attestation/verify.ts +131 -0
  126. package/src/cli.ts +407 -0
  127. package/src/index.ts +21 -0
  128. package/src/integration.test.ts +108 -0
  129. package/src/policy/engine.test.ts +95 -0
  130. package/src/policy/engine.ts +162 -0
  131. package/src/proxy/gateway.test.ts +108 -0
  132. package/src/proxy/gateway.ts +328 -0
  133. package/src/proxy/mcp-server-adapter.test.ts +197 -0
  134. package/src/proxy/mcp-server-adapter.ts +140 -0
  135. package/src/proxy/upstream-manager.test.ts +534 -0
  136. package/src/proxy/upstream-manager.ts +326 -0
  137. package/src/telemetry/logger.test.ts +139 -0
  138. package/src/telemetry/logger.ts +72 -0
  139. package/src/telemetry/metrics.test.ts +125 -0
  140. package/src/telemetry/metrics.ts +83 -0
  141. package/src/telemetry/tracer.ts +90 -0
  142. package/src/types.ts +113 -0
  143. package/src/wrap/proxy.test.ts +175 -0
  144. package/src/wrap/proxy.ts +192 -0
  145. package/tsconfig.json +18 -0
@@ -0,0 +1,124 @@
1
+ import { describe, it, expect, beforeEach, vi } from "vitest";
2
+ import { Logger } from "./logger.js";
3
+ describe("Logger", () => {
4
+ let lines;
5
+ let logger;
6
+ beforeEach(() => {
7
+ lines = [];
8
+ logger = new Logger({
9
+ component: "test",
10
+ level: "debug",
11
+ output: (line) => lines.push(line),
12
+ });
13
+ });
14
+ describe("structured output", () => {
15
+ it("outputs valid JSON lines", () => {
16
+ logger.info("hello world");
17
+ expect(lines).toHaveLength(1);
18
+ const parsed = JSON.parse(lines[0]);
19
+ expect(parsed).toHaveProperty("timestamp");
20
+ expect(parsed).toHaveProperty("level", "info");
21
+ expect(parsed).toHaveProperty("component", "test");
22
+ expect(parsed).toHaveProperty("message", "hello world");
23
+ });
24
+ it("includes ISO 8601 timestamp", () => {
25
+ logger.info("msg");
26
+ const parsed = JSON.parse(lines[0]);
27
+ expect(() => new Date(parsed.timestamp)).not.toThrow();
28
+ expect(parsed.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/);
29
+ });
30
+ it("includes arbitrary context fields", () => {
31
+ logger.info("tool call", { tool: "my_tool", durationMs: 42, upstream: "server-a" });
32
+ const parsed = JSON.parse(lines[0]);
33
+ expect(parsed.tool).toBe("my_tool");
34
+ expect(parsed.durationMs).toBe(42);
35
+ expect(parsed.upstream).toBe("server-a");
36
+ });
37
+ });
38
+ describe("log levels", () => {
39
+ it("outputs debug messages when level is debug", () => {
40
+ logger.debug("trace msg");
41
+ expect(lines).toHaveLength(1);
42
+ expect(JSON.parse(lines[0]).level).toBe("debug");
43
+ });
44
+ it("outputs info messages", () => {
45
+ logger.info("info msg");
46
+ expect(lines).toHaveLength(1);
47
+ expect(JSON.parse(lines[0]).level).toBe("info");
48
+ });
49
+ it("outputs warn messages", () => {
50
+ logger.warn("warning");
51
+ expect(lines).toHaveLength(1);
52
+ expect(JSON.parse(lines[0]).level).toBe("warn");
53
+ });
54
+ it("outputs error messages", () => {
55
+ logger.error("failure");
56
+ expect(lines).toHaveLength(1);
57
+ expect(JSON.parse(lines[0]).level).toBe("error");
58
+ });
59
+ });
60
+ describe("level filtering", () => {
61
+ it("suppresses debug when level is info", () => {
62
+ const infoLogger = new Logger({
63
+ component: "test",
64
+ level: "info",
65
+ output: (line) => lines.push(line),
66
+ });
67
+ infoLogger.debug("should not appear");
68
+ infoLogger.info("should appear");
69
+ expect(lines).toHaveLength(1);
70
+ expect(JSON.parse(lines[0]).message).toBe("should appear");
71
+ });
72
+ it("suppresses info and debug when level is warn", () => {
73
+ const warnLogger = new Logger({
74
+ component: "test",
75
+ level: "warn",
76
+ output: (line) => lines.push(line),
77
+ });
78
+ warnLogger.debug("no");
79
+ warnLogger.info("no");
80
+ warnLogger.warn("yes");
81
+ warnLogger.error("yes");
82
+ expect(lines).toHaveLength(2);
83
+ });
84
+ it("only outputs error when level is error", () => {
85
+ const errorLogger = new Logger({
86
+ component: "test",
87
+ level: "error",
88
+ output: (line) => lines.push(line),
89
+ });
90
+ errorLogger.debug("no");
91
+ errorLogger.info("no");
92
+ errorLogger.warn("no");
93
+ errorLogger.error("yes");
94
+ expect(lines).toHaveLength(1);
95
+ });
96
+ });
97
+ describe("child logger", () => {
98
+ it("creates child with different component", () => {
99
+ const child = logger.child({ component: "sub-system" });
100
+ child.info("child message");
101
+ const parsed = JSON.parse(lines[0]);
102
+ expect(parsed.component).toBe("sub-system");
103
+ });
104
+ it("child inherits parent output", () => {
105
+ const child = logger.child({ component: "child" });
106
+ child.warn("from child");
107
+ expect(lines).toHaveLength(1);
108
+ expect(JSON.parse(lines[0]).component).toBe("child");
109
+ });
110
+ });
111
+ describe("default output", () => {
112
+ it("writes to stderr by default", () => {
113
+ const stderrWrite = vi.spyOn(process.stderr, "write").mockImplementation(() => true);
114
+ const defaultLogger = new Logger({ component: "default-test", level: "info" });
115
+ defaultLogger.info("stderr test");
116
+ expect(stderrWrite).toHaveBeenCalled();
117
+ const written = stderrWrite.mock.calls[0][0];
118
+ expect(written).toContain("stderr test");
119
+ expect(written.endsWith("\n")).toBe(true);
120
+ stderrWrite.mockRestore();
121
+ });
122
+ });
123
+ });
124
+ //# sourceMappingURL=logger.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../../src/telemetry/logger.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { Counter, Histogram, Gauge } from "@opentelemetry/api";
2
+ import type { TelemetryConfig } from "../types.js";
3
+ export interface MetricLabels {
4
+ toolCall: {
5
+ namespace: string;
6
+ tool: string;
7
+ principal: string;
8
+ success: string;
9
+ };
10
+ duration: {
11
+ namespace: string;
12
+ upstream: string;
13
+ };
14
+ upstreamStatus: {
15
+ upstream: string;
16
+ status: string;
17
+ };
18
+ policyDenial: {
19
+ principal: string;
20
+ tool: string;
21
+ reason: string;
22
+ };
23
+ }
24
+ export declare class GatewayMetrics {
25
+ private meter;
26
+ private _toolCallsTotal;
27
+ private _toolCallDurationMs;
28
+ private _upstreamStatus;
29
+ private _policyDenialsTotal;
30
+ private _enabled;
31
+ constructor(config: TelemetryConfig);
32
+ recordToolCall(labels: MetricLabels["toolCall"]): void;
33
+ recordDuration(durationMs: number, labels: MetricLabels["duration"]): void;
34
+ setUpstreamStatus(upstream: string, status: string, value: number): void;
35
+ recordPolicyDenial(labels: MetricLabels["policyDenial"]): void;
36
+ get toolCallsTotal(): Counter;
37
+ get toolCallDurationMs(): Histogram;
38
+ get upstreamStatus(): Gauge;
39
+ get policyDenialsTotal(): Counter;
40
+ }
41
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAS,MAAM,oBAAoB,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClF,QAAQ,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,cAAc,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,YAAY,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,mBAAmB,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAU;gBAEd,MAAM,EAAE,eAAe;IA0BnC,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI;IAKtD,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI;IAK1E,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKxE,kBAAkB,CAAC,MAAM,EAAE,YAAY,CAAC,cAAc,CAAC,GAAG,IAAI;IAK9D,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,kBAAkB,IAAI,SAAS,CAElC;IAED,IAAI,cAAc,IAAI,KAAK,CAE1B;IAED,IAAI,kBAAkB,IAAI,OAAO,CAEhC;CACF"}
@@ -0,0 +1,64 @@
1
+ import { metrics, ValueType } from "@opentelemetry/api";
2
+ const METER_NAME = "mcp-audit-gateway";
3
+ export class GatewayMetrics {
4
+ meter;
5
+ _toolCallsTotal;
6
+ _toolCallDurationMs;
7
+ _upstreamStatus;
8
+ _policyDenialsTotal;
9
+ _enabled;
10
+ constructor(config) {
11
+ this._enabled = config.enabled;
12
+ this.meter = metrics.getMeter(METER_NAME, "0.1.0");
13
+ this._toolCallsTotal = this.meter.createCounter("mcp.gateway.tool_calls_total", {
14
+ description: "Total number of tool calls processed by the gateway",
15
+ valueType: ValueType.INT,
16
+ });
17
+ this._toolCallDurationMs = this.meter.createHistogram("mcp.gateway.tool_call_duration_ms", {
18
+ description: "Duration of tool call execution in milliseconds",
19
+ unit: "ms",
20
+ valueType: ValueType.DOUBLE,
21
+ });
22
+ this._upstreamStatus = this.meter.createGauge("mcp.gateway.upstream_status", {
23
+ description: "Current status of upstream servers (1=healthy, 0=unhealthy)",
24
+ valueType: ValueType.INT,
25
+ });
26
+ this._policyDenialsTotal = this.meter.createCounter("mcp.gateway.policy_denials_total", {
27
+ description: "Total number of policy denials",
28
+ valueType: ValueType.INT,
29
+ });
30
+ }
31
+ recordToolCall(labels) {
32
+ if (!this._enabled)
33
+ return;
34
+ this._toolCallsTotal.add(1, labels);
35
+ }
36
+ recordDuration(durationMs, labels) {
37
+ if (!this._enabled)
38
+ return;
39
+ this._toolCallDurationMs.record(durationMs, labels);
40
+ }
41
+ setUpstreamStatus(upstream, status, value) {
42
+ if (!this._enabled)
43
+ return;
44
+ this._upstreamStatus.record(value, { upstream, status });
45
+ }
46
+ recordPolicyDenial(labels) {
47
+ if (!this._enabled)
48
+ return;
49
+ this._policyDenialsTotal.add(1, labels);
50
+ }
51
+ get toolCallsTotal() {
52
+ return this._toolCallsTotal;
53
+ }
54
+ get toolCallDurationMs() {
55
+ return this._toolCallDurationMs;
56
+ }
57
+ get upstreamStatus() {
58
+ return this._upstreamStatus;
59
+ }
60
+ get policyDenialsTotal() {
61
+ return this._policyDenialsTotal;
62
+ }
63
+ }
64
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,UAAU,GAAG,mBAAmB,CAAC;AASvC,MAAM,OAAO,cAAc;IACjB,KAAK,CAAQ;IACb,eAAe,CAAU;IACzB,mBAAmB,CAAY;IAC/B,eAAe,CAAQ;IACvB,mBAAmB,CAAU;IAC7B,QAAQ,CAAU;IAE1B,YAAY,MAAuB;QACjC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,8BAA8B,EAAE;YAC9E,WAAW,EAAE,qDAAqD;YAClE,SAAS,EAAE,SAAS,CAAC,GAAG;SACzB,CAAC,CAAC;QAEH,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,mCAAmC,EAAE;YACzF,WAAW,EAAE,iDAAiD;YAC9D,IAAI,EAAE,IAAI;YACV,SAAS,EAAE,SAAS,CAAC,MAAM;SAC5B,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,6BAA6B,EAAE;YAC3E,WAAW,EAAE,6DAA6D;YAC1E,SAAS,EAAE,SAAS,CAAC,GAAG;SACzB,CAAC,CAAC;QAEH,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,kCAAkC,EAAE;YACtF,WAAW,EAAE,gCAAgC;YAC7C,SAAS,EAAE,SAAS,CAAC,GAAG;SACzB,CAAC,CAAC;IACL,CAAC;IAED,cAAc,CAAC,MAAgC;QAC7C,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,cAAc,CAAC,UAAkB,EAAE,MAAgC;QACjE,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IAED,iBAAiB,CAAC,QAAgB,EAAE,MAAc,EAAE,KAAa;QAC/D,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,kBAAkB,CAAC,MAAoC;QACrD,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,IAAI,kBAAkB;QACpB,OAAO,IAAI,CAAC,mBAAmB,CAAC;IAClC,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,IAAI,kBAAkB;QACpB,OAAO,IAAI,CAAC,mBAAmB,CAAC;IAClC,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=metrics.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.test.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,93 @@
1
+ import { describe, it, expect, beforeEach, vi } from "vitest";
2
+ import { metrics } from "@opentelemetry/api";
3
+ import { GatewayMetrics } from "./metrics.js";
4
+ const testConfig = {
5
+ enabled: true,
6
+ serviceName: "test-gateway",
7
+ sampleRate: 1.0,
8
+ };
9
+ describe("GatewayMetrics", () => {
10
+ let gatewayMetrics;
11
+ beforeEach(() => {
12
+ gatewayMetrics = new GatewayMetrics(testConfig);
13
+ });
14
+ describe("construction", () => {
15
+ it("creates all metric instruments", () => {
16
+ expect(gatewayMetrics.toolCallsTotal).toBeDefined();
17
+ expect(gatewayMetrics.toolCallDurationMs).toBeDefined();
18
+ expect(gatewayMetrics.upstreamStatus).toBeDefined();
19
+ expect(gatewayMetrics.policyDenialsTotal).toBeDefined();
20
+ });
21
+ });
22
+ describe("recordToolCall", () => {
23
+ it("increments tool_calls_total counter without throwing", () => {
24
+ expect(() => gatewayMetrics.recordToolCall({
25
+ namespace: "test",
26
+ tool: "test/my_tool",
27
+ principal: "agent:user1",
28
+ success: "true",
29
+ })).not.toThrow();
30
+ });
31
+ it("accepts different label combinations", () => {
32
+ expect(() => gatewayMetrics.recordToolCall({
33
+ namespace: "prod",
34
+ tool: "prod/fetch_data",
35
+ principal: "anonymous",
36
+ success: "false",
37
+ })).not.toThrow();
38
+ });
39
+ });
40
+ describe("recordDuration", () => {
41
+ it("records duration histogram without throwing", () => {
42
+ expect(() => gatewayMetrics.recordDuration(42.5, {
43
+ namespace: "test",
44
+ upstream: "my-server",
45
+ })).not.toThrow();
46
+ });
47
+ it("handles zero duration", () => {
48
+ expect(() => gatewayMetrics.recordDuration(0, {
49
+ namespace: "test",
50
+ upstream: "fast-server",
51
+ })).not.toThrow();
52
+ });
53
+ it("handles large durations", () => {
54
+ expect(() => gatewayMetrics.recordDuration(30000, {
55
+ namespace: "test",
56
+ upstream: "slow-server",
57
+ })).not.toThrow();
58
+ });
59
+ });
60
+ describe("setUpstreamStatus", () => {
61
+ it("records gauge value for healthy status", () => {
62
+ expect(() => gatewayMetrics.setUpstreamStatus("my-upstream", "healthy", 1)).not.toThrow();
63
+ });
64
+ it("records gauge value for unhealthy status", () => {
65
+ expect(() => gatewayMetrics.setUpstreamStatus("my-upstream", "unavailable", 0)).not.toThrow();
66
+ });
67
+ });
68
+ describe("recordPolicyDenial", () => {
69
+ it("increments policy_denials_total counter without throwing", () => {
70
+ expect(() => gatewayMetrics.recordPolicyDenial({
71
+ principal: "agent:blocked",
72
+ tool: "test/dangerous_tool",
73
+ reason: "unauthorized",
74
+ })).not.toThrow();
75
+ });
76
+ it("records denial with rate limit reason", () => {
77
+ expect(() => gatewayMetrics.recordPolicyDenial({
78
+ principal: "agent:heavy",
79
+ tool: "test/expensive_tool",
80
+ reason: "rate_limit_exceeded",
81
+ })).not.toThrow();
82
+ });
83
+ });
84
+ describe("with custom MeterProvider", () => {
85
+ it("uses the global meter provider", () => {
86
+ const getMeterSpy = vi.spyOn(metrics, "getMeter");
87
+ new GatewayMetrics(testConfig);
88
+ expect(getMeterSpy).toHaveBeenCalledWith("mcp-audit-gateway", "0.1.0");
89
+ getMeterSpy.mockRestore();
90
+ });
91
+ });
92
+ });
93
+ //# sourceMappingURL=metrics.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.test.js","sourceRoot":"","sources":["../../src/telemetry/metrics.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Span } from "@opentelemetry/api";
2
+ import type { TelemetryConfig } from "../types.js";
3
+ export declare class GatewayTracer {
4
+ private config;
5
+ private tracer;
6
+ constructor(config: TelemetryConfig);
7
+ startRouteSpan(method: string, toolName: string | undefined, upstream: string, traceContext?: {
8
+ traceparent?: string;
9
+ tracestate?: string;
10
+ }): Span;
11
+ endSpan(span: Span, success: boolean, errorCode?: number): void;
12
+ recordDuration(span: Span, durationMs: number): void;
13
+ getTraceParent(span: Span): string;
14
+ private extractContext;
15
+ }
16
+ //# sourceMappingURL=tracer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../src/telemetry/tracer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAuB,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAkBnD,qBAAa,aAAa;IAGZ,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAAS;gBAEH,MAAM,EAAE,eAAe;IAI3C,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3D,IAAI;IA+BP,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAU/D,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAIpD,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAMlC,OAAO,CAAC,cAAc;CAMvB"}
@@ -0,0 +1,71 @@
1
+ import { trace, context, SpanKind, SpanStatusCode, propagation, INVALID_SPAN_CONTEXT } from "@opentelemetry/api";
2
+ const NOOP_SPAN = {
3
+ spanContext() { return INVALID_SPAN_CONTEXT; },
4
+ setAttribute() { return this; },
5
+ setAttributes() { return this; },
6
+ addEvent() { return this; },
7
+ addLink() { return this; },
8
+ addLinks() { return this; },
9
+ setStatus() { return this; },
10
+ updateName() { return this; },
11
+ end() { },
12
+ isRecording() { return false; },
13
+ recordException() { },
14
+ };
15
+ const TRACER_NAME = "mcp-audit-gateway";
16
+ export class GatewayTracer {
17
+ config;
18
+ tracer;
19
+ constructor(config) {
20
+ this.config = config;
21
+ this.tracer = trace.getTracer(TRACER_NAME, "0.1.0");
22
+ }
23
+ startRouteSpan(method, toolName, upstream, traceContext) {
24
+ if (!this.config.enabled)
25
+ return NOOP_SPAN;
26
+ const spanName = toolName
27
+ ? `mcp.gateway/route ${upstream}`
28
+ : `mcp.${method}`;
29
+ const parentContext = traceContext?.traceparent
30
+ ? this.extractContext(traceContext)
31
+ : context.active();
32
+ const span = this.tracer.startSpan(spanName, {
33
+ kind: SpanKind.INTERNAL,
34
+ attributes: {
35
+ "mcp.method": method,
36
+ "mcp.gateway.name": this.config.serviceName,
37
+ "mcp.gateway.route.target": upstream,
38
+ },
39
+ }, parentContext);
40
+ if (toolName) {
41
+ span.setAttribute("mcp.tool.name", toolName);
42
+ }
43
+ return span;
44
+ }
45
+ endSpan(span, success, errorCode) {
46
+ if (!success) {
47
+ span.setStatus({ code: SpanStatusCode.ERROR });
48
+ if (errorCode != null) {
49
+ span.setAttribute("mcp.error.code", errorCode);
50
+ }
51
+ }
52
+ span.end();
53
+ }
54
+ recordDuration(span, durationMs) {
55
+ span.setAttribute("mcp.duration_ms", durationMs);
56
+ }
57
+ getTraceParent(span) {
58
+ const spanContext = span.spanContext();
59
+ const flags = spanContext.traceFlags.toString(16).padStart(2, "0");
60
+ return `00-${spanContext.traceId}-${spanContext.spanId}-${flags}`;
61
+ }
62
+ extractContext(traceContext) {
63
+ const carrier = {};
64
+ if (traceContext.traceparent)
65
+ carrier["traceparent"] = traceContext.traceparent;
66
+ if (traceContext.tracestate)
67
+ carrier["tracestate"] = traceContext.tracestate;
68
+ return propagation.extract(context.active(), carrier);
69
+ }
70
+ }
71
+ //# sourceMappingURL=tracer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/telemetry/tracer.ts"],"names":[],"mappings":"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"}