@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 CHANGED
@@ -52,6 +52,22 @@ track(server, {
52
52
  With `enableAITracing: true`, tool calls also emit `$ai_span` events with `$ai_trace_id` and `$ai_span_id`.
53
53
  The regular `mcp_tool_call` event includes the same trace/span IDs so it can be joined back to the LLM analytics span.
54
54
 
55
+ ### Conversation ID (opt-in)
56
+
57
+ When `enableConversationId: true` is passed to `track()`, the SDK injects an optional `conversation_id` argument into every tool's input schema and tells the agent to reuse the value the server returns. When the agent omits it on a call, the SDK mints a UUID and appends a short text block to the tool's response asking the agent to echo the same `conversation_id` on subsequent calls. The value the agent supplies (or the SDK mints) is captured on PostHog events as `$mcp_conversation_id` — separate from `$session_id`, which is unchanged. Off by default.
58
+
59
+ ```ts
60
+ track(server, {
61
+ apiKey: process.env.POSTHOG_API_KEY,
62
+ enableConversationId: true,
63
+ });
64
+ ```
65
+
66
+ **Caveats:**
67
+
68
+ - The prompt-back is appended as a regular `text` content block (the only channel MCP currently offers for server→agent communication). Consumers that surface raw tool-call content to end users will see `[SERVER]: Reuse conversation_id=…` in their UI. If/when the MCP spec grows a server-directives channel (e.g. on `_meta`), the SDK will move there.
69
+ - The captured `$mcp_conversation_id` value is agent-controlled when the agent supplies one — the SDK accepts any non-empty string. Customers wanting to bind it to their own session scheme (chat ID, JWT `jti`, request ID) can do so freely; the trade-off is that nothing prevents a misbehaving agent from sending arbitrary values.
70
+
55
71
  The SDK sends events through `posthog-node`, so it uses the same PostHog ingestion client, batching, retry, flush, and shutdown behavior as the existing Node SDK.
56
72
 
57
73
  If your application already owns a PostHog client, pass it in instead:
@@ -86,6 +102,7 @@ Important properties:
86
102
  - `$mcp_intent` from the `context` argument, or from `intentFallback` when no context was provided
87
103
  - `$mcp_intent_source` as `context_parameter` or `inferred`
88
104
  - `$mcp_tool_name` and `$mcp_resource_name`
105
+ - `$mcp_tool_description`, the tool's current `description` at the moment of the call — populated on `mcp_tool_call` and on the paired `$exception` event so the description is visible inline while triaging
89
106
  - `$mcp_parameters` and `$mcp_response`, after redaction and truncation
90
107
  - `$mcp_duration_ms`
91
108
  - `$mcp_is_error`
package/dist/index.cjs CHANGED
@@ -350,6 +350,7 @@ function getRequestResourceName(request) {
350
350
  //#endregion
351
351
  //#region src/modules/constants.ts
352
352
  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."`;
353
+ 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.";
353
354
  const POSTHOG_MCP_ANALYTICS_SOURCE = "posthog_mcp_analytics";
354
355
  const PostHogMCPAnalyticsEvent = {
355
356
  AiSpan: "$ai_span",
@@ -376,6 +377,7 @@ const PostHogMCPAnalyticsProperty = {
376
377
  AiTraceId: "$ai_trace_id",
377
378
  ClientName: "$mcp_client_name",
378
379
  ClientVersion: "$mcp_client_version",
380
+ ConversationId: "$mcp_conversation_id",
379
381
  DurationMs: "$mcp_duration_ms",
380
382
  IsError: "$mcp_is_error",
381
383
  Intent: "$mcp_intent",
@@ -387,6 +389,7 @@ const PostHogMCPAnalyticsProperty = {
387
389
  ServerVersion: "$mcp_server_version",
388
390
  SessionId: "$session_id",
389
391
  Source: "$mcp_source",
392
+ ToolDescription: "$mcp_tool_description",
390
393
  ToolName: "$mcp_tool_name"
391
394
  };
392
395
  //#endregion
@@ -421,6 +424,7 @@ function buildCaptureEvent(event, options) {
421
424
  [PostHogMCPAnalyticsProperty.SessionId]: event.sessionId,
422
425
  [PostHogMCPAnalyticsProperty.Source]: POSTHOG_MCP_ANALYTICS_SOURCE
423
426
  };
427
+ addConversationIdProperty(event, properties);
424
428
  addCommonEventProperties(event, properties);
425
429
  addTraceReferenceProperties(event, properties, options);
426
430
  addCustomEventProperties(event, properties);
@@ -446,11 +450,15 @@ function addTraceReferenceProperties(event, properties, options) {
446
450
  properties[PostHogMCPAnalyticsProperty.AiTraceId] = getAITraceId(event);
447
451
  properties[PostHogMCPAnalyticsProperty.AiSpanId] = getAISpanId(event);
448
452
  }
453
+ function addConversationIdProperty(event, properties) {
454
+ if (event.conversationId !== void 0 && event.conversationId !== "") properties[PostHogMCPAnalyticsProperty.ConversationId] = event.conversationId;
455
+ }
449
456
  function addCommonEventProperties(event, properties) {
450
457
  if (event.resourceName) {
451
458
  properties[PostHogMCPAnalyticsProperty.ResourceName] = event.resourceName;
452
459
  if (event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolName] = event.resourceName;
453
460
  }
461
+ if (event.toolDescription && event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolDescription] = event.toolDescription;
454
462
  if (event.duration !== void 0) properties[PostHogMCPAnalyticsProperty.DurationMs] = event.duration;
455
463
  if (event.serverName) properties[PostHogMCPAnalyticsProperty.ServerName] = event.serverName;
456
464
  if (event.serverVersion) properties[PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
@@ -477,6 +485,7 @@ function buildExceptionEvent(event) {
477
485
  $exception_source: "backend",
478
486
  [PostHogMCPAnalyticsProperty.SessionId]: event.sessionId
479
487
  };
488
+ addConversationIdProperty(event, properties);
480
489
  if (event.error) {
481
490
  if (event.error.message) properties.$exception_message = event.error.message;
482
491
  if (event.error.type) properties.$exception_type = event.error.type;
@@ -486,6 +495,7 @@ function buildExceptionEvent(event) {
486
495
  properties[PostHogMCPAnalyticsProperty.ResourceName] = event.resourceName;
487
496
  if (event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolName] = event.resourceName;
488
497
  }
498
+ if (event.toolDescription && event.eventType === MCPAnalyticsEventType.mcpToolsCall) properties[PostHogMCPAnalyticsProperty.ToolDescription] = event.toolDescription;
489
499
  if (event.serverName) properties[PostHogMCPAnalyticsProperty.ServerName] = event.serverName;
490
500
  if (event.serverVersion) properties[PostHogMCPAnalyticsProperty.ServerVersion] = event.serverVersion;
491
501
  if (event.clientName) properties[PostHogMCPAnalyticsProperty.ClientName] = event.clientName;
@@ -510,6 +520,7 @@ function buildAISpanEvent(event) {
510
520
  [PostHogMCPAnalyticsProperty.SessionId]: event.sessionId,
511
521
  [PostHogMCPAnalyticsProperty.Source]: POSTHOG_MCP_ANALYTICS_SOURCE
512
522
  };
523
+ addConversationIdProperty(event, properties);
513
524
  if (event.duration !== void 0) properties[PostHogMCPAnalyticsProperty.AiLatency] = event.duration / 1e3;
514
525
  if (event.isError && event.error) properties.$ai_error = event.error;
515
526
  if (event.parameters !== void 0) properties[PostHogMCPAnalyticsProperty.AiInputState] = event.parameters;
@@ -544,6 +555,7 @@ const PROTECTED_FIELDS = new Set([
544
555
  "identifyActorName",
545
556
  "identifyData",
546
557
  "resourceName",
558
+ "toolDescription",
547
559
  "eventType",
548
560
  "actorId",
549
561
  "tags",
@@ -721,7 +733,7 @@ function sanitizeParameters(obj) {
721
733
  }
722
734
  //#endregion
723
735
  //#region package.json
724
- var version = "0.0.3";
736
+ var version = "0.0.5";
725
737
  //#endregion
726
738
  //#region src/modules/session.ts
727
739
  function newSessionId() {
@@ -1181,12 +1193,14 @@ function publishEvent(server, eventInput) {
1181
1193
  identifyActorName: sessionInfo.identifyActorName,
1182
1194
  identifyActorData: sessionInfo.identifyActorData,
1183
1195
  resourceName: eventInput.resourceName,
1196
+ toolDescription: eventInput.toolDescription,
1184
1197
  parameters: eventInput.parameters,
1185
1198
  response: eventInput.response,
1186
1199
  userIntent: eventInput.userIntent,
1187
1200
  userIntentSource: eventInput.userIntentSource,
1188
1201
  isError: eventInput.isError,
1189
1202
  error: eventInput.error,
1203
+ conversationId: eventInput.conversationId,
1190
1204
  redactionFn: eventInput.redactionFn,
1191
1205
  tags: eventInput.tags,
1192
1206
  properties: eventInput.properties
@@ -1923,6 +1937,112 @@ function setupMCPAnalyticsTools(server) {
1923
1937
  }
1924
1938
  }
1925
1939
  //#endregion
1940
+ //#region src/modules/conversation-id.ts
1941
+ const CONVERSATION_ID_PARAM_NAME = "conversation_id";
1942
+ function addConversationIdToTool(tool) {
1943
+ const modifiedTool = { ...tool };
1944
+ const toolName = tool.name || "unknown";
1945
+ const schema = modifiedTool.inputSchema;
1946
+ if (schema?.properties?.["conversation_id"]) {
1947
+ writeToLog(`WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`);
1948
+ return modifiedTool;
1949
+ }
1950
+ if (schema?.oneOf || schema?.allOf || schema?.anyOf) {
1951
+ writeToLog(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`);
1952
+ return modifiedTool;
1953
+ }
1954
+ if (!modifiedTool.inputSchema) modifiedTool.inputSchema = {
1955
+ type: "object",
1956
+ properties: {},
1957
+ required: []
1958
+ };
1959
+ modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema));
1960
+ const inputSchema = modifiedTool.inputSchema;
1961
+ if (!inputSchema.properties) inputSchema.properties = {};
1962
+ if (inputSchema.additionalProperties === false) inputSchema.additionalProperties = void 0;
1963
+ inputSchema.properties[CONVERSATION_ID_PARAM_NAME] = {
1964
+ type: "string",
1965
+ description: DEFAULT_CONVERSATION_ID_DESCRIPTION
1966
+ };
1967
+ return modifiedTool;
1968
+ }
1969
+ function addConversationIdToTools(tools) {
1970
+ return tools.map((tool) => {
1971
+ if (tool.name === "get_more_tools") return tool;
1972
+ return addConversationIdToTool(tool);
1973
+ });
1974
+ }
1975
+ /**
1976
+ * Decides which conversation_id to use for a tool call:
1977
+ * - disabled or get_more_tools → none
1978
+ * - agent supplied a value → use it
1979
+ * - agent omitted → mint a UUID
1980
+ */
1981
+ function resolveConversationId(enabled, args, toolName) {
1982
+ if (!enabled || toolName === "get_more_tools") return {
1983
+ minted: false,
1984
+ conversationId: void 0
1985
+ };
1986
+ const supplied = extractConversationId(args);
1987
+ if (supplied) return {
1988
+ minted: false,
1989
+ conversationId: supplied
1990
+ };
1991
+ return {
1992
+ minted: true,
1993
+ conversationId: (0, node_crypto.randomUUID)()
1994
+ };
1995
+ }
1996
+ /**
1997
+ * Predicate matching the same eligibility checks injectConversationIdPromptBack uses,
1998
+ * exposed so callers can pre-decide whether the prompt-back will actually land
1999
+ * (and clear event.conversationId if not, to avoid orphan ids in analytics).
2000
+ */
2001
+ function canInjectConversationIdPromptBack(result) {
2002
+ if (!(result && typeof result === "object")) return false;
2003
+ const resultObj = result;
2004
+ if (resultObj.isError === true) return false;
2005
+ return Array.isArray(resultObj.content);
2006
+ }
2007
+ function extractConversationId(args) {
2008
+ if (!(args && typeof args === "object")) return;
2009
+ const value = args[CONVERSATION_ID_PARAM_NAME];
2010
+ if (typeof value !== "string") return;
2011
+ const trimmed = value.trim();
2012
+ return trimmed.length > 0 ? trimmed : void 0;
2013
+ }
2014
+ function cloneRequestWithoutConversationId(request) {
2015
+ if (!request.params || typeof request.params !== "object") return request;
2016
+ const args = request.params.arguments;
2017
+ if (!(args && typeof args === "object")) return request;
2018
+ return {
2019
+ ...request,
2020
+ params: {
2021
+ ...request.params,
2022
+ arguments: stripConversationId(args)
2023
+ }
2024
+ };
2025
+ }
2026
+ function stripConversationId(args) {
2027
+ if (!args || typeof args !== "object" || !("conversation_id" in args)) return args;
2028
+ const { [CONVERSATION_ID_PARAM_NAME]: _omit, ...rest } = args;
2029
+ return rest;
2030
+ }
2031
+ function buildConversationIdPromptBack(conversationId) {
2032
+ return {
2033
+ type: "text",
2034
+ 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.`
2035
+ };
2036
+ }
2037
+ function injectConversationIdPromptBack(result, conversationId) {
2038
+ if (!canInjectConversationIdPromptBack(result)) return result;
2039
+ const resultObj = result;
2040
+ return {
2041
+ ...resultObj,
2042
+ content: [...resultObj.content, buildConversationIdPromptBack(conversationId)]
2043
+ };
2044
+ }
2045
+ //#endregion
1926
2046
  //#region src/modules/intent.ts
1927
2047
  function getContextArgument$2(request) {
1928
2048
  const context = request.params?.arguments?.context;
@@ -2018,9 +2138,11 @@ async function getTracedToolsList(server, originalListToolsHandler, request, ext
2018
2138
  const data = getServerTrackingData(server);
2019
2139
  let tools = (await originalListToolsHandler(request, extra)).tools || [];
2020
2140
  if (data && isContextEnabled(data.options.context)) tools = addContextParameterToTools(tools, getContextDescription(data.options.context));
2141
+ if (data?.options.enableConversationId) tools = addConversationIdToTools(tools);
2021
2142
  if (data?.options.reportMissing) {
2022
2143
  if (!tools.some((tool) => tool?.name === "get_more_tools")) tools.push(getReportMissingToolDescriptor());
2023
2144
  }
2145
+ if (data) cacheToolDescriptions(data.toolDescriptions, tools);
2024
2146
  return tools;
2025
2147
  } catch (error) {
2026
2148
  writeToLog(`Warning: Original list tools handler failed, this suggests an error PostHog MCP analytics did not cause - ${error}`);
@@ -2102,30 +2224,39 @@ async function handleToolCallRequest(server, originalCallToolHandler, request, e
2102
2224
  writeToLog("Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called track(server, options) before using tool calls.");
2103
2225
  return await originalCallToolHandler?.(request, extra);
2104
2226
  }
2227
+ const conversation = resolveConversationId(data.options.enableConversationId ?? false, request.params?.arguments, request.params?.name);
2228
+ const downstreamRequest = conversation.conversationId ? cloneRequestWithoutConversationId(request) : request;
2229
+ const toolName = request.params?.name;
2105
2230
  const event = {
2106
2231
  sessionId: getServerSessionId(server, extra),
2107
- resourceName: request.params?.name || "Unknown Tool Name",
2108
- parameters: buildCapturedMcpParameters(request),
2232
+ conversationId: conversation.conversationId,
2233
+ resourceName: toolName || "Unknown Tool Name",
2234
+ parameters: buildCapturedMcpParameters(downstreamRequest),
2109
2235
  eventType: MCPAnalyticsEventType.mcpToolsCall,
2110
2236
  timestamp: /* @__PURE__ */ new Date(),
2237
+ toolDescription: toolName ? data.toolDescriptions.get(toolName) : void 0,
2111
2238
  redactionFn: data.options.redactSensitiveInformation
2112
2239
  };
2113
2240
  try {
2114
2241
  await handleIdentify(server, data, request, extra);
2115
2242
  await applyResolvedMetadata$1(event, data, request, extra);
2116
2243
  setEventIntent(event, await resolveToolCallIntent(data, request, extra));
2117
- const result = await executeToolCall(server, originalCallToolHandler, request, extra, event);
2244
+ const result = await executeToolCall(server, originalCallToolHandler, downstreamRequest, extra, event);
2118
2245
  if (isToolResultError$1(result)) {
2119
2246
  event.isError = true;
2120
2247
  event.error = captureException(result);
2121
2248
  } else event.isError = false;
2122
- event.response = result;
2249
+ let finalResult = result;
2250
+ if (conversation.minted) if (canInjectConversationIdPromptBack(result)) finalResult = injectConversationIdPromptBack(result, conversation.conversationId);
2251
+ else event.conversationId = void 0;
2252
+ event.response = finalResult;
2123
2253
  event.duration = getEventDuration(event);
2124
2254
  publishEvent(server, event);
2125
- return result;
2255
+ return finalResult;
2126
2256
  } catch (error) {
2127
2257
  event.isError = true;
2128
2258
  event.error = captureException(error);
2259
+ if (conversation.minted) event.conversationId = void 0;
2129
2260
  event.duration = getEventDuration(event);
2130
2261
  publishEvent(server, event);
2131
2262
  throw error;
@@ -2157,6 +2288,10 @@ function getContextArgument$1(request) {
2157
2288
  function getEventDuration(event) {
2158
2289
  return event.timestamp ? Date.now() - event.timestamp.getTime() : 0;
2159
2290
  }
2291
+ function cacheToolDescriptions(cache, tools) {
2292
+ if (!tools) return;
2293
+ for (const tool of tools) if (tool?.name && typeof tool.description === "string") cache.set(tool.name, tool.description);
2294
+ }
2160
2295
  //#endregion
2161
2296
  //#region src/modules/mcp-sdk-compat.ts
2162
2297
  /**
@@ -2244,7 +2379,8 @@ function addTracingToToolRegistry(tools, server) {
2244
2379
  }
2245
2380
  function setupListenerToRegisteredTools(server) {
2246
2381
  try {
2247
- if (!getServerTrackingData(server.server)) {
2382
+ const data = getServerTrackingData(server.server);
2383
+ if (!data) {
2248
2384
  writeToLog("Warning: Cannot setup listener - no tracking data found");
2249
2385
  return;
2250
2386
  }
@@ -2252,6 +2388,7 @@ function setupListenerToRegisteredTools(server) {
2252
2388
  set(target, property, value) {
2253
2389
  try {
2254
2390
  if (typeof property === "string" && value && typeof value === "object" && hasToolFunction(value)) {
2391
+ if (typeof value.description === "string") data.toolDescriptions.set(property, value.description);
2255
2392
  if (value[MCP_ANALYTICS_PROCESSED]) {
2256
2393
  writeToLog(`Tool ${String(property)} already processed, skipping proxy wrapping`);
2257
2394
  return Reflect.set(target, property, value);
@@ -2317,14 +2454,14 @@ function addTracingToToolCallbackInternal(tool, toolName, _server) {
2317
2454
  args = void 0;
2318
2455
  extra = params[0];
2319
2456
  }
2320
- const removeContextFromArgs = (args) => {
2321
- if (args && typeof args === "object" && "context" in args) {
2322
- const { context: _context, ...argsWithoutContext } = args;
2323
- return argsWithoutContext;
2457
+ const removeContextFromArgs = (input) => {
2458
+ if (input && typeof input === "object" && "context" in input) {
2459
+ const { context: _context, ...rest } = input;
2460
+ return rest;
2324
2461
  }
2325
- return args;
2462
+ return input;
2326
2463
  };
2327
- const cleanedArgs = toolName === "get_more_tools" ? args : removeContextFromArgs(args);
2464
+ const cleanedArgs = toolName === "get_more_tools" ? args : stripConversationId(removeContextFromArgs(args));
2328
2465
  try {
2329
2466
  if (cleanedArgs === void 0) return await originalCallback(extra);
2330
2467
  return await originalCallback(cleanedArgs, extra);
@@ -2358,26 +2495,31 @@ function createToolsCallWrapper(originalHandler, server) {
2358
2495
  }
2359
2496
  async function handleWrappedToolsCall(originalHandler, server, request, extra) {
2360
2497
  const startTime = /* @__PURE__ */ new Date();
2361
- const tracing = await initializeToolCallEvent(server, request, extra, startTime);
2498
+ const conversation = resolveConversationId(getServerTrackingData(server)?.options.enableConversationId ?? false, request.params?.arguments, request.params?.name);
2499
+ const tracing = await initializeToolCallEvent(server, request, conversation.conversationId ? cloneRequestWithoutConversationId(request) : request, extra, startTime, conversation);
2362
2500
  if (request?.params?.name === "get_more_tools") return await executeReportMissingTool(server, request, tracing, startTime);
2363
2501
  return await executeOriginalTool(originalHandler, server, request, extra, tracing, startTime);
2364
2502
  }
2365
- async function initializeToolCallEvent(server, request, extra, startTime) {
2503
+ async function initializeToolCallEvent(server, request, downstreamRequest, extra, startTime, conversation) {
2366
2504
  try {
2367
2505
  const data = getServerTrackingData(server);
2368
2506
  if (!data) {
2369
2507
  writeToLog("Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called track(server, options) before using tool calls.");
2370
2508
  return {
2371
2509
  event: null,
2510
+ mintedConversationId: void 0,
2372
2511
  shouldPublishEvent: false
2373
2512
  };
2374
2513
  }
2514
+ const toolName = request.params?.name;
2375
2515
  const event = {
2376
2516
  sessionId: getServerSessionId(server, extra),
2377
- resourceName: request.params?.name || "Unknown Tool",
2378
- parameters: buildCapturedMcpParameters(request),
2517
+ conversationId: conversation.conversationId,
2518
+ resourceName: toolName || "Unknown Tool",
2519
+ parameters: buildCapturedMcpParameters(downstreamRequest),
2379
2520
  eventType: MCPAnalyticsEventType.mcpToolsCall,
2380
2521
  timestamp: startTime,
2522
+ toolDescription: toolName ? data.toolDescriptions.get(toolName) : void 0,
2381
2523
  redactionFn: data.options.redactSensitiveInformation
2382
2524
  };
2383
2525
  await handleIdentify(server, data, request, extra);
@@ -2386,12 +2528,14 @@ async function initializeToolCallEvent(server, request, extra, startTime) {
2386
2528
  setEventIntent(event, await resolveToolCallIntent(data, request, extra));
2387
2529
  return {
2388
2530
  event,
2531
+ mintedConversationId: conversation.minted ? conversation.conversationId : void 0,
2389
2532
  shouldPublishEvent: true
2390
2533
  };
2391
2534
  } catch (error) {
2392
2535
  writeToLog(`Warning: PostHog MCP analytics tracing failed for tool ${request.params?.name}, falling back to original handler - ${error}`);
2393
2536
  return {
2394
2537
  event: null,
2538
+ mintedConversationId: void 0,
2395
2539
  shouldPublishEvent: false
2396
2540
  };
2397
2541
  }
@@ -2419,14 +2563,20 @@ async function executeReportMissingTool(server, request, tracing, startTime) {
2419
2563
  async function executeOriginalTool(originalHandler, server, request, extra, tracing, startTime) {
2420
2564
  try {
2421
2565
  const result = await originalHandler(request, extra);
2422
- publishSuccessfulToolEvent(server, tracing, result, startTime, {
2566
+ let finalResult = result;
2567
+ if (tracing.mintedConversationId) {
2568
+ if (canInjectConversationIdPromptBack(result)) finalResult = injectConversationIdPromptBack(result, tracing.mintedConversationId);
2569
+ else if (tracing.event) tracing.event.conversationId = void 0;
2570
+ }
2571
+ publishSuccessfulToolEvent(server, tracing, finalResult, startTime, {
2423
2572
  capturedError: extra?.__mcp_analytics_error,
2424
2573
  clearCapturedError: () => {
2425
2574
  if (extra) extra.__mcp_analytics_error = void 0;
2426
2575
  }
2427
2576
  });
2428
- return result;
2577
+ return finalResult;
2429
2578
  } catch (error) {
2579
+ if (tracing.mintedConversationId && tracing.event) tracing.event.conversationId = void 0;
2430
2580
  publishFailedToolEvent(server, tracing, error, startTime);
2431
2581
  throw error;
2432
2582
  }
@@ -2459,16 +2609,20 @@ function publishFailedToolEvent(server, tracing, error, startTime) {
2459
2609
  }
2460
2610
  function setupTracking(server) {
2461
2611
  try {
2462
- getServerTrackingData(server.server);
2612
+ const mcpAnalyticsData = getServerTrackingData(server.server);
2463
2613
  setupToolsCallHandlerWrapping(server);
2464
2614
  setupInitializeTracing(server);
2465
2615
  server._registeredTools = addTracingToToolRegistry(server._registeredTools, server);
2616
+ if (mcpAnalyticsData) seedToolDescriptionsFromRegistry(mcpAnalyticsData.toolDescriptions, server._registeredTools);
2466
2617
  setupListToolsTracing(server);
2467
2618
  setupListenerToRegisteredTools(server);
2468
2619
  } catch (error) {
2469
2620
  writeToLog(`Warning: Failed to setup tool call tracing - ${error}`);
2470
2621
  }
2471
2622
  }
2623
+ function seedToolDescriptionsFromRegistry(cache, tools) {
2624
+ for (const [name, tool] of Object.entries(tools)) if (typeof tool?.description === "string") cache.set(name, tool.description);
2625
+ }
2472
2626
  //#endregion
2473
2627
  //#region src/index.ts
2474
2628
  /**
@@ -2604,6 +2758,7 @@ function buildTrackingData(lowLevelServer, options) {
2604
2758
  sessionId: newSessionId(),
2605
2759
  lastActivity: /* @__PURE__ */ new Date(),
2606
2760
  identifiedSessions: /* @__PURE__ */ new Map(),
2761
+ toolDescriptions: /* @__PURE__ */ new Map(),
2607
2762
  sessionInfo: getSessionInfo(lowLevelServer, void 0),
2608
2763
  options: {
2609
2764
  reportMissing: options.reportMissing ?? false,
@@ -2617,7 +2772,8 @@ function buildTrackingData(lowLevelServer, options) {
2617
2772
  eventProperties: options.eventProperties,
2618
2773
  host: options.host,
2619
2774
  posthogClient: options.posthogClient,
2620
- posthogOptions: options.posthogOptions
2775
+ posthogOptions: options.posthogOptions,
2776
+ enableConversationId: options.enableConversationId ?? false
2621
2777
  },
2622
2778
  sessionSource: "generated"
2623
2779
  };