@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.
- package/LICENSE +64 -0
- package/README.md +64 -0
- package/dist/extensions/constants.d.ts +9 -0
- package/dist/extensions/constants.d.ts.map +1 -1
- package/dist/extensions/constants.js +9 -0
- package/dist/extensions/constants.mjs +9 -0
- package/dist/extensions/event-types.d.ts +1 -0
- package/dist/extensions/event-types.d.ts.map +1 -1
- package/dist/extensions/event-types.js +1 -0
- package/dist/extensions/event-types.mjs +1 -0
- package/dist/extensions/feedback.d.ts +41 -0
- package/dist/extensions/feedback.d.ts.map +1 -0
- package/dist/extensions/feedback.js +259 -0
- package/dist/extensions/feedback.mjs +200 -0
- package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-highlevel.js +23 -2
- package/dist/extensions/instrument-highlevel.mjs +25 -4
- package/dist/extensions/instrument-lowlevel.d.ts +4 -3
- package/dist/extensions/instrument-lowlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-lowlevel.js +23 -2
- package/dist/extensions/instrument-lowlevel.mjs +25 -4
- package/dist/extensions/instrumentation.d.ts +33 -13
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +103 -9
- package/dist/extensions/instrumentation.mjs +99 -8
- package/dist/extensions/internal.js +9 -2
- package/dist/extensions/internal.mjs +9 -2
- package/dist/extensions/mcp-payloads.d.ts +19 -0
- package/dist/extensions/mcp-payloads.d.ts.map +1 -1
- package/dist/extensions/mcp-payloads.js +217 -7
- package/dist/extensions/mcp-payloads.mjs +210 -6
- package/dist/extensions/posthog-events.d.ts.map +1 -1
- package/dist/extensions/posthog-events.js +1 -0
- package/dist/extensions/posthog-events.mjs +1 -0
- package/dist/extensions/posthog-mcp.d.ts +23 -3
- package/dist/extensions/posthog-mcp.d.ts.map +1 -1
- package/dist/extensions/posthog-mcp.js +27 -1
- package/dist/extensions/posthog-mcp.mjs +27 -1
- package/dist/extensions/sanitization.d.ts.map +1 -1
- package/dist/extensions/sanitization.js +2 -1
- package/dist/extensions/sanitization.mjs +3 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.mjs +5 -1
- package/dist/types.d.ts +114 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +4 -4
- package/src/extensions/constants.ts +9 -0
- package/src/extensions/event-types.ts +1 -0
- package/src/extensions/feedback.ts +349 -0
- package/src/extensions/instrument-highlevel.ts +45 -2
- package/src/extensions/instrument-lowlevel.ts +49 -5
- package/src/extensions/instrumentation.ts +170 -17
- package/src/extensions/internal.ts +13 -2
- package/src/extensions/mcp-payloads.ts +443 -7
- package/src/extensions/posthog-events.ts +1 -0
- package/src/extensions/posthog-mcp.ts +74 -3
- package/src/extensions/sanitization.ts +14 -6
- package/src/index.ts +24 -3
- package/src/types.ts +120 -0
- 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
|
|
65
|
-
const
|
|
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,
|
|
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: !
|
|
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)(
|
|
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
|
|
24
|
-
const
|
|
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,
|
|
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: !
|
|
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(
|
|
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
|
|
162
|
-
|
|
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
|
|
123
|
-
|
|
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":"
|
|
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"}
|