@posthog/mcp 0.10.6 → 0.10.8
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/dist/extensions/analytics-parameters.d.ts +7 -2
- package/dist/extensions/analytics-parameters.d.ts.map +1 -1
- package/dist/extensions/analytics-parameters.js +4 -2
- package/dist/extensions/analytics-parameters.mjs +4 -2
- package/dist/extensions/capture.d.ts +2 -2
- package/dist/extensions/capture.d.ts.map +1 -1
- package/dist/extensions/capture.js +2 -2
- package/dist/extensions/capture.mjs +2 -2
- package/dist/extensions/conversation-id.d.ts +37 -8
- package/dist/extensions/conversation-id.d.ts.map +1 -1
- package/dist/extensions/conversation-id.js +8 -13
- package/dist/extensions/conversation-id.mjs +8 -13
- package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-highlevel.js +1 -1
- package/dist/extensions/instrument-highlevel.mjs +1 -1
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +86 -42
- package/dist/extensions/instrumentation.mjs +88 -44
- package/dist/extensions/internal.d.ts +10 -2
- package/dist/extensions/internal.d.ts.map +1 -1
- package/dist/extensions/internal.js +25 -9
- package/dist/extensions/internal.mjs +19 -6
- package/dist/extensions/output-instructions.d.ts +70 -0
- package/dist/extensions/output-instructions.d.ts.map +1 -0
- package/dist/extensions/output-instructions.js +131 -0
- package/dist/extensions/output-instructions.mjs +82 -0
- package/dist/extensions/session.d.ts +26 -5
- package/dist/extensions/session.d.ts.map +1 -1
- package/dist/extensions/session.js +35 -15
- package/dist/extensions/session.mjs +33 -16
- package/dist/types.d.ts +23 -1
- 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 +3 -3
- package/src/extensions/analytics-parameters.ts +15 -2
- package/src/extensions/capture.ts +13 -6
- package/src/extensions/conversation-id.ts +51 -29
- package/src/extensions/instrument-highlevel.ts +3 -1
- package/src/extensions/instrumentation.ts +151 -60
- package/src/extensions/internal.ts +30 -7
- package/src/extensions/output-instructions.ts +231 -0
- package/src/extensions/session.ts +128 -29
- package/src/types.ts +23 -1
- package/src/version.ts +1 -1
|
@@ -12,6 +12,11 @@ export interface AnalyticsInjectableJsonSchema {
|
|
|
12
12
|
export declare function hasAnalyticsParameter(schema: AnalyticsInjectableJsonSchema | undefined, parameterName: string): boolean;
|
|
13
13
|
export declare function canInjectAnalyticsParameter(schema: AnalyticsInjectableJsonSchema | undefined, parameterName: string): boolean;
|
|
14
14
|
export declare function analyticsOwnsParameter(inputSchema: unknown, parameterName: string): boolean;
|
|
15
|
-
export declare function getAnalyticsParameterOwnership(inputSchema: unknown): AnalyticsParameterOwnership;
|
|
16
|
-
|
|
15
|
+
export declare function getAnalyticsParameterOwnership(inputSchema: unknown, outputSchema?: unknown): AnalyticsParameterOwnership;
|
|
16
|
+
/**
|
|
17
|
+
* Removes the arguments we injected, leaving the host's own. Input-side only, so
|
|
18
|
+
* it takes just those two flags rather than the whole ownership record — callers
|
|
19
|
+
* that have no output-schema context should not have to invent a value for it.
|
|
20
|
+
*/
|
|
21
|
+
export declare function stripOwnedAnalyticsArguments(args: unknown, ownership: Pick<AnalyticsParameterOwnership, 'context' | 'conversationId'>): unknown;
|
|
17
22
|
//# sourceMappingURL=analytics-parameters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics-parameters.d.ts","sourceRoot":"","sources":["../../src/extensions/analytics-parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"analytics-parameters.d.ts","sourceRoot":"","sources":["../../src/extensions/analytics-parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;AAiB3D,MAAM,WAAW,6BAA6B;IAC5C,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,6BAA6B,GAAG,SAAS,EACjD,aAAa,EAAE,MAAM,GACpB,OAAO,CAET;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,6BAA6B,GAAG,SAAS,EACjD,aAAa,EAAE,MAAM,GACpB,OAAO,CAIT;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAyB3F;AAED,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,OAAO,EACpB,YAAY,CAAC,EAAE,OAAO,GACrB,2BAA2B,CAM7B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,IAAI,CAAC,2BAA2B,EAAE,SAAS,GAAG,gBAAgB,CAAC,GACzE,OAAO,CAWT"}
|
|
@@ -31,6 +31,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
31
31
|
stripOwnedAnalyticsArguments: ()=>stripOwnedAnalyticsArguments
|
|
32
32
|
});
|
|
33
33
|
const external_mcp_sdk_compat_js_namespaceObject = require("./mcp-sdk-compat.js");
|
|
34
|
+
const external_output_instructions_js_namespaceObject = require("./output-instructions.js");
|
|
34
35
|
const JSON_SCHEMA_KEYWORDS = [
|
|
35
36
|
'$defs',
|
|
36
37
|
'$ref',
|
|
@@ -63,10 +64,11 @@ function analyticsOwnsParameter(inputSchema, parameterName) {
|
|
|
63
64
|
if ('_def' in schema || '_zod' in schema || '~standard' in schema) return canInjectAnalyticsParameter(void 0, parameterName);
|
|
64
65
|
return canInjectAnalyticsParameter(schema, parameterName);
|
|
65
66
|
}
|
|
66
|
-
function getAnalyticsParameterOwnership(inputSchema) {
|
|
67
|
+
function getAnalyticsParameterOwnership(inputSchema, outputSchema) {
|
|
67
68
|
return {
|
|
68
69
|
context: analyticsOwnsParameter(inputSchema, 'context'),
|
|
69
|
-
conversationId: analyticsOwnsParameter(inputSchema, 'conversation_id')
|
|
70
|
+
conversationId: analyticsOwnsParameter(inputSchema, 'conversation_id'),
|
|
71
|
+
outputInstructions: (0, external_output_instructions_js_namespaceObject.canDeclareOutputInstructions)(outputSchema)
|
|
70
72
|
};
|
|
71
73
|
}
|
|
72
74
|
function stripOwnedAnalyticsArguments(args, ownership) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getObjectShape, isZodRawShapeCompat } from "./mcp-sdk-compat.mjs";
|
|
2
|
+
import { canDeclareOutputInstructions } from "./output-instructions.mjs";
|
|
2
3
|
const JSON_SCHEMA_KEYWORDS = [
|
|
3
4
|
'$defs',
|
|
4
5
|
'$ref',
|
|
@@ -31,10 +32,11 @@ function analyticsOwnsParameter(inputSchema, parameterName) {
|
|
|
31
32
|
if ('_def' in schema || '_zod' in schema || '~standard' in schema) return canInjectAnalyticsParameter(void 0, parameterName);
|
|
32
33
|
return canInjectAnalyticsParameter(schema, parameterName);
|
|
33
34
|
}
|
|
34
|
-
function getAnalyticsParameterOwnership(inputSchema) {
|
|
35
|
+
function getAnalyticsParameterOwnership(inputSchema, outputSchema) {
|
|
35
36
|
return {
|
|
36
37
|
context: analyticsOwnsParameter(inputSchema, 'context'),
|
|
37
|
-
conversationId: analyticsOwnsParameter(inputSchema, 'conversation_id')
|
|
38
|
+
conversationId: analyticsOwnsParameter(inputSchema, 'conversation_id'),
|
|
39
|
+
outputInstructions: canDeclareOutputInstructions(outputSchema)
|
|
38
40
|
};
|
|
39
41
|
}
|
|
40
42
|
function stripOwnedAnalyticsArguments(args, ownership) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MCPServerLike, McpEvent } from '../types';
|
|
1
|
+
import type { MCPServerLike, McpEvent, SessionInfo } from '../types';
|
|
2
2
|
import type { LoggerFn } from './logger';
|
|
3
3
|
/**
|
|
4
4
|
* Materializes an `McpEvent` against the server's tracking data + session info,
|
|
@@ -10,5 +10,5 @@ import type { LoggerFn } from './logger';
|
|
|
10
10
|
* Auto-capture callers (tool calls, listings, identify) intentionally ignore the
|
|
11
11
|
* return value, keeping the tool path isolated from analytics latency/errors.
|
|
12
12
|
*/
|
|
13
|
-
export declare function captureEvent(server: MCPServerLike, eventInput: McpEvent, logger: LoggerFn): Promise<void> | undefined;
|
|
13
|
+
export declare function captureEvent(server: MCPServerLike, eventInput: McpEvent, logger: LoggerFn, requestAttribution?: SessionInfo): Promise<void> | undefined;
|
|
14
14
|
//# sourceMappingURL=capture.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/extensions/capture.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/extensions/capture.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAGpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGxC;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,QAAQ,EACpB,MAAM,EAAE,QAAQ,EAChB,kBAAkB,CAAC,EAAE,WAAW,GAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAoE3B"}
|
|
@@ -29,12 +29,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
29
29
|
const external_event_types_js_namespaceObject = require("./event-types.js");
|
|
30
30
|
const external_internal_js_namespaceObject = require("./internal.js");
|
|
31
31
|
const external_session_js_namespaceObject = require("./session.js");
|
|
32
|
-
function captureEvent(server, eventInput, logger) {
|
|
32
|
+
function captureEvent(server, eventInput, logger, requestAttribution) {
|
|
33
33
|
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
|
|
34
34
|
if (!data) return void logger('Warning: Server tracking data not found. Event will not be published.');
|
|
35
35
|
const sink = data.sink;
|
|
36
36
|
if (!sink) return;
|
|
37
|
-
const sessionInfo = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, eventInput.sessionId);
|
|
37
|
+
const sessionInfo = requestAttribution ?? (0, external_session_js_namespaceObject.getSessionInfo)(server, data, eventInput.sessionId);
|
|
38
38
|
const duration = eventInput.duration || (eventInput.timestamp ? Date.now() - eventInput.timestamp.getTime() : void 0);
|
|
39
39
|
const fullEvent = {
|
|
40
40
|
id: eventInput.id || '',
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { MCPAnalyticsEventType } from "./event-types.mjs";
|
|
2
2
|
import { getServerTrackingData } from "./internal.mjs";
|
|
3
3
|
import { getSessionInfo } from "./session.mjs";
|
|
4
|
-
function captureEvent(server, eventInput, logger) {
|
|
4
|
+
function captureEvent(server, eventInput, logger, requestAttribution) {
|
|
5
5
|
const data = getServerTrackingData(server);
|
|
6
6
|
if (!data) return void logger('Warning: Server tracking data not found. Event will not be published.');
|
|
7
7
|
const sink = data.sink;
|
|
8
8
|
if (!sink) return;
|
|
9
|
-
const sessionInfo = getSessionInfo(server, data, eventInput.sessionId);
|
|
9
|
+
const sessionInfo = requestAttribution ?? getSessionInfo(server, data, eventInput.sessionId);
|
|
10
10
|
const duration = eventInput.duration || (eventInput.timestamp ? Date.now() - eventInput.timestamp.getTime() : void 0);
|
|
11
11
|
const fullEvent = {
|
|
12
12
|
id: eventInput.id || '',
|
|
@@ -7,7 +7,13 @@ export interface ConversationIdInjectableTool {
|
|
|
7
7
|
[key: string]: unknown;
|
|
8
8
|
}
|
|
9
9
|
export declare function addConversationIdToTool<TTool extends ConversationIdInjectableTool>(tool: TTool, logger?: LoggerFn): TTool;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Injects `conversation_id` across a tool listing, including the virtual
|
|
12
|
+
* `get_more_tools` tool. Its calls publish `$mcp_missing_capability`, and a
|
|
13
|
+
* capability gap is only meaningful next to the work that hit it — so it belongs
|
|
14
|
+
* in the same session as the surrounding tool calls.
|
|
15
|
+
*/
|
|
16
|
+
export declare function addConversationIdToTools<TTool extends ConversationIdInjectableTool>(tools: TTool[], logger?: LoggerFn): TTool[];
|
|
11
17
|
export type ConversationIdResolution = {
|
|
12
18
|
minted: false;
|
|
13
19
|
conversationId: string | undefined;
|
|
@@ -17,15 +23,38 @@ export type ConversationIdResolution = {
|
|
|
17
23
|
};
|
|
18
24
|
/**
|
|
19
25
|
* Decides which conversation_id to use for a tool call:
|
|
20
|
-
* - disabled
|
|
21
|
-
* - agent
|
|
22
|
-
* -
|
|
26
|
+
* - disabled → none
|
|
27
|
+
* - agent echoed a handle we could have minted → use it
|
|
28
|
+
* - anything else → mint a fresh one
|
|
29
|
+
*
|
|
30
|
+
* The shape check matters because this value becomes `$session_id`, and the
|
|
31
|
+
* derivation is deterministic so that two pods agree — which also means two
|
|
32
|
+
* *callers* sending the same string land in the same session. The strings agents
|
|
33
|
+
* invent are not random (`conv-1`, `1`, `session`), so trusting them verbatim
|
|
34
|
+
* would silently merge unrelated conversations, potentially across users.
|
|
35
|
+
*
|
|
36
|
+
* A compliant agent echoes the uuidv7 we minted and is unaffected. Anything else
|
|
37
|
+
* is treated exactly as if the handle were absent: mint, and prompt back. Shape
|
|
38
|
+
* rather than a registry of issued ids, because a per-request server has no
|
|
39
|
+
* memory of what it minted.
|
|
40
|
+
*
|
|
41
|
+
* This narrows the problem, it does not prove provenance: a caller supplying a
|
|
42
|
+
* well-formed uuidv7 is trusted, so two that pick the *same* one still merge. That
|
|
43
|
+
* residue is far smaller than the case it replaces — an agent ignoring the
|
|
44
|
+
* parameter description reaches for `conv-1` or `1`, not a conforming uuidv7 — and
|
|
45
|
+
* closing it needs a signed handle, i.e. a secret shared by every pod. Worth doing
|
|
46
|
+
* if this ever anchors something security-bearing; `$session_id` is an analytics
|
|
47
|
+
* grouping key, so it does not today.
|
|
23
48
|
*/
|
|
24
|
-
export declare function resolveConversationId(enabled: boolean, args: unknown
|
|
49
|
+
export declare function resolveConversationId(enabled: boolean, args: unknown): ConversationIdResolution;
|
|
25
50
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
51
|
+
* Whether the prompt-back can ride this result's `content`. The only requirement
|
|
52
|
+
* is an array to append to.
|
|
53
|
+
*
|
|
54
|
+
* Errored results included on purpose. A tool that fails on the first call of a
|
|
55
|
+
* conversation is exactly when the agent needs the session handle: without it the
|
|
56
|
+
* retry starts a fresh conversation, so the failure and its fix land in different
|
|
57
|
+
* sessions.
|
|
29
58
|
*/
|
|
30
59
|
export declare function canInjectConversationIdPromptBack(result: unknown): boolean;
|
|
31
60
|
export declare function extractConversationId(args: unknown): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-id.d.ts","sourceRoot":"","sources":["../../src/extensions/conversation-id.ts"],"names":[],"mappings":"AAMA,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"conversation-id.d.ts","sourceRoot":"","sources":["../../src/extensions/conversation-id.ts"],"names":[],"mappings":"AAMA,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAE7C,eAAO,MAAM,0BAA0B,oBAAoB,CAAA;AAE3D,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,6BAA6B,CAAA;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,SAAS,4BAA4B,EAChF,IAAI,EAAE,KAAK,EACX,MAAM,GAAE,QAAc,GACrB,KAAK,CA4CP;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,SAAS,4BAA4B,EACjF,KAAK,EAAE,KAAK,EAAE,EACd,MAAM,GAAE,QAAc,GACrB,KAAK,EAAE,CAET;AAQD,MAAM,MAAM,wBAAwB,GAChC;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,wBAAwB,CAa/F;AAED;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAK1E;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAUvE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAM1D;AAED,wBAAgB,6BAA6B,CAAC,cAAc,EAAE,MAAM,GAAG;IACrE,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAKA;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAS/F"}
|
|
@@ -38,7 +38,6 @@ const core_namespaceObject = require("@posthog/core");
|
|
|
38
38
|
const external_analytics_parameters_js_namespaceObject = require("./analytics-parameters.js");
|
|
39
39
|
const external_constants_js_namespaceObject = require("./constants.js");
|
|
40
40
|
const external_logger_js_namespaceObject = require("./logger.js");
|
|
41
|
-
const external_tools_js_namespaceObject = require("./tools.js");
|
|
42
41
|
const CONVERSATION_ID_PARAM_NAME = 'conversation_id';
|
|
43
42
|
function addConversationIdToTool(tool, logger = external_logger_js_namespaceObject.log) {
|
|
44
43
|
const modifiedTool = {
|
|
@@ -65,21 +64,19 @@ function addConversationIdToTool(tool, logger = external_logger_js_namespaceObje
|
|
|
65
64
|
};
|
|
66
65
|
return modifiedTool;
|
|
67
66
|
}
|
|
68
|
-
function addConversationIdToTools(tools,
|
|
69
|
-
return tools.map((tool)=>
|
|
70
|
-
if (skipMissingCapabilityTool && tool.name === missingCapabilityToolName) return tool;
|
|
71
|
-
return addConversationIdToTool(tool, logger);
|
|
72
|
-
});
|
|
67
|
+
function addConversationIdToTools(tools, logger = external_logger_js_namespaceObject.log) {
|
|
68
|
+
return tools.map((tool)=>addConversationIdToTool(tool, logger));
|
|
73
69
|
}
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
const MINTED_CONVERSATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
71
|
+
function resolveConversationId(enabled, args) {
|
|
72
|
+
if (!enabled) return {
|
|
76
73
|
minted: false,
|
|
77
74
|
conversationId: void 0
|
|
78
75
|
};
|
|
79
76
|
const supplied = extractConversationId(args);
|
|
80
|
-
if (supplied) return {
|
|
77
|
+
if (supplied && MINTED_CONVERSATION_ID.test(supplied)) return {
|
|
81
78
|
minted: false,
|
|
82
|
-
conversationId: supplied
|
|
79
|
+
conversationId: supplied.toLowerCase()
|
|
83
80
|
};
|
|
84
81
|
return {
|
|
85
82
|
minted: true,
|
|
@@ -88,9 +85,7 @@ function resolveConversationId(enabled, args, toolName, missingCapabilityToolNam
|
|
|
88
85
|
}
|
|
89
86
|
function canInjectConversationIdPromptBack(result) {
|
|
90
87
|
if (!(result && 'object' == typeof result)) return false;
|
|
91
|
-
|
|
92
|
-
if (true === resultObj.isError) return false;
|
|
93
|
-
return Array.isArray(resultObj.content);
|
|
88
|
+
return Array.isArray(result.content);
|
|
94
89
|
}
|
|
95
90
|
function extractConversationId(args) {
|
|
96
91
|
if (!(args && 'object' == typeof args)) return;
|
|
@@ -2,7 +2,6 @@ import { uuidv7 } from "@posthog/core";
|
|
|
2
2
|
import { canInjectAnalyticsParameter, hasAnalyticsParameter } from "./analytics-parameters.mjs";
|
|
3
3
|
import { DEFAULT_CONVERSATION_ID_DESCRIPTION } from "./constants.mjs";
|
|
4
4
|
import { log } from "./logger.mjs";
|
|
5
|
-
import { GET_MORE_TOOLS_NAME } from "./tools.mjs";
|
|
6
5
|
const CONVERSATION_ID_PARAM_NAME = 'conversation_id';
|
|
7
6
|
function addConversationIdToTool(tool, logger = log) {
|
|
8
7
|
const modifiedTool = {
|
|
@@ -29,21 +28,19 @@ function addConversationIdToTool(tool, logger = log) {
|
|
|
29
28
|
};
|
|
30
29
|
return modifiedTool;
|
|
31
30
|
}
|
|
32
|
-
function addConversationIdToTools(tools,
|
|
33
|
-
return tools.map((tool)=>
|
|
34
|
-
if (skipMissingCapabilityTool && tool.name === missingCapabilityToolName) return tool;
|
|
35
|
-
return addConversationIdToTool(tool, logger);
|
|
36
|
-
});
|
|
31
|
+
function addConversationIdToTools(tools, logger = log) {
|
|
32
|
+
return tools.map((tool)=>addConversationIdToTool(tool, logger));
|
|
37
33
|
}
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
const MINTED_CONVERSATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
35
|
+
function resolveConversationId(enabled, args) {
|
|
36
|
+
if (!enabled) return {
|
|
40
37
|
minted: false,
|
|
41
38
|
conversationId: void 0
|
|
42
39
|
};
|
|
43
40
|
const supplied = extractConversationId(args);
|
|
44
|
-
if (supplied) return {
|
|
41
|
+
if (supplied && MINTED_CONVERSATION_ID.test(supplied)) return {
|
|
45
42
|
minted: false,
|
|
46
|
-
conversationId: supplied
|
|
43
|
+
conversationId: supplied.toLowerCase()
|
|
47
44
|
};
|
|
48
45
|
return {
|
|
49
46
|
minted: true,
|
|
@@ -52,9 +49,7 @@ function resolveConversationId(enabled, args, toolName, missingCapabilityToolNam
|
|
|
52
49
|
}
|
|
53
50
|
function canInjectConversationIdPromptBack(result) {
|
|
54
51
|
if (!(result && 'object' == typeof result)) return false;
|
|
55
|
-
|
|
56
|
-
if (true === resultObj.isError) return false;
|
|
57
|
-
return Array.isArray(resultObj.content);
|
|
52
|
+
return Array.isArray(result.content);
|
|
58
53
|
}
|
|
59
54
|
function extractConversationId(args) {
|
|
60
55
|
if (!(args && 'object' == typeof args)) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-highlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-highlevel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,sBAAsB,EAIvB,MAAM,UAAU,CAAA;AASjB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"instrument-highlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-highlevel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,sBAAsB,EAIvB,MAAM,UAAU,CAAA;AASjB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAgQxC,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CA2BhG"}
|
|
@@ -177,7 +177,7 @@ async function handleToolCallRequest(highLevelServer, server, originalCallToolHa
|
|
|
177
177
|
request,
|
|
178
178
|
extra,
|
|
179
179
|
execute: (downstreamRequest)=>originalCallToolHandler(downstreamRequest, extra),
|
|
180
|
-
parameterOwnership: registeredTool ? (0, external_analytics_parameters_js_namespaceObject.getAnalyticsParameterOwnership)(registeredTool.inputSchema) : void 0,
|
|
180
|
+
parameterOwnership: registeredTool ? (0, external_analytics_parameters_js_namespaceObject.getAnalyticsParameterOwnership)(registeredTool.inputSchema, registeredTool.outputSchema) : void 0,
|
|
181
181
|
takeCapturedError: ()=>{
|
|
182
182
|
const captured = extra?.__mcp_analytics_error;
|
|
183
183
|
if (extra) extra.__mcp_analytics_error = void 0;
|
|
@@ -149,7 +149,7 @@ async function handleToolCallRequest(highLevelServer, server, originalCallToolHa
|
|
|
149
149
|
request,
|
|
150
150
|
extra,
|
|
151
151
|
execute: (downstreamRequest)=>originalCallToolHandler(downstreamRequest, extra),
|
|
152
|
-
parameterOwnership: registeredTool ? getAnalyticsParameterOwnership(registeredTool.inputSchema) : void 0,
|
|
152
|
+
parameterOwnership: registeredTool ? getAnalyticsParameterOwnership(registeredTool.inputSchema, registeredTool.outputSchema) : void 0,
|
|
153
153
|
takeCapturedError: ()=>{
|
|
154
154
|
const captured = extra?.__mcp_analytics_error;
|
|
155
155
|
if (extra) extra.__mcp_analytics_error = void 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,EACV,2BAA2B,EAC3B,6BAA6B,EAC7B,gBAAgB,EAChB,cAAc,EACd,aAAa,
|
|
1
|
+
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,EACV,2BAA2B,EAC3B,6BAA6B,EAC7B,gBAAgB,EAChB,cAAc,EACd,aAAa,EAId,MAAM,UAAU,CAAA;AAajB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAIrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAQxC;;;;;;GAMG;AAEH,KAAK,iBAAiB,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,6BAA6B,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE7G,2EAA2E;AAC3E,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE3E,UAAU,mBAAmB;IAC3B,MAAM,EAAE,aAAa,CAAA;IACrB,IAAI,EAAE,gBAAgB,CAAA;IACtB,OAAO,EAAE,cAAc,CAAA;IACvB,KAAK,CAAC,EAAE,6BAA6B,CAAA;IACrC,OAAO,EAAE,YAAY,CAAA;IACrB,2FAA2F;IAC3F,kBAAkB,CAAC,EAAE,2BAA2B,CAAA;IAChD;;;;OAIG;IACH,SAAS,CAAC,EAAE,qBAAqB,CAAA;IACjC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAA;CAClC;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmDnF;AAqND;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,MAAM,EAAE,aAAa,EACrB,eAAe,EAAE,iBAAiB,EAClC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,6BAA6B,GAAG,SAAS,KAC7C,OAAO,CAAC,OAAO,CAAC,CAAA;AAwBrB,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CA8BvG;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,6BAA6B,GAAG,SAAS,EAChD,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAoB9B;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,aAAa,EACrB,wBAAwB,EAAE,iBAAiB,EAC3C,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,6BAA6B,GAAG,SAAS,EAChD,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAqD9C;AAqFD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CASnH;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGtE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAUjH;AA+GD;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,aAAa,EACrB,yBAAyB,EAAE,iBAAiB,EAC5C,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,6BAA6B,GAAG,SAAS,EAChD,MAAM,EAAE,QAAQ,GACf,OAAO,CAAC,OAAO,CAAC,CA2DlB"}
|
|
@@ -37,6 +37,7 @@ const external_analytics_parameters_js_namespaceObject = require("./analytics-pa
|
|
|
37
37
|
const external_context_parameters_js_namespaceObject = require("./context-parameters.js");
|
|
38
38
|
const external_conversation_id_js_namespaceObject = require("./conversation-id.js");
|
|
39
39
|
const external_client_identity_js_namespaceObject = require("./client-identity.js");
|
|
40
|
+
const external_output_instructions_js_namespaceObject = require("./output-instructions.js");
|
|
40
41
|
const external_capture_js_namespaceObject = require("./capture.js");
|
|
41
42
|
const external_event_types_js_namespaceObject = require("./event-types.js");
|
|
42
43
|
const external_exceptions_js_namespaceObject = require("./exceptions.js");
|
|
@@ -52,27 +53,29 @@ async function captureToolCall(params) {
|
|
|
52
53
|
const { server, data, request, extra, execute, parameterOwnership, eventType, explicitContextIntent, takeCapturedError } = params;
|
|
53
54
|
const resolvedEventType = eventType ?? external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpToolsCall;
|
|
54
55
|
const ownership = getActiveAnalyticsParameterOwnership(data, request.params?.name, parameterOwnership, resolvedEventType === external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpMissingCapability);
|
|
55
|
-
const conversation = (0, external_conversation_id_js_namespaceObject.resolveConversationId)(ownership.conversationId, request.params?.arguments
|
|
56
|
+
const conversation = (0, external_conversation_id_js_namespaceObject.resolveConversationId)(ownership.conversationId, request.params?.arguments);
|
|
56
57
|
const downstreamRequest = cloneRequestWithoutOwnedAnalyticsArguments(request, ownership);
|
|
57
58
|
const startTime = new Date();
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
59
|
+
const preparedEvent = await prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, resolvedEventType);
|
|
60
|
+
if (preparedEvent && explicitContextIntent) (0, external_intent_js_namespaceObject.setExplicitContextIntent)(preparedEvent.event, explicitContextIntent);
|
|
60
61
|
let result;
|
|
61
62
|
try {
|
|
62
63
|
result = await execute(downstreamRequest);
|
|
63
64
|
} catch (error) {
|
|
64
|
-
publishFailedToolEvent(server,
|
|
65
|
+
publishFailedToolEvent(server, preparedEvent, error, startTime, conversation, data.logger);
|
|
65
66
|
throw error;
|
|
66
67
|
}
|
|
67
|
-
const finalResult =
|
|
68
|
-
publishSuccessfulToolEvent(server,
|
|
68
|
+
const finalResult = applyConversationInstructions(preparedEvent?.event ?? null, result, conversation, ownership);
|
|
69
|
+
publishSuccessfulToolEvent(server, preparedEvent, finalResult, startTime, data.logger, takeCapturedError);
|
|
69
70
|
return finalResult;
|
|
70
71
|
}
|
|
71
72
|
function getActiveAnalyticsParameterOwnership(data, toolName, override, isMissingCapabilityTool) {
|
|
72
|
-
const
|
|
73
|
+
const listed = toolName ? data.toolAnalyticsParameterOwnership.get(toolName) : void 0;
|
|
74
|
+
const ownership = override ?? listed;
|
|
73
75
|
return {
|
|
74
76
|
context: !isMissingCapabilityTool && (0, external_context_parameters_js_namespaceObject.isContextEnabled)(data.options.context) && ownership?.context === true,
|
|
75
|
-
conversationId:
|
|
77
|
+
conversationId: true === data.options.enableConversationId && ownership?.conversationId === true,
|
|
78
|
+
outputInstructions: true === data.options.enableConversationId && listed?.outputInstructions === true
|
|
76
79
|
};
|
|
77
80
|
}
|
|
78
81
|
function cloneRequestWithoutOwnedAnalyticsArguments(request, ownership) {
|
|
@@ -89,8 +92,10 @@ function cloneRequestWithoutOwnedAnalyticsArguments(request, ownership) {
|
|
|
89
92
|
}
|
|
90
93
|
async function prepareToolCallEvent(server, data, request, downstreamRequest, extra, startTime, conversation, ownership, eventType) {
|
|
91
94
|
try {
|
|
92
|
-
const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
|
|
93
|
-
|
|
95
|
+
const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra, conversation.conversationId);
|
|
96
|
+
const sessionInfo = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, sessionId);
|
|
97
|
+
const identity = await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, sessionInfo, extra, !!conversation.conversationId);
|
|
98
|
+
const requestAttribution = (0, external_internal_js_namespaceObject.withIdentity)(sessionInfo, identity);
|
|
94
99
|
const toolName = request.params?.name;
|
|
95
100
|
const event = {
|
|
96
101
|
sessionId,
|
|
@@ -105,20 +110,35 @@ async function prepareToolCallEvent(server, data, request, downstreamRequest, ex
|
|
|
105
110
|
(0, external_client_identity_js_namespaceObject.stampMetaClientInfo)(event, request);
|
|
106
111
|
await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
|
|
107
112
|
(0, external_intent_js_namespaceObject.setEventIntent)(event, await (0, external_intent_js_namespaceObject.resolveToolCallIntent)(data, request, ownership.context, extra));
|
|
108
|
-
return
|
|
113
|
+
return {
|
|
114
|
+
event,
|
|
115
|
+
requestAttribution
|
|
116
|
+
};
|
|
109
117
|
} catch (error) {
|
|
110
118
|
data.logger(`Warning: PostHog MCP analytics instrumentation failed for tool ${request.params?.name}, the tool will still run - ${error}`);
|
|
111
119
|
return null;
|
|
112
120
|
}
|
|
113
121
|
}
|
|
114
|
-
function
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
122
|
+
function applyConversationInstructions(event, result, conversation, ownership) {
|
|
123
|
+
const conversationId = conversation.conversationId;
|
|
124
|
+
if (!conversationId) return result;
|
|
125
|
+
let updated = result;
|
|
126
|
+
let delivered = false;
|
|
127
|
+
if (ownership.outputInstructions) {
|
|
128
|
+
const mirrored = (0, external_output_instructions_js_namespaceObject.mirrorInstructionsIntoStructuredContent)(updated, conversationId);
|
|
129
|
+
delivered = mirrored !== updated;
|
|
130
|
+
updated = mirrored;
|
|
131
|
+
}
|
|
132
|
+
if (conversation.minted && (0, external_conversation_id_js_namespaceObject.canInjectConversationIdPromptBack)(updated)) {
|
|
133
|
+
updated = (0, external_conversation_id_js_namespaceObject.injectConversationIdPromptBack)(updated, conversationId);
|
|
134
|
+
delivered = true;
|
|
135
|
+
}
|
|
136
|
+
if (!delivered && conversation.minted && event) event.conversationId = void 0;
|
|
137
|
+
return updated;
|
|
119
138
|
}
|
|
120
|
-
function publishSuccessfulToolEvent(server,
|
|
121
|
-
if (!
|
|
139
|
+
function publishSuccessfulToolEvent(server, preparedEvent, result, startTime, logger, takeCapturedError) {
|
|
140
|
+
if (!preparedEvent) return;
|
|
141
|
+
const { event, requestAttribution } = preparedEvent;
|
|
122
142
|
try {
|
|
123
143
|
if ((0, external_tracing_helpers_js_namespaceObject.isToolResultError)(result)) {
|
|
124
144
|
event.isError = true;
|
|
@@ -127,19 +147,20 @@ function publishSuccessfulToolEvent(server, event, result, startTime, logger, ta
|
|
|
127
147
|
} else event.isError = false;
|
|
128
148
|
event.response = result;
|
|
129
149
|
event.duration = Date.now() - startTime.getTime();
|
|
130
|
-
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger);
|
|
150
|
+
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger, requestAttribution);
|
|
131
151
|
} catch (error) {
|
|
132
152
|
logger(`Warning: PostHog MCP analytics failed to publish tool event - ${error}`);
|
|
133
153
|
}
|
|
134
154
|
}
|
|
135
|
-
function publishFailedToolEvent(server,
|
|
136
|
-
if (!
|
|
155
|
+
function publishFailedToolEvent(server, preparedEvent, error, startTime, conversation, logger) {
|
|
156
|
+
if (!preparedEvent) return;
|
|
157
|
+
const { event, requestAttribution } = preparedEvent;
|
|
137
158
|
try {
|
|
138
159
|
if (conversation.minted) event.conversationId = void 0;
|
|
139
160
|
event.isError = true;
|
|
140
161
|
event.error = (0, external_exceptions_js_namespaceObject.captureException)(error);
|
|
141
162
|
event.duration = Date.now() - startTime.getTime();
|
|
142
|
-
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger);
|
|
163
|
+
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger, requestAttribution);
|
|
143
164
|
} catch (publishError) {
|
|
144
165
|
logger(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`);
|
|
145
166
|
}
|
|
@@ -194,15 +215,17 @@ async function isToolAdvertised(server, toolName, extra, logger) {
|
|
|
194
215
|
async function handleListToolsRequest(server, originalListToolsHandler, request, extra, logger) {
|
|
195
216
|
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
|
|
196
217
|
const startTime = new Date();
|
|
218
|
+
const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
|
|
219
|
+
const requestAttribution = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, sessionId);
|
|
197
220
|
const event = {
|
|
198
|
-
sessionId
|
|
221
|
+
sessionId,
|
|
199
222
|
parameters: (0, external_mcp_payloads_js_namespaceObject.buildCapturedMcpParameters)(request),
|
|
200
223
|
eventType: external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpToolsList,
|
|
201
224
|
timestamp: startTime
|
|
202
225
|
};
|
|
203
226
|
(0, external_client_identity_js_namespaceObject.stampMetaClientInfo)(event, request);
|
|
204
227
|
if (data) await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
|
|
205
|
-
const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger);
|
|
228
|
+
const tools = await getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger, requestAttribution);
|
|
206
229
|
if (!data) {
|
|
207
230
|
logger('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');
|
|
208
231
|
return {
|
|
@@ -214,7 +237,7 @@ async function handleListToolsRequest(server, originalListToolsHandler, request,
|
|
|
214
237
|
event.error = (0, external_exceptions_js_namespaceObject.captureException)('No tools were sent to MCP client.');
|
|
215
238
|
event.isError = true;
|
|
216
239
|
event.duration = Date.now() - startTime.getTime();
|
|
217
|
-
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger);
|
|
240
|
+
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger, requestAttribution);
|
|
218
241
|
return {
|
|
219
242
|
tools
|
|
220
243
|
};
|
|
@@ -225,20 +248,20 @@ async function handleListToolsRequest(server, originalListToolsHandler, request,
|
|
|
225
248
|
event.listedToolNames = collectListedToolNames(tools);
|
|
226
249
|
event.isError = false;
|
|
227
250
|
event.duration = Date.now() - startTime.getTime();
|
|
228
|
-
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger);
|
|
251
|
+
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger, requestAttribution);
|
|
229
252
|
return {
|
|
230
253
|
tools
|
|
231
254
|
};
|
|
232
255
|
}
|
|
233
256
|
function cacheToolAnalyticsParameterOwnership(cache, tools) {
|
|
234
|
-
for (const tool of tools)if (tool?.name) cache.set(tool.name, (0, external_analytics_parameters_js_namespaceObject.getAnalyticsParameterOwnership)(tool.inputSchema));
|
|
257
|
+
for (const tool of tools)if (tool?.name) cache.set(tool.name, (0, external_analytics_parameters_js_namespaceObject.getAnalyticsParameterOwnership)(tool.inputSchema, tool.outputSchema));
|
|
235
258
|
}
|
|
236
259
|
function collectListedToolNames(tools) {
|
|
237
260
|
if (!tools || 0 === tools.length) return;
|
|
238
261
|
const names = tools.map((tool)=>tool?.name).filter((name)=>'string' == typeof name);
|
|
239
262
|
return names.length > 0 ? names : void 0;
|
|
240
263
|
}
|
|
241
|
-
async function getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger) {
|
|
264
|
+
async function getTracedToolsList(server, originalListToolsHandler, request, extra, event, logger, requestAttribution) {
|
|
242
265
|
try {
|
|
243
266
|
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
|
|
244
267
|
const originalResponse = await originalListToolsHandler(request, extra);
|
|
@@ -249,16 +272,21 @@ async function getTracedToolsList(server, originalListToolsHandler, request, ext
|
|
|
249
272
|
if (data && (0, external_context_parameters_js_namespaceObject.isContextEnabled)(data.options.context)) tools = (0, external_context_parameters_js_namespaceObject.addContextParameterToTools)(tools, (0, external_context_parameters_js_namespaceObject.getContextDescription)(data.options.context), data.logger);
|
|
250
273
|
if (data) {
|
|
251
274
|
const missingToolName = (0, external_tools_js_namespaceObject.resolveMissingCapabilityToolName)(data.options);
|
|
252
|
-
let injectedMissingCapabilityTool = false;
|
|
253
275
|
if (data.options.reportMissing) {
|
|
254
276
|
const alreadyPresent = tools.some((tool)=>tool?.name === missingToolName);
|
|
255
277
|
if (alreadyPresent) data.logger(`Warning: Cannot inject missing-capability tool "${missingToolName}" because a real tool already uses that name. The real tool will not be intercepted.`);
|
|
256
278
|
else {
|
|
257
|
-
|
|
258
|
-
|
|
279
|
+
const virtualTool = (0, external_tools_js_namespaceObject.getReportMissingToolDescriptor)(missingToolName);
|
|
280
|
+
tools.push(virtualTool);
|
|
281
|
+
cacheToolAnalyticsParameterOwnership(data.toolAnalyticsParameterOwnership, [
|
|
282
|
+
virtualTool
|
|
283
|
+
]);
|
|
259
284
|
}
|
|
260
285
|
}
|
|
261
|
-
if (data.options.enableConversationId)
|
|
286
|
+
if (data.options.enableConversationId) {
|
|
287
|
+
tools = (0, external_conversation_id_js_namespaceObject.addConversationIdToTools)(tools, data.logger);
|
|
288
|
+
tools = (0, external_output_instructions_js_namespaceObject.addInstructionsToOutputSchemas)(tools, data.logger);
|
|
289
|
+
}
|
|
262
290
|
}
|
|
263
291
|
if (data) {
|
|
264
292
|
cacheToolDescriptions(data.toolDescriptions, tools);
|
|
@@ -270,7 +298,7 @@ async function getTracedToolsList(server, originalListToolsHandler, request, ext
|
|
|
270
298
|
event.error = (0, external_exceptions_js_namespaceObject.captureException)(error);
|
|
271
299
|
event.isError = true;
|
|
272
300
|
event.duration = event.timestamp ? Date.now() - event.timestamp.getTime() : 0;
|
|
273
|
-
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger);
|
|
301
|
+
(0, external_capture_js_namespaceObject.captureEvent)(server, event, logger, requestAttribution);
|
|
274
302
|
throw error;
|
|
275
303
|
}
|
|
276
304
|
}
|
|
@@ -319,19 +347,19 @@ function mintStatelessSessionOnInitialize(server, data, request, extra) {
|
|
|
319
347
|
return;
|
|
320
348
|
}
|
|
321
349
|
}
|
|
322
|
-
function upgradeMintedTokenToNegotiated(server,
|
|
350
|
+
function upgradeMintedTokenToNegotiated(server, mintedSessionId, sessionInfo, negotiatedProtocolVersion, logger) {
|
|
323
351
|
try {
|
|
324
352
|
const transport = server.transport;
|
|
325
353
|
if (!transport) return;
|
|
326
354
|
const token = (0, external_session_token_js_namespaceObject.encodeSessionId)({
|
|
327
355
|
sessionId: mintedSessionId,
|
|
328
|
-
clientName:
|
|
329
|
-
clientVersion:
|
|
356
|
+
clientName: sessionInfo.clientName,
|
|
357
|
+
clientVersion: sessionInfo.clientVersion,
|
|
330
358
|
protocolVersion: negotiatedProtocolVersion
|
|
331
359
|
});
|
|
332
360
|
(0, external_session_token_js_namespaceObject.writeSessionIdToTransport)(transport, token);
|
|
333
361
|
} catch (error) {
|
|
334
|
-
|
|
362
|
+
logger(`Warning: PostHog MCP analytics failed to upgrade the stateless session token - ${error}`);
|
|
335
363
|
}
|
|
336
364
|
}
|
|
337
365
|
function readInitializeClientInfo(request) {
|
|
@@ -351,7 +379,15 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
|
|
|
351
379
|
}
|
|
352
380
|
const mintedSessionId = mintStatelessSessionOnInitialize(server, data, request, extra);
|
|
353
381
|
const sessionId = (0, external_session_js_namespaceObject.getSessionId)(server, extra);
|
|
354
|
-
|
|
382
|
+
const sessionInfo = (0, external_session_js_namespaceObject.getSessionInfo)(server, data, sessionId);
|
|
383
|
+
const initializeClientInfo = readInitializeClientInfo(request);
|
|
384
|
+
const requestSessionInfo = {
|
|
385
|
+
...sessionInfo,
|
|
386
|
+
clientName: initializeClientInfo?.name ?? sessionInfo.clientName,
|
|
387
|
+
clientVersion: initializeClientInfo?.version ?? sessionInfo.clientVersion
|
|
388
|
+
};
|
|
389
|
+
const identity = await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, requestSessionInfo, extra);
|
|
390
|
+
const requestAttribution = (0, external_internal_js_namespaceObject.withIdentity)(requestSessionInfo, identity);
|
|
355
391
|
const event = {
|
|
356
392
|
sessionId,
|
|
357
393
|
resourceName: request.params?.name || 'Unknown Tool Name',
|
|
@@ -365,10 +401,18 @@ async function handleInitializeRequest(server, originalInitializeHandler, reques
|
|
|
365
401
|
event.response = result;
|
|
366
402
|
const negotiatedProtocolVersion = readProtocolVersion(result, request);
|
|
367
403
|
event.protocolVersion = negotiatedProtocolVersion;
|
|
368
|
-
data.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
404
|
+
if (data.sessionId === sessionId) {
|
|
405
|
+
data.sessionInfo = {
|
|
406
|
+
...data.sessionInfo,
|
|
407
|
+
protocolVersion: negotiatedProtocolVersion
|
|
408
|
+
};
|
|
409
|
+
(0, external_internal_js_namespaceObject.setServerTrackingData)(server, data);
|
|
410
|
+
}
|
|
411
|
+
if (mintedSessionId) upgradeMintedTokenToNegotiated(server, mintedSessionId, requestSessionInfo, negotiatedProtocolVersion, data.logger);
|
|
412
|
+
(0, external_capture_js_namespaceObject.captureEvent)(server, event, data.logger, {
|
|
413
|
+
...requestAttribution,
|
|
414
|
+
protocolVersion: negotiatedProtocolVersion
|
|
415
|
+
});
|
|
372
416
|
return result;
|
|
373
417
|
}
|
|
374
418
|
function readProtocolVersion(result, request) {
|