@posthog/mcp 0.0.3 → 0.0.5
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 +17 -0
- package/dist/index.cjs +177 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +177 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.d.cts
CHANGED
|
@@ -23,6 +23,7 @@ interface MCPAnalyticsOptions {
|
|
|
23
23
|
apiKey?: string | null;
|
|
24
24
|
context?: boolean | MCPAnalyticsContextOptions;
|
|
25
25
|
enableAITracing?: boolean;
|
|
26
|
+
enableConversationId?: boolean;
|
|
26
27
|
enableTracing?: boolean;
|
|
27
28
|
eventProperties?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => JsonRecord | null | Promise<JsonRecord | null>;
|
|
28
29
|
eventTags?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Record<string, string> | null | Promise<Record<string, string> | null>;
|
|
@@ -92,6 +93,7 @@ declare const PostHogMCPAnalyticsProperty: {
|
|
|
92
93
|
readonly AiTraceId: "$ai_trace_id";
|
|
93
94
|
readonly ClientName: "$mcp_client_name";
|
|
94
95
|
readonly ClientVersion: "$mcp_client_version";
|
|
96
|
+
readonly ConversationId: "$mcp_conversation_id";
|
|
95
97
|
readonly DurationMs: "$mcp_duration_ms";
|
|
96
98
|
readonly IsError: "$mcp_is_error";
|
|
97
99
|
readonly Intent: "$mcp_intent";
|
|
@@ -103,6 +105,7 @@ declare const PostHogMCPAnalyticsProperty: {
|
|
|
103
105
|
readonly ServerVersion: "$mcp_server_version";
|
|
104
106
|
readonly SessionId: "$session_id";
|
|
105
107
|
readonly Source: "$mcp_source";
|
|
108
|
+
readonly ToolDescription: "$mcp_tool_description";
|
|
106
109
|
readonly ToolName: "$mcp_tool_name";
|
|
107
110
|
};
|
|
108
111
|
type PostHogMCPAnalyticsProperty = (typeof PostHogMCPAnalyticsProperty)[keyof typeof PostHogMCPAnalyticsProperty];
|
package/dist/index.d.mts
CHANGED
|
@@ -22,6 +22,7 @@ interface MCPAnalyticsOptions {
|
|
|
22
22
|
apiKey?: string | null;
|
|
23
23
|
context?: boolean | MCPAnalyticsContextOptions;
|
|
24
24
|
enableAITracing?: boolean;
|
|
25
|
+
enableConversationId?: boolean;
|
|
25
26
|
enableTracing?: boolean;
|
|
26
27
|
eventProperties?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => JsonRecord | null | Promise<JsonRecord | null>;
|
|
27
28
|
eventTags?: (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Record<string, string> | null | Promise<Record<string, string> | null>;
|
|
@@ -91,6 +92,7 @@ declare const PostHogMCPAnalyticsProperty: {
|
|
|
91
92
|
readonly AiTraceId: "$ai_trace_id";
|
|
92
93
|
readonly ClientName: "$mcp_client_name";
|
|
93
94
|
readonly ClientVersion: "$mcp_client_version";
|
|
95
|
+
readonly ConversationId: "$mcp_conversation_id";
|
|
94
96
|
readonly DurationMs: "$mcp_duration_ms";
|
|
95
97
|
readonly IsError: "$mcp_is_error";
|
|
96
98
|
readonly Intent: "$mcp_intent";
|
|
@@ -102,6 +104,7 @@ declare const PostHogMCPAnalyticsProperty: {
|
|
|
102
104
|
readonly ServerVersion: "$mcp_server_version";
|
|
103
105
|
readonly SessionId: "$session_id";
|
|
104
106
|
readonly Source: "$mcp_source";
|
|
107
|
+
readonly ToolDescription: "$mcp_tool_description";
|
|
105
108
|
readonly ToolName: "$mcp_tool_name";
|
|
106
109
|
};
|
|
107
110
|
type PostHogMCPAnalyticsProperty = (typeof PostHogMCPAnalyticsProperty)[keyof typeof PostHogMCPAnalyticsProperty];
|
package/dist/index.mjs
CHANGED
|
@@ -349,6 +349,7 @@ function getRequestResourceName(request) {
|
|
|
349
349
|
//#endregion
|
|
350
350
|
//#region src/modules/constants.ts
|
|
351
351
|
const DEFAULT_CONTEXT_PARAMETER_DESCRIPTION = `Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): "Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization."`;
|
|
352
|
+
const DEFAULT_CONVERSATION_ID_DESCRIPTION = "Echo the conversation_id from the server's previous response. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it.";
|
|
352
353
|
const POSTHOG_MCP_ANALYTICS_SOURCE = "posthog_mcp_analytics";
|
|
353
354
|
const PostHogMCPAnalyticsEvent = {
|
|
354
355
|
AiSpan: "$ai_span",
|
|
@@ -375,6 +376,7 @@ const PostHogMCPAnalyticsProperty = {
|
|
|
375
376
|
AiTraceId: "$ai_trace_id",
|
|
376
377
|
ClientName: "$mcp_client_name",
|
|
377
378
|
ClientVersion: "$mcp_client_version",
|
|
379
|
+
ConversationId: "$mcp_conversation_id",
|
|
378
380
|
DurationMs: "$mcp_duration_ms",
|
|
379
381
|
IsError: "$mcp_is_error",
|
|
380
382
|
Intent: "$mcp_intent",
|
|
@@ -386,6 +388,7 @@ const PostHogMCPAnalyticsProperty = {
|
|
|
386
388
|
ServerVersion: "$mcp_server_version",
|
|
387
389
|
SessionId: "$session_id",
|
|
388
390
|
Source: "$mcp_source",
|
|
391
|
+
ToolDescription: "$mcp_tool_description",
|
|
389
392
|
ToolName: "$mcp_tool_name"
|
|
390
393
|
};
|
|
391
394
|
//#endregion
|
|
@@ -420,6 +423,7 @@ function buildCaptureEvent(event, options) {
|
|
|
420
423
|
[PostHogMCPAnalyticsProperty.SessionId]: event.sessionId,
|
|
421
424
|
[PostHogMCPAnalyticsProperty.Source]: POSTHOG_MCP_ANALYTICS_SOURCE
|
|
422
425
|
};
|
|
426
|
+
addConversationIdProperty(event, properties);
|
|
423
427
|
addCommonEventProperties(event, properties);
|
|
424
428
|
addTraceReferenceProperties(event, properties, options);
|
|
425
429
|
addCustomEventProperties(event, properties);
|
|
@@ -445,11 +449,15 @@ function addTraceReferenceProperties(event, properties, options) {
|
|
|
445
449
|
properties[PostHogMCPAnalyticsProperty.AiTraceId] = getAITraceId(event);
|
|
446
450
|
properties[PostHogMCPAnalyticsProperty.AiSpanId] = getAISpanId(event);
|
|
447
451
|
}
|
|
452
|
+
function addConversationIdProperty(event, properties) {
|
|
453
|
+
if (event.conversationId !== void 0 && event.conversationId !== "") properties[PostHogMCPAnalyticsProperty.ConversationId] = event.conversationId;
|
|
454
|
+
}
|
|
448
455
|
function addCommonEventProperties(event, properties) {
|
|
449
456
|
if (event.resourceName) {
|
|
450
457
|
properties[PostHogMCPAnalyticsProperty.ResourceName] = event.resourceName;
|
|
451
458
|
if (event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolName] = event.resourceName;
|
|
452
459
|
}
|
|
460
|
+
if (event.toolDescription && event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolDescription] = event.toolDescription;
|
|
453
461
|
if (event.duration !== void 0) properties[PostHogMCPAnalyticsProperty.DurationMs] = event.duration;
|
|
454
462
|
if (event.serverName) properties[PostHogMCPAnalyticsProperty.ServerName] = event.serverName;
|
|
455
463
|
if (event.serverVersion) properties[PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
|
|
@@ -476,6 +484,7 @@ function buildExceptionEvent(event) {
|
|
|
476
484
|
$exception_source: "backend",
|
|
477
485
|
[PostHogMCPAnalyticsProperty.SessionId]: event.sessionId
|
|
478
486
|
};
|
|
487
|
+
addConversationIdProperty(event, properties);
|
|
479
488
|
if (event.error) {
|
|
480
489
|
if (event.error.message) properties.$exception_message = event.error.message;
|
|
481
490
|
if (event.error.type) properties.$exception_type = event.error.type;
|
|
@@ -485,6 +494,7 @@ function buildExceptionEvent(event) {
|
|
|
485
494
|
properties[PostHogMCPAnalyticsProperty.ResourceName] = event.resourceName;
|
|
486
495
|
if (event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolName] = event.resourceName;
|
|
487
496
|
}
|
|
497
|
+
if (event.toolDescription && event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolDescription] = event.toolDescription;
|
|
488
498
|
if (event.serverName) properties[PostHogMCPAnalyticsProperty.ServerName] = event.serverName;
|
|
489
499
|
if (event.serverVersion) properties[PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
|
|
490
500
|
if (event.clientName) properties[PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
|
|
@@ -509,6 +519,7 @@ function buildAISpanEvent(event) {
|
|
|
509
519
|
[PostHogMCPAnalyticsProperty.SessionId]: event.sessionId,
|
|
510
520
|
[PostHogMCPAnalyticsProperty.Source]: POSTHOG_MCP_ANALYTICS_SOURCE
|
|
511
521
|
};
|
|
522
|
+
addConversationIdProperty(event, properties);
|
|
512
523
|
if (event.duration !== void 0) properties[PostHogMCPAnalyticsProperty.AiLatency] = event.duration / 1e3;
|
|
513
524
|
if (event.isError && event.error) properties.$ai_error = event.error;
|
|
514
525
|
if (event.parameters !== void 0) properties[PostHogMCPAnalyticsProperty.AiInputState] = event.parameters;
|
|
@@ -543,6 +554,7 @@ const PROTECTED_FIELDS = new Set([
|
|
|
543
554
|
"identifyActorName",
|
|
544
555
|
"identifyData",
|
|
545
556
|
"resourceName",
|
|
557
|
+
"toolDescription",
|
|
546
558
|
"eventType",
|
|
547
559
|
"actorId",
|
|
548
560
|
"tags",
|
|
@@ -720,7 +732,7 @@ function sanitizeParameters(obj) {
|
|
|
720
732
|
}
|
|
721
733
|
//#endregion
|
|
722
734
|
//#region package.json
|
|
723
|
-
var version = "0.0.
|
|
735
|
+
var version = "0.0.5";
|
|
724
736
|
//#endregion
|
|
725
737
|
//#region src/modules/session.ts
|
|
726
738
|
function newSessionId() {
|
|
@@ -1180,12 +1192,14 @@ function publishEvent(server, eventInput) {
|
|
|
1180
1192
|
identifyActorName: sessionInfo.identifyActorName,
|
|
1181
1193
|
identifyActorData: sessionInfo.identifyActorData,
|
|
1182
1194
|
resourceName: eventInput.resourceName,
|
|
1195
|
+
toolDescription: eventInput.toolDescription,
|
|
1183
1196
|
parameters: eventInput.parameters,
|
|
1184
1197
|
response: eventInput.response,
|
|
1185
1198
|
userIntent: eventInput.userIntent,
|
|
1186
1199
|
userIntentSource: eventInput.userIntentSource,
|
|
1187
1200
|
isError: eventInput.isError,
|
|
1188
1201
|
error: eventInput.error,
|
|
1202
|
+
conversationId: eventInput.conversationId,
|
|
1189
1203
|
redactionFn: eventInput.redactionFn,
|
|
1190
1204
|
tags: eventInput.tags,
|
|
1191
1205
|
properties: eventInput.properties
|
|
@@ -1922,6 +1936,112 @@ function setupMCPAnalyticsTools(server) {
|
|
|
1922
1936
|
}
|
|
1923
1937
|
}
|
|
1924
1938
|
//#endregion
|
|
1939
|
+
//#region src/modules/conversation-id.ts
|
|
1940
|
+
const CONVERSATION_ID_PARAM_NAME = "conversation_id";
|
|
1941
|
+
function addConversationIdToTool(tool) {
|
|
1942
|
+
const modifiedTool = { ...tool };
|
|
1943
|
+
const toolName = tool.name || "unknown";
|
|
1944
|
+
const schema = modifiedTool.inputSchema;
|
|
1945
|
+
if (schema?.properties?.["conversation_id"]) {
|
|
1946
|
+
writeToLog(`WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`);
|
|
1947
|
+
return modifiedTool;
|
|
1948
|
+
}
|
|
1949
|
+
if (schema?.oneOf || schema?.allOf || schema?.anyOf) {
|
|
1950
|
+
writeToLog(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`);
|
|
1951
|
+
return modifiedTool;
|
|
1952
|
+
}
|
|
1953
|
+
if (!modifiedTool.inputSchema) modifiedTool.inputSchema = {
|
|
1954
|
+
type: "object",
|
|
1955
|
+
properties: {},
|
|
1956
|
+
required: []
|
|
1957
|
+
};
|
|
1958
|
+
modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema));
|
|
1959
|
+
const inputSchema = modifiedTool.inputSchema;
|
|
1960
|
+
if (!inputSchema.properties) inputSchema.properties = {};
|
|
1961
|
+
if (inputSchema.additionalProperties === false) inputSchema.additionalProperties = void 0;
|
|
1962
|
+
inputSchema.properties[CONVERSATION_ID_PARAM_NAME] = {
|
|
1963
|
+
type: "string",
|
|
1964
|
+
description: DEFAULT_CONVERSATION_ID_DESCRIPTION
|
|
1965
|
+
};
|
|
1966
|
+
return modifiedTool;
|
|
1967
|
+
}
|
|
1968
|
+
function addConversationIdToTools(tools) {
|
|
1969
|
+
return tools.map((tool) => {
|
|
1970
|
+
if (tool.name === "get_more_tools") return tool;
|
|
1971
|
+
return addConversationIdToTool(tool);
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
/**
|
|
1975
|
+
* Decides which conversation_id to use for a tool call:
|
|
1976
|
+
* - disabled or get_more_tools → none
|
|
1977
|
+
* - agent supplied a value → use it
|
|
1978
|
+
* - agent omitted → mint a UUID
|
|
1979
|
+
*/
|
|
1980
|
+
function resolveConversationId(enabled, args, toolName) {
|
|
1981
|
+
if (!enabled || toolName === "get_more_tools") return {
|
|
1982
|
+
minted: false,
|
|
1983
|
+
conversationId: void 0
|
|
1984
|
+
};
|
|
1985
|
+
const supplied = extractConversationId(args);
|
|
1986
|
+
if (supplied) return {
|
|
1987
|
+
minted: false,
|
|
1988
|
+
conversationId: supplied
|
|
1989
|
+
};
|
|
1990
|
+
return {
|
|
1991
|
+
minted: true,
|
|
1992
|
+
conversationId: randomUUID()
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Predicate matching the same eligibility checks injectConversationIdPromptBack uses,
|
|
1997
|
+
* exposed so callers can pre-decide whether the prompt-back will actually land
|
|
1998
|
+
* (and clear event.conversationId if not, to avoid orphan ids in analytics).
|
|
1999
|
+
*/
|
|
2000
|
+
function canInjectConversationIdPromptBack(result) {
|
|
2001
|
+
if (!(result && typeof result === "object")) return false;
|
|
2002
|
+
const resultObj = result;
|
|
2003
|
+
if (resultObj.isError === true) return false;
|
|
2004
|
+
return Array.isArray(resultObj.content);
|
|
2005
|
+
}
|
|
2006
|
+
function extractConversationId(args) {
|
|
2007
|
+
if (!(args && typeof args === "object")) return;
|
|
2008
|
+
const value = args[CONVERSATION_ID_PARAM_NAME];
|
|
2009
|
+
if (typeof value !== "string") return;
|
|
2010
|
+
const trimmed = value.trim();
|
|
2011
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
2012
|
+
}
|
|
2013
|
+
function cloneRequestWithoutConversationId(request) {
|
|
2014
|
+
if (!request.params || typeof request.params !== "object") return request;
|
|
2015
|
+
const args = request.params.arguments;
|
|
2016
|
+
if (!(args && typeof args === "object")) return request;
|
|
2017
|
+
return {
|
|
2018
|
+
...request,
|
|
2019
|
+
params: {
|
|
2020
|
+
...request.params,
|
|
2021
|
+
arguments: stripConversationId(args)
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
function stripConversationId(args) {
|
|
2026
|
+
if (!args || typeof args !== "object" || !("conversation_id" in args)) return args;
|
|
2027
|
+
const { [CONVERSATION_ID_PARAM_NAME]: _omit, ...rest } = args;
|
|
2028
|
+
return rest;
|
|
2029
|
+
}
|
|
2030
|
+
function buildConversationIdPromptBack(conversationId) {
|
|
2031
|
+
return {
|
|
2032
|
+
type: "text",
|
|
2033
|
+
text: `[SERVER]: Reuse conversation_id=${conversationId} on every subsequent tool call in this conversation. Required for the server to correlate calls and provide context-aware results.`
|
|
2034
|
+
};
|
|
2035
|
+
}
|
|
2036
|
+
function injectConversationIdPromptBack(result, conversationId) {
|
|
2037
|
+
if (!canInjectConversationIdPromptBack(result)) return result;
|
|
2038
|
+
const resultObj = result;
|
|
2039
|
+
return {
|
|
2040
|
+
...resultObj,
|
|
2041
|
+
content: [...resultObj.content, buildConversationIdPromptBack(conversationId)]
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
//#endregion
|
|
1925
2045
|
//#region src/modules/intent.ts
|
|
1926
2046
|
function getContextArgument$2(request) {
|
|
1927
2047
|
const context = request.params?.arguments?.context;
|
|
@@ -2017,9 +2137,11 @@ async function getTracedToolsList(server, originalListToolsHandler, request, ext
|
|
|
2017
2137
|
const data = getServerTrackingData(server);
|
|
2018
2138
|
let tools = (await originalListToolsHandler(request, extra)).tools || [];
|
|
2019
2139
|
if (data && isContextEnabled(data.options.context)) tools = addContextParameterToTools(tools, getContextDescription(data.options.context));
|
|
2140
|
+
if (data?.options.enableConversationId) tools = addConversationIdToTools(tools);
|
|
2020
2141
|
if (data?.options.reportMissing) {
|
|
2021
2142
|
if (!tools.some((tool) => tool?.name === "get_more_tools")) tools.push(getReportMissingToolDescriptor());
|
|
2022
2143
|
}
|
|
2144
|
+
if (data) cacheToolDescriptions(data.toolDescriptions, tools);
|
|
2023
2145
|
return tools;
|
|
2024
2146
|
} catch (error) {
|
|
2025
2147
|
writeToLog(`Warning: Original list tools handler failed, this suggests an error PostHog MCP analytics did not cause - ${error}`);
|
|
@@ -2101,30 +2223,39 @@ async function handleToolCallRequest(server, originalCallToolHandler, request, e
|
|
|
2101
2223
|
writeToLog("Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called track(server, options) before using tool calls.");
|
|
2102
2224
|
return await originalCallToolHandler?.(request, extra);
|
|
2103
2225
|
}
|
|
2226
|
+
const conversation = resolveConversationId(data.options.enableConversationId ?? false, request.params?.arguments, request.params?.name);
|
|
2227
|
+
const downstreamRequest = conversation.conversationId ? cloneRequestWithoutConversationId(request) : request;
|
|
2228
|
+
const toolName = request.params?.name;
|
|
2104
2229
|
const event = {
|
|
2105
2230
|
sessionId: getServerSessionId(server, extra),
|
|
2106
|
-
|
|
2107
|
-
|
|
2231
|
+
conversationId: conversation.conversationId,
|
|
2232
|
+
resourceName: toolName || "Unknown Tool Name",
|
|
2233
|
+
parameters: buildCapturedMcpParameters(downstreamRequest),
|
|
2108
2234
|
eventType: MCPAnalyticsEventType.mcpToolsCall,
|
|
2109
2235
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2236
|
+
toolDescription: toolName ? data.toolDescriptions.get(toolName) : void 0,
|
|
2110
2237
|
redactionFn: data.options.redactSensitiveInformation
|
|
2111
2238
|
};
|
|
2112
2239
|
try {
|
|
2113
2240
|
await handleIdentify(server, data, request, extra);
|
|
2114
2241
|
await applyResolvedMetadata$1(event, data, request, extra);
|
|
2115
2242
|
setEventIntent(event, await resolveToolCallIntent(data, request, extra));
|
|
2116
|
-
const result = await executeToolCall(server, originalCallToolHandler,
|
|
2243
|
+
const result = await executeToolCall(server, originalCallToolHandler, downstreamRequest, extra, event);
|
|
2117
2244
|
if (isToolResultError$1(result)) {
|
|
2118
2245
|
event.isError = true;
|
|
2119
2246
|
event.error = captureException(result);
|
|
2120
2247
|
} else event.isError = false;
|
|
2121
|
-
|
|
2248
|
+
let finalResult = result;
|
|
2249
|
+
if (conversation.minted) if (canInjectConversationIdPromptBack(result)) finalResult = injectConversationIdPromptBack(result, conversation.conversationId);
|
|
2250
|
+
else event.conversationId = void 0;
|
|
2251
|
+
event.response = finalResult;
|
|
2122
2252
|
event.duration = getEventDuration(event);
|
|
2123
2253
|
publishEvent(server, event);
|
|
2124
|
-
return
|
|
2254
|
+
return finalResult;
|
|
2125
2255
|
} catch (error) {
|
|
2126
2256
|
event.isError = true;
|
|
2127
2257
|
event.error = captureException(error);
|
|
2258
|
+
if (conversation.minted) event.conversationId = void 0;
|
|
2128
2259
|
event.duration = getEventDuration(event);
|
|
2129
2260
|
publishEvent(server, event);
|
|
2130
2261
|
throw error;
|
|
@@ -2156,6 +2287,10 @@ function getContextArgument$1(request) {
|
|
|
2156
2287
|
function getEventDuration(event) {
|
|
2157
2288
|
return event.timestamp ? Date.now() - event.timestamp.getTime() : 0;
|
|
2158
2289
|
}
|
|
2290
|
+
function cacheToolDescriptions(cache, tools) {
|
|
2291
|
+
if (!tools) return;
|
|
2292
|
+
for (const tool of tools) if (tool?.name && typeof tool.description === "string") cache.set(tool.name, tool.description);
|
|
2293
|
+
}
|
|
2159
2294
|
//#endregion
|
|
2160
2295
|
//#region src/modules/mcp-sdk-compat.ts
|
|
2161
2296
|
/**
|
|
@@ -2243,7 +2378,8 @@ function addTracingToToolRegistry(tools, server) {
|
|
|
2243
2378
|
}
|
|
2244
2379
|
function setupListenerToRegisteredTools(server) {
|
|
2245
2380
|
try {
|
|
2246
|
-
|
|
2381
|
+
const data = getServerTrackingData(server.server);
|
|
2382
|
+
if (!data) {
|
|
2247
2383
|
writeToLog("Warning: Cannot setup listener - no tracking data found");
|
|
2248
2384
|
return;
|
|
2249
2385
|
}
|
|
@@ -2251,6 +2387,7 @@ function setupListenerToRegisteredTools(server) {
|
|
|
2251
2387
|
set(target, property, value) {
|
|
2252
2388
|
try {
|
|
2253
2389
|
if (typeof property === "string" && value && typeof value === "object" && hasToolFunction(value)) {
|
|
2390
|
+
if (typeof value.description === "string") data.toolDescriptions.set(property, value.description);
|
|
2254
2391
|
if (value[MCP_ANALYTICS_PROCESSED]) {
|
|
2255
2392
|
writeToLog(`Tool ${String(property)} already processed, skipping proxy wrapping`);
|
|
2256
2393
|
return Reflect.set(target, property, value);
|
|
@@ -2316,14 +2453,14 @@ function addTracingToToolCallbackInternal(tool, toolName, _server) {
|
|
|
2316
2453
|
args = void 0;
|
|
2317
2454
|
extra = params[0];
|
|
2318
2455
|
}
|
|
2319
|
-
const removeContextFromArgs = (
|
|
2320
|
-
if (
|
|
2321
|
-
const { context: _context, ...
|
|
2322
|
-
return
|
|
2456
|
+
const removeContextFromArgs = (input) => {
|
|
2457
|
+
if (input && typeof input === "object" && "context" in input) {
|
|
2458
|
+
const { context: _context, ...rest } = input;
|
|
2459
|
+
return rest;
|
|
2323
2460
|
}
|
|
2324
|
-
return
|
|
2461
|
+
return input;
|
|
2325
2462
|
};
|
|
2326
|
-
const cleanedArgs = toolName === "get_more_tools" ? args : removeContextFromArgs(args);
|
|
2463
|
+
const cleanedArgs = toolName === "get_more_tools" ? args : stripConversationId(removeContextFromArgs(args));
|
|
2327
2464
|
try {
|
|
2328
2465
|
if (cleanedArgs === void 0) return await originalCallback(extra);
|
|
2329
2466
|
return await originalCallback(cleanedArgs, extra);
|
|
@@ -2357,26 +2494,31 @@ function createToolsCallWrapper(originalHandler, server) {
|
|
|
2357
2494
|
}
|
|
2358
2495
|
async function handleWrappedToolsCall(originalHandler, server, request, extra) {
|
|
2359
2496
|
const startTime = /* @__PURE__ */ new Date();
|
|
2360
|
-
const
|
|
2497
|
+
const conversation = resolveConversationId(getServerTrackingData(server)?.options.enableConversationId ?? false, request.params?.arguments, request.params?.name);
|
|
2498
|
+
const tracing = await initializeToolCallEvent(server, request, conversation.conversationId ? cloneRequestWithoutConversationId(request) : request, extra, startTime, conversation);
|
|
2361
2499
|
if (request?.params?.name === "get_more_tools") return await executeReportMissingTool(server, request, tracing, startTime);
|
|
2362
2500
|
return await executeOriginalTool(originalHandler, server, request, extra, tracing, startTime);
|
|
2363
2501
|
}
|
|
2364
|
-
async function initializeToolCallEvent(server, request, extra, startTime) {
|
|
2502
|
+
async function initializeToolCallEvent(server, request, downstreamRequest, extra, startTime, conversation) {
|
|
2365
2503
|
try {
|
|
2366
2504
|
const data = getServerTrackingData(server);
|
|
2367
2505
|
if (!data) {
|
|
2368
2506
|
writeToLog("Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called track(server, options) before using tool calls.");
|
|
2369
2507
|
return {
|
|
2370
2508
|
event: null,
|
|
2509
|
+
mintedConversationId: void 0,
|
|
2371
2510
|
shouldPublishEvent: false
|
|
2372
2511
|
};
|
|
2373
2512
|
}
|
|
2513
|
+
const toolName = request.params?.name;
|
|
2374
2514
|
const event = {
|
|
2375
2515
|
sessionId: getServerSessionId(server, extra),
|
|
2376
|
-
|
|
2377
|
-
|
|
2516
|
+
conversationId: conversation.conversationId,
|
|
2517
|
+
resourceName: toolName || "Unknown Tool",
|
|
2518
|
+
parameters: buildCapturedMcpParameters(downstreamRequest),
|
|
2378
2519
|
eventType: MCPAnalyticsEventType.mcpToolsCall,
|
|
2379
2520
|
timestamp: startTime,
|
|
2521
|
+
toolDescription: toolName ? data.toolDescriptions.get(toolName) : void 0,
|
|
2380
2522
|
redactionFn: data.options.redactSensitiveInformation
|
|
2381
2523
|
};
|
|
2382
2524
|
await handleIdentify(server, data, request, extra);
|
|
@@ -2385,12 +2527,14 @@ async function initializeToolCallEvent(server, request, extra, startTime) {
|
|
|
2385
2527
|
setEventIntent(event, await resolveToolCallIntent(data, request, extra));
|
|
2386
2528
|
return {
|
|
2387
2529
|
event,
|
|
2530
|
+
mintedConversationId: conversation.minted ? conversation.conversationId : void 0,
|
|
2388
2531
|
shouldPublishEvent: true
|
|
2389
2532
|
};
|
|
2390
2533
|
} catch (error) {
|
|
2391
2534
|
writeToLog(`Warning: PostHog MCP analytics tracing failed for tool ${request.params?.name}, falling back to original handler - ${error}`);
|
|
2392
2535
|
return {
|
|
2393
2536
|
event: null,
|
|
2537
|
+
mintedConversationId: void 0,
|
|
2394
2538
|
shouldPublishEvent: false
|
|
2395
2539
|
};
|
|
2396
2540
|
}
|
|
@@ -2418,14 +2562,20 @@ async function executeReportMissingTool(server, request, tracing, startTime) {
|
|
|
2418
2562
|
async function executeOriginalTool(originalHandler, server, request, extra, tracing, startTime) {
|
|
2419
2563
|
try {
|
|
2420
2564
|
const result = await originalHandler(request, extra);
|
|
2421
|
-
|
|
2565
|
+
let finalResult = result;
|
|
2566
|
+
if (tracing.mintedConversationId) {
|
|
2567
|
+
if (canInjectConversationIdPromptBack(result)) finalResult = injectConversationIdPromptBack(result, tracing.mintedConversationId);
|
|
2568
|
+
else if (tracing.event) tracing.event.conversationId = void 0;
|
|
2569
|
+
}
|
|
2570
|
+
publishSuccessfulToolEvent(server, tracing, finalResult, startTime, {
|
|
2422
2571
|
capturedError: extra?.__mcp_analytics_error,
|
|
2423
2572
|
clearCapturedError: () => {
|
|
2424
2573
|
if (extra) extra.__mcp_analytics_error = void 0;
|
|
2425
2574
|
}
|
|
2426
2575
|
});
|
|
2427
|
-
return
|
|
2576
|
+
return finalResult;
|
|
2428
2577
|
} catch (error) {
|
|
2578
|
+
if (tracing.mintedConversationId && tracing.event) tracing.event.conversationId = void 0;
|
|
2429
2579
|
publishFailedToolEvent(server, tracing, error, startTime);
|
|
2430
2580
|
throw error;
|
|
2431
2581
|
}
|
|
@@ -2458,16 +2608,20 @@ function publishFailedToolEvent(server, tracing, error, startTime) {
|
|
|
2458
2608
|
}
|
|
2459
2609
|
function setupTracking(server) {
|
|
2460
2610
|
try {
|
|
2461
|
-
getServerTrackingData(server.server);
|
|
2611
|
+
const mcpAnalyticsData = getServerTrackingData(server.server);
|
|
2462
2612
|
setupToolsCallHandlerWrapping(server);
|
|
2463
2613
|
setupInitializeTracing(server);
|
|
2464
2614
|
server._registeredTools = addTracingToToolRegistry(server._registeredTools, server);
|
|
2615
|
+
if (mcpAnalyticsData) seedToolDescriptionsFromRegistry(mcpAnalyticsData.toolDescriptions, server._registeredTools);
|
|
2465
2616
|
setupListToolsTracing(server);
|
|
2466
2617
|
setupListenerToRegisteredTools(server);
|
|
2467
2618
|
} catch (error) {
|
|
2468
2619
|
writeToLog(`Warning: Failed to setup tool call tracing - ${error}`);
|
|
2469
2620
|
}
|
|
2470
2621
|
}
|
|
2622
|
+
function seedToolDescriptionsFromRegistry(cache, tools) {
|
|
2623
|
+
for (const [name, tool] of Object.entries(tools)) if (typeof tool?.description === "string") cache.set(name, tool.description);
|
|
2624
|
+
}
|
|
2471
2625
|
//#endregion
|
|
2472
2626
|
//#region src/index.ts
|
|
2473
2627
|
/**
|
|
@@ -2603,6 +2757,7 @@ function buildTrackingData(lowLevelServer, options) {
|
|
|
2603
2757
|
sessionId: newSessionId(),
|
|
2604
2758
|
lastActivity: /* @__PURE__ */ new Date(),
|
|
2605
2759
|
identifiedSessions: /* @__PURE__ */ new Map(),
|
|
2760
|
+
toolDescriptions: /* @__PURE__ */ new Map(),
|
|
2606
2761
|
sessionInfo: getSessionInfo(lowLevelServer, void 0),
|
|
2607
2762
|
options: {
|
|
2608
2763
|
reportMissing: options.reportMissing ?? false,
|
|
@@ -2616,7 +2771,8 @@ function buildTrackingData(lowLevelServer, options) {
|
|
|
2616
2771
|
eventProperties: options.eventProperties,
|
|
2617
2772
|
host: options.host,
|
|
2618
2773
|
posthogClient: options.posthogClient,
|
|
2619
|
-
posthogOptions: options.posthogOptions
|
|
2774
|
+
posthogOptions: options.posthogOptions,
|
|
2775
|
+
enableConversationId: options.enableConversationId ?? false
|
|
2620
2776
|
},
|
|
2621
2777
|
sessionSource: "generated"
|
|
2622
2778
|
};
|