@posthog/mcp 0.14.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +64 -0
  2. package/README.md +64 -0
  3. package/dist/extensions/constants.d.ts +9 -0
  4. package/dist/extensions/constants.d.ts.map +1 -1
  5. package/dist/extensions/constants.js +9 -0
  6. package/dist/extensions/constants.mjs +9 -0
  7. package/dist/extensions/event-types.d.ts +1 -0
  8. package/dist/extensions/event-types.d.ts.map +1 -1
  9. package/dist/extensions/event-types.js +1 -0
  10. package/dist/extensions/event-types.mjs +1 -0
  11. package/dist/extensions/feedback.d.ts +41 -0
  12. package/dist/extensions/feedback.d.ts.map +1 -0
  13. package/dist/extensions/feedback.js +259 -0
  14. package/dist/extensions/feedback.mjs +200 -0
  15. package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
  16. package/dist/extensions/instrument-highlevel.js +23 -2
  17. package/dist/extensions/instrument-highlevel.mjs +25 -4
  18. package/dist/extensions/instrument-lowlevel.d.ts +4 -3
  19. package/dist/extensions/instrument-lowlevel.d.ts.map +1 -1
  20. package/dist/extensions/instrument-lowlevel.js +23 -2
  21. package/dist/extensions/instrument-lowlevel.mjs +25 -4
  22. package/dist/extensions/instrumentation.d.ts +33 -13
  23. package/dist/extensions/instrumentation.d.ts.map +1 -1
  24. package/dist/extensions/instrumentation.js +103 -9
  25. package/dist/extensions/instrumentation.mjs +99 -8
  26. package/dist/extensions/internal.js +9 -2
  27. package/dist/extensions/internal.mjs +9 -2
  28. package/dist/extensions/mcp-payloads.d.ts +19 -0
  29. package/dist/extensions/mcp-payloads.d.ts.map +1 -1
  30. package/dist/extensions/mcp-payloads.js +217 -7
  31. package/dist/extensions/mcp-payloads.mjs +210 -6
  32. package/dist/extensions/posthog-events.d.ts.map +1 -1
  33. package/dist/extensions/posthog-events.js +1 -0
  34. package/dist/extensions/posthog-events.mjs +1 -0
  35. package/dist/extensions/posthog-mcp.d.ts +23 -3
  36. package/dist/extensions/posthog-mcp.d.ts.map +1 -1
  37. package/dist/extensions/posthog-mcp.js +27 -1
  38. package/dist/extensions/posthog-mcp.mjs +27 -1
  39. package/dist/extensions/sanitization.d.ts.map +1 -1
  40. package/dist/extensions/sanitization.js +2 -1
  41. package/dist/extensions/sanitization.mjs +3 -2
  42. package/dist/index.d.ts +5 -4
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +10 -0
  45. package/dist/index.mjs +5 -1
  46. package/dist/types.d.ts +114 -0
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/version.d.ts +1 -1
  49. package/dist/version.js +1 -1
  50. package/dist/version.mjs +1 -1
  51. package/package.json +4 -4
  52. package/src/extensions/constants.ts +9 -0
  53. package/src/extensions/event-types.ts +1 -0
  54. package/src/extensions/feedback.ts +349 -0
  55. package/src/extensions/instrument-highlevel.ts +45 -2
  56. package/src/extensions/instrument-lowlevel.ts +49 -5
  57. package/src/extensions/instrumentation.ts +170 -17
  58. package/src/extensions/internal.ts +13 -2
  59. package/src/extensions/mcp-payloads.ts +443 -7
  60. package/src/extensions/posthog-events.ts +1 -0
  61. package/src/extensions/posthog-mcp.ts +74 -3
  62. package/src/extensions/sanitization.ts +14 -6
  63. package/src/index.ts +24 -3
  64. package/src/types.ts +120 -0
  65. package/src/version.ts +1 -1
@@ -37,7 +37,8 @@ __webpack_require__.d(__webpack_exports__, {
37
37
  isToolAdvertised: ()=>isToolAdvertised,
38
38
  patchRequestHandlers: ()=>patchRequestHandlers,
39
39
  readToolMetaCategory: ()=>readToolMetaCategory,
40
- registerFallbackRequestHandler: ()=>registerFallbackRequestHandler
40
+ registerFallbackRequestHandler: ()=>registerFallbackRequestHandler,
41
+ traceResourceRequest: ()=>traceResourceRequest
41
42
  });
42
43
  const external_analytics_parameters_js_namespaceObject = require("./analytics-parameters.js");
43
44
  const external_context_parameters_js_namespaceObject = require("./context-parameters.js");
@@ -56,18 +57,25 @@ const external_mcp_sdk_compat_js_namespaceObject = require("./mcp-sdk-compat.js"
56
57
  const external_request_headers_js_namespaceObject = require("./request-headers.js");
57
58
  const external_session_js_namespaceObject = require("./session.js");
58
59
  const external_session_token_js_namespaceObject = require("./session-token.js");
60
+ const external_feedback_js_namespaceObject = require("./feedback.js");
59
61
  const external_tools_js_namespaceObject = require("./tools.js");
60
62
  const external_tracing_helpers_js_namespaceObject = require("./tracing-helpers.js");
61
63
  async function captureToolCall(params) {
62
- const { server, data, request, extra, execute, parameterOwnership, eventType, explicitContextIntent, takeCapturedError } = params;
64
+ const { server, data, request, extra, execute, parameterOwnership, eventType, explicitContextIntent, extraEventProperties, omitCapturedParameters, takeCapturedError } = params;
63
65
  const resolvedEventType = eventType ?? external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpToolsCall;
64
- const ownership = getActiveAnalyticsParameterOwnership(data, request.params?.name, parameterOwnership, resolvedEventType === external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpMissingCapability);
65
- const canCaptureContextIntent = resolvedEventType !== external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpMissingCapability && (0, external_context_parameters_js_namespaceObject.isContextEnabled)(data.options.context) && (ownership.context || !ownership.contextOwnershipKnown);
66
+ const isVirtualAnalyticsTool = resolvedEventType === external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpMissingCapability || resolvedEventType === external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpFeedback;
67
+ const ownership = getActiveAnalyticsParameterOwnership(data, request.params?.name, parameterOwnership, isVirtualAnalyticsTool);
68
+ const canCaptureContextIntent = !isVirtualAnalyticsTool && (0, external_context_parameters_js_namespaceObject.isContextEnabled)(data.options.context) && (ownership.context || !ownership.contextOwnershipKnown);
66
69
  const conversation = (0, external_conversation_id_js_namespaceObject.resolveConversationId)(ownership.conversationId, request.params?.arguments);
67
70
  const downstreamRequest = cloneRequestWithoutOwnedAnalyticsArguments(request, ownership);
68
71
  const startTime = new Date();
69
72
  const preparedEvent = await prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, resolvedEventType, canCaptureContextIntent);
70
73
  if (preparedEvent && explicitContextIntent) (0, external_intent_js_namespaceObject.setExplicitContextIntent)(preparedEvent.event, explicitContextIntent);
74
+ if (preparedEvent && extraEventProperties) preparedEvent.event.properties = {
75
+ ...preparedEvent.event.properties,
76
+ ...extraEventProperties
77
+ };
78
+ if (preparedEvent && omitCapturedParameters) preparedEvent.event.parameters = void 0;
71
79
  let result;
72
80
  try {
73
81
  result = await execute(downstreamRequest);
@@ -79,12 +87,12 @@ async function captureToolCall(params) {
79
87
  publishSuccessfulToolEvent(server, preparedEvent, finalResult, startTime, data.logger, takeCapturedError, result);
80
88
  return finalResult;
81
89
  }
82
- function getActiveAnalyticsParameterOwnership(data, toolName, override, isMissingCapabilityTool) {
90
+ function getActiveAnalyticsParameterOwnership(data, toolName, override, isVirtualAnalyticsTool) {
83
91
  const listed = toolName ? data.toolAnalyticsParameterOwnership.get(toolName) : void 0;
84
92
  const ownership = override ?? listed;
85
93
  return {
86
94
  contextOwnershipKnown: void 0 !== ownership,
87
- context: !isMissingCapabilityTool && (0, external_context_parameters_js_namespaceObject.isContextEnabled)(data.options.context) && ownership?.context === true,
95
+ context: !isVirtualAnalyticsTool && (0, external_context_parameters_js_namespaceObject.isContextEnabled)(data.options.context) && ownership?.context === true,
88
96
  conversationId: true === data.options.enableConversationId && ownership?.conversationId === true,
89
97
  llmModel: (0, external_model_parameters_js_namespaceObject.isCaptureModelEnabled)(data.options.captureModel) && ownership?.llmModel === true,
90
98
  outputInstructions: true === data.options.enableConversationId && listed?.outputInstructions === true
@@ -182,6 +190,77 @@ function publishFailedToolEvent(server, preparedEvent, error, startTime, convers
182
190
  logger(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`);
183
191
  }
184
192
  }
193
+ function publishResourceEvent(server, preparedEvent, startTime, params, outcome) {
194
+ if (!preparedEvent) return;
195
+ const { event, requestAttribution } = preparedEvent;
196
+ try {
197
+ if ('error' in outcome) {
198
+ event.isError = true;
199
+ event.error = (0, external_exceptions_js_namespaceObject.captureException)(outcome.error);
200
+ } else {
201
+ event.isError = false;
202
+ if (params.eventType === external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpResourcesList) event.response = outcome.result;
203
+ }
204
+ event.duration = Date.now() - startTime.getTime();
205
+ (0, external_capture_js_namespaceObject.captureEvent)(server, event, params.logger, requestAttribution);
206
+ } catch (error) {
207
+ params.logger(`Warning: PostHog MCP analytics failed to publish ${params.request.method} analytics - ${error}`);
208
+ }
209
+ }
210
+ function traceResourceRequest(eventType, logger) {
211
+ return (server, originalHandler, request, extra)=>captureResourceRequest({
212
+ server,
213
+ originalHandler,
214
+ request,
215
+ extra,
216
+ eventType,
217
+ logger
218
+ });
219
+ }
220
+ async function captureResourceRequest(params) {
221
+ const { server, originalHandler, request, extra, eventType, logger } = params;
222
+ const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
223
+ if (!data) {
224
+ logger('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using resources.');
225
+ return await originalHandler(request, extra);
226
+ }
227
+ const startTime = new Date();
228
+ let preparedEvent = null;
229
+ try {
230
+ const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
231
+ const sessionInfo = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, sessionId);
232
+ const event = {
233
+ sessionId,
234
+ eventType,
235
+ parameters: (0, external_mcp_payloads_js_namespaceObject.buildCapturedMcpParameters)(request),
236
+ resourceName: eventType === external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpResourcesRead ? request.params?.uri : void 0,
237
+ timestamp: startTime
238
+ };
239
+ (0, external_client_identity_js_namespaceObject.stampClientIdentity)(event, request, extra, server);
240
+ (0, external_transport_identity_js_namespaceObject.stampTransportIdentity)(event, extra);
241
+ const identity = await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, sessionInfo, extra);
242
+ await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
243
+ preparedEvent = {
244
+ event,
245
+ requestAttribution: (0, external_internal_js_namespaceObject.withIdentity)(sessionInfo, identity)
246
+ };
247
+ } catch (error) {
248
+ logger(`Warning: PostHog MCP analytics could not prepare ${request.method} analytics - ${error}`);
249
+ }
250
+ let result;
251
+ try {
252
+ result = await originalHandler(request, extra);
253
+ } catch (error) {
254
+ publishResourceEvent(server, preparedEvent, startTime, params, {
255
+ error
256
+ });
257
+ throw error;
258
+ }
259
+ publishResourceEvent(server, preparedEvent, startTime, params, {
260
+ result
261
+ });
262
+ return result;
263
+ }
185
264
  const originalRequestHandlers = new WeakMap();
186
265
  function rememberOriginalRequestHandler(server, handlerName, originalHandler) {
187
266
  let handlers = originalRequestHandlers.get(server);
@@ -217,9 +296,9 @@ function patchRequestHandlers(server, patches) {
217
296
  return result;
218
297
  };
219
298
  }
220
- function getVirtualToolParameterOwnership(data, toolName) {
299
+ function getVirtualToolParameterOwnership(data, toolName, virtualToolInputSchema) {
221
300
  return {
222
- ...(0, external_analytics_parameters_js_namespaceObject.getAnalyticsParameterOwnership)((0, external_tools_js_namespaceObject.getReportMissingToolDescriptor)(toolName).inputSchema),
301
+ ...(0, external_analytics_parameters_js_namespaceObject.getAnalyticsParameterOwnership)(virtualToolInputSchema),
223
302
  conversationId: data.toolAnalyticsParameterOwnership.get(toolName)?.conversationId === true
224
303
  };
225
304
  }
@@ -305,6 +384,19 @@ async function getTracedToolsList(server, originalListToolsHandler, request, ext
305
384
  ]);
306
385
  }
307
386
  }
387
+ const feedbackOptions = (0, external_feedback_js_namespaceObject.resolveCollectFeedbackOptions)(data.options.collectFeedback);
388
+ if (feedbackOptions) {
389
+ const feedbackToolName = feedbackOptions.toolName ?? external_feedback_js_namespaceObject.SEND_FEEDBACK_TOOL_NAME;
390
+ const alreadyPresent = tools.some((tool)=>tool?.name === feedbackToolName);
391
+ if (alreadyPresent) data.logger(`Warning: Cannot inject agent-feedback tool "${feedbackToolName}" because a real tool already uses that name. The real tool will not be intercepted.`);
392
+ else {
393
+ const virtualTool = (0, external_feedback_js_namespaceObject.getFeedbackToolDescriptor)(feedbackOptions);
394
+ tools.push(virtualTool);
395
+ cacheToolAnalyticsParameterOwnership(data.toolAnalyticsParameterOwnership, [
396
+ virtualTool
397
+ ]);
398
+ }
399
+ }
308
400
  if ((0, external_model_parameters_js_namespaceObject.isCaptureModelEnabled)(data.options.captureModel)) tools = (0, external_model_parameters_js_namespaceObject.addModelParameterToTools)(tools, (0, external_model_parameters_js_namespaceObject.getModelDescription)(data.options.captureModel), data.logger);
309
401
  if (data.options.enableConversationId) {
310
402
  tools = (0, external_conversation_id_js_namespaceObject.addConversationIdToTools)(tools, data.logger);
@@ -461,6 +553,7 @@ exports.isToolAdvertised = __webpack_exports__.isToolAdvertised;
461
553
  exports.patchRequestHandlers = __webpack_exports__.patchRequestHandlers;
462
554
  exports.readToolMetaCategory = __webpack_exports__.readToolMetaCategory;
463
555
  exports.registerFallbackRequestHandler = __webpack_exports__.registerFallbackRequestHandler;
556
+ exports.traceResourceRequest = __webpack_exports__.traceResourceRequest;
464
557
  for(var __rspack_i in __webpack_exports__)if (-1 === [
465
558
  "cacheToolCategories",
466
559
  "cacheToolDescriptions",
@@ -471,7 +564,8 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
471
564
  "isToolAdvertised",
472
565
  "patchRequestHandlers",
473
566
  "readToolMetaCategory",
474
- "registerFallbackRequestHandler"
567
+ "registerFallbackRequestHandler",
568
+ "traceResourceRequest"
475
569
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
476
570
  Object.defineProperty(exports, '__esModule', {
477
571
  value: true
@@ -15,18 +15,25 @@ import { readRequestHandlerMethod } from "./mcp-sdk-compat.mjs";
15
15
  import { getRequestHeaders } from "./request-headers.mjs";
16
16
  import { getSessionId, getSessionInfo, isModernEraRequest, newSessionId } from "./session.mjs";
17
17
  import { encodeSessionId, readMcpSessionHeader, writeSessionIdToTransport } from "./session-token.mjs";
18
+ import { SEND_FEEDBACK_TOOL_NAME, getFeedbackToolDescriptor, resolveCollectFeedbackOptions } from "./feedback.mjs";
18
19
  import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from "./tools.mjs";
19
20
  import { applyResolvedMetadata, isToolResultError } from "./tracing-helpers.mjs";
20
21
  async function captureToolCall(params) {
21
- const { server, data, request, extra, execute, parameterOwnership, eventType, explicitContextIntent, takeCapturedError } = params;
22
+ const { server, data, request, extra, execute, parameterOwnership, eventType, explicitContextIntent, extraEventProperties, omitCapturedParameters, takeCapturedError } = params;
22
23
  const resolvedEventType = eventType ?? MCPAnalyticsEventType.mcpToolsCall;
23
- const ownership = getActiveAnalyticsParameterOwnership(data, request.params?.name, parameterOwnership, resolvedEventType === MCPAnalyticsEventType.mcpMissingCapability);
24
- const canCaptureContextIntent = resolvedEventType !== MCPAnalyticsEventType.mcpMissingCapability && isContextEnabled(data.options.context) && (ownership.context || !ownership.contextOwnershipKnown);
24
+ const isVirtualAnalyticsTool = resolvedEventType === MCPAnalyticsEventType.mcpMissingCapability || resolvedEventType === MCPAnalyticsEventType.mcpFeedback;
25
+ const ownership = getActiveAnalyticsParameterOwnership(data, request.params?.name, parameterOwnership, isVirtualAnalyticsTool);
26
+ const canCaptureContextIntent = !isVirtualAnalyticsTool && isContextEnabled(data.options.context) && (ownership.context || !ownership.contextOwnershipKnown);
25
27
  const conversation = resolveConversationId(ownership.conversationId, request.params?.arguments);
26
28
  const downstreamRequest = cloneRequestWithoutOwnedAnalyticsArguments(request, ownership);
27
29
  const startTime = new Date();
28
30
  const preparedEvent = await prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, resolvedEventType, canCaptureContextIntent);
29
31
  if (preparedEvent && explicitContextIntent) setExplicitContextIntent(preparedEvent.event, explicitContextIntent);
32
+ if (preparedEvent && extraEventProperties) preparedEvent.event.properties = {
33
+ ...preparedEvent.event.properties,
34
+ ...extraEventProperties
35
+ };
36
+ if (preparedEvent && omitCapturedParameters) preparedEvent.event.parameters = void 0;
30
37
  let result;
31
38
  try {
32
39
  result = await execute(downstreamRequest);
@@ -38,12 +45,12 @@ async function captureToolCall(params) {
38
45
  publishSuccessfulToolEvent(server, preparedEvent, finalResult, startTime, data.logger, takeCapturedError, result);
39
46
  return finalResult;
40
47
  }
41
- function getActiveAnalyticsParameterOwnership(data, toolName, override, isMissingCapabilityTool) {
48
+ function getActiveAnalyticsParameterOwnership(data, toolName, override, isVirtualAnalyticsTool) {
42
49
  const listed = toolName ? data.toolAnalyticsParameterOwnership.get(toolName) : void 0;
43
50
  const ownership = override ?? listed;
44
51
  return {
45
52
  contextOwnershipKnown: void 0 !== ownership,
46
- context: !isMissingCapabilityTool && isContextEnabled(data.options.context) && ownership?.context === true,
53
+ context: !isVirtualAnalyticsTool && isContextEnabled(data.options.context) && ownership?.context === true,
47
54
  conversationId: true === data.options.enableConversationId && ownership?.conversationId === true,
48
55
  llmModel: isCaptureModelEnabled(data.options.captureModel) && ownership?.llmModel === true,
49
56
  outputInstructions: true === data.options.enableConversationId && listed?.outputInstructions === true
@@ -141,6 +148,77 @@ function publishFailedToolEvent(server, preparedEvent, error, startTime, convers
141
148
  logger(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`);
142
149
  }
143
150
  }
151
+ function publishResourceEvent(server, preparedEvent, startTime, params, outcome) {
152
+ if (!preparedEvent) return;
153
+ const { event, requestAttribution } = preparedEvent;
154
+ try {
155
+ if ('error' in outcome) {
156
+ event.isError = true;
157
+ event.error = captureException(outcome.error);
158
+ } else {
159
+ event.isError = false;
160
+ if (params.eventType === MCPAnalyticsEventType.mcpResourcesList) event.response = outcome.result;
161
+ }
162
+ event.duration = Date.now() - startTime.getTime();
163
+ captureEvent(server, event, params.logger, requestAttribution);
164
+ } catch (error) {
165
+ params.logger(`Warning: PostHog MCP analytics failed to publish ${params.request.method} analytics - ${error}`);
166
+ }
167
+ }
168
+ function traceResourceRequest(eventType, logger) {
169
+ return (server, originalHandler, request, extra)=>captureResourceRequest({
170
+ server,
171
+ originalHandler,
172
+ request,
173
+ extra,
174
+ eventType,
175
+ logger
176
+ });
177
+ }
178
+ async function captureResourceRequest(params) {
179
+ const { server, originalHandler, request, extra, eventType, logger } = params;
180
+ const data = getServerTrackingData(server);
181
+ if (!data) {
182
+ logger('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using resources.');
183
+ return await originalHandler(request, extra);
184
+ }
185
+ const startTime = new Date();
186
+ let preparedEvent = null;
187
+ try {
188
+ const sessionId = getSessionId(server, extra);
189
+ const sessionInfo = getSessionInfo(server, data, sessionId);
190
+ const event = {
191
+ sessionId,
192
+ eventType,
193
+ parameters: buildCapturedMcpParameters(request),
194
+ resourceName: eventType === MCPAnalyticsEventType.mcpResourcesRead ? request.params?.uri : void 0,
195
+ timestamp: startTime
196
+ };
197
+ stampClientIdentity(event, request, extra, server);
198
+ stampTransportIdentity(event, extra);
199
+ const identity = await handleIdentify(server, data, sessionId, request, sessionInfo, extra);
200
+ await applyResolvedMetadata(event, data, request, extra);
201
+ preparedEvent = {
202
+ event,
203
+ requestAttribution: withIdentity(sessionInfo, identity)
204
+ };
205
+ } catch (error) {
206
+ logger(`Warning: PostHog MCP analytics could not prepare ${request.method} analytics - ${error}`);
207
+ }
208
+ let result;
209
+ try {
210
+ result = await originalHandler(request, extra);
211
+ } catch (error) {
212
+ publishResourceEvent(server, preparedEvent, startTime, params, {
213
+ error
214
+ });
215
+ throw error;
216
+ }
217
+ publishResourceEvent(server, preparedEvent, startTime, params, {
218
+ result
219
+ });
220
+ return result;
221
+ }
144
222
  const originalRequestHandlers = new WeakMap();
145
223
  function rememberOriginalRequestHandler(server, handlerName, originalHandler) {
146
224
  let handlers = originalRequestHandlers.get(server);
@@ -176,9 +254,9 @@ function patchRequestHandlers(server, patches) {
176
254
  return result;
177
255
  };
178
256
  }
179
- function getVirtualToolParameterOwnership(data, toolName) {
257
+ function getVirtualToolParameterOwnership(data, toolName, virtualToolInputSchema) {
180
258
  return {
181
- ...getAnalyticsParameterOwnership(getReportMissingToolDescriptor(toolName).inputSchema),
259
+ ...getAnalyticsParameterOwnership(virtualToolInputSchema),
182
260
  conversationId: data.toolAnalyticsParameterOwnership.get(toolName)?.conversationId === true
183
261
  };
184
262
  }
@@ -264,6 +342,19 @@ async function getTracedToolsList(server, originalListToolsHandler, request, ext
264
342
  ]);
265
343
  }
266
344
  }
345
+ const feedbackOptions = resolveCollectFeedbackOptions(data.options.collectFeedback);
346
+ if (feedbackOptions) {
347
+ const feedbackToolName = feedbackOptions.toolName ?? SEND_FEEDBACK_TOOL_NAME;
348
+ const alreadyPresent = tools.some((tool)=>tool?.name === feedbackToolName);
349
+ if (alreadyPresent) data.logger(`Warning: Cannot inject agent-feedback tool "${feedbackToolName}" because a real tool already uses that name. The real tool will not be intercepted.`);
350
+ else {
351
+ const virtualTool = getFeedbackToolDescriptor(feedbackOptions);
352
+ tools.push(virtualTool);
353
+ cacheToolAnalyticsParameterOwnership(data.toolAnalyticsParameterOwnership, [
354
+ virtualTool
355
+ ]);
356
+ }
357
+ }
267
358
  if (isCaptureModelEnabled(data.options.captureModel)) tools = addModelParameterToTools(tools, getModelDescription(data.options.captureModel), data.logger);
268
359
  if (data.options.enableConversationId) {
269
360
  tools = addConversationIdToTools(tools, data.logger);
@@ -410,4 +501,4 @@ function readProtocolVersion(result, request) {
410
501
  const requested = request.params?.protocolVersion;
411
502
  return 'string' == typeof requested && requested.length > 0 ? requested : void 0;
412
503
  }
413
- export { cacheToolCategories, cacheToolDescriptions, captureToolCall, getVirtualToolParameterOwnership, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, readToolMetaCategory, registerFallbackRequestHandler };
504
+ export { cacheToolCategories, cacheToolDescriptions, captureToolCall, getVirtualToolParameterOwnership, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, readToolMetaCategory, registerFallbackRequestHandler, traceResourceRequest };
@@ -158,8 +158,15 @@ async function resolveEventProperties(data, request, extra) {
158
158
  function getRequestResourceName(request) {
159
159
  if (!request || 'object' != typeof request || !('params' in request)) return 'Unknown';
160
160
  const params = request.params;
161
- if (!params || 'object' != typeof params || !('name' in params)) return 'Unknown';
162
- return 'string' == typeof params.name ? params.name : 'Unknown';
161
+ if (!params || 'object' != typeof params) return 'Unknown';
162
+ for (const key of [
163
+ 'name',
164
+ 'uri'
165
+ ]){
166
+ const value = params[key];
167
+ if ('string' == typeof value) return value;
168
+ }
169
+ return 'Unknown';
163
170
  }
164
171
  exports.IdentityCache = __webpack_exports__.IdentityCache;
165
172
  exports.areIdentitiesEqual = __webpack_exports__.areIdentitiesEqual;
@@ -119,7 +119,14 @@ async function resolveEventProperties(data, request, extra) {
119
119
  function getRequestResourceName(request) {
120
120
  if (!request || 'object' != typeof request || !('params' in request)) return 'Unknown';
121
121
  const params = request.params;
122
- if (!params || 'object' != typeof params || !('name' in params)) return 'Unknown';
123
- return 'string' == typeof params.name ? params.name : 'Unknown';
122
+ if (!params || 'object' != typeof params) return 'Unknown';
123
+ for (const key of [
124
+ 'name',
125
+ 'uri'
126
+ ]){
127
+ const value = params[key];
128
+ if ('string' == typeof value) return value;
129
+ }
130
+ return 'Unknown';
124
131
  }
125
132
  export { IdentityCache, areIdentitiesEqual, getServerTrackingData, handleIdentify, mergeIdentities, resolveEventProperties, setServerTrackingData, withIdentity };
@@ -1,4 +1,17 @@
1
1
  type JsonRecord = Record<string, unknown>;
2
+ /**
3
+ * Sanitizes agent-narrated free text (`$mcp_intent`, the `send_feedback`
4
+ * fields): structured PII on top of the passes every captured string gets.
5
+ *
6
+ * Every step of the order is load-bearing. The binary gate reads the value as it
7
+ * arrived, because splicing `[redacted]` into a blob — a Luhn-valid run inside
8
+ * base64 is enough — stops it looking like base64 and would ship it whole.
9
+ * Credentials go before PII, because a PII pattern can cut a token in half (a
10
+ * phone-shaped run inside one) and leave the halves behind. PII goes before the
11
+ * URL pass, because the URL rewrite percent-encodes the `@` that the email
12
+ * pattern anchors on.
13
+ */
14
+ export declare function sanitizeFreeText(value: string): string;
2
15
  /**
3
16
  * Redacts structured personal identifiers (emails, IP addresses, credit-card
4
17
  * numbers, US SSNs, and phone numbers) from a free-text string. Intended for the
@@ -10,6 +23,12 @@ type JsonRecord = Record<string, unknown>;
10
23
  */
11
24
  export declare function redactPii(value: string): string;
12
25
  export declare function sanitizeCapturedValue(value: unknown): unknown;
26
+ /**
27
+ * {@link sanitizeCapturedValue} with the intent-grade string pass
28
+ * ({@link sanitizeFreeText}) on every string leaf, so nested agent-narrated
29
+ * values get structured-PII redaction in the load-bearing order too.
30
+ */
31
+ export declare function sanitizeFreeTextValue(value: unknown): unknown;
13
32
  export declare function buildCapturedMcpParameters(request: unknown): JsonRecord;
14
33
  export {};
15
34
  //# sourceMappingURL=mcp-payloads.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-payloads.d.ts","sourceRoot":"","sources":["../../src/extensions/mcp-payloads.ts"],"names":[],"mappings":"AAmEA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAiGzC;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAU/C;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA0B7D;AA6BD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAiBvE"}
1
+ {"version":3,"file":"mcp-payloads.d.ts","sourceRoot":"","sources":["../../src/extensions/mcp-payloads.ts"],"names":[],"mappings":"AAoHA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAyYzC;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtD;AA6DD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAU/C;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE7D;AAyDD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAiBvE"}