@posthog/mcp 0.10.0 → 0.10.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/extensions/capture.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAMvD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CA+DnG"}
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/extensions/capture.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAMvD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAkEnG"}
@@ -49,8 +49,8 @@ function captureEvent(server, eventInput) {
49
49
  sdkVersion: sessionInfo.sdkVersion,
50
50
  serverName: sessionInfo.serverName,
51
51
  serverVersion: sessionInfo.serverVersion,
52
- clientName: sessionInfo.clientName,
53
- clientVersion: sessionInfo.clientVersion,
52
+ clientName: eventInput.clientName ?? sessionInfo.clientName,
53
+ clientVersion: eventInput.clientVersion ?? sessionInfo.clientVersion,
54
54
  identifyActorGivenId: sessionInfo.identifyActorGivenId,
55
55
  identifyActorData: sessionInfo.identifyActorData,
56
56
  groups: sessionInfo.identifyActorGroups,
@@ -21,8 +21,8 @@ function captureEvent(server, eventInput) {
21
21
  sdkVersion: sessionInfo.sdkVersion,
22
22
  serverName: sessionInfo.serverName,
23
23
  serverVersion: sessionInfo.serverVersion,
24
- clientName: sessionInfo.clientName,
25
- clientVersion: sessionInfo.clientVersion,
24
+ clientName: eventInput.clientName ?? sessionInfo.clientName,
25
+ clientVersion: eventInput.clientVersion ?? sessionInfo.clientVersion,
26
26
  identifyActorGivenId: sessionInfo.identifyActorGivenId,
27
27
  identifyActorData: sessionInfo.identifyActorData,
28
28
  groups: sessionInfo.identifyActorGroups,
@@ -0,0 +1,39 @@
1
+ import type { McpEvent, MCPRequestLike } from '../types';
2
+ /**
3
+ * Client identity under the MCP 2026-07-28 (stateless) revision.
4
+ *
5
+ * That revision removes the `initialize` handshake and the `Mcp-Session-Id`
6
+ * header (SEP-2575 / SEP-2567). Client name/version and the protocol version no
7
+ * longer arrive once at `initialize` — they travel in every request's
8
+ * `params._meta` under these reverse-DNS keys. We mirror the literal key strings
9
+ * here rather than depend on the (still beta) v2 SDK, which is not a dependency
10
+ * of this package.
11
+ */
12
+ export declare const META_CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo";
13
+ export declare const META_PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion";
14
+ export interface MetaClientInfo {
15
+ clientName?: string;
16
+ clientVersion?: string;
17
+ protocolVersion?: string;
18
+ }
19
+ /**
20
+ * Reads the client name/version and protocol version a modern client puts in
21
+ * `params._meta`. Returns `undefined` when the request carries none (e.g. a
22
+ * legacy client, which sends this on `initialize` instead). Never throws.
23
+ */
24
+ export declare function readMetaClientInfo(request: MCPRequestLike): MetaClientInfo | undefined;
25
+ /**
26
+ * Stamps any client identity found in `params._meta` directly onto the event
27
+ * being built for *this* request, so it carries `$mcp_client_name`,
28
+ * `$mcp_client_version`, and `$mcp_protocol_version` even when there was no
29
+ * `initialize` to learn them from (the modern stateless case).
30
+ *
31
+ * Writing to the event — a per-request object — rather than the server-wide
32
+ * `sessionInfo` keeps identity correct when one instrumented server multiplexes
33
+ * concurrent requests from different clients (which the stateless spec allows):
34
+ * a sibling request can't clobber this event's attribution between now and when
35
+ * it's captured. Only fields the request actually carries are set, so a request
36
+ * without `_meta` leaves the event's existing values untouched.
37
+ */
38
+ export declare function stampMetaClientInfo(event: McpEvent, request: MCPRequestLike): void;
39
+ //# sourceMappingURL=client-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-identity.d.ts","sourceRoot":"","sources":["../../src/extensions/client-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAExD;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,uCAAuC,CAAA;AACxE,eAAO,MAAM,yBAAyB,4CAA4C,CAAA;AAElF,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,GAAG,SAAS,CAyBtF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAclF"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ META_CLIENT_INFO_KEY: ()=>META_CLIENT_INFO_KEY,
28
+ META_PROTOCOL_VERSION_KEY: ()=>META_PROTOCOL_VERSION_KEY,
29
+ readMetaClientInfo: ()=>readMetaClientInfo,
30
+ stampMetaClientInfo: ()=>stampMetaClientInfo
31
+ });
32
+ const META_CLIENT_INFO_KEY = 'io.modelcontextprotocol/clientInfo';
33
+ const META_PROTOCOL_VERSION_KEY = 'io.modelcontextprotocol/protocolVersion';
34
+ function readMetaClientInfo(request) {
35
+ const meta = request.params?._meta;
36
+ if (!meta || 'object' != typeof meta) return;
37
+ const record = meta;
38
+ const result = {};
39
+ const clientInfo = record[META_CLIENT_INFO_KEY];
40
+ if (clientInfo && 'object' == typeof clientInfo) {
41
+ const { name, version } = clientInfo;
42
+ if ('string' == typeof name && name.length > 0) result.clientName = name;
43
+ if ('string' == typeof version && version.length > 0) result.clientVersion = version;
44
+ }
45
+ const protocolVersion = record[META_PROTOCOL_VERSION_KEY];
46
+ if ('string' == typeof protocolVersion && protocolVersion.length > 0) result.protocolVersion = protocolVersion;
47
+ return result.clientName || result.clientVersion || result.protocolVersion ? result : void 0;
48
+ }
49
+ function stampMetaClientInfo(event, request) {
50
+ const info = readMetaClientInfo(request);
51
+ if (!info) return;
52
+ if (info.clientName) event.clientName = info.clientName;
53
+ if (info.clientVersion) event.clientVersion = info.clientVersion;
54
+ if (info.protocolVersion) event.protocolVersion = info.protocolVersion;
55
+ }
56
+ exports.META_CLIENT_INFO_KEY = __webpack_exports__.META_CLIENT_INFO_KEY;
57
+ exports.META_PROTOCOL_VERSION_KEY = __webpack_exports__.META_PROTOCOL_VERSION_KEY;
58
+ exports.readMetaClientInfo = __webpack_exports__.readMetaClientInfo;
59
+ exports.stampMetaClientInfo = __webpack_exports__.stampMetaClientInfo;
60
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
61
+ "META_CLIENT_INFO_KEY",
62
+ "META_PROTOCOL_VERSION_KEY",
63
+ "readMetaClientInfo",
64
+ "stampMetaClientInfo"
65
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
66
+ Object.defineProperty(exports, '__esModule', {
67
+ value: true
68
+ });
@@ -0,0 +1,25 @@
1
+ const META_CLIENT_INFO_KEY = 'io.modelcontextprotocol/clientInfo';
2
+ const META_PROTOCOL_VERSION_KEY = 'io.modelcontextprotocol/protocolVersion';
3
+ function readMetaClientInfo(request) {
4
+ const meta = request.params?._meta;
5
+ if (!meta || 'object' != typeof meta) return;
6
+ const record = meta;
7
+ const result = {};
8
+ const clientInfo = record[META_CLIENT_INFO_KEY];
9
+ if (clientInfo && 'object' == typeof clientInfo) {
10
+ const { name, version } = clientInfo;
11
+ if ('string' == typeof name && name.length > 0) result.clientName = name;
12
+ if ('string' == typeof version && version.length > 0) result.clientVersion = version;
13
+ }
14
+ const protocolVersion = record[META_PROTOCOL_VERSION_KEY];
15
+ if ('string' == typeof protocolVersion && protocolVersion.length > 0) result.protocolVersion = protocolVersion;
16
+ return result.clientName || result.clientVersion || result.protocolVersion ? result : void 0;
17
+ }
18
+ function stampMetaClientInfo(event, request) {
19
+ const info = readMetaClientInfo(request);
20
+ if (!info) return;
21
+ if (info.clientName) event.clientName = info.clientName;
22
+ if (info.clientVersion) event.clientVersion = info.clientVersion;
23
+ if (info.protocolVersion) event.protocolVersion = info.protocolVersion;
24
+ }
25
+ export { META_CLIENT_INFO_KEY, META_PROTOCOL_VERSION_KEY, readMetaClientInfo, stampMetaClientInfo };
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,EACV,6BAA6B,EAC7B,gBAAgB,EAChB,cAAc,EACd,aAAa,EAGd,MAAM,UAAU,CAAA;AAWjB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAYrD;;;;;;GAMG;AAEH,KAAK,iBAAiB,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,6BAA6B,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE7G;;;;GAIG;AACH,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE3E,UAAU,mBAAmB;IAC3B,MAAM,EAAE,aAAa,CAAA;IACrB,IAAI,EAAE,gBAAgB,CAAA;IACtB,OAAO,EAAE,cAAc,CAAA;IACvB,KAAK,CAAC,EAAE,6BAA6B,CAAA;IACrC,OAAO,EAAE,YAAY,CAAA;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,qBAAqB,CAAA;IACjC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAA;CAClC;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuCnF;AAgHD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,MAAM,EAAE,aAAa,EACrB,eAAe,EAAE,iBAAiB,EAClC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,6BAA6B,GAAG,SAAS,KAC7C,OAAO,CAAC,OAAO,CAAC,CAAA;AAErB;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CAqBvG;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,aAAa,EACrB,wBAAwB,EAAE,iBAAiB,EAC3C,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC;IAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAwC9C;AAwDD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CASnH;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGtE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAUjH;AA8GD;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,aAAa,EACrB,yBAAyB,EAAE,iBAAiB,EAC5C,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,OAAO,CAAC,CAsClB"}
1
+ {"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,EACV,6BAA6B,EAC7B,gBAAgB,EAChB,cAAc,EACd,aAAa,EAGd,MAAM,UAAU,CAAA;AAYjB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAYrD;;;;;;GAMG;AAEH,KAAK,iBAAiB,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,6BAA6B,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE7G;;;;GAIG;AACH,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE3E,UAAU,mBAAmB;IAC3B,MAAM,EAAE,aAAa,CAAA;IACrB,IAAI,EAAE,gBAAgB,CAAA;IACtB,OAAO,EAAE,cAAc,CAAA;IACvB,KAAK,CAAC,EAAE,6BAA6B,CAAA;IACrC,OAAO,EAAE,YAAY,CAAA;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,qBAAqB,CAAA;IACjC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAA;CAClC;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuCnF;AAoHD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,MAAM,EAAE,aAAa,EACrB,eAAe,EAAE,iBAAiB,EAClC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,6BAA6B,GAAG,SAAS,KAC7C,OAAO,CAAC,OAAO,CAAC,CAAA;AAErB;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CAqBvG;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,aAAa,EACrB,wBAAwB,EAAE,iBAAiB,EAC3C,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC;IAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAyC9C;AAwDD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CASnH;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGtE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAUjH;AA8GD;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,aAAa,EACrB,yBAAyB,EAAE,iBAAiB,EAC5C,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,OAAO,CAAC,CA0ClB"}
@@ -34,6 +34,7 @@ __webpack_require__.d(__webpack_exports__, {
34
34
  });
35
35
  const external_context_parameters_js_namespaceObject = require("./context-parameters.js");
36
36
  const external_conversation_id_js_namespaceObject = require("./conversation-id.js");
37
+ const external_client_identity_js_namespaceObject = require("./client-identity.js");
37
38
  const external_capture_js_namespaceObject = require("./capture.js");
38
39
  const external_event_types_js_namespaceObject = require("./event-types.js");
39
40
  const external_exceptions_js_namespaceObject = require("./exceptions.js");
@@ -79,6 +80,7 @@ async function prepareToolCallEvent(server, data, request, downstreamRequest, ex
79
80
  toolCategory: toolName ? data.toolCategories.get(toolName) : void 0,
80
81
  toolDescription: toolName ? data.toolDescriptions.get(toolName) : void 0
81
82
  };
83
+ (0, external_client_identity_js_namespaceObject.stampMetaClientInfo)(event, request);
82
84
  await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
83
85
  (0, external_intent_js_namespaceObject.setEventIntent)(event, await (0, external_intent_js_namespaceObject.resolveToolCallIntent)(data, request, extra));
84
86
  return event;
@@ -143,6 +145,7 @@ async function handleListToolsRequest(server, originalListToolsHandler, request,
143
145
  eventType: external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpToolsList,
144
146
  timestamp: startTime
145
147
  };
148
+ (0, external_client_identity_js_namespaceObject.stampMetaClientInfo)(event, request);
146
149
  if (data) await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
147
150
  const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event);
148
151
  if (!data) {
@@ -288,6 +291,7 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
288
291
  parameters: (0, external_mcp_payloads_js_namespaceObject.buildCapturedMcpParameters)(request),
289
292
  timestamp: new Date()
290
293
  };
294
+ (0, external_client_identity_js_namespaceObject.stampMetaClientInfo)(event, request);
291
295
  await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
292
296
  const result = await originalInitializeHandler(request, extra);
293
297
  event.response = result;
@@ -1,5 +1,6 @@
1
1
  import { addContextParameterToTools, getContextDescription, isContextEnabled } from "./context-parameters.mjs";
2
2
  import { addConversationIdToTools, canInjectConversationIdPromptBack, cloneRequestWithoutConversationId, injectConversationIdPromptBack, resolveConversationId } from "./conversation-id.mjs";
3
+ import { stampMetaClientInfo } from "./client-identity.mjs";
3
4
  import { captureEvent } from "./capture.mjs";
4
5
  import { MCPAnalyticsEventType } from "./event-types.mjs";
5
6
  import { captureException } from "./exceptions.mjs";
@@ -45,6 +46,7 @@ async function prepareToolCallEvent(server, data, request, downstreamRequest, ex
45
46
  toolCategory: toolName ? data.toolCategories.get(toolName) : void 0,
46
47
  toolDescription: toolName ? data.toolDescriptions.get(toolName) : void 0
47
48
  };
49
+ stampMetaClientInfo(event, request);
48
50
  await applyResolvedMetadata(event, data, request, extra);
49
51
  setEventIntent(event, await resolveToolCallIntent(data, request, extra));
50
52
  return event;
@@ -109,6 +111,7 @@ async function handleListToolsRequest(server, originalListToolsHandler, request,
109
111
  eventType: MCPAnalyticsEventType.mcpToolsList,
110
112
  timestamp: startTime
111
113
  };
114
+ stampMetaClientInfo(event, request);
112
115
  if (data) await applyResolvedMetadata(event, data, request, extra);
113
116
  const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event);
114
117
  if (!data) {
@@ -254,6 +257,7 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
254
257
  parameters: buildCapturedMcpParameters(request),
255
258
  timestamp: new Date()
256
259
  };
260
+ stampMetaClientInfo(event, request);
257
261
  await applyResolvedMetadata(event, data, request, extra);
258
262
  const result = await originalInitializeHandler(request, extra);
259
263
  event.response = result;
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/extensions/internal.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,6BAA6B,EAC7B,gBAAgB,EAChB,cAAc,EACd,aAAa,EAEb,YAAY,EACb,MAAM,UAAU,CAAA;AAKjB;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAErB,OAAO,SAAO;IAI1B,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAWhD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI;IAapD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI/B,IAAI,IAAI,MAAM;CAGf;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAEzF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAEzF;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,CA4B5E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,YAAY,CAapG;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAUzC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/extensions/internal.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,6BAA6B,EAC7B,gBAAgB,EAChB,cAAc,EACd,aAAa,EAEb,YAAY,EACb,MAAM,UAAU,CAAA;AAMjB;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAErB,OAAO,SAAO;IAI1B,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAWhD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI;IAapD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI/B,IAAI,IAAI,MAAM;CAGf;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAEzF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAEzF;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,CA4B5E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,YAAY,CAapG;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,IAAI,CAAC,CAgDf;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAUzC"}
@@ -35,6 +35,7 @@ __webpack_require__.d(__webpack_exports__, {
35
35
  const external_event_types_js_namespaceObject = require("./event-types.js");
36
36
  const external_logger_js_namespaceObject = require("./logger.js");
37
37
  const external_capture_js_namespaceObject = require("./capture.js");
38
+ const external_client_identity_js_namespaceObject = require("./client-identity.js");
38
39
  class IdentityCache {
39
40
  constructor(maxSize = 1000){
40
41
  this._cache = new Map();
@@ -106,6 +107,7 @@ async function handleIdentify(server, data, sessionId, request, extra) {
106
107
  },
107
108
  timestamp: new Date()
108
109
  };
110
+ (0, external_client_identity_js_namespaceObject.stampMetaClientInfo)(identifyEvent, request);
109
111
  try {
110
112
  const identityResult = 'function' == typeof data.options.identify ? await data.options.identify(request, extra) : data.options.identify;
111
113
  if (identityResult) {
@@ -1,6 +1,7 @@
1
1
  import { MCPAnalyticsEventType } from "./event-types.mjs";
2
2
  import { log } from "./logger.mjs";
3
3
  import { captureEvent } from "./capture.mjs";
4
+ import { stampMetaClientInfo } from "./client-identity.mjs";
4
5
  class IdentityCache {
5
6
  constructor(maxSize = 1000){
6
7
  this._cache = new Map();
@@ -72,6 +73,7 @@ async function handleIdentify(server, data, sessionId, request, extra) {
72
73
  },
73
74
  timestamp: new Date()
74
75
  };
76
+ stampMetaClientInfo(identifyEvent, request);
75
77
  try {
76
78
  const identityResult = 'function' == typeof data.options.identify ? await data.options.identify(request, extra) : data.options.identify;
77
79
  if (identityResult) {
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const version = "0.10.0";
1
+ export declare const version = "0.10.1";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -26,7 +26,7 @@ __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  version: ()=>version
28
28
  });
29
- const version = '0.10.0';
29
+ const version = '0.10.1';
30
30
  exports.version = __webpack_exports__.version;
31
31
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
32
32
  "version"
package/dist/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- const version = '0.10.0';
1
+ const version = '0.10.1';
2
2
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/mcp",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "bugs": {
5
5
  "url": "https://github.com/PostHog/posthog-js/issues"
6
6
  },
@@ -28,7 +28,7 @@
28
28
  "module": "dist/index.mjs",
29
29
  "types": "dist/index.d.ts",
30
30
  "dependencies": {
31
- "@posthog/core": "^1.44.0"
31
+ "@posthog/core": "^1.45.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@babel/preset-env": "^7.27.1",
@@ -39,8 +39,8 @@
39
39
  "@types/node": "^20.0.0",
40
40
  "jest": "29.7.0",
41
41
  "zod": "^3.25.0",
42
- "posthog-node": "^5.46.0",
43
- "@posthog-tooling/tsconfig-base": "1.1.1"
42
+ "@posthog-tooling/tsconfig-base": "1.1.1",
43
+ "posthog-node": "^5.46.1"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@modelcontextprotocol/sdk": ">=1.26.0",
@@ -48,8 +48,11 @@ export function captureEvent(server: MCPServerLike, eventInput: McpEvent): Promi
48
48
  sdkVersion: sessionInfo.sdkVersion,
49
49
  serverName: sessionInfo.serverName,
50
50
  serverVersion: sessionInfo.serverVersion,
51
- clientName: sessionInfo.clientName,
52
- clientVersion: sessionInfo.clientVersion,
51
+ // Prefer identity the event captured for *this* request (from `_meta`, see
52
+ // stampMetaClientInfo) over the server-wide sessionInfo, so a concurrent
53
+ // request from another client can't misattribute this one.
54
+ clientName: eventInput.clientName ?? sessionInfo.clientName,
55
+ clientVersion: eventInput.clientVersion ?? sessionInfo.clientVersion,
53
56
  identifyActorGivenId: sessionInfo.identifyActorGivenId,
54
57
  identifyActorData: sessionInfo.identifyActorData,
55
58
  groups: sessionInfo.identifyActorGroups,
@@ -0,0 +1,81 @@
1
+ import type { McpEvent, MCPRequestLike } from '../types'
2
+
3
+ /**
4
+ * Client identity under the MCP 2026-07-28 (stateless) revision.
5
+ *
6
+ * That revision removes the `initialize` handshake and the `Mcp-Session-Id`
7
+ * header (SEP-2575 / SEP-2567). Client name/version and the protocol version no
8
+ * longer arrive once at `initialize` — they travel in every request's
9
+ * `params._meta` under these reverse-DNS keys. We mirror the literal key strings
10
+ * here rather than depend on the (still beta) v2 SDK, which is not a dependency
11
+ * of this package.
12
+ */
13
+ export const META_CLIENT_INFO_KEY = 'io.modelcontextprotocol/clientInfo'
14
+ export const META_PROTOCOL_VERSION_KEY = 'io.modelcontextprotocol/protocolVersion'
15
+
16
+ export interface MetaClientInfo {
17
+ clientName?: string
18
+ clientVersion?: string
19
+ protocolVersion?: string
20
+ }
21
+
22
+ /**
23
+ * Reads the client name/version and protocol version a modern client puts in
24
+ * `params._meta`. Returns `undefined` when the request carries none (e.g. a
25
+ * legacy client, which sends this on `initialize` instead). Never throws.
26
+ */
27
+ export function readMetaClientInfo(request: MCPRequestLike): MetaClientInfo | undefined {
28
+ const meta = request.params?._meta
29
+ if (!meta || typeof meta !== 'object') {
30
+ return undefined
31
+ }
32
+ const record = meta as Record<string, unknown>
33
+ const result: MetaClientInfo = {}
34
+
35
+ const clientInfo = record[META_CLIENT_INFO_KEY]
36
+ if (clientInfo && typeof clientInfo === 'object') {
37
+ const { name, version } = clientInfo as Record<string, unknown>
38
+ if (typeof name === 'string' && name.length > 0) {
39
+ result.clientName = name
40
+ }
41
+ if (typeof version === 'string' && version.length > 0) {
42
+ result.clientVersion = version
43
+ }
44
+ }
45
+
46
+ const protocolVersion = record[META_PROTOCOL_VERSION_KEY]
47
+ if (typeof protocolVersion === 'string' && protocolVersion.length > 0) {
48
+ result.protocolVersion = protocolVersion
49
+ }
50
+
51
+ return result.clientName || result.clientVersion || result.protocolVersion ? result : undefined
52
+ }
53
+
54
+ /**
55
+ * Stamps any client identity found in `params._meta` directly onto the event
56
+ * being built for *this* request, so it carries `$mcp_client_name`,
57
+ * `$mcp_client_version`, and `$mcp_protocol_version` even when there was no
58
+ * `initialize` to learn them from (the modern stateless case).
59
+ *
60
+ * Writing to the event — a per-request object — rather than the server-wide
61
+ * `sessionInfo` keeps identity correct when one instrumented server multiplexes
62
+ * concurrent requests from different clients (which the stateless spec allows):
63
+ * a sibling request can't clobber this event's attribution between now and when
64
+ * it's captured. Only fields the request actually carries are set, so a request
65
+ * without `_meta` leaves the event's existing values untouched.
66
+ */
67
+ export function stampMetaClientInfo(event: McpEvent, request: MCPRequestLike): void {
68
+ const info = readMetaClientInfo(request)
69
+ if (!info) {
70
+ return
71
+ }
72
+ if (info.clientName) {
73
+ event.clientName = info.clientName
74
+ }
75
+ if (info.clientVersion) {
76
+ event.clientVersion = info.clientVersion
77
+ }
78
+ if (info.protocolVersion) {
79
+ event.protocolVersion = info.protocolVersion
80
+ }
81
+ }
@@ -21,6 +21,7 @@ import {
21
21
  injectConversationIdPromptBack,
22
22
  resolveConversationId,
23
23
  } from './conversation-id'
24
+ import { stampMetaClientInfo } from './client-identity'
24
25
  import { captureEvent } from './capture'
25
26
  import { MCPAnalyticsEventType } from './event-types'
26
27
  import { captureException } from './exceptions'
@@ -152,6 +153,10 @@ async function prepareToolCallEvent(
152
153
  toolCategory: toolName ? data.toolCategories.get(toolName) : undefined,
153
154
  toolDescription: toolName ? data.toolDescriptions.get(toolName) : undefined,
154
155
  }
156
+ // Modern (stateless) clients carry client name/version + protocol version in
157
+ // `_meta` on every request rather than at `initialize`; stamp them onto this
158
+ // event now so concurrent requests can't cross-attribute it.
159
+ stampMetaClientInfo(event, request)
155
160
 
156
161
  await applyResolvedMetadata(event, data, request, extra)
157
162
  setEventIntent(event, await resolveToolCallIntent(data, request, extra))
@@ -297,6 +302,7 @@ export async function handleListToolsRequest(
297
302
  eventType: MCPAnalyticsEventType.mcpToolsList,
298
303
  timestamp: startTime,
299
304
  }
305
+ stampMetaClientInfo(event, request)
300
306
 
301
307
  if (data) {
302
308
  await applyResolvedMetadata(event, data, request, extra)
@@ -555,6 +561,10 @@ export async function handleInitializeRequest(
555
561
  parameters: buildCapturedMcpParameters(request),
556
562
  timestamp: new Date(),
557
563
  }
564
+ // Harmless for a legacy `initialize` (client info rides the body there, and the
565
+ // negotiated protocol version below overrides any `_meta` one); picks up client
566
+ // info if a client also sends it in `_meta`.
567
+ stampMetaClientInfo(event, request)
558
568
 
559
569
  await applyResolvedMetadata(event, data, request, extra)
560
570
 
@@ -14,6 +14,7 @@ import type {
14
14
  import { MCPAnalyticsEventType } from './event-types'
15
15
  import { log } from './logger'
16
16
  import { captureEvent } from './capture'
17
+ import { stampMetaClientInfo } from './client-identity'
17
18
 
18
19
  /**
19
20
  * Bounded LRU cache for session identities, capped at `maxSize` entries so a
@@ -141,6 +142,7 @@ export async function handleIdentify(
141
142
  parameters: { request, extra },
142
143
  timestamp: new Date(),
143
144
  }
145
+ stampMetaClientInfo(identifyEvent, request)
144
146
 
145
147
  try {
146
148
  const identityResult =
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '0.10.0'
1
+ export const version = '0.10.1'