@listo-ai/mcp-observability 0.5.1 → 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.
package/README.md CHANGED
@@ -85,7 +85,7 @@ import { createTelemetryClient } from '@listo-ai/mcp-observability/client';
85
85
 
86
86
  const client = createTelemetryClient({
87
87
  endpoint: 'https://myapp.com/telemetry',
88
- deviceId: localStorage.getItem('device_id') ?? undefined,
88
+ userId: localStorage.getItem('user_id') ?? undefined,
89
89
  });
90
90
 
91
91
  // Share the session ID across widget instances
@@ -240,7 +240,7 @@ observability.recordBusinessEvent('product_search', {
240
240
  status: 'ok',
241
241
  category: 'conversion',
242
242
  sessionId: 'sess-abc',
243
- deviceId: 'device-xyz',
243
+ userId: 'user-xyz',
244
244
  tenantId: 'tenant-1',
245
245
  });
246
246
  ```
@@ -253,7 +253,7 @@ Options:
253
253
  | `status` | `'ok' \| 'error'?` | Event status. Error events bypass sampling |
254
254
  | `category` | `EventCategory?` | `'conversion'`, `'engagement'`, `'impression'`, `'navigation'`, or `'system'` |
255
255
  | `sessionId` | `string?` | Session identifier for journey tracking |
256
- | `deviceId` | `string?` | Device identifier for cross-session user identification |
256
+ | `userId` | `string?` | User identifier for cross-session identification |
257
257
  | `tenantId` | `string?` | Tenant identifier for multi-tenant apps |
258
258
 
259
259
  ### `observability.recordUiEvent(event)`
@@ -476,6 +476,7 @@ Browser interaction events via `recordUiEvent()` or the `POST /telemetry/event`
476
476
  | `NODE_ENV` | No | `development` / `staging` / `production` -- controls defaults |
477
477
  | `TELEMETRY_SAMPLE_RATE` | No | Override sampling percentage (0.0 - 1.0) |
478
478
  | `TELEMETRY_CAPTURE_PAYLOADS` | No | Enable/disable payload capture |
479
+ | `HMAC_SECRET` | No | Secret key for HMAC-SHA-256 hashing of `sessionId`/`userId` in MCP events. Without it, falls back to SHA-256 |
479
480
 
480
481
  ## Security
481
482
 
package/dist/client.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export interface TelemetryClientOptions {
2
2
  endpoint: string;
3
3
  sessionId?: string;
4
- deviceId?: string;
4
+ userId?: string;
5
5
  tenantId?: string;
6
6
  locale?: string;
7
7
  batchSize?: number;
@@ -12,7 +12,7 @@ export interface TelemetryClientOptions {
12
12
  export declare class TelemetryClient {
13
13
  private readonly endpoint;
14
14
  private readonly sessionId;
15
- private readonly deviceId?;
15
+ private readonly userId?;
16
16
  private readonly batchSize;
17
17
  private readonly flushIntervalMs;
18
18
  private readonly onError;
@@ -23,7 +23,7 @@ export declare class TelemetryClient {
23
23
  private destroyed;
24
24
  constructor(options: TelemetryClientOptions);
25
25
  getSessionId(): string;
26
- getDeviceId(): string | undefined;
26
+ getUserId(): string | undefined;
27
27
  track(name: string, properties?: Record<string, unknown>, category?: string): void;
28
28
  trackUi(name: string, options: {
29
29
  action?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAgBD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE,sBAAsB;IAuB3C,YAAY,IAAI,MAAM;IAItB,WAAW,IAAI,MAAM,GAAG,SAAS;IAIjC,KAAK,CACH,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI;IAcP,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACtC,GACA,IAAI;IAiBP,UAAU,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK7D,KAAK,IAAI,IAAI;IAMb,OAAO,IAAI,IAAI;IAef,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,IAAI;IA8BZ,OAAO,CAAC,sBAAsB,CAI5B;CACH;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,GAC9B,eAAe,CAEjB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAgBD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE,sBAAsB;IAuB3C,YAAY,IAAI,MAAM;IAItB,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B,KAAK,CACH,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI;IAcP,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACtC,GACA,IAAI;IAiBP,UAAU,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK7D,KAAK,IAAI,IAAI;IAMb,OAAO,IAAI,IAAI;IAef,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,IAAI;IA8BZ,OAAO,CAAC,sBAAsB,CAI5B;CACH;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,GAC9B,eAAe,CAEjB"}
package/dist/client.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export class TelemetryClient {
2
2
  endpoint;
3
3
  sessionId;
4
- deviceId;
4
+ userId;
5
5
  batchSize;
6
6
  flushIntervalMs;
7
7
  onError;
@@ -13,7 +13,7 @@ export class TelemetryClient {
13
13
  constructor(options) {
14
14
  this.endpoint = options.endpoint.replace(/\/+$/, '');
15
15
  this.sessionId = options.sessionId ?? globalThis.crypto.randomUUID();
16
- this.deviceId = options.deviceId;
16
+ this.userId = options.userId;
17
17
  this.batchSize = options.batchSize ?? 20;
18
18
  this.flushIntervalMs = options.flushIntervalMs ?? 5000;
19
19
  this.onError = options.onError ?? (() => { });
@@ -30,8 +30,8 @@ export class TelemetryClient {
30
30
  getSessionId() {
31
31
  return this.sessionId;
32
32
  }
33
- getDeviceId() {
34
- return this.deviceId;
33
+ getUserId() {
34
+ return this.userId;
35
35
  }
36
36
  track(name, properties, category) {
37
37
  if (this.destroyed)
@@ -40,7 +40,7 @@ export class TelemetryClient {
40
40
  name,
41
41
  timestamp: Date.now(),
42
42
  sessionId: this.sessionId,
43
- deviceId: this.deviceId,
43
+ userId: this.userId,
44
44
  tenantId: this.context.tenantId,
45
45
  locale: this.context.locale,
46
46
  category,
@@ -54,7 +54,7 @@ export class TelemetryClient {
54
54
  name,
55
55
  timestamp: Date.now(),
56
56
  sessionId: this.sessionId,
57
- deviceId: this.deviceId,
57
+ userId: this.userId,
58
58
  tenantId: this.context.tenantId,
59
59
  locale: this.context.locale,
60
60
  action: options.action,
@@ -1,8 +1,21 @@
1
1
  import type { Request, Response, NextFunction } from 'express';
2
- import type { McpObservability } from './index.js';
2
+ import type { McpObservability, Platform } from './index.js';
3
3
  declare const TELEMETRY_SINK_KEY: unique symbol;
4
4
  declare const OBSERVABILITY_KEY: unique symbol;
5
5
  declare function setGlobal<T>(key: symbol, value: T): void;
6
+ /**
7
+ * Infer a `Platform` value from an HTTP `Origin` header.
8
+ *
9
+ * Returns `undefined` when the origin is missing, malformed, or doesn't match
10
+ * any known host pattern — i.e. the helper itself is honest about not
11
+ * recognising a host. The built-in POST handlers default that case to
12
+ * `'other'` before recording, so emitted events always have `platform`
13
+ * populated. If you build your own telemetry router around this helper,
14
+ * apply the same `?? 'other'` fallback to match the convention.
15
+ *
16
+ * Exported so consumers can reuse the same mapping in custom telemetry routers.
17
+ */
18
+ export declare function platformFromOrigin(origin: string | string[] | undefined): Platform | undefined;
6
19
  /**
7
20
  * Express middleware for automatic HTTP request tracking
8
21
  *
@@ -1 +1 @@
1
- {"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../src/endpoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,YAAY,CAAC;AAEjE,QAAA,MAAM,kBAAkB,eAAsC,CAAC;AAC/D,QAAA,MAAM,iBAAiB,eAAsC,CAAC;AAe9D,iBAAS,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAEjD;AA4CD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,gBAAgB,IAChD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,mBAW9D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AAEH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,GAAG,OAySvD;AAED,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../src/endpoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAgB,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3E,QAAA,MAAM,kBAAkB,eAAsC,CAAC;AAC/D,QAAA,MAAM,iBAAiB,eAAsC,CAAC;AAe9D,iBAAS,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAEjD;AA+CD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GACpC,QAAQ,GAAG,SAAS,CAatB;AA4BD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,gBAAgB,IAChD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,mBAW9D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AAEH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,GAAG,OA4TvD;AAED,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC"}
package/dist/endpoints.js CHANGED
@@ -21,7 +21,8 @@ const UI_EVENT_FIELDS = new Set([
21
21
  'widgetId',
22
22
  'toolName',
23
23
  'sessionId',
24
- 'deviceId',
24
+ 'userId',
25
+ 'platform',
25
26
  'tenantId',
26
27
  'locale',
27
28
  'properties',
@@ -33,7 +34,55 @@ const VALID_CATEGORIES = new Set([
33
34
  'navigation',
34
35
  'system',
35
36
  ]);
37
+ const VALID_PLATFORMS = new Set(['claude', 'chatgpt', 'other']);
36
38
  const MAX_EVENT_BODY_SIZE = 8192;
39
+ /**
40
+ * Origin → platform mapping for UI events POSTed from MCP-host iframe sandboxes.
41
+ *
42
+ * MCP hosts serve widget content from a per-binding subdomain on a host-controlled
43
+ * domain (so widget JS runs cross-origin to the consuming MCP server). The Origin
44
+ * header on widget-side fetches identifies the host deterministically:
45
+ *
46
+ * - https://<hash>.claudemcpcontent.com → Claude (web + Desktop both use this)
47
+ * - https://*.oaiusercontent.com → ChatGPT (Apps SDK widget sandbox)
48
+ * - https://*.chatgpt.com → ChatGPT (some widget contexts)
49
+ *
50
+ * Add new entries when supporting additional MCP hosts. First match wins.
51
+ */
52
+ const PLATFORM_ORIGIN_PATTERNS = [
53
+ [/(?:^|\.)claudemcpcontent\.com$/i, 'claude'],
54
+ [/(?:^|\.)oaiusercontent\.com$/i, 'chatgpt'],
55
+ [/(?:^|\.)chatgpt\.com$/i, 'chatgpt'],
56
+ ];
57
+ /**
58
+ * Infer a `Platform` value from an HTTP `Origin` header.
59
+ *
60
+ * Returns `undefined` when the origin is missing, malformed, or doesn't match
61
+ * any known host pattern — i.e. the helper itself is honest about not
62
+ * recognising a host. The built-in POST handlers default that case to
63
+ * `'other'` before recording, so emitted events always have `platform`
64
+ * populated. If you build your own telemetry router around this helper,
65
+ * apply the same `?? 'other'` fallback to match the convention.
66
+ *
67
+ * Exported so consumers can reuse the same mapping in custom telemetry routers.
68
+ */
69
+ export function platformFromOrigin(origin) {
70
+ const value = Array.isArray(origin) ? origin[0] : origin;
71
+ if (!value || typeof value !== 'string')
72
+ return undefined;
73
+ let hostname;
74
+ try {
75
+ hostname = new URL(value).hostname;
76
+ }
77
+ catch {
78
+ return undefined;
79
+ }
80
+ for (const [pattern, platform] of PLATFORM_ORIGIN_PATTERNS) {
81
+ if (pattern.test(hostname))
82
+ return platform;
83
+ }
84
+ return undefined;
85
+ }
37
86
  function validateUiEventBody(body) {
38
87
  if (!body || typeof body !== 'object' || Array.isArray(body))
39
88
  return null;
@@ -44,6 +93,11 @@ function validateUiEventBody(body) {
44
93
  (typeof raw.category !== 'string' || !VALID_CATEGORIES.has(raw.category))) {
45
94
  return null;
46
95
  }
96
+ if (raw.platform !== undefined &&
97
+ (typeof raw.platform !== 'string' ||
98
+ !VALID_PLATFORMS.has(raw.platform))) {
99
+ return null;
100
+ }
47
101
  const cleaned = {};
48
102
  for (const key of UI_EVENT_FIELDS) {
49
103
  if (key in raw) {
@@ -310,6 +364,16 @@ export function createTelemetryRouter(expressModule) {
310
364
  .json({ error: 'Invalid event: "name" string required' });
311
365
  return;
312
366
  }
367
+ // Infer platform from the Origin header when the client didn't supply
368
+ // one. Explicit values from the body always win — the inference only
369
+ // fills the gap. Widgets running in MCP-host iframe sandboxes (Claude's
370
+ // claudemcpcontent.com, ChatGPT's oaiusercontent.com) get correctly
371
+ // tagged with no widget-side change required. Anything else (unknown
372
+ // origin, no Origin header) is bucketed as 'other' so the field is
373
+ // always populated — matches `detectPlatform`'s behavior on mcp_request.
374
+ if (validated.platform === undefined) {
375
+ validated.platform = platformFromOrigin(req.headers.origin) ?? 'other';
376
+ }
313
377
  const observability = getGlobal(OBSERVABILITY_KEY);
314
378
  if (observability) {
315
379
  observability.recordUiEvent(validated);
@@ -328,12 +392,19 @@ export function createTelemetryRouter(expressModule) {
328
392
  res.status(400).json({ error: 'Maximum 100 events per batch' });
329
393
  return;
330
394
  }
395
+ // Compute once per batch — all events in the batch share the same Origin.
396
+ // Defaults to 'other' when the Origin doesn't match a known platform, so
397
+ // every emitted event has the field populated. Matches single /event behavior.
398
+ const fallbackPlatform = platformFromOrigin(req.headers.origin) ?? 'other';
331
399
  const observability = getGlobal(OBSERVABILITY_KEY);
332
400
  let accepted = 0;
333
401
  let rejected = 0;
334
402
  for (const raw of events) {
335
403
  const validated = validateUiEventBody(raw);
336
404
  if (validated) {
405
+ if (validated.platform === undefined) {
406
+ validated.platform = fallbackPlatform;
407
+ }
337
408
  if (observability) {
338
409
  observability.recordUiEvent(validated);
339
410
  }
package/dist/index.d.ts CHANGED
@@ -44,6 +44,7 @@ export type McpRequestEvent = {
44
44
  latencyMs: number;
45
45
  tenantId?: string;
46
46
  sessionId?: string;
47
+ userId?: string;
47
48
  platform?: Platform;
48
49
  locale?: string;
49
50
  userAgent?: string;
@@ -79,7 +80,7 @@ export type BusinessEvent = {
79
80
  status?: EventStatus;
80
81
  category?: EventCategory;
81
82
  sessionId?: string;
82
- deviceId?: string;
83
+ userId?: string;
83
84
  tenantId?: string;
84
85
  properties?: Record<string, unknown>;
85
86
  };
@@ -95,7 +96,8 @@ export type UiEvent = {
95
96
  widgetId?: string;
96
97
  toolName?: string;
97
98
  sessionId?: string;
98
- deviceId?: string;
99
+ userId?: string;
100
+ platform?: Platform;
99
101
  tenantId?: string;
100
102
  locale?: string;
101
103
  properties?: Record<string, unknown>;
@@ -121,6 +123,7 @@ type HttpTrackingContext = {
121
123
  };
122
124
  type McpTrackingContext = {
123
125
  sessionId?: string;
126
+ userId?: string;
124
127
  tenantId?: string;
125
128
  platform?: Platform;
126
129
  locale?: string;
@@ -248,7 +251,7 @@ export type BusinessEventOptions = {
248
251
  status?: EventStatus;
249
252
  category?: EventCategory;
250
253
  sessionId?: string;
251
- deviceId?: string;
254
+ userId?: string;
252
255
  tenantId?: string;
253
256
  };
254
257
  export declare class McpObservability {
@@ -263,7 +266,7 @@ export declare class McpObservability {
263
266
  constructor(options: ObservabilityOptions);
264
267
  recordUiEvent(event: Omit<UiEvent, 'timestamp' | 'service' | 'type'>): void;
265
268
  trackHttpRequest(req: IncomingMessage, res: ServerResponse, handler: (ctx: HttpTrackingContext) => Promise<void>): Promise<void>;
266
- wrapMcpHandler<TRequest, TResponse>(requestKind: string, handler: (request: TRequest) => Promise<TResponse> | TResponse, context?: (request: TRequest) => McpTrackingContext): (request: TRequest) => Promise<TResponse>;
269
+ wrapMcpHandler<TRequest, TResponse, TExtra = unknown>(requestKind: string, handler: (request: TRequest, extra?: TExtra) => Promise<TResponse> | TResponse, context?: (request: TRequest, extra?: TExtra) => McpTrackingContext): (request: TRequest, extra?: TExtra) => Promise<TResponse>;
267
270
  recordSession(event: Omit<McpSessionEvent, 'timestamp' | 'service'>): void;
268
271
  recordBusinessEvent(name: string, options?: BusinessEventOptions): void;
269
272
  private baseMcpFields;
@@ -285,6 +288,9 @@ export declare function createMcpObservability(options: ObservabilityOptions): M
285
288
  * 4. Fallback — 'other' when any hints are provided but no known platform matched
286
289
  */
287
290
  export declare function detectPlatform(hints?: PlatformHints): Platform;
291
+ /** @internal Reset cached HMAC secret — only for testing. */
292
+ export declare function _resetHmacSecretCache(): void;
293
+ export declare function hashIdentifier(value: string | undefined): string | undefined;
288
294
  export { RemoteSink, createRemoteSink, type RemoteSinkOptions, } from './remote-sink.js';
289
295
  export { createMcpObservabilityEasy, type EasySetupConfig, } from './easy-setup.js';
290
296
  export { createTelemetryRouter, expressTelemetry } from './endpoints.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createHash, randomUUID } from 'node:crypto';
1
+ import { createHash, createHmac, randomUUID } from 'node:crypto';
2
2
  export class InMemorySink {
3
3
  events = [];
4
4
  limit;
@@ -187,18 +187,20 @@ export class McpObservability {
187
187
  }
188
188
  }
189
189
  wrapMcpHandler(requestKind, handler, context) {
190
- return async (request) => {
191
- const metadata = context?.(request) ?? {};
190
+ return async (request, extra) => {
191
+ const metadata = context?.(request, extra) ?? {};
192
192
  const requestId = metadata.requestId ?? randomUUID();
193
193
  const start = performance.now();
194
194
  try {
195
- const result = await handler(request);
195
+ const result = await handler(request, extra);
196
196
  const sanitizedArgs = metadata.args
197
197
  ? this.sanitizePayload(metadata.args)
198
198
  : undefined;
199
199
  const sanitizedResult = metadata.resultPreview
200
200
  ? this.sanitizePayload(metadata.resultPreview(result))
201
201
  : undefined;
202
+ const hashedSessionId = hashIdentifier(metadata.sessionId);
203
+ const hashedUserId = hashIdentifier(metadata.userId);
202
204
  this.safeEmit({
203
205
  ...this.baseMcpFields(),
204
206
  type: 'mcp_request',
@@ -210,7 +212,8 @@ export class McpObservability {
210
212
  status: 'ok',
211
213
  latencyMs: performance.now() - start,
212
214
  tenantId: metadata.tenantId,
213
- sessionId: metadata.sessionId,
215
+ sessionId: hashedSessionId,
216
+ userId: hashedUserId,
214
217
  platform: metadata.platform,
215
218
  locale: metadata.locale,
216
219
  userAgent: metadata.userAgent,
@@ -241,6 +244,8 @@ export class McpObservability {
241
244
  const sanitizedArgs = metadata.args
242
245
  ? this.sanitizePayload(metadata.args)
243
246
  : undefined;
247
+ const hashedSessionId = hashIdentifier(metadata.sessionId);
248
+ const hashedUserId = hashIdentifier(metadata.userId);
244
249
  this.safeEmit({
245
250
  ...this.baseMcpFields(),
246
251
  type: 'mcp_request',
@@ -252,7 +257,8 @@ export class McpObservability {
252
257
  status: 'error',
253
258
  latencyMs: performance.now() - start,
254
259
  tenantId: metadata.tenantId,
255
- sessionId: metadata.sessionId,
260
+ sessionId: hashedSessionId,
261
+ userId: hashedUserId,
256
262
  platform: metadata.platform,
257
263
  locale: metadata.locale,
258
264
  userAgent: metadata.userAgent,
@@ -289,7 +295,7 @@ export class McpObservability {
289
295
  status: options?.status,
290
296
  category: options?.category,
291
297
  sessionId: options?.sessionId,
292
- deviceId: options?.deviceId,
298
+ userId: options?.userId,
293
299
  tenantId: options?.tenantId,
294
300
  };
295
301
  this.safeEmit(event);
@@ -433,6 +439,26 @@ export function detectPlatform(hints) {
433
439
  // 4. Nothing matched — bucket as 'other'
434
440
  return 'other';
435
441
  }
442
+ let _hmacSecret;
443
+ function getHmacSecret() {
444
+ if (_hmacSecret === undefined) {
445
+ _hmacSecret = process.env.HMAC_SECRET ?? '';
446
+ }
447
+ return _hmacSecret || undefined;
448
+ }
449
+ /** @internal Reset cached HMAC secret — only for testing. */
450
+ export function _resetHmacSecretCache() {
451
+ _hmacSecret = undefined;
452
+ }
453
+ export function hashIdentifier(value) {
454
+ if (!value)
455
+ return value;
456
+ const secret = getHmacSecret();
457
+ if (secret) {
458
+ return createHmac('sha256', secret).update(value).digest('hex');
459
+ }
460
+ return createHash('sha256').update(value).digest('hex');
461
+ }
436
462
  function hashPayload(payload) {
437
463
  try {
438
464
  const json = JSON.stringify(payload);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@listo-ai/mcp-observability",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "Lightweight telemetry SDK for MCP servers and web applications. Captures HTTP requests, MCP tool invocations, business events, and UI interactions with built-in payload sanitization.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",