@posthog/mcp 0.9.0 → 0.10.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 +8 -0
- package/dist/extensions/capture.d.ts.map +1 -1
- package/dist/extensions/capture.js +1 -0
- package/dist/extensions/capture.mjs +1 -0
- package/dist/extensions/constants.d.ts +1 -0
- package/dist/extensions/constants.d.ts.map +1 -1
- package/dist/extensions/constants.js +1 -0
- package/dist/extensions/constants.mjs +1 -0
- package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +33 -2
- package/dist/extensions/instrumentation.mjs +33 -2
- package/dist/extensions/internal.d.ts +4 -2
- package/dist/extensions/internal.d.ts.map +1 -1
- package/dist/extensions/internal.js +5 -2
- package/dist/extensions/internal.mjs +5 -2
- package/dist/extensions/posthog-events.js +2 -0
- package/dist/extensions/posthog-events.mjs +2 -0
- package/dist/extensions/posthog-mcp.js +1 -0
- package/dist/extensions/posthog-mcp.mjs +1 -0
- package/dist/extensions/session-token.d.ts +7 -0
- package/dist/extensions/session-token.d.ts.map +1 -1
- package/dist/extensions/session-token.js +2 -0
- package/dist/extensions/session-token.mjs +2 -0
- package/dist/extensions/session.d.ts.map +1 -1
- package/dist/extensions/session.js +2 -0
- package/dist/extensions/session.mjs +2 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +4 -4
- package/src/extensions/capture.ts +4 -0
- package/src/extensions/constants.ts +1 -0
- package/src/extensions/instrument-highlevel.ts +9 -3
- package/src/extensions/instrumentation.ts +73 -7
- package/src/extensions/internal.ts +19 -4
- package/src/extensions/mcp-sdk-compat.ts +1 -1
- package/src/extensions/posthog-events.ts +8 -0
- package/src/extensions/posthog-mcp.ts +1 -0
- package/src/extensions/session-token.ts +15 -1
- package/src/extensions/session.ts +4 -0
- package/src/types.ts +19 -0
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,14 @@ as a token carrying the session id and client name/version. Clients replay the h
|
|
|
15
15
|
every request, so any pod keeps `$session_id` and `$mcp_client_name`/`$mcp_client_version`
|
|
16
16
|
stable with no server-side store.
|
|
17
17
|
|
|
18
|
+
A standalone `$identify` event fires **at most once per session** — at `initialize` (or, on a
|
|
19
|
+
long-lived server, when the identity first appears or materially changes). Tool calls on other
|
|
20
|
+
pods reuse the identity to stamp `distinct_id`/`$set` on every event **without** re-publishing
|
|
21
|
+
`$identify`, so person **properties** are never lost. (Edge case: if identity isn't resolvable
|
|
22
|
+
until _after_ `initialize`, the first `$identify` is suppressed too, so pre-identify anonymous
|
|
23
|
+
events aren't aliased onto the user — see `docs/ARCHITECTURE.md` §4.) To drop `$identify`
|
|
24
|
+
entirely, return `null` from `beforeSend` when `event === '$identify'`.
|
|
25
|
+
|
|
18
26
|
### Streamable HTTP: set `enableJsonResponse: true`
|
|
19
27
|
|
|
20
28
|
The token is minted onto the `Mcp-Session-Id` **response** header from inside the `initialize`
|
|
@@ -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,
|
|
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"}
|
|
@@ -55,6 +55,7 @@ function captureEvent(server, eventInput) {
|
|
|
55
55
|
identifyActorData: sessionInfo.identifyActorData,
|
|
56
56
|
groups: sessionInfo.identifyActorGroups,
|
|
57
57
|
resourceName: eventInput.resourceName,
|
|
58
|
+
protocolVersion: eventInput.protocolVersion ?? sessionInfo.protocolVersion,
|
|
58
59
|
toolCategory: eventInput.toolCategory,
|
|
59
60
|
toolDescription: eventInput.toolDescription,
|
|
60
61
|
listedToolNames: eventInput.listedToolNames,
|
|
@@ -27,6 +27,7 @@ function captureEvent(server, eventInput) {
|
|
|
27
27
|
identifyActorData: sessionInfo.identifyActorData,
|
|
28
28
|
groups: sessionInfo.identifyActorGroups,
|
|
29
29
|
resourceName: eventInput.resourceName,
|
|
30
|
+
protocolVersion: eventInput.protocolVersion ?? sessionInfo.protocolVersion,
|
|
30
31
|
toolCategory: eventInput.toolCategory,
|
|
31
32
|
toolDescription: eventInput.toolDescription,
|
|
32
33
|
listedToolNames: eventInput.listedToolNames,
|
|
@@ -29,6 +29,7 @@ export declare const PostHogMCPAnalyticsProperty: {
|
|
|
29
29
|
readonly IntentSource: "$mcp_intent_source";
|
|
30
30
|
readonly ListedToolNames: "$mcp_listed_tool_names";
|
|
31
31
|
readonly Parameters: "$mcp_parameters";
|
|
32
|
+
readonly ProtocolVersion: "$mcp_protocol_version";
|
|
32
33
|
readonly ResourceName: "$mcp_resource_name";
|
|
33
34
|
readonly Response: "$mcp_response";
|
|
34
35
|
readonly ServerName: "$mcp_server_name";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/extensions/constants.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,6BAA6B,KAAK,CAAA;AAE/C,eAAO,MAAM,qCAAqC,2hBAAyhB,CAAA;AAE3kB,eAAO,MAAM,mCAAmC,4LACsI,CAAA;AAEtL,eAAO,MAAM,4BAA4B,0BAA0B,CAAA;AAMnE,eAAO,MAAM,oBAAoB,qBAAqB,CAAA;AAItD,eAAO,MAAM,wBAAwB;;;;;;;;;;;;CAY3B,CAAA;AAEV,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,OAAO,wBAAwB,CAAC,CAAA;AAE/G,eAAO,MAAM,2BAA2B
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/extensions/constants.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,6BAA6B,KAAK,CAAA;AAE/C,eAAO,MAAM,qCAAqC,2hBAAyhB,CAAA;AAE3kB,eAAO,MAAM,mCAAmC,4LACsI,CAAA;AAEtL,eAAO,MAAM,4BAA4B,0BAA0B,CAAA;AAMnE,eAAO,MAAM,oBAAoB,qBAAqB,CAAA;AAItD,eAAO,MAAM,wBAAwB;;;;;;;;;;;;CAY3B,CAAA;AAEV,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,OAAO,wBAAwB,CAAC,CAAA;AAE/G,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;CAsB9B,CAAA;AAEV,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,OAAO,2BAA2B,CAAC,CAAA"}
|
|
@@ -62,6 +62,7 @@ const PostHogMCPAnalyticsProperty = {
|
|
|
62
62
|
IntentSource: '$mcp_intent_source',
|
|
63
63
|
ListedToolNames: '$mcp_listed_tool_names',
|
|
64
64
|
Parameters: '$mcp_parameters',
|
|
65
|
+
ProtocolVersion: '$mcp_protocol_version',
|
|
65
66
|
ResourceName: '$mcp_resource_name',
|
|
66
67
|
Response: '$mcp_response',
|
|
67
68
|
ServerName: '$mcp_server_name',
|
|
@@ -28,6 +28,7 @@ const PostHogMCPAnalyticsProperty = {
|
|
|
28
28
|
IntentSource: '$mcp_intent_source',
|
|
29
29
|
ListedToolNames: '$mcp_listed_tool_names',
|
|
30
30
|
Parameters: '$mcp_parameters',
|
|
31
|
+
ProtocolVersion: '$mcp_protocol_version',
|
|
31
32
|
ResourceName: '$mcp_resource_name',
|
|
32
33
|
Response: '$mcp_response',
|
|
33
34
|
ServerName: '$mcp_server_name',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-highlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-highlevel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"instrument-highlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-highlevel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,sBAAsB,EAIvB,MAAM,UAAU,CAAA;AAqPjB,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAwB9E"}
|
|
@@ -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;
|
|
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"}
|
|
@@ -227,20 +227,40 @@ function mintStatelessSessionOnInitialize(server, data, request, extra) {
|
|
|
227
227
|
if (!transport || extra?.sessionId || transport.sessionId) return;
|
|
228
228
|
const sessionId = (0, external_session_js_namespaceObject.newSessionId)();
|
|
229
229
|
const clientInfo = readInitializeClientInfo(request);
|
|
230
|
+
const requestedProtocolVersion = readProtocolVersion(void 0, request);
|
|
230
231
|
const token = (0, external_session_token_js_namespaceObject.encodeSessionId)({
|
|
231
232
|
sessionId,
|
|
232
233
|
clientName: clientInfo?.name,
|
|
233
|
-
clientVersion: clientInfo?.version
|
|
234
|
+
clientVersion: clientInfo?.version,
|
|
235
|
+
protocolVersion: requestedProtocolVersion
|
|
234
236
|
});
|
|
235
237
|
if (!(0, external_session_token_js_namespaceObject.writeSessionIdToTransport)(transport, token)) return;
|
|
236
238
|
data.sessionId = sessionId;
|
|
237
239
|
data.sessionSource = 'token';
|
|
238
240
|
data.sessionInfo.clientName = clientInfo?.name;
|
|
239
241
|
data.sessionInfo.clientVersion = clientInfo?.version;
|
|
242
|
+
data.sessionInfo.protocolVersion = requestedProtocolVersion;
|
|
240
243
|
data.lastActivity = new Date();
|
|
241
244
|
(0, external_internal_js_namespaceObject.setServerTrackingData)(server, data);
|
|
245
|
+
return sessionId;
|
|
242
246
|
} catch (error) {
|
|
243
247
|
(0, external_logger_js_namespaceObject.log)(`Warning: PostHog MCP analytics failed to mint a stateless session id - ${error}`);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion) {
|
|
252
|
+
try {
|
|
253
|
+
const transport = server.transport;
|
|
254
|
+
if (!transport) return;
|
|
255
|
+
const token = (0, external_session_token_js_namespaceObject.encodeSessionId)({
|
|
256
|
+
sessionId: mintedSessionId,
|
|
257
|
+
clientName: data.sessionInfo.clientName,
|
|
258
|
+
clientVersion: data.sessionInfo.clientVersion,
|
|
259
|
+
protocolVersion: negotiatedProtocolVersion
|
|
260
|
+
});
|
|
261
|
+
(0, external_session_token_js_namespaceObject.writeSessionIdToTransport)(transport, token);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
(0, external_logger_js_namespaceObject.log)(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`);
|
|
244
264
|
}
|
|
245
265
|
}
|
|
246
266
|
function readInitializeClientInfo(request) {
|
|
@@ -258,7 +278,7 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
|
|
|
258
278
|
(0, external_logger_js_namespaceObject.log)('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');
|
|
259
279
|
return await originalInitializeHandler(request, extra);
|
|
260
280
|
}
|
|
261
|
-
mintStatelessSessionOnInitialize(server, data, request, extra);
|
|
281
|
+
const mintedSessionId = mintStatelessSessionOnInitialize(server, data, request, extra);
|
|
262
282
|
const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
|
|
263
283
|
await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, extra);
|
|
264
284
|
const event = {
|
|
@@ -271,9 +291,20 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
|
|
|
271
291
|
await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
|
|
272
292
|
const result = await originalInitializeHandler(request, extra);
|
|
273
293
|
event.response = result;
|
|
294
|
+
const negotiatedProtocolVersion = readProtocolVersion(result, request);
|
|
295
|
+
event.protocolVersion = negotiatedProtocolVersion;
|
|
296
|
+
data.sessionInfo.protocolVersion = negotiatedProtocolVersion;
|
|
297
|
+
(0, external_internal_js_namespaceObject.setServerTrackingData)(server, data);
|
|
298
|
+
if (mintedSessionId) upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion);
|
|
274
299
|
(0, external_capture_js_namespaceObject.captureEvent)(server, event);
|
|
275
300
|
return result;
|
|
276
301
|
}
|
|
302
|
+
function readProtocolVersion(result, request) {
|
|
303
|
+
const negotiated = result?.protocolVersion;
|
|
304
|
+
if ('string' == typeof negotiated && negotiated.length > 0) return negotiated;
|
|
305
|
+
const requested = request.params?.protocolVersion;
|
|
306
|
+
return 'string' == typeof requested && requested.length > 0 ? requested : void 0;
|
|
307
|
+
}
|
|
277
308
|
exports.cacheToolCategories = __webpack_exports__.cacheToolCategories;
|
|
278
309
|
exports.cacheToolDescriptions = __webpack_exports__.cacheToolDescriptions;
|
|
279
310
|
exports.captureToolCall = __webpack_exports__.captureToolCall;
|
|
@@ -193,20 +193,40 @@ function mintStatelessSessionOnInitialize(server, data, request, extra) {
|
|
|
193
193
|
if (!transport || extra?.sessionId || transport.sessionId) return;
|
|
194
194
|
const sessionId = newSessionId();
|
|
195
195
|
const clientInfo = readInitializeClientInfo(request);
|
|
196
|
+
const requestedProtocolVersion = readProtocolVersion(void 0, request);
|
|
196
197
|
const token = encodeSessionId({
|
|
197
198
|
sessionId,
|
|
198
199
|
clientName: clientInfo?.name,
|
|
199
|
-
clientVersion: clientInfo?.version
|
|
200
|
+
clientVersion: clientInfo?.version,
|
|
201
|
+
protocolVersion: requestedProtocolVersion
|
|
200
202
|
});
|
|
201
203
|
if (!writeSessionIdToTransport(transport, token)) return;
|
|
202
204
|
data.sessionId = sessionId;
|
|
203
205
|
data.sessionSource = 'token';
|
|
204
206
|
data.sessionInfo.clientName = clientInfo?.name;
|
|
205
207
|
data.sessionInfo.clientVersion = clientInfo?.version;
|
|
208
|
+
data.sessionInfo.protocolVersion = requestedProtocolVersion;
|
|
206
209
|
data.lastActivity = new Date();
|
|
207
210
|
setServerTrackingData(server, data);
|
|
211
|
+
return sessionId;
|
|
208
212
|
} catch (error) {
|
|
209
213
|
log(`Warning: PostHog MCP analytics failed to mint a stateless session id - ${error}`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion) {
|
|
218
|
+
try {
|
|
219
|
+
const transport = server.transport;
|
|
220
|
+
if (!transport) return;
|
|
221
|
+
const token = encodeSessionId({
|
|
222
|
+
sessionId: mintedSessionId,
|
|
223
|
+
clientName: data.sessionInfo.clientName,
|
|
224
|
+
clientVersion: data.sessionInfo.clientVersion,
|
|
225
|
+
protocolVersion: negotiatedProtocolVersion
|
|
226
|
+
});
|
|
227
|
+
writeSessionIdToTransport(transport, token);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
log(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`);
|
|
210
230
|
}
|
|
211
231
|
}
|
|
212
232
|
function readInitializeClientInfo(request) {
|
|
@@ -224,7 +244,7 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
|
|
|
224
244
|
log('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');
|
|
225
245
|
return await originalInitializeHandler(request, extra);
|
|
226
246
|
}
|
|
227
|
-
mintStatelessSessionOnInitialize(server, data, request, extra);
|
|
247
|
+
const mintedSessionId = mintStatelessSessionOnInitialize(server, data, request, extra);
|
|
228
248
|
const sessionId = getSessionId(server, extra);
|
|
229
249
|
await handleIdentify(server, data, sessionId, request, extra);
|
|
230
250
|
const event = {
|
|
@@ -237,7 +257,18 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
|
|
|
237
257
|
await applyResolvedMetadata(event, data, request, extra);
|
|
238
258
|
const result = await originalInitializeHandler(request, extra);
|
|
239
259
|
event.response = result;
|
|
260
|
+
const negotiatedProtocolVersion = readProtocolVersion(result, request);
|
|
261
|
+
event.protocolVersion = negotiatedProtocolVersion;
|
|
262
|
+
data.sessionInfo.protocolVersion = negotiatedProtocolVersion;
|
|
263
|
+
setServerTrackingData(server, data);
|
|
264
|
+
if (mintedSessionId) upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion);
|
|
240
265
|
captureEvent(server, event);
|
|
241
266
|
return result;
|
|
242
267
|
}
|
|
268
|
+
function readProtocolVersion(result, request) {
|
|
269
|
+
const negotiated = result?.protocolVersion;
|
|
270
|
+
if ('string' == typeof negotiated && negotiated.length > 0) return negotiated;
|
|
271
|
+
const requested = request.params?.protocolVersion;
|
|
272
|
+
return 'string' == typeof requested && requested.length > 0 ? requested : void 0;
|
|
273
|
+
}
|
|
243
274
|
export { cacheToolCategories, cacheToolDescriptions, captureToolCall, handleInitializeRequest, handleListToolsRequest, patchRequestHandlers, readToolMetaCategory };
|
|
@@ -19,8 +19,10 @@ export declare function setServerTrackingData(server: MCPServerLike, data: MCPAn
|
|
|
19
19
|
export declare function areIdentitiesEqual(a: UserIdentity, b: UserIdentity): boolean;
|
|
20
20
|
export declare function mergeIdentities(previous: UserIdentity | undefined, next: UserIdentity): UserIdentity;
|
|
21
21
|
/**
|
|
22
|
-
* Resolves the optional `identify` callback
|
|
23
|
-
*
|
|
22
|
+
* Resolves the optional `identify` callback on every request (the resolved
|
|
23
|
+
* identity is what stamps `distinct_id`/`$set` onto events), but publishes the
|
|
24
|
+
* `$identify` event at most once per session: at `initialize`, when a
|
|
25
|
+
* long-lived server first sees the identity, or when it materially changes.
|
|
24
26
|
*/
|
|
25
27
|
export declare function handleIdentify(server: MCPServerLike, data: MCPAnalyticsData, sessionId: string, request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra): Promise<void>;
|
|
26
28
|
/**
|
|
@@ -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
|
|
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"}
|
|
@@ -111,9 +111,12 @@ async function handleIdentify(server, data, sessionId, request, extra) {
|
|
|
111
111
|
if (identityResult) {
|
|
112
112
|
const previousIdentity = data.identifiedSessions.get(sessionId);
|
|
113
113
|
const mergedIdentity = mergeIdentities(previousIdentity, identityResult);
|
|
114
|
-
const
|
|
114
|
+
const changed = void 0 !== previousIdentity && !areIdentitiesEqual(previousIdentity, mergedIdentity);
|
|
115
|
+
const firstSeen = void 0 === previousIdentity;
|
|
116
|
+
const announcedAtInitialize = 'token' === data.sessionSource && 'initialize' !== request.method;
|
|
117
|
+
const shouldPublish = changed || firstSeen && !announcedAtInitialize;
|
|
115
118
|
data.identifiedSessions.set(sessionId, mergedIdentity);
|
|
116
|
-
if (
|
|
119
|
+
if (shouldPublish) {
|
|
117
120
|
(0, external_logger_js_namespaceObject.log)(`Identified session ${sessionId} with identity: ${JSON.stringify(mergedIdentity)}`);
|
|
118
121
|
(0, external_capture_js_namespaceObject.captureEvent)(server, identifyEvent);
|
|
119
122
|
}
|
|
@@ -77,9 +77,12 @@ async function handleIdentify(server, data, sessionId, request, extra) {
|
|
|
77
77
|
if (identityResult) {
|
|
78
78
|
const previousIdentity = data.identifiedSessions.get(sessionId);
|
|
79
79
|
const mergedIdentity = mergeIdentities(previousIdentity, identityResult);
|
|
80
|
-
const
|
|
80
|
+
const changed = void 0 !== previousIdentity && !areIdentitiesEqual(previousIdentity, mergedIdentity);
|
|
81
|
+
const firstSeen = void 0 === previousIdentity;
|
|
82
|
+
const announcedAtInitialize = 'token' === data.sessionSource && 'initialize' !== request.method;
|
|
83
|
+
const shouldPublish = changed || firstSeen && !announcedAtInitialize;
|
|
81
84
|
data.identifiedSessions.set(sessionId, mergedIdentity);
|
|
82
|
-
if (
|
|
85
|
+
if (shouldPublish) {
|
|
83
86
|
log(`Identified session ${sessionId} with identity: ${JSON.stringify(mergedIdentity)}`);
|
|
84
87
|
captureEvent(server, identifyEvent);
|
|
85
88
|
}
|
|
@@ -98,6 +98,7 @@ function addCommonEventProperties(event, properties) {
|
|
|
98
98
|
if (event.serverVersion) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
|
|
99
99
|
if (event.clientName) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
100
100
|
if (event.clientVersion) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion;
|
|
101
|
+
if (event.protocolVersion) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ProtocolVersion] = event.protocolVersion;
|
|
101
102
|
if (event.userIntent) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.Intent] = event.userIntent;
|
|
102
103
|
if (event.userIntentSource) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.IntentSource] = event.userIntentSource;
|
|
103
104
|
if (void 0 !== event.isError) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.IsError] = event.isError;
|
|
@@ -135,6 +136,7 @@ function buildExceptionEvent(event) {
|
|
|
135
136
|
if (event.serverVersion) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
|
|
136
137
|
if (event.clientName) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
137
138
|
if (event.clientVersion) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion;
|
|
139
|
+
if (event.protocolVersion) properties[external_constants_js_namespaceObject.PostHogMCPAnalyticsProperty.ProtocolVersion] = event.protocolVersion;
|
|
138
140
|
addCustomEventProperties(event, properties);
|
|
139
141
|
return {
|
|
140
142
|
event: external_constants_js_namespaceObject.PostHogMCPAnalyticsEvent.Exception,
|
|
@@ -70,6 +70,7 @@ function addCommonEventProperties(event, properties) {
|
|
|
70
70
|
if (event.serverVersion) properties[PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
|
|
71
71
|
if (event.clientName) properties[PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
72
72
|
if (event.clientVersion) properties[PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion;
|
|
73
|
+
if (event.protocolVersion) properties[PostHogMCPAnalyticsProperty.ProtocolVersion] = event.protocolVersion;
|
|
73
74
|
if (event.userIntent) properties[PostHogMCPAnalyticsProperty.Intent] = event.userIntent;
|
|
74
75
|
if (event.userIntentSource) properties[PostHogMCPAnalyticsProperty.IntentSource] = event.userIntentSource;
|
|
75
76
|
if (void 0 !== event.isError) properties[PostHogMCPAnalyticsProperty.IsError] = event.isError;
|
|
@@ -107,6 +108,7 @@ function buildExceptionEvent(event) {
|
|
|
107
108
|
if (event.serverVersion) properties[PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
|
|
108
109
|
if (event.clientName) properties[PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
109
110
|
if (event.clientVersion) properties[PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion;
|
|
111
|
+
if (event.protocolVersion) properties[PostHogMCPAnalyticsProperty.ProtocolVersion] = event.protocolVersion;
|
|
110
112
|
addCustomEventProperties(event, properties);
|
|
111
113
|
return {
|
|
112
114
|
event: PostHogMCPAnalyticsEvent.Exception,
|
|
@@ -114,6 +114,7 @@ function baseEvent(eventType, common) {
|
|
|
114
114
|
const event = {
|
|
115
115
|
eventType,
|
|
116
116
|
sessionId: common.sessionId,
|
|
117
|
+
protocolVersion: common.protocolVersion,
|
|
117
118
|
timestamp: common.timestamp ?? new Date(),
|
|
118
119
|
properties: common.properties,
|
|
119
120
|
groups: common.groups
|
|
@@ -18,6 +18,13 @@ export interface SessionTokenPayload {
|
|
|
18
18
|
clientName?: string;
|
|
19
19
|
/** MCP client version → `$mcp_client_version`. */
|
|
20
20
|
clientVersion?: string;
|
|
21
|
+
/**
|
|
22
|
+
* MCP protocol (spec) version → `$mcp_protocol_version`. The client's
|
|
23
|
+
* *requested* version — the only one known when the token is minted (before
|
|
24
|
+
* the initialize handler negotiates). Lets pods that never saw `initialize`
|
|
25
|
+
* still stamp the spec version on their events.
|
|
26
|
+
*/
|
|
27
|
+
protocolVersion?: string;
|
|
21
28
|
}
|
|
22
29
|
/**
|
|
23
30
|
* Encodes a session token for the `Mcp-Session-Id` response header. Also
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-token.d.ts","sourceRoot":"","sources":["../../src/extensions/session-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,kBAAkB,mBAAmB,CAAA;AAElD,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"session-token.d.ts","sourceRoot":"","sources":["../../src/extensions/session-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,kBAAkB,mBAAmB,CAAA;AAElD,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAWD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAepE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAiC1E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAgBzE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAsBpF"}
|
|
@@ -42,6 +42,7 @@ function encodeSessionId(payload) {
|
|
|
42
42
|
};
|
|
43
43
|
if ('string' == typeof payload.clientName && payload.clientName.length > 0) wire.cn = payload.clientName.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
44
44
|
if ('string' == typeof payload.clientVersion && payload.clientVersion.length > 0) wire.cv = payload.clientVersion.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
45
|
+
if ('string' == typeof payload.protocolVersion && payload.protocolVersion.length > 0) wire.pv = payload.protocolVersion.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
45
46
|
return utf8ToBase64Url(JSON.stringify(wire));
|
|
46
47
|
}
|
|
47
48
|
function decodeSessionId(value) {
|
|
@@ -61,6 +62,7 @@ function decodeSessionId(value) {
|
|
|
61
62
|
};
|
|
62
63
|
if ('string' == typeof wire.cn && wire.cn.length > 0) payload.clientName = wire.cn.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
63
64
|
if ('string' == typeof wire.cv && wire.cv.length > 0) payload.clientVersion = wire.cv.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
65
|
+
if ('string' == typeof wire.pv && wire.pv.length > 0) payload.protocolVersion = wire.pv.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
64
66
|
return payload;
|
|
65
67
|
}
|
|
66
68
|
function readMcpSessionHeader(headers) {
|
|
@@ -10,6 +10,7 @@ function encodeSessionId(payload) {
|
|
|
10
10
|
};
|
|
11
11
|
if ('string' == typeof payload.clientName && payload.clientName.length > 0) wire.cn = payload.clientName.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
12
12
|
if ('string' == typeof payload.clientVersion && payload.clientVersion.length > 0) wire.cv = payload.clientVersion.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
13
|
+
if ('string' == typeof payload.protocolVersion && payload.protocolVersion.length > 0) wire.pv = payload.protocolVersion.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
13
14
|
return utf8ToBase64Url(JSON.stringify(wire));
|
|
14
15
|
}
|
|
15
16
|
function decodeSessionId(value) {
|
|
@@ -29,6 +30,7 @@ function decodeSessionId(value) {
|
|
|
29
30
|
};
|
|
30
31
|
if ('string' == typeof wire.cn && wire.cn.length > 0) payload.clientName = wire.cn.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
31
32
|
if ('string' == typeof wire.cv && wire.cv.length > 0) payload.clientVersion = wire.cv.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
33
|
+
if ('string' == typeof wire.pv && wire.pv.length > 0) payload.protocolVersion = wire.pv.slice(0, MAX_CLIENT_FIELD_LENGTH);
|
|
32
34
|
return payload;
|
|
33
35
|
}
|
|
34
36
|
function readMcpSessionHeader(headers) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/extensions/session.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,6BAA6B,EAC7B,gBAAgB,EAChB,aAAa,EAEb,WAAW,EACZ,MAAM,UAAU,CAAA;AAMjB,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,6BAA6B,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/extensions/session.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,6BAA6B,EAC7B,gBAAgB,EAChB,aAAa,EAEb,WAAW,EACZ,MAAM,UAAU,CAAA;AAMjB,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,6BAA6B,GAAG,MAAM,CAgCjG;AAgBD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,gBAAgB,GAAG,SAAS,EAClC,SAAS,CAAC,EAAE,MAAM,GACjB,WAAW,CAmCb"}
|
|
@@ -50,6 +50,7 @@ function getSessionId(server, extra) {
|
|
|
50
50
|
data.sessionSource = 'token';
|
|
51
51
|
data.sessionInfo.clientName = token.clientName;
|
|
52
52
|
data.sessionInfo.clientVersion = token.clientVersion;
|
|
53
|
+
data.sessionInfo.protocolVersion = token.protocolVersion;
|
|
53
54
|
sessionId = token.sessionId;
|
|
54
55
|
} else if (extra?.sessionId) {
|
|
55
56
|
data.sessionSource = 'mcp';
|
|
@@ -81,6 +82,7 @@ function getSessionInfo(server, data, sessionId) {
|
|
|
81
82
|
serverVersion: server._serverInfo?.version,
|
|
82
83
|
clientName: clientInfo?.name,
|
|
83
84
|
clientVersion: clientInfo?.version,
|
|
85
|
+
protocolVersion: data?.sessionInfo.protocolVersion,
|
|
84
86
|
identifyActorGivenId: actorInfo?.distinctId,
|
|
85
87
|
identifyActorData: actorInfo?.properties || {},
|
|
86
88
|
identifyActorGroups: actorInfo?.groups
|
|
@@ -19,6 +19,7 @@ function getSessionId(server, extra) {
|
|
|
19
19
|
data.sessionSource = 'token';
|
|
20
20
|
data.sessionInfo.clientName = token.clientName;
|
|
21
21
|
data.sessionInfo.clientVersion = token.clientVersion;
|
|
22
|
+
data.sessionInfo.protocolVersion = token.protocolVersion;
|
|
22
23
|
sessionId = token.sessionId;
|
|
23
24
|
} else if (extra?.sessionId) {
|
|
24
25
|
data.sessionSource = 'mcp';
|
|
@@ -50,6 +51,7 @@ function getSessionInfo(server, data, sessionId) {
|
|
|
50
51
|
serverVersion: server._serverInfo?.version,
|
|
51
52
|
clientName: clientInfo?.name,
|
|
52
53
|
clientVersion: clientInfo?.version,
|
|
54
|
+
protocolVersion: data?.sessionInfo.protocolVersion,
|
|
53
55
|
identifyActorGivenId: actorInfo?.distinctId,
|
|
54
56
|
identifyActorData: actorInfo?.properties || {},
|
|
55
57
|
identifyActorGroups: actorInfo?.groups
|
package/dist/types.d.ts
CHANGED
|
@@ -59,6 +59,8 @@ export interface MCPAnalyticsOptions {
|
|
|
59
59
|
/**
|
|
60
60
|
* Identify the calling user. Returning a non-null value sets `distinct_id` and `$set`
|
|
61
61
|
* on subsequent events for the session. Object form is treated as a static identity.
|
|
62
|
+
* A standalone `$identify` event is published once per session — at `initialize`, or
|
|
63
|
+
* when a long-lived server sees the identity appear or change — never per tool call.
|
|
62
64
|
*/
|
|
63
65
|
identify?: ((request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Promise<UserIdentity | null>) | UserIdentity | null;
|
|
64
66
|
/**
|
|
@@ -140,6 +142,12 @@ export interface Event {
|
|
|
140
142
|
listedToolNames?: string[];
|
|
141
143
|
parameters?: unknown;
|
|
142
144
|
properties?: JsonRecord | null;
|
|
145
|
+
/**
|
|
146
|
+
* Negotiated MCP protocol (spec) version → `$mcp_protocol_version`. Learned at
|
|
147
|
+
* `initialize` and carried onto every event for the session (see SessionInfo) —
|
|
148
|
+
* used to track spec adoption and to slice event metrics by spec version.
|
|
149
|
+
*/
|
|
150
|
+
protocolVersion?: string;
|
|
143
151
|
resourceName?: string;
|
|
144
152
|
response?: unknown;
|
|
145
153
|
sdkLanguage?: string;
|
|
@@ -222,6 +230,11 @@ export interface SessionInfo {
|
|
|
222
230
|
identifyActorGivenId?: string;
|
|
223
231
|
identifyActorGroups?: Record<string, string>;
|
|
224
232
|
ipAddress?: string;
|
|
233
|
+
/**
|
|
234
|
+
* Negotiated MCP protocol (spec) version, learned at `initialize` and carried
|
|
235
|
+
* forward for the session (across pods via the session token) → `$mcp_protocol_version`.
|
|
236
|
+
*/
|
|
237
|
+
protocolVersion?: string;
|
|
225
238
|
sdkLanguage?: string;
|
|
226
239
|
sdkVersion?: string;
|
|
227
240
|
serverName?: string;
|
|
@@ -262,6 +275,12 @@ export interface McpCaptureCommon {
|
|
|
262
275
|
distinctId?: string;
|
|
263
276
|
/** Session id → `$session_id`. Omitted from the event entirely when not provided. */
|
|
264
277
|
sessionId?: string;
|
|
278
|
+
/**
|
|
279
|
+
* Negotiated MCP protocol (spec) version → `$mcp_protocol_version`. Pass it on
|
|
280
|
+
* every capture for the session (like `sessionId`) so later events carry it too,
|
|
281
|
+
* not just the initialize event — the `PostHogMCP` client holds no per-session state.
|
|
282
|
+
*/
|
|
283
|
+
protocolVersion?: string;
|
|
265
284
|
/** Person properties → `$set` (e.g. `{ name, email, plan }`). */
|
|
266
285
|
setProperties?: JsonRecord;
|
|
267
286
|
/** Group memberships → `$groups`. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD,+FAA+F;AAC/F,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC,eAAe,CAAA;AAC3D,qEAAqE;AACrE,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAA;AAEjD,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,4FAA4F;AAC5F,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD;AAED,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,2FAA2F;IAC3F,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,GAAG,0BAA0B,CAAA;IAC9C
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.
|
|
1
|
+
export declare const version = "0.10.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,WAAW,CAAA"}
|
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.
|
|
29
|
+
const version = '0.10.0';
|
|
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.
|
|
1
|
+
const version = '0.10.0';
|
|
2
2
|
export { version };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
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.
|
|
31
|
+
"@posthog/core": "^1.44.0"
|
|
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
|
-
"
|
|
43
|
-
"posthog-
|
|
42
|
+
"posthog-node": "^5.46.0",
|
|
43
|
+
"@posthog-tooling/tsconfig-base": "1.1.1"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@modelcontextprotocol/sdk": ">=1.26.0",
|
|
@@ -54,6 +54,10 @@ export function captureEvent(server: MCPServerLike, eventInput: McpEvent): Promi
|
|
|
54
54
|
identifyActorData: sessionInfo.identifyActorData,
|
|
55
55
|
groups: sessionInfo.identifyActorGroups,
|
|
56
56
|
resourceName: eventInput.resourceName,
|
|
57
|
+
// The `initialize` event sets the negotiated version directly; every other
|
|
58
|
+
// event inherits it from sessionInfo (persisted at initialize, recovered
|
|
59
|
+
// cross-pod from the session token).
|
|
60
|
+
protocolVersion: eventInput.protocolVersion ?? sessionInfo.protocolVersion,
|
|
57
61
|
toolCategory: eventInput.toolCategory,
|
|
58
62
|
toolDescription: eventInput.toolDescription,
|
|
59
63
|
listedToolNames: eventInput.listedToolNames,
|
|
@@ -48,6 +48,7 @@ export const PostHogMCPAnalyticsProperty = {
|
|
|
48
48
|
IntentSource: '$mcp_intent_source',
|
|
49
49
|
ListedToolNames: '$mcp_listed_tool_names',
|
|
50
50
|
Parameters: '$mcp_parameters',
|
|
51
|
+
ProtocolVersion: '$mcp_protocol_version',
|
|
51
52
|
ResourceName: '$mcp_resource_name',
|
|
52
53
|
Response: '$mcp_response',
|
|
53
54
|
ServerName: '$mcp_server_name',
|
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
// Licensed under the MIT License: https://github.com/agentcathq/agentcat-typescript-sdk/blob/main/LICENSE
|
|
5
5
|
|
|
6
6
|
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
CompatibleRequestHandlerExtra,
|
|
9
|
+
HighLevelMCPServerLike,
|
|
10
|
+
MCPServerLike,
|
|
11
|
+
RegisteredTool,
|
|
12
|
+
ToolCallback,
|
|
13
|
+
} from '../types'
|
|
8
14
|
import { stripConversationId } from './conversation-id'
|
|
9
15
|
import { MCPAnalyticsEventType } from './event-types'
|
|
10
16
|
import { getServerTrackingData } from './internal'
|
|
@@ -34,7 +40,7 @@ type ProcessedRegisteredTool = RegisteredTool & {
|
|
|
34
40
|
[MCP_ANALYTICS_PROCESSED]?: boolean
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
function isCallbackUpdate(value: unknown): value is { callback:
|
|
43
|
+
function isCallbackUpdate(value: unknown): value is { callback: ToolCallback } {
|
|
38
44
|
return !!value && typeof value === 'object' && 'callback' in value && typeof value.callback === 'function'
|
|
39
45
|
}
|
|
40
46
|
|
|
@@ -81,7 +87,7 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
81
87
|
const updateObj = updateArgs[0]
|
|
82
88
|
if (isCallbackUpdate(updateObj)) {
|
|
83
89
|
const wrappedTool = addTracingToToolCallbackInternal(
|
|
84
|
-
{ callback: updateObj.callback }
|
|
90
|
+
{ callback: updateObj.callback },
|
|
85
91
|
property,
|
|
86
92
|
server
|
|
87
93
|
)
|
|
@@ -436,35 +436,76 @@ function mintStatelessSessionOnInitialize(
|
|
|
436
436
|
data: MCPAnalyticsData,
|
|
437
437
|
request: MCPRequestLike,
|
|
438
438
|
extra: CompatibleRequestHandlerExtra | undefined
|
|
439
|
-
):
|
|
439
|
+
): string | undefined {
|
|
440
440
|
try {
|
|
441
441
|
const headers = extra?.requestInfo?.headers
|
|
442
442
|
if (!headers || typeof headers !== 'object') {
|
|
443
|
-
return // not an HTTP transport (stdio/in-memory) — nothing to mint into
|
|
443
|
+
return undefined // not an HTTP transport (stdio/in-memory) — nothing to mint into
|
|
444
444
|
}
|
|
445
445
|
if (readMcpSessionHeader(headers)) {
|
|
446
|
-
return // client already replays a session id (ours or the transport's)
|
|
446
|
+
return undefined // client already replays a session id (ours or the transport's)
|
|
447
447
|
}
|
|
448
448
|
const transport = server.transport
|
|
449
449
|
if (!transport || extra?.sessionId || transport.sessionId) {
|
|
450
|
-
return // stateful transports manage their own session id — leave it alone
|
|
450
|
+
return undefined // stateful transports manage their own session id — leave it alone
|
|
451
451
|
}
|
|
452
452
|
|
|
453
453
|
const sessionId = newSessionId()
|
|
454
454
|
const clientInfo = readInitializeClientInfo(request)
|
|
455
|
-
|
|
455
|
+
// Minted before the handler negotiates, so only the client's *requested*
|
|
456
|
+
// version is available here; `handleInitializeRequest` re-mints the token
|
|
457
|
+
// with the negotiated version once the handler has run.
|
|
458
|
+
const requestedProtocolVersion = readProtocolVersion(undefined, request)
|
|
459
|
+
const token = encodeSessionId({
|
|
460
|
+
sessionId,
|
|
461
|
+
clientName: clientInfo?.name,
|
|
462
|
+
clientVersion: clientInfo?.version,
|
|
463
|
+
protocolVersion: requestedProtocolVersion,
|
|
464
|
+
})
|
|
456
465
|
if (!writeSessionIdToTransport(transport, token)) {
|
|
457
|
-
return // transport can't carry a response session id — keep generated behavior
|
|
466
|
+
return undefined // transport can't carry a response session id — keep generated behavior
|
|
458
467
|
}
|
|
459
468
|
|
|
460
469
|
data.sessionId = sessionId
|
|
461
470
|
data.sessionSource = 'token'
|
|
462
471
|
data.sessionInfo.clientName = clientInfo?.name
|
|
463
472
|
data.sessionInfo.clientVersion = clientInfo?.version
|
|
473
|
+
data.sessionInfo.protocolVersion = requestedProtocolVersion
|
|
464
474
|
data.lastActivity = new Date()
|
|
465
475
|
setServerTrackingData(server, data)
|
|
476
|
+
return sessionId
|
|
466
477
|
} catch (error) {
|
|
467
478
|
log(`Warning: PostHog MCP analytics failed to mint a stateless session id - ${error}`)
|
|
479
|
+
return undefined
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Rewrite the minted token to carry the *negotiated* protocol version now that
|
|
485
|
+
* the handler has run. Without this, a server that downgrades the client's
|
|
486
|
+
* requested version would replay the requested one on later requests (and to
|
|
487
|
+
* other pods), reporting a version the session is not actually using.
|
|
488
|
+
*/
|
|
489
|
+
function upgradeMintedTokenToNegotiated(
|
|
490
|
+
server: MCPServerLike,
|
|
491
|
+
data: MCPAnalyticsData,
|
|
492
|
+
mintedSessionId: string,
|
|
493
|
+
negotiatedProtocolVersion: string | undefined
|
|
494
|
+
): void {
|
|
495
|
+
try {
|
|
496
|
+
const transport = server.transport
|
|
497
|
+
if (!transport) {
|
|
498
|
+
return
|
|
499
|
+
}
|
|
500
|
+
const token = encodeSessionId({
|
|
501
|
+
sessionId: mintedSessionId,
|
|
502
|
+
clientName: data.sessionInfo.clientName,
|
|
503
|
+
clientVersion: data.sessionInfo.clientVersion,
|
|
504
|
+
protocolVersion: negotiatedProtocolVersion,
|
|
505
|
+
})
|
|
506
|
+
writeSessionIdToTransport(transport, token)
|
|
507
|
+
} catch (error) {
|
|
508
|
+
log(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`)
|
|
468
509
|
}
|
|
469
510
|
}
|
|
470
511
|
|
|
@@ -503,7 +544,7 @@ export async function handleInitializeRequest(
|
|
|
503
544
|
}
|
|
504
545
|
|
|
505
546
|
// Mint first so the `$mcp_initialize` event below already carries the minted id.
|
|
506
|
-
mintStatelessSessionOnInitialize(server, data, request, extra)
|
|
547
|
+
const mintedSessionId = mintStatelessSessionOnInitialize(server, data, request, extra)
|
|
507
548
|
const sessionId = getSessionId(server, extra)
|
|
508
549
|
await handleIdentify(server, data, sessionId, request, extra)
|
|
509
550
|
|
|
@@ -519,6 +560,31 @@ export async function handleInitializeRequest(
|
|
|
519
560
|
|
|
520
561
|
const result = await originalInitializeHandler(request, extra)
|
|
521
562
|
event.response = result
|
|
563
|
+
// The negotiated version (off the response) supersedes the requested one the
|
|
564
|
+
// mint stored — persist it so every later event on this pod carries it, and
|
|
565
|
+
// re-mint the token so pods replaying it report the negotiated version too.
|
|
566
|
+
const negotiatedProtocolVersion = readProtocolVersion(result, request)
|
|
567
|
+
event.protocolVersion = negotiatedProtocolVersion
|
|
568
|
+
data.sessionInfo.protocolVersion = negotiatedProtocolVersion
|
|
569
|
+
setServerTrackingData(server, data)
|
|
570
|
+
if (mintedSessionId) {
|
|
571
|
+
upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion)
|
|
572
|
+
}
|
|
522
573
|
captureEvent(server, event)
|
|
523
574
|
return result
|
|
524
575
|
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* The MCP spec (protocol) version this session speaks. Prefer the negotiated
|
|
579
|
+
* version off the initialize response — the version the server committed to and
|
|
580
|
+
* the session actually runs on — falling back to the client's requested version
|
|
581
|
+
* if the response omits it. Used to track spec-revision adoption.
|
|
582
|
+
*/
|
|
583
|
+
function readProtocolVersion(result: unknown, request: MCPRequestLike): string | undefined {
|
|
584
|
+
const negotiated = (result as Record<string, unknown> | null | undefined)?.protocolVersion
|
|
585
|
+
if (typeof negotiated === 'string' && negotiated.length > 0) {
|
|
586
|
+
return negotiated
|
|
587
|
+
}
|
|
588
|
+
const requested = request.params?.protocolVersion
|
|
589
|
+
return typeof requested === 'string' && requested.length > 0 ? requested : undefined
|
|
590
|
+
}
|
|
@@ -118,8 +118,10 @@ export function mergeIdentities(previous: UserIdentity | undefined, next: UserId
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
/**
|
|
121
|
-
* Resolves the optional `identify` callback
|
|
122
|
-
*
|
|
121
|
+
* Resolves the optional `identify` callback on every request (the resolved
|
|
122
|
+
* identity is what stamps `distinct_id`/`$set` onto events), but publishes the
|
|
123
|
+
* `$identify` event at most once per session: at `initialize`, when a
|
|
124
|
+
* long-lived server first sees the identity, or when it materially changes.
|
|
123
125
|
*/
|
|
124
126
|
export async function handleIdentify(
|
|
125
127
|
server: MCPServerLike,
|
|
@@ -147,11 +149,24 @@ export async function handleIdentify(
|
|
|
147
149
|
if (identityResult) {
|
|
148
150
|
const previousIdentity = data.identifiedSessions.get(sessionId)
|
|
149
151
|
const mergedIdentity = mergeIdentities(previousIdentity, identityResult)
|
|
150
|
-
|
|
152
|
+
// "First seen" means new to this instance's cache — which on a stateless
|
|
153
|
+
// pod (fresh instrument() per request) is every request. A token session
|
|
154
|
+
// was already announced by whichever pod handled `initialize`, so only the
|
|
155
|
+
// handshake, or a genuine change a long-lived server observed, publishes
|
|
156
|
+
// $identify. Every event still carries distinct_id/$set regardless, so
|
|
157
|
+
// person properties are never lost. Known gap: if identity is null at
|
|
158
|
+
// `initialize` but resolves later on a token session, that first $identify
|
|
159
|
+
// is suppressed too, so any pre-identify (anonymous) events aren't aliased
|
|
160
|
+
// onto the user. Inherent to statelessness (no pod knows a sibling already
|
|
161
|
+
// announced); revisit with the stateless-by-default rework.
|
|
162
|
+
const changed = previousIdentity !== undefined && !areIdentitiesEqual(previousIdentity, mergedIdentity)
|
|
163
|
+
const firstSeen = previousIdentity === undefined
|
|
164
|
+
const announcedAtInitialize = data.sessionSource === 'token' && request.method !== 'initialize'
|
|
165
|
+
const shouldPublish = changed || (firstSeen && !announcedAtInitialize)
|
|
151
166
|
|
|
152
167
|
data.identifiedSessions.set(sessionId, mergedIdentity)
|
|
153
168
|
|
|
154
|
-
if (
|
|
169
|
+
if (shouldPublish) {
|
|
155
170
|
log(`Identified session ${sessionId} with identity: ${JSON.stringify(mergedIdentity)}`)
|
|
156
171
|
captureEvent(server, identifyEvent)
|
|
157
172
|
}
|
|
@@ -151,6 +151,11 @@ function addCommonEventProperties(event: Event, properties: Record<string, unkno
|
|
|
151
151
|
if (event.clientVersion) {
|
|
152
152
|
properties[PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion
|
|
153
153
|
}
|
|
154
|
+
// Present on every event once negotiated at `initialize` (carried via
|
|
155
|
+
// sessionInfo / the session token). Absent only before the handshake.
|
|
156
|
+
if (event.protocolVersion) {
|
|
157
|
+
properties[PostHogMCPAnalyticsProperty.ProtocolVersion] = event.protocolVersion
|
|
158
|
+
}
|
|
154
159
|
if (event.userIntent) {
|
|
155
160
|
properties[PostHogMCPAnalyticsProperty.Intent] = event.userIntent
|
|
156
161
|
}
|
|
@@ -237,6 +242,9 @@ function buildExceptionEvent(event: Event): PostHogCaptureEvent {
|
|
|
237
242
|
if (event.clientVersion) {
|
|
238
243
|
properties[PostHogMCPAnalyticsProperty.ClientVersion] = event.clientVersion
|
|
239
244
|
}
|
|
245
|
+
if (event.protocolVersion) {
|
|
246
|
+
properties[PostHogMCPAnalyticsProperty.ProtocolVersion] = event.protocolVersion
|
|
247
|
+
}
|
|
240
248
|
|
|
241
249
|
addCustomEventProperties(event, properties)
|
|
242
250
|
|
|
@@ -243,6 +243,7 @@ function baseEvent(eventType: MCPAnalyticsEventType, common: McpCaptureCommon):
|
|
|
243
243
|
const event: McpEvent = {
|
|
244
244
|
eventType,
|
|
245
245
|
sessionId: common.sessionId,
|
|
246
|
+
protocolVersion: common.protocolVersion,
|
|
246
247
|
timestamp: common.timestamp ?? new Date(),
|
|
247
248
|
properties: common.properties,
|
|
248
249
|
groups: common.groups,
|
|
@@ -20,10 +20,18 @@ export interface SessionTokenPayload {
|
|
|
20
20
|
clientName?: string
|
|
21
21
|
/** MCP client version → `$mcp_client_version`. */
|
|
22
22
|
clientVersion?: string
|
|
23
|
+
/**
|
|
24
|
+
* MCP protocol (spec) version → `$mcp_protocol_version`. The client's
|
|
25
|
+
* *requested* version — the only one known when the token is minted (before
|
|
26
|
+
* the initialize handler negotiates). Lets pods that never saw `initialize`
|
|
27
|
+
* still stamp the spec version on their events.
|
|
28
|
+
*/
|
|
29
|
+
protocolVersion?: string
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
// On the wire the token is base64url(JSON) with shortened keys to keep the
|
|
26
|
-
// header small: sid = sessionId, cn = clientName, cv = clientVersion
|
|
33
|
+
// header small: sid = sessionId, cn = clientName, cv = clientVersion,
|
|
34
|
+
// pv = protocolVersion.
|
|
27
35
|
const MAX_TOKEN_LENGTH = 4096
|
|
28
36
|
const MAX_SESSION_ID_LENGTH = 128
|
|
29
37
|
const MAX_CLIENT_FIELD_LENGTH = 200
|
|
@@ -46,6 +54,9 @@ export function encodeSessionId(payload: SessionTokenPayload): string {
|
|
|
46
54
|
if (typeof payload.clientVersion === 'string' && payload.clientVersion.length > 0) {
|
|
47
55
|
wire.cv = payload.clientVersion.slice(0, MAX_CLIENT_FIELD_LENGTH)
|
|
48
56
|
}
|
|
57
|
+
if (typeof payload.protocolVersion === 'string' && payload.protocolVersion.length > 0) {
|
|
58
|
+
wire.pv = payload.protocolVersion.slice(0, MAX_CLIENT_FIELD_LENGTH)
|
|
59
|
+
}
|
|
49
60
|
return utf8ToBase64Url(JSON.stringify(wire))
|
|
50
61
|
}
|
|
51
62
|
|
|
@@ -83,6 +94,9 @@ export function decodeSessionId(value: unknown): SessionTokenPayload | null {
|
|
|
83
94
|
if (typeof wire.cv === 'string' && wire.cv.length > 0) {
|
|
84
95
|
payload.clientVersion = wire.cv.slice(0, MAX_CLIENT_FIELD_LENGTH)
|
|
85
96
|
}
|
|
97
|
+
if (typeof wire.pv === 'string' && wire.pv.length > 0) {
|
|
98
|
+
payload.protocolVersion = wire.pv.slice(0, MAX_CLIENT_FIELD_LENGTH)
|
|
99
|
+
}
|
|
86
100
|
return payload
|
|
87
101
|
}
|
|
88
102
|
|
|
@@ -51,6 +51,7 @@ export function getSessionId(server: MCPServerLike, extra?: CompatibleRequestHan
|
|
|
51
51
|
data.sessionSource = 'token'
|
|
52
52
|
data.sessionInfo.clientName = token.clientName
|
|
53
53
|
data.sessionInfo.clientVersion = token.clientVersion
|
|
54
|
+
data.sessionInfo.protocolVersion = token.protocolVersion
|
|
54
55
|
sessionId = token.sessionId
|
|
55
56
|
} else if (extra?.sessionId) {
|
|
56
57
|
// Session id issued by a stateful transport: hash it so the same MCP
|
|
@@ -110,6 +111,9 @@ export function getSessionInfo(
|
|
|
110
111
|
serverVersion: server._serverInfo?.version,
|
|
111
112
|
clientName: clientInfo?.name,
|
|
112
113
|
clientVersion: clientInfo?.version,
|
|
114
|
+
// No SDK getter for this (unlike getClientVersion) — the MCP SDK never
|
|
115
|
+
// retains the negotiated version, so it lives only where we stored it.
|
|
116
|
+
protocolVersion: data?.sessionInfo.protocolVersion,
|
|
113
117
|
identifyActorGivenId: actorInfo?.distinctId,
|
|
114
118
|
identifyActorData: actorInfo?.properties || {},
|
|
115
119
|
identifyActorGroups: actorInfo?.groups,
|
package/src/types.ts
CHANGED
|
@@ -70,6 +70,8 @@ export interface MCPAnalyticsOptions {
|
|
|
70
70
|
/**
|
|
71
71
|
* Identify the calling user. Returning a non-null value sets `distinct_id` and `$set`
|
|
72
72
|
* on subsequent events for the session. Object form is treated as a static identity.
|
|
73
|
+
* A standalone `$identify` event is published once per session — at `initialize`, or
|
|
74
|
+
* when a long-lived server sees the identity appear or change — never per tool call.
|
|
73
75
|
*/
|
|
74
76
|
identify?:
|
|
75
77
|
| ((request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Promise<UserIdentity | null>)
|
|
@@ -163,6 +165,12 @@ export interface Event {
|
|
|
163
165
|
listedToolNames?: string[]
|
|
164
166
|
parameters?: unknown
|
|
165
167
|
properties?: JsonRecord | null
|
|
168
|
+
/**
|
|
169
|
+
* Negotiated MCP protocol (spec) version → `$mcp_protocol_version`. Learned at
|
|
170
|
+
* `initialize` and carried onto every event for the session (see SessionInfo) —
|
|
171
|
+
* used to track spec adoption and to slice event metrics by spec version.
|
|
172
|
+
*/
|
|
173
|
+
protocolVersion?: string
|
|
166
174
|
resourceName?: string
|
|
167
175
|
response?: unknown
|
|
168
176
|
sdkLanguage?: string
|
|
@@ -252,6 +260,11 @@ export interface SessionInfo {
|
|
|
252
260
|
identifyActorGivenId?: string
|
|
253
261
|
identifyActorGroups?: Record<string, string>
|
|
254
262
|
ipAddress?: string
|
|
263
|
+
/**
|
|
264
|
+
* Negotiated MCP protocol (spec) version, learned at `initialize` and carried
|
|
265
|
+
* forward for the session (across pods via the session token) → `$mcp_protocol_version`.
|
|
266
|
+
*/
|
|
267
|
+
protocolVersion?: string
|
|
255
268
|
sdkLanguage?: string
|
|
256
269
|
sdkVersion?: string
|
|
257
270
|
serverName?: string
|
|
@@ -295,6 +308,12 @@ export interface McpCaptureCommon {
|
|
|
295
308
|
distinctId?: string
|
|
296
309
|
/** Session id → `$session_id`. Omitted from the event entirely when not provided. */
|
|
297
310
|
sessionId?: string
|
|
311
|
+
/**
|
|
312
|
+
* Negotiated MCP protocol (spec) version → `$mcp_protocol_version`. Pass it on
|
|
313
|
+
* every capture for the session (like `sessionId`) so later events carry it too,
|
|
314
|
+
* not just the initialize event — the `PostHogMCP` client holds no per-session state.
|
|
315
|
+
*/
|
|
316
|
+
protocolVersion?: string
|
|
298
317
|
/** Person properties → `$set` (e.g. `{ name, email, plan }`). */
|
|
299
318
|
setProperties?: JsonRecord
|
|
300
319
|
/** Group memberships → `$groups`. */
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.10.0'
|