@listo-ai/mcp-observability 0.4.0 → 0.5.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 +26 -1
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -0
- package/dist/endpoints.d.ts.map +1 -1
- package/dist/endpoints.js +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ This SDK provides comprehensive observability for [Model Context Protocol (MCP)]
|
|
|
14
14
|
- **Centralized analytics** -- Send telemetry data to a remote endpoint in production
|
|
15
15
|
- **Automatic tracking** -- HTTP requests via Express middleware, MCP tool invocations via handler wrapper
|
|
16
16
|
- **Payload sanitization** -- Built-in redaction of sensitive keys (`password`, `token`, `apiKey`, `secret`, `authorization`)
|
|
17
|
+
- **Platform detection** -- Automatically identify the AI platform (Claude, ChatGPT, or other) from request headers and metadata
|
|
17
18
|
- **Sampling** -- Configurable sampling rates with guaranteed capture of errors and session events
|
|
18
19
|
- **Zero runtime dependencies** -- Only relies on Node.js built-ins (`crypto`, `http`)
|
|
19
20
|
|
|
@@ -24,6 +25,7 @@ This SDK provides comprehensive observability for [Model Context Protocol (MCP)]
|
|
|
24
25
|
- [Browser Client](#browser-client)
|
|
25
26
|
- [How It Works](#how-it-works)
|
|
26
27
|
- [API Reference](#api-reference)
|
|
28
|
+
- [Platform Detection](#detectplatformhints)
|
|
27
29
|
- [Integration Guide](#integration-guide)
|
|
28
30
|
- [Event Types](#event-types)
|
|
29
31
|
- [Environment Variables](#environment-variables)
|
|
@@ -83,6 +85,7 @@ import { createTelemetryClient } from '@listo-ai/mcp-observability/client';
|
|
|
83
85
|
|
|
84
86
|
const client = createTelemetryClient({
|
|
85
87
|
endpoint: 'https://myapp.com/telemetry',
|
|
88
|
+
deviceId: localStorage.getItem('device_id') ?? undefined,
|
|
86
89
|
});
|
|
87
90
|
|
|
88
91
|
// Share the session ID across widget instances
|
|
@@ -237,6 +240,7 @@ observability.recordBusinessEvent('product_search', {
|
|
|
237
240
|
status: 'ok',
|
|
238
241
|
category: 'conversion',
|
|
239
242
|
sessionId: 'sess-abc',
|
|
243
|
+
deviceId: 'device-xyz',
|
|
240
244
|
tenantId: 'tenant-1',
|
|
241
245
|
});
|
|
242
246
|
```
|
|
@@ -249,6 +253,7 @@ Options:
|
|
|
249
253
|
| `status` | `'ok' \| 'error'?` | Event status. Error events bypass sampling |
|
|
250
254
|
| `category` | `EventCategory?` | `'conversion'`, `'engagement'`, `'impression'`, `'navigation'`, or `'system'` |
|
|
251
255
|
| `sessionId` | `string?` | Session identifier for journey tracking |
|
|
256
|
+
| `deviceId` | `string?` | Device identifier for cross-session user identification |
|
|
252
257
|
| `tenantId` | `string?` | Tenant identifier for multi-tenant apps |
|
|
253
258
|
|
|
254
259
|
### `observability.recordUiEvent(event)`
|
|
@@ -267,15 +272,33 @@ observability.recordUiEvent({
|
|
|
267
272
|
});
|
|
268
273
|
```
|
|
269
274
|
|
|
275
|
+
### `detectPlatform(hints?)`
|
|
276
|
+
|
|
277
|
+
Identify the AI platform calling your MCP server. Returns `'claude'`, `'chatgpt'`, or `'other'`.
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
import { detectPlatform } from '@listo-ai/mcp-observability';
|
|
281
|
+
|
|
282
|
+
const platform = detectPlatform({
|
|
283
|
+
headers: request.headers, // HTTP headers (user-agent, x-openai-*, x-anthropic-*)
|
|
284
|
+
meta: mcpRequest.params?._meta, // _meta key prefixes (openai/*, anthropic/*)
|
|
285
|
+
clientInfo: mcpRequest.params?.clientInfo // clientInfo.name fallback
|
|
286
|
+
});
|
|
287
|
+
// → 'claude', 'chatgpt', or 'other'
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Detection checks three signal tiers in order (first match wins): HTTP headers, `_meta` key prefixes, then `clientInfo.name`. See [Platform Detection docs](./docs/platform-detection.md) for details.
|
|
291
|
+
|
|
270
292
|
### `observability.recordSession(event)`
|
|
271
293
|
|
|
272
|
-
Record MCP session lifecycle events.
|
|
294
|
+
Record MCP session lifecycle events. Pass `platform` from `detectPlatform()` on session open to attribute the session to an AI platform.
|
|
273
295
|
|
|
274
296
|
```typescript
|
|
275
297
|
observability.recordSession({
|
|
276
298
|
type: 'mcp_session',
|
|
277
299
|
action: 'open',
|
|
278
300
|
sessionId: 'session-123',
|
|
301
|
+
platform: detectPlatform({ headers: request.headers }),
|
|
279
302
|
});
|
|
280
303
|
```
|
|
281
304
|
|
|
@@ -409,6 +432,7 @@ Recorded via `recordSession()`. Always captured regardless of sample rate.
|
|
|
409
432
|
type: 'mcp_session',
|
|
410
433
|
action: 'open', // or 'close'
|
|
411
434
|
sessionId: 'session-123',
|
|
435
|
+
platform: 'claude', // 'claude', 'chatgpt', or 'other'
|
|
412
436
|
}
|
|
413
437
|
```
|
|
414
438
|
|
|
@@ -503,6 +527,7 @@ Full Amplitude-style documentation is available in the [`docs/`](./docs/) direct
|
|
|
503
527
|
| [Track HTTP](./docs/track-http.md) | `expressTelemetry()` + `trackHttpRequest()` |
|
|
504
528
|
| [Wrap MCP Handlers](./docs/wrap-mcp-handlers.md) | `wrapMcpHandler()`, context fields |
|
|
505
529
|
| [Sessions](./docs/sessions.md) | `recordSession()`, always-capture behavior |
|
|
530
|
+
| [Platform Detection](./docs/platform-detection.md) | `detectPlatform()`, header/meta/clientInfo signals |
|
|
506
531
|
| [Business Events](./docs/business-events.md) | `recordBusinessEvent()` |
|
|
507
532
|
| [UI Events](./docs/ui-events.md) | `recordUiEvent()` + POST endpoint |
|
|
508
533
|
| [Browser Client](./docs/client.md) | `TelemetryClient` for browser apps |
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface TelemetryClientOptions {
|
|
2
2
|
endpoint: string;
|
|
3
3
|
sessionId?: string;
|
|
4
|
+
deviceId?: string;
|
|
4
5
|
tenantId?: string;
|
|
5
6
|
locale?: string;
|
|
6
7
|
batchSize?: number;
|
|
@@ -11,6 +12,7 @@ export interface TelemetryClientOptions {
|
|
|
11
12
|
export declare class TelemetryClient {
|
|
12
13
|
private readonly endpoint;
|
|
13
14
|
private readonly sessionId;
|
|
15
|
+
private readonly deviceId?;
|
|
14
16
|
private readonly batchSize;
|
|
15
17
|
private readonly flushIntervalMs;
|
|
16
18
|
private readonly onError;
|
|
@@ -21,6 +23,7 @@ export declare class TelemetryClient {
|
|
|
21
23
|
private destroyed;
|
|
22
24
|
constructor(options: TelemetryClientOptions);
|
|
23
25
|
getSessionId(): string;
|
|
26
|
+
getDeviceId(): string | undefined;
|
|
24
27
|
track(name: string, properties?: Record<string, unknown>, category?: string): void;
|
|
25
28
|
trackUi(name: string, options: {
|
|
26
29
|
action?: string;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -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,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;
|
|
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"}
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export class TelemetryClient {
|
|
2
2
|
endpoint;
|
|
3
3
|
sessionId;
|
|
4
|
+
deviceId;
|
|
4
5
|
batchSize;
|
|
5
6
|
flushIntervalMs;
|
|
6
7
|
onError;
|
|
@@ -12,6 +13,7 @@ export class TelemetryClient {
|
|
|
12
13
|
constructor(options) {
|
|
13
14
|
this.endpoint = options.endpoint.replace(/\/+$/, '');
|
|
14
15
|
this.sessionId = options.sessionId ?? globalThis.crypto.randomUUID();
|
|
16
|
+
this.deviceId = options.deviceId;
|
|
15
17
|
this.batchSize = options.batchSize ?? 20;
|
|
16
18
|
this.flushIntervalMs = options.flushIntervalMs ?? 5000;
|
|
17
19
|
this.onError = options.onError ?? (() => { });
|
|
@@ -28,6 +30,9 @@ export class TelemetryClient {
|
|
|
28
30
|
getSessionId() {
|
|
29
31
|
return this.sessionId;
|
|
30
32
|
}
|
|
33
|
+
getDeviceId() {
|
|
34
|
+
return this.deviceId;
|
|
35
|
+
}
|
|
31
36
|
track(name, properties, category) {
|
|
32
37
|
if (this.destroyed)
|
|
33
38
|
return;
|
|
@@ -35,6 +40,7 @@ export class TelemetryClient {
|
|
|
35
40
|
name,
|
|
36
41
|
timestamp: Date.now(),
|
|
37
42
|
sessionId: this.sessionId,
|
|
43
|
+
deviceId: this.deviceId,
|
|
38
44
|
tenantId: this.context.tenantId,
|
|
39
45
|
locale: this.context.locale,
|
|
40
46
|
category,
|
|
@@ -48,6 +54,7 @@ export class TelemetryClient {
|
|
|
48
54
|
name,
|
|
49
55
|
timestamp: Date.now(),
|
|
50
56
|
sessionId: this.sessionId,
|
|
57
|
+
deviceId: this.deviceId,
|
|
51
58
|
tenantId: this.context.tenantId,
|
|
52
59
|
locale: this.context.locale,
|
|
53
60
|
action: options.action,
|
package/dist/endpoints.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/endpoints.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
2
|
export type EventStatus = 'ok' | 'error';
|
|
3
3
|
export type EventCategory = 'conversion' | 'engagement' | 'impression' | 'navigation' | 'system';
|
|
4
|
+
export type KnownPlatform = 'claude' | 'chatgpt' | 'other';
|
|
5
|
+
export type Platform = KnownPlatform;
|
|
6
|
+
export type McpClientInfo = {
|
|
7
|
+
name: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
};
|
|
10
|
+
export type PlatformHints = {
|
|
11
|
+
headers?: Record<string, string | string[] | undefined>;
|
|
12
|
+
meta?: Record<string, unknown>;
|
|
13
|
+
clientInfo?: McpClientInfo;
|
|
14
|
+
};
|
|
4
15
|
export type HttpRequestEvent = {
|
|
5
16
|
type: 'http_request';
|
|
6
17
|
timestamp: number;
|
|
@@ -33,6 +44,7 @@ export type McpRequestEvent = {
|
|
|
33
44
|
latencyMs: number;
|
|
34
45
|
tenantId?: string;
|
|
35
46
|
sessionId?: string;
|
|
47
|
+
platform?: Platform;
|
|
36
48
|
locale?: string;
|
|
37
49
|
userAgent?: string;
|
|
38
50
|
argsHash?: string;
|
|
@@ -55,6 +67,7 @@ export type McpSessionEvent = {
|
|
|
55
67
|
environment?: string;
|
|
56
68
|
action: 'open' | 'close';
|
|
57
69
|
sessionId: string;
|
|
70
|
+
platform?: Platform;
|
|
58
71
|
};
|
|
59
72
|
export type BusinessEvent = {
|
|
60
73
|
type: 'business_event';
|
|
@@ -66,6 +79,7 @@ export type BusinessEvent = {
|
|
|
66
79
|
status?: EventStatus;
|
|
67
80
|
category?: EventCategory;
|
|
68
81
|
sessionId?: string;
|
|
82
|
+
deviceId?: string;
|
|
69
83
|
tenantId?: string;
|
|
70
84
|
properties?: Record<string, unknown>;
|
|
71
85
|
};
|
|
@@ -81,6 +95,7 @@ export type UiEvent = {
|
|
|
81
95
|
widgetId?: string;
|
|
82
96
|
toolName?: string;
|
|
83
97
|
sessionId?: string;
|
|
98
|
+
deviceId?: string;
|
|
84
99
|
tenantId?: string;
|
|
85
100
|
locale?: string;
|
|
86
101
|
properties?: Record<string, unknown>;
|
|
@@ -93,6 +108,7 @@ export type ObservabilityOptions = {
|
|
|
93
108
|
serviceName: string;
|
|
94
109
|
serviceVersion?: string;
|
|
95
110
|
environment?: string;
|
|
111
|
+
platform?: Platform;
|
|
96
112
|
sinks?: EventSink[];
|
|
97
113
|
sampleRate?: number;
|
|
98
114
|
redactKeys?: string[];
|
|
@@ -106,6 +122,7 @@ type HttpTrackingContext = {
|
|
|
106
122
|
type McpTrackingContext = {
|
|
107
123
|
sessionId?: string;
|
|
108
124
|
tenantId?: string;
|
|
125
|
+
platform?: Platform;
|
|
109
126
|
locale?: string;
|
|
110
127
|
userAgent?: string;
|
|
111
128
|
requestId?: string;
|
|
@@ -231,6 +248,7 @@ export type BusinessEventOptions = {
|
|
|
231
248
|
status?: EventStatus;
|
|
232
249
|
category?: EventCategory;
|
|
233
250
|
sessionId?: string;
|
|
251
|
+
deviceId?: string;
|
|
234
252
|
tenantId?: string;
|
|
235
253
|
};
|
|
236
254
|
export declare class McpObservability {
|
|
@@ -253,6 +271,20 @@ export declare class McpObservability {
|
|
|
253
271
|
private safeEmit;
|
|
254
272
|
}
|
|
255
273
|
export declare function createMcpObservability(options: ObservabilityOptions): McpObservability;
|
|
274
|
+
/**
|
|
275
|
+
* Detect the AI platform from available request signals.
|
|
276
|
+
*
|
|
277
|
+
* Returns 'claude', 'chatgpt', or 'other'. Unrecognised platforms
|
|
278
|
+
* are bucketed as 'other' — extend HEADER_RULES / META_PREFIX_MAP /
|
|
279
|
+
* CLIENT_NAME_MAP to add new known platforms.
|
|
280
|
+
*
|
|
281
|
+
* Detection order (first match wins):
|
|
282
|
+
* 1. HTTP headers — user-agent string and custom platform headers (e.g. x-openai-*, x-anthropic-*)
|
|
283
|
+
* 2. _meta key prefixes — namespaced keys in request.params._meta (e.g. "openai/session")
|
|
284
|
+
* 3. clientInfo.name — MCP initialize clientInfo (unreliable on some platforms)
|
|
285
|
+
* 4. Fallback — 'other' when any hints are provided but no known platform matched
|
|
286
|
+
*/
|
|
287
|
+
export declare function detectPlatform(hints?: PlatformHints): Platform;
|
|
256
288
|
export { RemoteSink, createRemoteSink, type RemoteSinkOptions, } from './remote-sink.js';
|
|
257
289
|
export { createMcpObservabilityEasy, type EasySetupConfig, } from './easy-setup.js';
|
|
258
290
|
export { createTelemetryRouter, expressTelemetry } from './endpoints.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC;AAEzC,MAAM,MAAM,aAAa,GACrB,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,QAAQ,CAAC;AAEb,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -211,6 +211,7 @@ export class McpObservability {
|
|
|
211
211
|
latencyMs: performance.now() - start,
|
|
212
212
|
tenantId: metadata.tenantId,
|
|
213
213
|
sessionId: metadata.sessionId,
|
|
214
|
+
platform: metadata.platform,
|
|
214
215
|
locale: metadata.locale,
|
|
215
216
|
userAgent: metadata.userAgent,
|
|
216
217
|
conversationId: metadata.conversationId,
|
|
@@ -252,6 +253,7 @@ export class McpObservability {
|
|
|
252
253
|
latencyMs: performance.now() - start,
|
|
253
254
|
tenantId: metadata.tenantId,
|
|
254
255
|
sessionId: metadata.sessionId,
|
|
256
|
+
platform: metadata.platform,
|
|
255
257
|
locale: metadata.locale,
|
|
256
258
|
userAgent: metadata.userAgent,
|
|
257
259
|
conversationId: metadata.conversationId,
|
|
@@ -287,6 +289,7 @@ export class McpObservability {
|
|
|
287
289
|
status: options?.status,
|
|
288
290
|
category: options?.category,
|
|
289
291
|
sessionId: options?.sessionId,
|
|
292
|
+
deviceId: options?.deviceId,
|
|
290
293
|
tenantId: options?.tenantId,
|
|
291
294
|
};
|
|
292
295
|
this.safeEmit(event);
|
|
@@ -342,6 +345,94 @@ export class McpObservability {
|
|
|
342
345
|
export function createMcpObservability(options) {
|
|
343
346
|
return new McpObservability(options);
|
|
344
347
|
}
|
|
348
|
+
const HEADER_RULES = [
|
|
349
|
+
// ChatGPT / OpenAI — user-agent contains "openai" or x-openai-* headers present
|
|
350
|
+
[
|
|
351
|
+
(ua, h) => ua.includes('openai') ||
|
|
352
|
+
Object.keys(h).some((k) => k.startsWith('x-openai-')),
|
|
353
|
+
'chatgpt',
|
|
354
|
+
],
|
|
355
|
+
// Claude / Anthropic — user-agent contains "claude" or "anthropic", or x-anthropic-* headers
|
|
356
|
+
[
|
|
357
|
+
(ua, h) => ua.includes('claude') ||
|
|
358
|
+
ua.includes('anthropic') ||
|
|
359
|
+
Object.keys(h).some((k) => k.startsWith('x-anthropic-')),
|
|
360
|
+
'claude',
|
|
361
|
+
],
|
|
362
|
+
];
|
|
363
|
+
// _meta key prefixes → platform
|
|
364
|
+
const META_PREFIX_MAP = [
|
|
365
|
+
['openai/', 'chatgpt'],
|
|
366
|
+
['anthropic/', 'claude'],
|
|
367
|
+
['claude/', 'claude'],
|
|
368
|
+
];
|
|
369
|
+
// clientInfo.name fallback map
|
|
370
|
+
const CLIENT_NAME_MAP = {
|
|
371
|
+
'claude-desktop': 'claude',
|
|
372
|
+
claude: 'claude',
|
|
373
|
+
chatgpt: 'chatgpt',
|
|
374
|
+
};
|
|
375
|
+
const IGNORED_CLIENT_NAMES = new Set([
|
|
376
|
+
'unavailable',
|
|
377
|
+
'unknown',
|
|
378
|
+
'n/a',
|
|
379
|
+
'none',
|
|
380
|
+
'',
|
|
381
|
+
]);
|
|
382
|
+
/**
|
|
383
|
+
* Detect the AI platform from available request signals.
|
|
384
|
+
*
|
|
385
|
+
* Returns 'claude', 'chatgpt', or 'other'. Unrecognised platforms
|
|
386
|
+
* are bucketed as 'other' — extend HEADER_RULES / META_PREFIX_MAP /
|
|
387
|
+
* CLIENT_NAME_MAP to add new known platforms.
|
|
388
|
+
*
|
|
389
|
+
* Detection order (first match wins):
|
|
390
|
+
* 1. HTTP headers — user-agent string and custom platform headers (e.g. x-openai-*, x-anthropic-*)
|
|
391
|
+
* 2. _meta key prefixes — namespaced keys in request.params._meta (e.g. "openai/session")
|
|
392
|
+
* 3. clientInfo.name — MCP initialize clientInfo (unreliable on some platforms)
|
|
393
|
+
* 4. Fallback — 'other' when any hints are provided but no known platform matched
|
|
394
|
+
*/
|
|
395
|
+
export function detectPlatform(hints) {
|
|
396
|
+
if (!hints)
|
|
397
|
+
return 'other';
|
|
398
|
+
// 1. Headers: normalise to lowercase keys, check user-agent + custom headers
|
|
399
|
+
if (hints.headers && Object.keys(hints.headers).length > 0) {
|
|
400
|
+
const lowerHeaders = {};
|
|
401
|
+
for (const [k, v] of Object.entries(hints.headers)) {
|
|
402
|
+
if (v !== undefined) {
|
|
403
|
+
lowerHeaders[k.toLowerCase()] = Array.isArray(v) ? v.join(', ') : v;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const ua = (lowerHeaders['user-agent'] ?? '').toLowerCase();
|
|
407
|
+
for (const [test, platform] of HEADER_RULES) {
|
|
408
|
+
if (test(ua, lowerHeaders))
|
|
409
|
+
return platform;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// 2. _meta key prefixes
|
|
413
|
+
if (hints.meta && typeof hints.meta === 'object') {
|
|
414
|
+
const keys = Object.keys(hints.meta);
|
|
415
|
+
for (const [prefix, platform] of META_PREFIX_MAP) {
|
|
416
|
+
if (keys.some((k) => k.toLowerCase().startsWith(prefix)))
|
|
417
|
+
return platform;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// 3. clientInfo.name fallback
|
|
421
|
+
if (hints.clientInfo?.name) {
|
|
422
|
+
const name = hints.clientInfo.name.toLowerCase().trim();
|
|
423
|
+
if (!IGNORED_CLIENT_NAMES.has(name)) {
|
|
424
|
+
if (CLIENT_NAME_MAP[name])
|
|
425
|
+
return CLIENT_NAME_MAP[name];
|
|
426
|
+
for (const [key, platform] of Object.entries(CLIENT_NAME_MAP)) {
|
|
427
|
+
if (name.startsWith(`${key}-`) || name.startsWith(`${key}/`)) {
|
|
428
|
+
return platform;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// 4. Nothing matched — bucket as 'other'
|
|
434
|
+
return 'other';
|
|
435
|
+
}
|
|
345
436
|
function hashPayload(payload) {
|
|
346
437
|
try {
|
|
347
438
|
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.
|
|
3
|
+
"version": "0.5.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",
|