Sign In

@posthog/mcp

Package Overview
Dependencies
Maintainers
22
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@posthog/mcp - npm Package Compare versions

Comparing version
0.10.6
to
0.10.7
+2
-2
dist/extensions/capture.d.ts

@@ -1,2 +0,2 @@

import type { MCPServerLike, McpEvent } from '../types';
import type { MCPServerLike, McpEvent, SessionInfo } from '../types';
import type { LoggerFn } from './logger';

@@ -13,3 +13,3 @@ /**

*/
export declare function captureEvent(server: MCPServerLike, eventInput: McpEvent, logger: LoggerFn): Promise<void> | undefined;
export declare function captureEvent(server: MCPServerLike, eventInput: McpEvent, logger: LoggerFn, requestAttribution?: SessionInfo): Promise<void> | undefined;
//# sourceMappingURL=capture.d.ts.map

@@ -1,1 +0,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;AAGvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGxC;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAkErH"}
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/extensions/capture.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAGpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGxC;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,QAAQ,EACpB,MAAM,EAAE,QAAQ,EAChB,kBAAkB,CAAC,EAAE,WAAW,GAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAoE3B"}

@@ -32,3 +32,3 @@ "use strict";

const external_session_js_namespaceObject = require("./session.js");
function captureEvent(server, eventInput, logger) {
function captureEvent(server, eventInput, logger, requestAttribution) {
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);

@@ -38,3 +38,3 @@ if (!data) return void logger('Warning: Server tracking data not found. Event will not be published.');

if (!sink) return;
const sessionInfo = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, eventInput.sessionId);
const sessionInfo = requestAttribution ?? (0, external_session_js_namespaceObject.getSessionInfo)(server, data, eventInput.sessionId);
const duration = eventInput.duration || (eventInput.timestamp ? Date.now() - eventInput.timestamp.getTime() : void 0);

@@ -41,0 +41,0 @@ const fullEvent = {

import { MCPAnalyticsEventType } from "./event-types.mjs";
import { getServerTrackingData } from "./internal.mjs";
import { getSessionInfo } from "./session.mjs";
function captureEvent(server, eventInput, logger) {
function captureEvent(server, eventInput, logger, requestAttribution) {
const data = getServerTrackingData(server);

@@ -9,3 +9,3 @@ if (!data) return void logger('Warning: Server tracking data not found. Event will not be published.');

if (!sink) return;
const sessionInfo = getSessionInfo(server, data, eventInput.sessionId);
const sessionInfo = requestAttribution ?? getSessionInfo(server, data, eventInput.sessionId);
const duration = eventInput.duration || (eventInput.timestamp ? Date.now() - eventInput.timestamp.getTime() : void 0);

@@ -12,0 +12,0 @@ const fullEvent = {

@@ -1,1 +0,1 @@

{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"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"}

@@ -58,4 +58,4 @@ "use strict";

const startTime = new Date();
const event = await prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, resolvedEventType);
if (event && explicitContextIntent) (0, external_intent_js_namespaceObject.setExplicitContextIntent)(event, explicitContextIntent);
const preparedEvent = await prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, resolvedEventType);
if (preparedEvent && explicitContextIntent) (0, external_intent_js_namespaceObject.setExplicitContextIntent)(preparedEvent.event, explicitContextIntent);
let result;

@@ -65,7 +65,7 @@ try {

} catch (error) {
publishFailedToolEvent(server, event, error, startTime, conversation, data.logger);
publishFailedToolEvent(server, preparedEvent, error, startTime, conversation, data.logger);
throw error;
}
const finalResult = applyConversationPromptBack(event, result, conversation);
publishSuccessfulToolEvent(server, event, finalResult, startTime, data.logger, takeCapturedError);
const finalResult = applyConversationPromptBack(preparedEvent?.event ?? null, result, conversation);
publishSuccessfulToolEvent(server, preparedEvent, finalResult, startTime, data.logger, takeCapturedError);
return finalResult;

@@ -95,3 +95,5 @@ }

const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, extra);
const sessionInfo = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, sessionId);
const identity = await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, sessionInfo, extra);
const requestAttribution = (0, external_internal_js_namespaceObject.withIdentity)(sessionInfo, identity);
const toolName = request.params?.name;

@@ -111,3 +113,6 @@ const event = {

(0, external_intent_js_namespaceObject.setEventIntent)(event, await (0, external_intent_js_namespaceObject.resolveToolCallIntent)(data, request, ownership.context, extra));
return event;
return {
event,
requestAttribution
};
} catch (error) {

@@ -124,4 +129,5 @@ data.logger(`Warning: PostHog MCP analytics instrumentation failed for tool ${request.params?.name}, the tool will still run - ${error}`);

}
function publishSuccessfulToolEvent(server, event, result, startTime, logger, takeCapturedError) {
if (!event) return;
function publishSuccessfulToolEvent(server, preparedEvent, result, startTime, logger, takeCapturedError) {
if (!preparedEvent) return;
const { event, requestAttribution } = preparedEvent;
try {

@@ -135,3 +141,3 @@ if ((0, external_tracing_helpers_js_namespaceObject.isToolResultError)(result)) {

event.duration = Date.now() - startTime.getTime();
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger);
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger, requestAttribution);
} catch (error) {

@@ -141,4 +147,5 @@ logger(`Warning: PostHog MCP analytics failed to publish tool event - ${error}`);

}
function publishFailedToolEvent(server, event, error, startTime, conversation, logger) {
if (!event) return;
function publishFailedToolEvent(server, preparedEvent, error, startTime, conversation, logger) {
if (!preparedEvent) return;
const { event, requestAttribution } = preparedEvent;
try {

@@ -149,3 +156,3 @@ if (conversation.minted) event.conversationId = void 0;

event.duration = Date.now() - startTime.getTime();
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger);
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger, requestAttribution);
} catch (publishError) {

@@ -205,4 +212,6 @@ logger(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`);

const startTime = new Date();
const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
const requestAttribution = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, sessionId);
const event = {
sessionId: (0, external_session_js_namespaceObject.getSessionId)(server, extra),
sessionId,
parameters: (0, external_mcp_payloads_js_namespaceObject.buildCapturedMcpParameters)(request),

@@ -214,3 +223,3 @@ eventType: external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpToolsList,

if (data) await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger);
const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger, requestAttribution);
if (!data) {

@@ -227,3 +236,3 @@ logger('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');

event.duration = Date.now() - startTime.getTime();
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger);
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger, requestAttribution);
return {

@@ -239,3 +248,3 @@ tools

event.duration = Date.now() - startTime.getTime();
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger);
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger, requestAttribution);
return {

@@ -253,3 +262,3 @@ tools

}
async function getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger) {
async function getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger, requestAttribution) {
try {

@@ -286,3 +295,3 @@ const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);

event.duration = event.timestamp ? Date.now() - event.timestamp.getTime() : 0;
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger);
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger, requestAttribution);
throw error;

@@ -336,3 +345,3 @@ }

}
function upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion) {
function upgradeMintedTokenToNegotiated(server, mintedSessionId, sessionInfo, negotiatedProtocolVersion, logger) {
try {

@@ -343,4 +352,4 @@ const transport = server.transport;

sessionId: mintedSessionId,
clientName: data.sessionInfo.clientName,
clientVersion: data.sessionInfo.clientVersion,
clientName: sessionInfo.clientName,
clientVersion: sessionInfo.clientVersion,
protocolVersion: negotiatedProtocolVersion

@@ -350,3 +359,3 @@ });

} catch (error) {
data.logger(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`);
logger(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`);
}

@@ -371,3 +380,11 @@ }

const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, extra);
const sessionInfo = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, sessionId);
const initializeClientInfo = readInitializeClientInfo(request);
const requestSessionInfo = {
...sessionInfo,
clientName: initializeClientInfo?.name ?? sessionInfo.clientName,
clientVersion: initializeClientInfo?.version ?? sessionInfo.clientVersion
};
const identity = await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, requestSessionInfo, extra);
const requestAttribution = (0, external_internal_js_namespaceObject.withIdentity)(requestSessionInfo, identity);
const event = {

@@ -386,6 +403,14 @@ sessionId,

event.protocolVersion = negotiatedProtocolVersion;
data.sessionInfo.protocolVersion = negotiatedProtocolVersion;
(0, external_internal_js_namespaceObject.setServerTrackingData)(server, data);
if (mintedSessionId) upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion);
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger);
if (data.sessionId === sessionId) {
data.sessionInfo = {
...data.sessionInfo,
protocolVersion: negotiatedProtocolVersion
};
(0, external_internal_js_namespaceObject.setServerTrackingData)(server, data);
}
if (mintedSessionId) upgradeMintedTokenToNegotiated(server, mintedSessionId, requestSessionInfo, negotiatedProtocolVersion, data.logger);
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger, {
...requestAttribution,
protocolVersion: negotiatedProtocolVersion
});
return result;

@@ -392,0 +417,0 @@ }

@@ -9,6 +9,6 @@ import { getAnalyticsParameterOwnership, stripOwnedAnalyticsArguments } from "./analytics-parameters.mjs";

import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from "./intent.mjs";
import { getServerTrackingData, handleIdentify, setServerTrackingData } from "./internal.mjs";
import { getServerTrackingData, handleIdentify, setServerTrackingData, withIdentity } from "./internal.mjs";
import { buildCapturedMcpParameters } from "./mcp-payloads.mjs";
import { getLiteralValue, getObjectShape } from "./mcp-sdk-compat.mjs";
import { getSessionId, newSessionId } from "./session.mjs";
import { getSessionId, getSessionInfo, newSessionId } from "./session.mjs";
import { encodeSessionId, readMcpSessionHeader, writeSessionIdToTransport } from "./session-token.mjs";

@@ -24,4 +24,4 @@ import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from "./tools.mjs";

const startTime = new Date();
const event = await prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, resolvedEventType);
if (event && explicitContextIntent) setExplicitContextIntent(event, explicitContextIntent);
const preparedEvent = await prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, resolvedEventType);
if (preparedEvent && explicitContextIntent) setExplicitContextIntent(preparedEvent.event, explicitContextIntent);
let result;

@@ -31,7 +31,7 @@ try {

} catch (error) {
publishFailedToolEvent(server, event, error, startTime, conversation, data.logger);
publishFailedToolEvent(server, preparedEvent, error, startTime, conversation, data.logger);
throw error;
}
const finalResult = applyConversationPromptBack(event, result, conversation);
publishSuccessfulToolEvent(server, event, finalResult, startTime, data.logger, takeCapturedError);
const finalResult = applyConversationPromptBack(preparedEvent?.event ?? null, result, conversation);
publishSuccessfulToolEvent(server, preparedEvent, finalResult, startTime, data.logger, takeCapturedError);
return finalResult;

@@ -61,3 +61,5 @@ }

const sessionId = getSessionId(server, extra);
await handleIdentify(server, data, sessionId, request, extra);
const sessionInfo = getSessionInfo(server, data, sessionId);
const identity = await handleIdentify(server, data, sessionId, request, sessionInfo, extra);
const requestAttribution = withIdentity(sessionInfo, identity);
const toolName = request.params?.name;

@@ -77,3 +79,6 @@ const event = {

setEventIntent(event, await resolveToolCallIntent(data, request, ownership.context, extra));
return event;
return {
event,
requestAttribution
};
} catch (error) {

@@ -90,4 +95,5 @@ data.logger(`Warning: PostHog MCP analytics instrumentation failed for tool ${request.params?.name}, the tool will still run - ${error}`);

}
function publishSuccessfulToolEvent(server, event, result, startTime, logger, takeCapturedError) {
if (!event) return;
function publishSuccessfulToolEvent(server, preparedEvent, result, startTime, logger, takeCapturedError) {
if (!preparedEvent) return;
const { event, requestAttribution } = preparedEvent;
try {

@@ -101,3 +107,3 @@ if (isToolResultError(result)) {

event.duration = Date.now() - startTime.getTime();
captureEvent(server, event, logger);
captureEvent(server, event, logger, requestAttribution);
} catch (error) {

@@ -107,4 +113,5 @@ logger(`Warning: PostHog MCP analytics failed to publish tool event - ${error}`);

}
function publishFailedToolEvent(server, event, error, startTime, conversation, logger) {
if (!event) return;
function publishFailedToolEvent(server, preparedEvent, error, startTime, conversation, logger) {
if (!preparedEvent) return;
const { event, requestAttribution } = preparedEvent;
try {

@@ -115,3 +122,3 @@ if (conversation.minted) event.conversationId = void 0;

event.duration = Date.now() - startTime.getTime();
captureEvent(server, event, logger);
captureEvent(server, event, logger, requestAttribution);
} catch (publishError) {

@@ -171,4 +178,6 @@ logger(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`);

const startTime = new Date();
const sessionId = getSessionId(server, extra);
const requestAttribution = getSessionInfo(server, data, sessionId);
const event = {
sessionId: getSessionId(server, extra),
sessionId,
parameters: buildCapturedMcpParameters(request),

@@ -180,3 +189,3 @@ eventType: MCPAnalyticsEventType.mcpToolsList,

if (data) await applyResolvedMetadata(event, data, request, extra);
const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger);
const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger, requestAttribution);
if (!data) {

@@ -193,3 +202,3 @@ logger('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');

event.duration = Date.now() - startTime.getTime();
captureEvent(server, event, data.logger);
captureEvent(server, event, data.logger, requestAttribution);
return {

@@ -205,3 +214,3 @@ tools

event.duration = Date.now() - startTime.getTime();
captureEvent(server, event, data.logger);
captureEvent(server, event, data.logger, requestAttribution);
return {

@@ -219,3 +228,3 @@ tools

}
async function getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger) {
async function getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger, requestAttribution) {
try {

@@ -252,3 +261,3 @@ const data = getServerTrackingData(server);

event.duration = event.timestamp ? Date.now() - event.timestamp.getTime() : 0;
captureEvent(server, event, logger);
captureEvent(server, event, logger, requestAttribution);
throw error;

@@ -302,3 +311,3 @@ }

}
function upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion) {
function upgradeMintedTokenToNegotiated(server, mintedSessionId, sessionInfo, negotiatedProtocolVersion, logger) {
try {

@@ -309,4 +318,4 @@ const transport = server.transport;

sessionId: mintedSessionId,
clientName: data.sessionInfo.clientName,
clientVersion: data.sessionInfo.clientVersion,
clientName: sessionInfo.clientName,
clientVersion: sessionInfo.clientVersion,
protocolVersion: negotiatedProtocolVersion

@@ -316,3 +325,3 @@ });

} catch (error) {
data.logger(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`);
logger(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`);
}

@@ -337,3 +346,11 @@ }

const sessionId = getSessionId(server, extra);
await handleIdentify(server, data, sessionId, request, extra);
const sessionInfo = getSessionInfo(server, data, sessionId);
const initializeClientInfo = readInitializeClientInfo(request);
const requestSessionInfo = {
...sessionInfo,
clientName: initializeClientInfo?.name ?? sessionInfo.clientName,
clientVersion: initializeClientInfo?.version ?? sessionInfo.clientVersion
};
const identity = await handleIdentify(server, data, sessionId, request, requestSessionInfo, extra);
const requestAttribution = withIdentity(requestSessionInfo, identity);
const event = {

@@ -352,6 +369,14 @@ sessionId,

event.protocolVersion = negotiatedProtocolVersion;
data.sessionInfo.protocolVersion = negotiatedProtocolVersion;
setServerTrackingData(server, data);
if (mintedSessionId) upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion);
captureEvent(server, event, data.logger);
if (data.sessionId === sessionId) {
data.sessionInfo = {
...data.sessionInfo,
protocolVersion: negotiatedProtocolVersion
};
setServerTrackingData(server, data);
}
if (mintedSessionId) upgradeMintedTokenToNegotiated(server, mintedSessionId, requestSessionInfo, negotiatedProtocolVersion, data.logger);
captureEvent(server, event, data.logger, {
...requestAttribution,
protocolVersion: negotiatedProtocolVersion
});
return result;

@@ -358,0 +383,0 @@ }

@@ -1,2 +0,2 @@

import type { CompatibleRequestHandlerExtra, MCPAnalyticsData, MCPRequestLike, MCPServerLike, UserIdentity } from '../types';
import type { CompatibleRequestHandlerExtra, MCPAnalyticsData, MCPRequestLike, MCPServerLike, SessionInfo, UserIdentity } from '../types';
/**

@@ -27,3 +27,4 @@ * Bounded LRU cache for session identities, capped at `maxSize` entries so a

*/
export declare function handleIdentify(server: MCPServerLike, data: MCPAnalyticsData, sessionId: string, request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra): Promise<void>;
export declare function handleIdentify(server: MCPServerLike, data: MCPAnalyticsData, sessionId: string, request: MCPRequestLike, requestAttribution: SessionInfo, extra?: CompatibleRequestHandlerExtra): Promise<UserIdentity | undefined>;
export declare function withIdentity(sessionInfo: SessionInfo, identity: UserIdentity | undefined): SessionInfo;
/**

@@ -30,0 +31,0 @@ * Resolves the `eventProperties` callback. Returns null when no callback is

@@ -1,1 +0,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,CAkDf;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"}
{"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,WAAW,EACX,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,kBAAkB,EAAE,WAAW,EAC/B,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAsDnC;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,GAAG,SAAS,GAAG,WAAW,CAOtG;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"}

@@ -29,7 +29,8 @@ "use strict";

areIdentitiesEqual: ()=>areIdentitiesEqual,
getServerTrackingData: ()=>getServerTrackingData,
setServerTrackingData: ()=>setServerTrackingData,
resolveEventProperties: ()=>resolveEventProperties,
withIdentity: ()=>withIdentity,
handleIdentify: ()=>handleIdentify,
getServerTrackingData: ()=>getServerTrackingData,
IdentityCache: ()=>IdentityCache,
setServerTrackingData: ()=>setServerTrackingData
IdentityCache: ()=>IdentityCache
});

@@ -98,4 +99,6 @@ const external_event_types_js_namespaceObject = require("./event-types.js");

}
async function handleIdentify(server, data, sessionId, request, extra) {
if (!data.options.identify) return;
async function handleIdentify(server, data, sessionId, request, requestAttribution, extra) {
const identityBeforeRequest = data.identifiedSessions.get(sessionId);
const sessionSourceBeforeIdentify = data.sessionSource;
if (!data.options.identify) return identityBeforeRequest;
const identifyEvent = {

@@ -119,3 +122,3 @@ sessionId,

const firstSeen = void 0 === previousIdentity;
const announcedAtInitialize = 'token' === data.sessionSource && 'initialize' !== request.method;
const announcedAtInitialize = 'token' === sessionSourceBeforeIdentify && 'initialize' !== request.method;
const shouldPublish = changed || firstSeen && !announcedAtInitialize;

@@ -125,9 +128,20 @@ data.identifiedSessions.set(sessionId, mergedIdentity);

data.logger(`Identified session ${sessionId}`);
(0, external_capture_js_namespaceObject.captureEvent)(server, identifyEvent, data.logger);
(0, external_capture_js_namespaceObject.captureEvent)(server, identifyEvent, data.logger, withIdentity(requestAttribution, mergedIdentity));
}
} else data.logger(`Warning: Supplied identify function returned null for session ${sessionId}`);
return mergedIdentity;
}
data.logger(`Warning: Supplied identify function returned null for session ${sessionId}`);
} catch (error) {
data.logger(`Error: User supplied identify function threw an error while identifying session ${sessionId} - ${error}`);
}
return identityBeforeRequest;
}
function withIdentity(sessionInfo, identity) {
return {
...sessionInfo,
identifyActorGivenId: identity?.distinctId,
identifyActorData: identity?.properties || {},
identifyActorGroups: identity?.groups
};
}
async function resolveEventProperties(data, request, extra) {

@@ -155,2 +169,3 @@ if (!data.options.eventProperties) return null;

exports.setServerTrackingData = __webpack_exports__.setServerTrackingData;
exports.withIdentity = __webpack_exports__.withIdentity;
for(var __webpack_i__ in __webpack_exports__)if (-1 === [

@@ -163,3 +178,4 @@ "IdentityCache",

"resolveEventProperties",
"setServerTrackingData"
"setServerTrackingData",
"withIdentity"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];

@@ -166,0 +182,0 @@ Object.defineProperty(exports, '__esModule', {

@@ -63,4 +63,6 @@ import { MCPAnalyticsEventType } from "./event-types.mjs";

}
async function handleIdentify(server, data, sessionId, request, extra) {
if (!data.options.identify) return;
async function handleIdentify(server, data, sessionId, request, requestAttribution, extra) {
const identityBeforeRequest = data.identifiedSessions.get(sessionId);
const sessionSourceBeforeIdentify = data.sessionSource;
if (!data.options.identify) return identityBeforeRequest;
const identifyEvent = {

@@ -84,3 +86,3 @@ sessionId,

const firstSeen = void 0 === previousIdentity;
const announcedAtInitialize = 'token' === data.sessionSource && 'initialize' !== request.method;
const announcedAtInitialize = 'token' === sessionSourceBeforeIdentify && 'initialize' !== request.method;
const shouldPublish = changed || firstSeen && !announcedAtInitialize;

@@ -90,9 +92,20 @@ data.identifiedSessions.set(sessionId, mergedIdentity);

data.logger(`Identified session ${sessionId}`);
captureEvent(server, identifyEvent, data.logger);
captureEvent(server, identifyEvent, data.logger, withIdentity(requestAttribution, mergedIdentity));
}
} else data.logger(`Warning: Supplied identify function returned null for session ${sessionId}`);
return mergedIdentity;
}
data.logger(`Warning: Supplied identify function returned null for session ${sessionId}`);
} catch (error) {
data.logger(`Error: User supplied identify function threw an error while identifying session ${sessionId} - ${error}`);
}
return identityBeforeRequest;
}
function withIdentity(sessionInfo, identity) {
return {
...sessionInfo,
identifyActorGivenId: identity?.distinctId,
identifyActorData: identity?.properties || {},
identifyActorGroups: identity?.groups
};
}
async function resolveEventProperties(data, request, extra) {

@@ -113,2 +126,2 @@ if (!data.options.eventProperties) return null;

}
export { IdentityCache, areIdentitiesEqual, getServerTrackingData, handleIdentify, mergeIdentities, resolveEventProperties, setServerTrackingData };
export { IdentityCache, areIdentitiesEqual, getServerTrackingData, handleIdentify, mergeIdentities, resolveEventProperties, setServerTrackingData, withIdentity };

@@ -93,3 +93,5 @@ "use strict";

(0, external_internal_js_namespaceObject.setServerTrackingData)(server, data);
return data.sessionInfo;
return {
...sessionInfo
};
}

@@ -96,0 +98,0 @@ exports.deriveSessionIdFromMCPSession = __webpack_exports__.deriveSessionIdFromMCPSession;

@@ -62,4 +62,6 @@ import { version } from "../version.mjs";

setServerTrackingData(server, data);
return data.sessionInfo;
return {
...sessionInfo
};
}
export { deriveSessionIdFromMCPSession, getSessionId, getSessionInfo, newSessionId };

@@ -1,2 +0,2 @@

export declare const version = "0.10.6";
export declare const version = "0.10.7";
//# sourceMappingURL=version.d.ts.map

@@ -29,3 +29,3 @@ "use strict";

});
const version = '0.10.6';
const version = '0.10.7';
exports.version = __webpack_exports__.version;

@@ -32,0 +32,0 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [

@@ -1,2 +0,2 @@

const version = '0.10.6';
const version = '0.10.7';
export { version };
{
"name": "@posthog/mcp",
"version": "0.10.6",
"version": "0.10.7",
"bugs": {

@@ -42,4 +42,4 @@ "url": "https://github.com/PostHog/posthog-js/issues"

"zod": "^3.25.0",
"posthog-node": "^5.47.8",
"@posthog-tooling/tsconfig-base": "1.1.1"
"@posthog-tooling/tsconfig-base": "1.1.1",
"posthog-node": "^5.47.9"
},

@@ -46,0 +46,0 @@ "peerDependencies": {

@@ -6,3 +6,3 @@ // Portions of this file are derived from agentcathq/agentcat-typescript-sdk

import type { MCPServerLike, McpEvent } from '../types'
import type { MCPServerLike, McpEvent, SessionInfo } from '../types'
import { MCPAnalyticsEventType } from './event-types'

@@ -23,3 +23,8 @@ import { getServerTrackingData } from './internal'

*/
export function captureEvent(server: MCPServerLike, eventInput: McpEvent, logger: LoggerFn): Promise<void> | undefined {
export function captureEvent(
server: MCPServerLike,
eventInput: McpEvent,
logger: LoggerFn,
requestAttribution?: SessionInfo
): Promise<void> | undefined {
const data = getServerTrackingData(server)

@@ -36,3 +41,6 @@ if (!data) {

const sessionInfo = getSessionInfo(server, data, eventInput.sessionId)
// Instrumented request paths pass an immutable snapshot resolved before any
// user callback or handler can yield to a concurrent request. Custom capture
// has no request context, so it intentionally falls back to current state.
const sessionInfo = requestAttribution ?? getSessionInfo(server, data, eventInput.sessionId)

@@ -54,5 +62,4 @@ const duration =

serverVersion: sessionInfo.serverVersion,
// Prefer identity the event captured for *this* request (from `_meta`, see
// stampMetaClientInfo) over the server-wide sessionInfo, so a concurrent
// request from another client can't misattribute this one.
// Prefer client metadata stamped onto this event from the request's `_meta`
// over sessionInfo, so concurrent stateless requests stay isolated.
clientName: eventInput.clientName ?? sessionInfo.clientName,

@@ -59,0 +66,0 @@ clientVersion: eventInput.clientVersion ?? sessionInfo.clientVersion,

@@ -15,2 +15,3 @@ // Portions of this file are derived from agentcathq/agentcat-typescript-sdk

ServerClientInfoLike,
SessionInfo,
} from '../types'

@@ -31,7 +32,7 @@ import { getAnalyticsParameterOwnership, stripOwnedAnalyticsArguments } from './analytics-parameters'

import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from './intent'
import { getServerTrackingData, handleIdentify, setServerTrackingData } from './internal'
import { getServerTrackingData, handleIdentify, setServerTrackingData, withIdentity } from './internal'
import type { LoggerFn } from './logger'
import { buildCapturedMcpParameters } from './mcp-payloads'
import { getLiteralValue, getObjectShape } from './mcp-sdk-compat'
import { getSessionId, newSessionId } from './session'
import { getSessionId, getSessionInfo, newSessionId } from './session'
import { encodeSessionId, readMcpSessionHeader, writeSessionIdToTransport } from './session-token'

@@ -123,3 +124,3 @@ import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from './tools'

const startTime = new Date()
const event = await prepareToolCallEvent(
const preparedEvent = await prepareToolCallEvent(
server,

@@ -135,4 +136,4 @@ data,

)
if (event && explicitContextIntent) {
setExplicitContextIntent(event, explicitContextIntent)
if (preparedEvent && explicitContextIntent) {
setExplicitContextIntent(preparedEvent.event, explicitContextIntent)
}

@@ -144,11 +145,16 @@

} catch (error) {
publishFailedToolEvent(server, event, error, startTime, conversation, data.logger)
publishFailedToolEvent(server, preparedEvent, error, startTime, conversation, data.logger)
throw error
}
const finalResult = applyConversationPromptBack(event, result, conversation)
publishSuccessfulToolEvent(server, event, finalResult, startTime, data.logger, takeCapturedError)
const finalResult = applyConversationPromptBack(preparedEvent?.event ?? null, result, conversation)
publishSuccessfulToolEvent(server, preparedEvent, finalResult, startTime, data.logger, takeCapturedError)
return finalResult
}
interface PreparedToolEvent {
event: McpEvent
requestAttribution: SessionInfo
}
function getActiveAnalyticsParameterOwnership(

@@ -196,6 +202,10 @@ data: MCPAnalyticsData,

eventType: MCPAnalyticsEventType
): Promise<McpEvent | null> {
): Promise<PreparedToolEvent | null> {
try {
const sessionId = getSessionId(server, extra)
await handleIdentify(server, data, sessionId, request, extra)
// Snapshot token/client/protocol metadata synchronously, before identify or
// metadata callbacks can yield and let another request replace shared state.
const sessionInfo = getSessionInfo(server, data, sessionId)
const identity = await handleIdentify(server, data, sessionId, request, sessionInfo, extra)
const requestAttribution = withIdentity(sessionInfo, identity)

@@ -220,3 +230,3 @@ const toolName = request.params?.name

setEventIntent(event, await resolveToolCallIntent(data, request, ownership.context, extra))
return event
return { event, requestAttribution }
} catch (error) {

@@ -254,3 +264,3 @@ data.logger(

server: MCPServerLike,
event: McpEvent | null,
preparedEvent: PreparedToolEvent | null,
result: unknown,

@@ -261,5 +271,6 @@ startTime: Date,

): void {
if (!event) {
if (!preparedEvent) {
return
}
const { event, requestAttribution } = preparedEvent
try {

@@ -275,3 +286,3 @@ if (isToolResultError(result)) {

event.duration = Date.now() - startTime.getTime()
captureEvent(server, event, logger)
captureEvent(server, event, logger, requestAttribution)
} catch (error) {

@@ -284,3 +295,3 @@ logger(`Warning: PostHog MCP analytics failed to publish tool event - ${error}`)

server: MCPServerLike,
event: McpEvent | null,
preparedEvent: PreparedToolEvent | null,
error: unknown,

@@ -291,5 +302,6 @@ startTime: Date,

): void {
if (!event) {
if (!preparedEvent) {
return
}
const { event, requestAttribution } = preparedEvent
try {

@@ -302,3 +314,3 @@ if (conversation.minted) {

event.duration = Date.now() - startTime.getTime()
captureEvent(server, event, logger)
captureEvent(server, event, logger, requestAttribution)
} catch (publishError) {

@@ -423,4 +435,8 @@ logger(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`)

const startTime = new Date()
const sessionId = getSessionId(server, extra)
// Snapshot before metadata resolution or the list handler can yield to a
// concurrent request using the same instrumented server.
const requestAttribution = getSessionInfo(server, data, sessionId)
const event: McpEvent = {
sessionId: getSessionId(server, extra),
sessionId,
parameters: buildCapturedMcpParameters(request),

@@ -436,3 +452,11 @@ eventType: MCPAnalyticsEventType.mcpToolsList,

const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger)
const tools = await getTracedToolsList(
server,
originalListToolsHandler,
request,
extra,
event,
logger,
requestAttribution
)

@@ -453,3 +477,3 @@ if (!data) {

event.duration = Date.now() - startTime.getTime()
captureEvent(server, event, data.logger)
captureEvent(server, event, data.logger, requestAttribution)
return { tools }

@@ -462,3 +486,3 @@ }

event.duration = Date.now() - startTime.getTime()
captureEvent(server, event, data.logger)
captureEvent(server, event, data.logger, requestAttribution)
return { tools }

@@ -493,3 +517,4 @@ }

event: McpEvent,
logger: LoggerFn
logger: LoggerFn,
requestAttribution: SessionInfo
): Promise<ListToolsResult['tools']> {

@@ -542,3 +567,3 @@ try {

event.duration = event.timestamp ? Date.now() - event.timestamp.getTime() : 0
captureEvent(server, event, logger)
captureEvent(server, event, logger, requestAttribution)
throw error

@@ -652,5 +677,6 @@ }

server: MCPServerLike,
data: MCPAnalyticsData,
mintedSessionId: string,
negotiatedProtocolVersion: string | undefined
sessionInfo: SessionInfo,
negotiatedProtocolVersion: string | undefined,
logger: LoggerFn
): void {

@@ -664,4 +690,4 @@ try {

sessionId: mintedSessionId,
clientName: data.sessionInfo.clientName,
clientVersion: data.sessionInfo.clientVersion,
clientName: sessionInfo.clientName,
clientVersion: sessionInfo.clientVersion,
protocolVersion: negotiatedProtocolVersion,

@@ -671,3 +697,3 @@ })

} catch (error) {
data.logger(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`)
logger(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`)
}

@@ -714,3 +740,13 @@ }

const sessionId = getSessionId(server, extra)
await handleIdentify(server, data, sessionId, request, extra)
// Snapshot before identify, metadata, or the initialize handler can yield to
// another request using the same instrumented server.
const sessionInfo = getSessionInfo(server, data, sessionId)
const initializeClientInfo = readInitializeClientInfo(request)
const requestSessionInfo: SessionInfo = {
...sessionInfo,
clientName: initializeClientInfo?.name ?? sessionInfo.clientName,
clientVersion: initializeClientInfo?.version ?? sessionInfo.clientVersion,
}
const identity = await handleIdentify(server, data, sessionId, request, requestSessionInfo, extra)
const requestAttribution = withIdentity(requestSessionInfo, identity)

@@ -738,8 +774,15 @@ const event: McpEvent = {

event.protocolVersion = negotiatedProtocolVersion
data.sessionInfo.protocolVersion = negotiatedProtocolVersion
setServerTrackingData(server, data)
// Do not let a delayed initialize overwrite whichever session became current
// while its callbacks or the original handler were awaiting.
if (data.sessionId === sessionId) {
data.sessionInfo = { ...data.sessionInfo, protocolVersion: negotiatedProtocolVersion }
setServerTrackingData(server, data)
}
if (mintedSessionId) {
upgradeMintedTokenToNegotiated(server, data, mintedSessionId, negotiatedProtocolVersion)
upgradeMintedTokenToNegotiated(server, mintedSessionId, requestSessionInfo, negotiatedProtocolVersion, data.logger)
}
captureEvent(server, event, data.logger)
captureEvent(server, event, data.logger, {
...requestAttribution,
protocolVersion: negotiatedProtocolVersion,
})
return result

@@ -746,0 +789,0 @@ }

@@ -12,2 +12,3 @@ // Portions of this file are derived from agentcathq/agentcat-typescript-sdk

McpEvent,
SessionInfo,
UserIdentity,

@@ -132,6 +133,9 @@ } from '../types'

request: MCPRequestLike,
requestAttribution: SessionInfo,
extra?: CompatibleRequestHandlerExtra
): Promise<void> {
): Promise<UserIdentity | undefined> {
const identityBeforeRequest = data.identifiedSessions.get(sessionId)
const sessionSourceBeforeIdentify = data.sessionSource
if (!data.options.identify) {
return
return identityBeforeRequest
}

@@ -167,3 +171,3 @@

const firstSeen = previousIdentity === undefined
const announcedAtInitialize = data.sessionSource === 'token' && request.method !== 'initialize'
const announcedAtInitialize = sessionSourceBeforeIdentify === 'token' && request.method !== 'initialize'
const shouldPublish = changed || (firstSeen && !announcedAtInitialize)

@@ -175,7 +179,8 @@

data.logger(`Identified session ${sessionId}`)
captureEvent(server, identifyEvent, data.logger)
captureEvent(server, identifyEvent, data.logger, withIdentity(requestAttribution, mergedIdentity))
}
} else {
data.logger(`Warning: Supplied identify function returned null for session ${sessionId}`)
return mergedIdentity
}
data.logger(`Warning: Supplied identify function returned null for session ${sessionId}`)
} catch (error) {

@@ -186,4 +191,14 @@ data.logger(

}
return identityBeforeRequest
}
export function withIdentity(sessionInfo: SessionInfo, identity: UserIdentity | undefined): SessionInfo {
return {
...sessionInfo,
identifyActorGivenId: identity?.distinctId,
identifyActorData: identity?.properties || {},
identifyActorGroups: identity?.groups,
}
}
/**

@@ -190,0 +205,0 @@ * Resolves the `eventProperties` callback. Returns null when no callback is

@@ -128,3 +128,3 @@ // Portions of this file are derived from agentcathq/agentcat-typescript-sdk

setServerTrackingData(server, data)
return data.sessionInfo
return { ...sessionInfo }
}

@@ -1,1 +0,1 @@

export const version = '0.10.6'
export const version = '0.10.7'