@posthog/mcp 0.10.1 → 0.10.3
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 +12 -0
- package/dist/extensions/analytics-parameters.d.ts.map +1 -0
- package/dist/extensions/analytics-parameters.js +44 -0
- package/dist/extensions/analytics-parameters.mjs +7 -0
- package/dist/extensions/context-parameters.d.ts +2 -11
- package/dist/extensions/context-parameters.d.ts.map +1 -1
- package/dist/extensions/context-parameters.js +4 -6
- package/dist/extensions/context-parameters.mjs +3 -6
- package/dist/extensions/conversation-id.d.ts +2 -11
- package/dist/extensions/conversation-id.d.ts.map +1 -1
- package/dist/extensions/conversation-id.js +4 -6
- package/dist/extensions/conversation-id.mjs +3 -6
- package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-highlevel.js +34 -12
- package/dist/extensions/instrument-highlevel.mjs +35 -13
- package/dist/extensions/mcp-payloads.d.ts.map +1 -1
- package/dist/extensions/mcp-payloads.js +17 -1
- package/dist/extensions/mcp-payloads.mjs +17 -1
- package/dist/extensions/mcp-sdk-compat.d.ts +1 -0
- package/dist/extensions/mcp-sdk-compat.d.ts.map +1 -1
- package/dist/extensions/mcp-sdk-compat.js +11 -2
- package/dist/extensions/mcp-sdk-compat.mjs +7 -1
- package/dist/extensions/sanitization.d.ts.map +1 -1
- package/dist/extensions/sanitization.js +11 -0
- package/dist/extensions/sanitization.mjs +11 -0
- 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/analytics-parameters.ts +23 -0
- package/src/extensions/context-parameters.ts +15 -23
- package/src/extensions/conversation-id.ts +18 -24
- package/src/extensions/instrument-highlevel.ts +65 -16
- package/src/extensions/mcp-payloads.ts +28 -2
- package/src/extensions/mcp-sdk-compat.ts +15 -0
- package/src/extensions/sanitization.ts +23 -1
- package/src/version.ts +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface AnalyticsInjectableJsonSchema {
|
|
2
|
+
additionalProperties?: boolean;
|
|
3
|
+
allOf?: unknown;
|
|
4
|
+
anyOf?: unknown;
|
|
5
|
+
oneOf?: unknown;
|
|
6
|
+
properties?: Record<string, unknown>;
|
|
7
|
+
required?: string[];
|
|
8
|
+
type?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function hasAnalyticsParameter(schema: AnalyticsInjectableJsonSchema | undefined, parameterName: string): boolean;
|
|
11
|
+
export declare function canInjectAnalyticsParameter(schema: AnalyticsInjectableJsonSchema | undefined, parameterName: string): boolean;
|
|
12
|
+
//# sourceMappingURL=analytics-parameters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-parameters.d.ts","sourceRoot":"","sources":["../../src/extensions/analytics-parameters.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,6BAA6B;IAC5C,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,CAET"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
canInjectAnalyticsParameter: ()=>canInjectAnalyticsParameter,
|
|
28
|
+
hasAnalyticsParameter: ()=>hasAnalyticsParameter
|
|
29
|
+
});
|
|
30
|
+
function hasAnalyticsParameter(schema, parameterName) {
|
|
31
|
+
return !!schema?.properties && Object.prototype.hasOwnProperty.call(schema.properties, parameterName);
|
|
32
|
+
}
|
|
33
|
+
function canInjectAnalyticsParameter(schema, parameterName) {
|
|
34
|
+
return !hasAnalyticsParameter(schema, parameterName) && !schema?.oneOf && !schema?.allOf && !schema?.anyOf;
|
|
35
|
+
}
|
|
36
|
+
exports.canInjectAnalyticsParameter = __webpack_exports__.canInjectAnalyticsParameter;
|
|
37
|
+
exports.hasAnalyticsParameter = __webpack_exports__.hasAnalyticsParameter;
|
|
38
|
+
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
39
|
+
"canInjectAnalyticsParameter",
|
|
40
|
+
"hasAnalyticsParameter"
|
|
41
|
+
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
42
|
+
Object.defineProperty(exports, '__esModule', {
|
|
43
|
+
value: true
|
|
44
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
function hasAnalyticsParameter(schema, parameterName) {
|
|
2
|
+
return !!schema?.properties && Object.prototype.hasOwnProperty.call(schema.properties, parameterName);
|
|
3
|
+
}
|
|
4
|
+
function canInjectAnalyticsParameter(schema, parameterName) {
|
|
5
|
+
return !hasAnalyticsParameter(schema, parameterName) && !schema?.oneOf && !schema?.allOf && !schema?.anyOf;
|
|
6
|
+
}
|
|
7
|
+
export { canInjectAnalyticsParameter, hasAnalyticsParameter };
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import type { MCPAnalyticsOptions } from '../types';
|
|
2
|
-
|
|
3
|
-
additionalProperties?: boolean;
|
|
4
|
-
allOf?: unknown;
|
|
5
|
-
anyOf?: unknown;
|
|
6
|
-
oneOf?: unknown;
|
|
7
|
-
properties?: Record<string, unknown>;
|
|
8
|
-
required?: string[];
|
|
9
|
-
type?: string;
|
|
10
|
-
}
|
|
2
|
+
import { type AnalyticsInjectableJsonSchema } from './analytics-parameters';
|
|
11
3
|
export interface ContextInjectableTool {
|
|
12
|
-
inputSchema?:
|
|
4
|
+
inputSchema?: AnalyticsInjectableJsonSchema;
|
|
13
5
|
name?: string;
|
|
14
6
|
[key: string]: unknown;
|
|
15
7
|
}
|
|
@@ -27,5 +19,4 @@ export declare function getContextDescription(context: MCPAnalyticsOptions['cont
|
|
|
27
19
|
*/
|
|
28
20
|
export declare function addContextParameterToTool<TTool extends ContextInjectableTool>(tool: TTool, contextDescriptionOverride?: string): TTool;
|
|
29
21
|
export declare function addContextParameterToTools<TTool extends ContextInjectableTool>(tools: TTool[], contextDescriptionOverride?: string): TTool[];
|
|
30
|
-
export {};
|
|
31
22
|
//# sourceMappingURL=context-parameters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-parameters.d.ts","sourceRoot":"","sources":["../../src/extensions/context-parameters.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"context-parameters.d.ts","sourceRoot":"","sources":["../../src/extensions/context-parameters.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,wBAAwB,CAAA;AAI/B,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,6BAA6B,CAAA;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC,GAAG,OAAO,CAEjF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAEjG;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,SAAS,qBAAqB,EAC3E,IAAI,EAAE,KAAK,EACX,0BAA0B,CAAC,EAAE,MAAM,GAClC,KAAK,CA6DP;AAED,wBAAgB,0BAA0B,CAAC,KAAK,SAAS,qBAAqB,EAC5E,KAAK,EAAE,KAAK,EAAE,EACd,0BAA0B,CAAC,EAAE,MAAM,GAClC,KAAK,EAAE,CAQT"}
|
|
@@ -29,6 +29,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
29
29
|
getContextDescription: ()=>getContextDescription,
|
|
30
30
|
isContextEnabled: ()=>isContextEnabled
|
|
31
31
|
});
|
|
32
|
+
const external_analytics_parameters_js_namespaceObject = require("./analytics-parameters.js");
|
|
32
33
|
const external_constants_js_namespaceObject = require("./constants.js");
|
|
33
34
|
const external_logger_js_namespaceObject = require("./logger.js");
|
|
34
35
|
function isContextEnabled(context) {
|
|
@@ -43,12 +44,9 @@ function addContextParameterToTool(tool, contextDescriptionOverride) {
|
|
|
43
44
|
};
|
|
44
45
|
const toolName = tool.name || 'unknown';
|
|
45
46
|
const schema = modifiedTool.inputSchema;
|
|
46
|
-
if (schema
|
|
47
|
-
(0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" already has 'context' parameter. Skipping context injection.`);
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
if (schema?.oneOf || schema?.allOf || schema?.anyOf) {
|
|
51
|
-
(0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping context injection.`);
|
|
47
|
+
if (!(0, external_analytics_parameters_js_namespaceObject.canInjectAnalyticsParameter)(schema, 'context')) {
|
|
48
|
+
if ((0, external_analytics_parameters_js_namespaceObject.hasAnalyticsParameter)(schema, 'context')) (0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" already has 'context' parameter. Skipping context injection.`);
|
|
49
|
+
else (0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping context injection.`);
|
|
52
50
|
return modifiedTool;
|
|
53
51
|
}
|
|
54
52
|
if (!modifiedTool.inputSchema) modifiedTool.inputSchema = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { canInjectAnalyticsParameter, hasAnalyticsParameter } from "./analytics-parameters.mjs";
|
|
1
2
|
import { DEFAULT_CONTEXT_PARAMETER_DESCRIPTION } from "./constants.mjs";
|
|
2
3
|
import { log } from "./logger.mjs";
|
|
3
4
|
function isContextEnabled(context) {
|
|
@@ -12,12 +13,8 @@ function addContextParameterToTool(tool, contextDescriptionOverride) {
|
|
|
12
13
|
};
|
|
13
14
|
const toolName = tool.name || 'unknown';
|
|
14
15
|
const schema = modifiedTool.inputSchema;
|
|
15
|
-
if (schema
|
|
16
|
-
log(`WARN: Tool "${toolName}" already has 'context' parameter. Skipping context injection.`);
|
|
17
|
-
return modifiedTool;
|
|
18
|
-
}
|
|
19
|
-
if (schema?.oneOf || schema?.allOf || schema?.anyOf) {
|
|
20
|
-
log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping context injection.`);
|
|
16
|
+
if (!canInjectAnalyticsParameter(schema, 'context')) {
|
|
17
|
+
hasAnalyticsParameter(schema, 'context') ? log(`WARN: Tool "${toolName}" already has 'context' parameter. Skipping context injection.`) : log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping context injection.`);
|
|
21
18
|
return modifiedTool;
|
|
22
19
|
}
|
|
23
20
|
if (!modifiedTool.inputSchema) modifiedTool.inputSchema = {
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
+
import { type AnalyticsInjectableJsonSchema } from './analytics-parameters';
|
|
1
2
|
export declare const CONVERSATION_ID_PARAM_NAME = "conversation_id";
|
|
2
|
-
interface JsonSchema {
|
|
3
|
-
additionalProperties?: boolean;
|
|
4
|
-
allOf?: unknown;
|
|
5
|
-
anyOf?: unknown;
|
|
6
|
-
oneOf?: unknown;
|
|
7
|
-
properties?: Record<string, unknown>;
|
|
8
|
-
required?: string[];
|
|
9
|
-
type?: string;
|
|
10
|
-
}
|
|
11
3
|
export interface ConversationIdInjectableTool {
|
|
12
|
-
inputSchema?:
|
|
4
|
+
inputSchema?: AnalyticsInjectableJsonSchema;
|
|
13
5
|
name?: string;
|
|
14
6
|
[key: string]: unknown;
|
|
15
7
|
}
|
|
@@ -48,5 +40,4 @@ export declare function buildConversationIdPromptBack(conversationId: string): {
|
|
|
48
40
|
text: string;
|
|
49
41
|
};
|
|
50
42
|
export declare function injectConversationIdPromptBack(result: unknown, conversationId: string): unknown;
|
|
51
|
-
export {};
|
|
52
43
|
//# sourceMappingURL=conversation-id.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-id.d.ts","sourceRoot":"","sources":["../../src/extensions/conversation-id.ts"],"names":[],"mappings":"
|
|
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;AAK/B,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,EAAE,IAAI,EAAE,KAAK,GAAG,KAAK,CA0CtG;AAED,wBAAgB,wBAAwB,CAAC,KAAK,SAAS,4BAA4B,EACjF,KAAK,EAAE,KAAK,EAAE,EACd,yBAAyB,GAAE,MAA4B,GACtD,KAAK,EAAE,CAOT;AAED,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;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,yBAAyB,GAAE,MAA4B,GACtD,wBAAwB,CAS1B;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAS1E;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAUvE;AAED,wBAAgB,iCAAiC,CAC/C,QAAQ,SAAS;IAAE,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CAAE,EAC3E,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAe7B;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"}
|
|
@@ -36,6 +36,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
36
36
|
canInjectConversationIdPromptBack: ()=>canInjectConversationIdPromptBack
|
|
37
37
|
});
|
|
38
38
|
const core_namespaceObject = require("@posthog/core");
|
|
39
|
+
const external_analytics_parameters_js_namespaceObject = require("./analytics-parameters.js");
|
|
39
40
|
const external_constants_js_namespaceObject = require("./constants.js");
|
|
40
41
|
const external_logger_js_namespaceObject = require("./logger.js");
|
|
41
42
|
const external_tools_js_namespaceObject = require("./tools.js");
|
|
@@ -46,12 +47,9 @@ function addConversationIdToTool(tool) {
|
|
|
46
47
|
};
|
|
47
48
|
const toolName = tool.name || 'unknown';
|
|
48
49
|
const schema = modifiedTool.inputSchema;
|
|
49
|
-
if (schema
|
|
50
|
-
(0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`);
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
if (schema?.oneOf || schema?.allOf || schema?.anyOf) {
|
|
54
|
-
(0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`);
|
|
50
|
+
if (!(0, external_analytics_parameters_js_namespaceObject.canInjectAnalyticsParameter)(schema, CONVERSATION_ID_PARAM_NAME)) {
|
|
51
|
+
if ((0, external_analytics_parameters_js_namespaceObject.hasAnalyticsParameter)(schema, CONVERSATION_ID_PARAM_NAME)) (0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`);
|
|
52
|
+
else (0, external_logger_js_namespaceObject.log)(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`);
|
|
55
53
|
return modifiedTool;
|
|
56
54
|
}
|
|
57
55
|
if (!modifiedTool.inputSchema) modifiedTool.inputSchema = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { uuidv7 } from "@posthog/core";
|
|
2
|
+
import { canInjectAnalyticsParameter, hasAnalyticsParameter } from "./analytics-parameters.mjs";
|
|
2
3
|
import { DEFAULT_CONVERSATION_ID_DESCRIPTION } from "./constants.mjs";
|
|
3
4
|
import { log } from "./logger.mjs";
|
|
4
5
|
import { GET_MORE_TOOLS_NAME } from "./tools.mjs";
|
|
@@ -9,12 +10,8 @@ function addConversationIdToTool(tool) {
|
|
|
9
10
|
};
|
|
10
11
|
const toolName = tool.name || 'unknown';
|
|
11
12
|
const schema = modifiedTool.inputSchema;
|
|
12
|
-
if (schema
|
|
13
|
-
log(`WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`);
|
|
14
|
-
return modifiedTool;
|
|
15
|
-
}
|
|
16
|
-
if (schema?.oneOf || schema?.allOf || schema?.anyOf) {
|
|
17
|
-
log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`);
|
|
13
|
+
if (!canInjectAnalyticsParameter(schema, CONVERSATION_ID_PARAM_NAME)) {
|
|
14
|
+
hasAnalyticsParameter(schema, CONVERSATION_ID_PARAM_NAME) ? log(`WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`) : log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`);
|
|
18
15
|
return modifiedTool;
|
|
19
16
|
}
|
|
20
17
|
if (!modifiedTool.inputSchema) modifiedTool.inputSchema = {
|
|
@@ -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;
|
|
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;AAsSjB,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAwB9E"}
|
|
@@ -26,7 +26,9 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
27
|
instrumentHighLevelServer: ()=>instrumentHighLevelServer
|
|
28
28
|
});
|
|
29
|
+
const external_analytics_parameters_js_namespaceObject = require("./analytics-parameters.js");
|
|
29
30
|
const external_conversation_id_js_namespaceObject = require("./conversation-id.js");
|
|
31
|
+
const external_context_parameters_js_namespaceObject = require("./context-parameters.js");
|
|
30
32
|
const external_event_types_js_namespaceObject = require("./event-types.js");
|
|
31
33
|
const external_internal_js_namespaceObject = require("./internal.js");
|
|
32
34
|
const external_logger_js_namespaceObject = require("./logger.js");
|
|
@@ -39,6 +41,27 @@ const MCP_ANALYTICS_PROCESSED = Symbol('__posthog_mcp_analytics_processed__');
|
|
|
39
41
|
function isCallbackUpdate(value) {
|
|
40
42
|
return !!value && 'object' == typeof value && 'callback' in value && 'function' == typeof value.callback;
|
|
41
43
|
}
|
|
44
|
+
function analyticsOwnsParameter(inputSchema, parameterName) {
|
|
45
|
+
if (!inputSchema || 'object' != typeof inputSchema) return (0, external_analytics_parameters_js_namespaceObject.canInjectAnalyticsParameter)(void 0, parameterName);
|
|
46
|
+
if ((0, external_mcp_sdk_compat_js_namespaceObject.isZodRawShapeCompat)(inputSchema)) return (0, external_analytics_parameters_js_namespaceObject.canInjectAnalyticsParameter)({
|
|
47
|
+
properties: inputSchema
|
|
48
|
+
}, parameterName);
|
|
49
|
+
const shape = (0, external_mcp_sdk_compat_js_namespaceObject.getObjectShape)(inputSchema);
|
|
50
|
+
if (shape) return (0, external_analytics_parameters_js_namespaceObject.canInjectAnalyticsParameter)({
|
|
51
|
+
properties: shape
|
|
52
|
+
}, parameterName);
|
|
53
|
+
const schema = inputSchema;
|
|
54
|
+
if ('_def' in schema || '_zod' in schema || '~standard' in schema) return (0, external_analytics_parameters_js_namespaceObject.canInjectAnalyticsParameter)(void 0, parameterName);
|
|
55
|
+
return (0, external_analytics_parameters_js_namespaceObject.canInjectAnalyticsParameter)(schema, parameterName);
|
|
56
|
+
}
|
|
57
|
+
function stripOwnedAnalyticsArguments(args, ownership) {
|
|
58
|
+
let cleanedArgs = args;
|
|
59
|
+
if (ownership.context && cleanedArgs && 'object' == typeof cleanedArgs && 'context' in cleanedArgs) {
|
|
60
|
+
const { context: _context, ...rest } = cleanedArgs;
|
|
61
|
+
cleanedArgs = rest;
|
|
62
|
+
}
|
|
63
|
+
return ownership.conversationId ? (0, external_conversation_id_js_namespaceObject.stripConversationId)(cleanedArgs) : cleanedArgs;
|
|
64
|
+
}
|
|
42
65
|
function addTracingToToolRegistry(tools, server) {
|
|
43
66
|
return Object.fromEntries(Object.entries(tools).map(([name, tool])=>[
|
|
44
67
|
name,
|
|
@@ -62,7 +85,8 @@ function setupListenerToRegisteredTools(server) {
|
|
|
62
85
|
(0, external_logger_js_namespaceObject.log)(`Tool ${String(property)} callback already wrapped, skipping proxy wrapping`);
|
|
63
86
|
return Reflect.set(target, property, value);
|
|
64
87
|
}
|
|
65
|
-
const
|
|
88
|
+
const getCurrentInputSchema = ()=>value.inputSchema;
|
|
89
|
+
const nextValue = addTracingToToolCallbackInternal(value, property, server, getCurrentInputSchema);
|
|
66
90
|
if ('function' == typeof nextValue.update) {
|
|
67
91
|
const originalUpdate = nextValue.update;
|
|
68
92
|
nextValue.update = function(...updateArgs) {
|
|
@@ -71,7 +95,7 @@ function setupListenerToRegisteredTools(server) {
|
|
|
71
95
|
if (isCallbackUpdate(updateObj)) {
|
|
72
96
|
const wrappedTool = addTracingToToolCallbackInternal({
|
|
73
97
|
callback: updateObj.callback
|
|
74
|
-
}, property, server);
|
|
98
|
+
}, property, server, getCurrentInputSchema);
|
|
75
99
|
updateObj.callback = (0, external_mcp_sdk_compat_js_namespaceObject.getToolFunction)(wrappedTool);
|
|
76
100
|
}
|
|
77
101
|
}
|
|
@@ -103,9 +127,10 @@ function setupListenerToRegisteredTools(server) {
|
|
|
103
127
|
(0, external_logger_js_namespaceObject.log)(`Warning: Failed to setup listener for registered tools - ${error}`);
|
|
104
128
|
}
|
|
105
129
|
}
|
|
106
|
-
function addTracingToToolCallbackInternal(tool, toolName, server) {
|
|
130
|
+
function addTracingToToolCallbackInternal(tool, toolName, server, getCurrentInputSchema = ()=>tool.inputSchema) {
|
|
107
131
|
const originalCallback = (0, external_mcp_sdk_compat_js_namespaceObject.getToolFunction)(tool);
|
|
108
|
-
const
|
|
132
|
+
const options = (0, external_internal_js_namespaceObject.getServerTrackingData)(server.server)?.options;
|
|
133
|
+
const missingToolName = (0, external_tools_js_namespaceObject.resolveMissingCapabilityToolName)(options);
|
|
109
134
|
if (wrappedCallbacks.has(originalCallback)) {
|
|
110
135
|
(0, external_logger_js_namespaceObject.log)(`Tool ${toolName} callback already wrapped, skipping re-wrap`);
|
|
111
136
|
return tool;
|
|
@@ -124,14 +149,11 @@ function addTracingToToolCallbackInternal(tool, toolName, server) {
|
|
|
124
149
|
args = void 0;
|
|
125
150
|
extra = params[0];
|
|
126
151
|
}
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return input;
|
|
133
|
-
};
|
|
134
|
-
const cleanedArgs = toolName === missingToolName ? args : (0, external_conversation_id_js_namespaceObject.stripConversationId)(removeContextFromArgs(args));
|
|
152
|
+
const inputSchema = getCurrentInputSchema();
|
|
153
|
+
const cleanedArgs = stripOwnedAnalyticsArguments(args, {
|
|
154
|
+
context: toolName !== missingToolName && (0, external_context_parameters_js_namespaceObject.isContextEnabled)(options?.context) && analyticsOwnsParameter(inputSchema, 'context'),
|
|
155
|
+
conversationId: toolName !== missingToolName && options?.enableConversationId === true && analyticsOwnsParameter(inputSchema, 'conversation_id')
|
|
156
|
+
});
|
|
135
157
|
try {
|
|
136
158
|
if (void 0 === cleanedArgs) {
|
|
137
159
|
const handler = originalCallback;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { canInjectAnalyticsParameter } from "./analytics-parameters.mjs";
|
|
1
2
|
import { stripConversationId } from "./conversation-id.mjs";
|
|
3
|
+
import { isContextEnabled } from "./context-parameters.mjs";
|
|
2
4
|
import { MCPAnalyticsEventType } from "./event-types.mjs";
|
|
3
5
|
import { getServerTrackingData } from "./internal.mjs";
|
|
4
6
|
import { log } from "./logger.mjs";
|
|
5
|
-
import { createWrappedTool, getToolFunction, hasToolFunction } from "./mcp-sdk-compat.mjs";
|
|
7
|
+
import { createWrappedTool, getObjectShape, getToolFunction, hasToolFunction, isZodRawShapeCompat } from "./mcp-sdk-compat.mjs";
|
|
6
8
|
import { handleReportMissing, resolveMissingCapabilityToolName } from "./tools.mjs";
|
|
7
9
|
import { captureToolCall, handleInitializeRequest, handleListToolsRequest, patchRequestHandlers, readToolMetaCategory } from "./instrumentation.mjs";
|
|
8
10
|
import { getContextArgument } from "./tracing-helpers.mjs";
|
|
@@ -11,6 +13,27 @@ const MCP_ANALYTICS_PROCESSED = Symbol('__posthog_mcp_analytics_processed__');
|
|
|
11
13
|
function isCallbackUpdate(value) {
|
|
12
14
|
return !!value && 'object' == typeof value && 'callback' in value && 'function' == typeof value.callback;
|
|
13
15
|
}
|
|
16
|
+
function analyticsOwnsParameter(inputSchema, parameterName) {
|
|
17
|
+
if (!inputSchema || 'object' != typeof inputSchema) return canInjectAnalyticsParameter(void 0, parameterName);
|
|
18
|
+
if (isZodRawShapeCompat(inputSchema)) return canInjectAnalyticsParameter({
|
|
19
|
+
properties: inputSchema
|
|
20
|
+
}, parameterName);
|
|
21
|
+
const shape = getObjectShape(inputSchema);
|
|
22
|
+
if (shape) return canInjectAnalyticsParameter({
|
|
23
|
+
properties: shape
|
|
24
|
+
}, parameterName);
|
|
25
|
+
const schema = inputSchema;
|
|
26
|
+
if ('_def' in schema || '_zod' in schema || '~standard' in schema) return canInjectAnalyticsParameter(void 0, parameterName);
|
|
27
|
+
return canInjectAnalyticsParameter(schema, parameterName);
|
|
28
|
+
}
|
|
29
|
+
function stripOwnedAnalyticsArguments(args, ownership) {
|
|
30
|
+
let cleanedArgs = args;
|
|
31
|
+
if (ownership.context && cleanedArgs && 'object' == typeof cleanedArgs && 'context' in cleanedArgs) {
|
|
32
|
+
const { context: _context, ...rest } = cleanedArgs;
|
|
33
|
+
cleanedArgs = rest;
|
|
34
|
+
}
|
|
35
|
+
return ownership.conversationId ? stripConversationId(cleanedArgs) : cleanedArgs;
|
|
36
|
+
}
|
|
14
37
|
function addTracingToToolRegistry(tools, server) {
|
|
15
38
|
return Object.fromEntries(Object.entries(tools).map(([name, tool])=>[
|
|
16
39
|
name,
|
|
@@ -34,7 +57,8 @@ function setupListenerToRegisteredTools(server) {
|
|
|
34
57
|
log(`Tool ${String(property)} callback already wrapped, skipping proxy wrapping`);
|
|
35
58
|
return Reflect.set(target, property, value);
|
|
36
59
|
}
|
|
37
|
-
const
|
|
60
|
+
const getCurrentInputSchema = ()=>value.inputSchema;
|
|
61
|
+
const nextValue = addTracingToToolCallbackInternal(value, property, server, getCurrentInputSchema);
|
|
38
62
|
if ('function' == typeof nextValue.update) {
|
|
39
63
|
const originalUpdate = nextValue.update;
|
|
40
64
|
nextValue.update = function(...updateArgs) {
|
|
@@ -43,7 +67,7 @@ function setupListenerToRegisteredTools(server) {
|
|
|
43
67
|
if (isCallbackUpdate(updateObj)) {
|
|
44
68
|
const wrappedTool = addTracingToToolCallbackInternal({
|
|
45
69
|
callback: updateObj.callback
|
|
46
|
-
}, property, server);
|
|
70
|
+
}, property, server, getCurrentInputSchema);
|
|
47
71
|
updateObj.callback = getToolFunction(wrappedTool);
|
|
48
72
|
}
|
|
49
73
|
}
|
|
@@ -75,9 +99,10 @@ function setupListenerToRegisteredTools(server) {
|
|
|
75
99
|
log(`Warning: Failed to setup listener for registered tools - ${error}`);
|
|
76
100
|
}
|
|
77
101
|
}
|
|
78
|
-
function addTracingToToolCallbackInternal(tool, toolName, server) {
|
|
102
|
+
function addTracingToToolCallbackInternal(tool, toolName, server, getCurrentInputSchema = ()=>tool.inputSchema) {
|
|
79
103
|
const originalCallback = getToolFunction(tool);
|
|
80
|
-
const
|
|
104
|
+
const options = getServerTrackingData(server.server)?.options;
|
|
105
|
+
const missingToolName = resolveMissingCapabilityToolName(options);
|
|
81
106
|
if (wrappedCallbacks.has(originalCallback)) {
|
|
82
107
|
log(`Tool ${toolName} callback already wrapped, skipping re-wrap`);
|
|
83
108
|
return tool;
|
|
@@ -96,14 +121,11 @@ function addTracingToToolCallbackInternal(tool, toolName, server) {
|
|
|
96
121
|
args = void 0;
|
|
97
122
|
extra = params[0];
|
|
98
123
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return input;
|
|
105
|
-
};
|
|
106
|
-
const cleanedArgs = toolName === missingToolName ? args : stripConversationId(removeContextFromArgs(args));
|
|
124
|
+
const inputSchema = getCurrentInputSchema();
|
|
125
|
+
const cleanedArgs = stripOwnedAnalyticsArguments(args, {
|
|
126
|
+
context: toolName !== missingToolName && isContextEnabled(options?.context) && analyticsOwnsParameter(inputSchema, 'context'),
|
|
127
|
+
conversationId: toolName !== missingToolName && options?.enableConversationId === true && analyticsOwnsParameter(inputSchema, 'conversation_id')
|
|
128
|
+
});
|
|
107
129
|
try {
|
|
108
130
|
if (void 0 === cleanedArgs) {
|
|
109
131
|
const handler = originalCallback;
|
|
@@ -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":"AAkBA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAsCzC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA0B7D;AA6BD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAiBvE"}
|
|
@@ -29,7 +29,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
29
29
|
});
|
|
30
30
|
const CONTEXT_ARGUMENT_NAME = 'context';
|
|
31
31
|
const REDACTED_VALUE = '[redacted]';
|
|
32
|
+
const BINARY_REDACTED_VALUE = '[binary data redacted - not supported by PostHog MCP analytics]';
|
|
32
33
|
const BASE64_PATTERN = /^[A-Za-z0-9+/\n\r]+=*$/;
|
|
34
|
+
const BASE64URL_PATTERN = /^[A-Za-z0-9_-]+={0,2}$/;
|
|
35
|
+
const BASE64URL_SPECIFIC_CHAR_PATTERN = /[-_]/;
|
|
36
|
+
const BASE64_DATA_URL_PREFIX_PATTERN = /^data:[^,\s]*;base64,/i;
|
|
37
|
+
const BASE64_DATA_URL_PAYLOAD_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;
|
|
33
38
|
const SIZE_GATE = 10240;
|
|
34
39
|
const POSTHOG_TOKEN_PATTERN = /\bph[a-z]_[A-Za-z0-9_-]{20,}\b/g;
|
|
35
40
|
const SENSITIVE_KEY_PATTERN = /^(authorization|cookie|set-cookie|x-api-key|api[-_]?key|api[-_]?token|access[-_]?token|refresh[-_]?token|token|password|secret|client[-_]?secret|private[-_]?key)$/i;
|
|
@@ -39,8 +44,19 @@ function isRecord(value) {
|
|
|
39
44
|
function shouldRedactKey(key) {
|
|
40
45
|
return SENSITIVE_KEY_PATTERN.test(key);
|
|
41
46
|
}
|
|
47
|
+
function isBase64DataUrl(value) {
|
|
48
|
+
const prefix = BASE64_DATA_URL_PREFIX_PATTERN.exec(value);
|
|
49
|
+
if (!prefix) return false;
|
|
50
|
+
let payload;
|
|
51
|
+
try {
|
|
52
|
+
payload = decodeURIComponent(value.slice(prefix[0].length));
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return BASE64_DATA_URL_PAYLOAD_PATTERN.test(payload.replace(/[\r\n]/g, ''));
|
|
57
|
+
}
|
|
42
58
|
function sanitizeString(value) {
|
|
43
|
-
if (value.length >= SIZE_GATE && BASE64_PATTERN.test(value)
|
|
59
|
+
if (value.length >= SIZE_GATE && (BASE64_PATTERN.test(value) || isBase64DataUrl(value) || BASE64URL_SPECIFIC_CHAR_PATTERN.test(value) && BASE64URL_PATTERN.test(value))) return BINARY_REDACTED_VALUE;
|
|
44
60
|
return value.replace(POSTHOG_TOKEN_PATTERN, REDACTED_VALUE);
|
|
45
61
|
}
|
|
46
62
|
function sanitizeCapturedValue(value) {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
const CONTEXT_ARGUMENT_NAME = 'context';
|
|
2
2
|
const REDACTED_VALUE = '[redacted]';
|
|
3
|
+
const BINARY_REDACTED_VALUE = '[binary data redacted - not supported by PostHog MCP analytics]';
|
|
3
4
|
const BASE64_PATTERN = /^[A-Za-z0-9+/\n\r]+=*$/;
|
|
5
|
+
const BASE64URL_PATTERN = /^[A-Za-z0-9_-]+={0,2}$/;
|
|
6
|
+
const BASE64URL_SPECIFIC_CHAR_PATTERN = /[-_]/;
|
|
7
|
+
const BASE64_DATA_URL_PREFIX_PATTERN = /^data:[^,\s]*;base64,/i;
|
|
8
|
+
const BASE64_DATA_URL_PAYLOAD_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;
|
|
4
9
|
const SIZE_GATE = 10240;
|
|
5
10
|
const POSTHOG_TOKEN_PATTERN = /\bph[a-z]_[A-Za-z0-9_-]{20,}\b/g;
|
|
6
11
|
const SENSITIVE_KEY_PATTERN = /^(authorization|cookie|set-cookie|x-api-key|api[-_]?key|api[-_]?token|access[-_]?token|refresh[-_]?token|token|password|secret|client[-_]?secret|private[-_]?key)$/i;
|
|
@@ -10,8 +15,19 @@ function isRecord(value) {
|
|
|
10
15
|
function shouldRedactKey(key) {
|
|
11
16
|
return SENSITIVE_KEY_PATTERN.test(key);
|
|
12
17
|
}
|
|
18
|
+
function isBase64DataUrl(value) {
|
|
19
|
+
const prefix = BASE64_DATA_URL_PREFIX_PATTERN.exec(value);
|
|
20
|
+
if (!prefix) return false;
|
|
21
|
+
let payload;
|
|
22
|
+
try {
|
|
23
|
+
payload = decodeURIComponent(value.slice(prefix[0].length));
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return BASE64_DATA_URL_PAYLOAD_PATTERN.test(payload.replace(/[\r\n]/g, ''));
|
|
28
|
+
}
|
|
13
29
|
function sanitizeString(value) {
|
|
14
|
-
if (value.length >= SIZE_GATE && BASE64_PATTERN.test(value)
|
|
30
|
+
if (value.length >= SIZE_GATE && (BASE64_PATTERN.test(value) || isBase64DataUrl(value) || BASE64URL_SPECIFIC_CHAR_PATTERN.test(value) && BASE64URL_PATTERN.test(value))) return BINARY_REDACTED_VALUE;
|
|
15
31
|
return value.replace(POSTHOG_TOKEN_PATTERN, REDACTED_VALUE);
|
|
16
32
|
}
|
|
17
33
|
function sanitizeCapturedValue(value) {
|
|
@@ -28,6 +28,7 @@ export declare function hasToolFunction(tool: unknown): tool is RegisteredTool;
|
|
|
28
28
|
*/
|
|
29
29
|
export declare function createWrappedTool(originalTool: RegisteredTool, wrappedFunction: ToolCallback): RegisteredTool;
|
|
30
30
|
export declare function isZ4Schema(schema: unknown): boolean;
|
|
31
|
+
export declare function isZodRawShapeCompat(schema: unknown): schema is Record<string, unknown>;
|
|
31
32
|
export declare function getObjectShape(schema: unknown): Record<string, unknown> | undefined;
|
|
32
33
|
export declare function getLiteralValue(schema: unknown): unknown;
|
|
33
34
|
//# sourceMappingURL=mcp-sdk-compat.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-sdk-compat.d.ts","sourceRoot":"","sources":["../../src/extensions/mcp-sdk-compat.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAK5D,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,YAAY,CAQlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAKxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAMrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,GAAG,cAAc,CAM7G;AAyBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAKnD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CA6BnF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAkCxD"}
|
|
1
|
+
{"version":3,"file":"mcp-sdk-compat.d.ts","sourceRoot":"","sources":["../../src/extensions/mcp-sdk-compat.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAK5D,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,YAAY,CAQlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAKxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAMrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,GAAG,cAAc,CAM7G;AAyBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAKnD;AAaD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEtF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CA6BnF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAkCxD"}
|
|
@@ -30,7 +30,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
30
30
|
getToolFunction: ()=>getToolFunction,
|
|
31
31
|
getToolFunctionKey: ()=>getToolFunctionKey,
|
|
32
32
|
hasToolFunction: ()=>hasToolFunction,
|
|
33
|
-
isZ4Schema: ()=>isZ4Schema
|
|
33
|
+
isZ4Schema: ()=>isZ4Schema,
|
|
34
|
+
isZodRawShapeCompat: ()=>isZodRawShapeCompat
|
|
34
35
|
});
|
|
35
36
|
function getToolFunction(tool) {
|
|
36
37
|
if ('handler' in tool && 'function' == typeof tool.handler) return tool.handler;
|
|
@@ -57,6 +58,12 @@ function isZ4Schema(schema) {
|
|
|
57
58
|
if (!schema || 'object' != typeof schema) return false;
|
|
58
59
|
return !!schema._zod;
|
|
59
60
|
}
|
|
61
|
+
function isZodTypeLike(value) {
|
|
62
|
+
return !!value && 'object' == typeof value && 'parse' in value && 'function' == typeof value.parse && 'safeParse' in value && 'function' == typeof value.safeParse;
|
|
63
|
+
}
|
|
64
|
+
function isZodRawShapeCompat(schema) {
|
|
65
|
+
return !!schema && 'object' == typeof schema && Object.values(schema).some(isZodTypeLike);
|
|
66
|
+
}
|
|
60
67
|
function getObjectShape(schema) {
|
|
61
68
|
if (!schema || 'object' != typeof schema) return;
|
|
62
69
|
let rawShape;
|
|
@@ -98,6 +105,7 @@ exports.getToolFunction = __webpack_exports__.getToolFunction;
|
|
|
98
105
|
exports.getToolFunctionKey = __webpack_exports__.getToolFunctionKey;
|
|
99
106
|
exports.hasToolFunction = __webpack_exports__.hasToolFunction;
|
|
100
107
|
exports.isZ4Schema = __webpack_exports__.isZ4Schema;
|
|
108
|
+
exports.isZodRawShapeCompat = __webpack_exports__.isZodRawShapeCompat;
|
|
101
109
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
102
110
|
"createWrappedTool",
|
|
103
111
|
"getLiteralValue",
|
|
@@ -105,7 +113,8 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
|
105
113
|
"getToolFunction",
|
|
106
114
|
"getToolFunctionKey",
|
|
107
115
|
"hasToolFunction",
|
|
108
|
-
"isZ4Schema"
|
|
116
|
+
"isZ4Schema",
|
|
117
|
+
"isZodRawShapeCompat"
|
|
109
118
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
110
119
|
Object.defineProperty(exports, '__esModule', {
|
|
111
120
|
value: true
|
|
@@ -23,6 +23,12 @@ function isZ4Schema(schema) {
|
|
|
23
23
|
if (!schema || 'object' != typeof schema) return false;
|
|
24
24
|
return !!schema._zod;
|
|
25
25
|
}
|
|
26
|
+
function isZodTypeLike(value) {
|
|
27
|
+
return !!value && 'object' == typeof value && 'parse' in value && 'function' == typeof value.parse && 'safeParse' in value && 'function' == typeof value.safeParse;
|
|
28
|
+
}
|
|
29
|
+
function isZodRawShapeCompat(schema) {
|
|
30
|
+
return !!schema && 'object' == typeof schema && Object.values(schema).some(isZodTypeLike);
|
|
31
|
+
}
|
|
26
32
|
function getObjectShape(schema) {
|
|
27
33
|
if (!schema || 'object' != typeof schema) return;
|
|
28
34
|
let rawShape;
|
|
@@ -57,4 +63,4 @@ function getLiteralValue(schema) {
|
|
|
57
63
|
const directValue = schema.value;
|
|
58
64
|
if (void 0 !== directValue) return directValue;
|
|
59
65
|
}
|
|
60
|
-
export { createWrappedTool, getLiteralValue, getObjectShape, getToolFunction, getToolFunctionKey, hasToolFunction, isZ4Schema };
|
|
66
|
+
export { createWrappedTool, getLiteralValue, getObjectShape, getToolFunction, getToolFunctionKey, hasToolFunction, isZ4Schema, isZodRawShapeCompat };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitization.d.ts","sourceRoot":"","sources":["../../src/extensions/sanitization.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"sanitization.d.ts","sourceRoot":"","sources":["../../src/extensions/sanitization.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAmB,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAShE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,KAAK,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAuBrE"}
|
|
@@ -37,8 +37,19 @@ function sanitizeEvent(event) {
|
|
|
37
37
|
if (null != result.response) result.response = sanitizeResponse(result.response);
|
|
38
38
|
if (null != result.parameters) result.parameters = sanitizeParameters(result.parameters);
|
|
39
39
|
if (null != result.userIntent) result.userIntent = (0, external_mcp_payloads_js_namespaceObject.sanitizeCapturedValue)(result.userIntent);
|
|
40
|
+
if (null != result.error) result.error = sanitizeExceptionValues(result.error);
|
|
40
41
|
return result;
|
|
41
42
|
}
|
|
43
|
+
function sanitizeExceptionValues(error) {
|
|
44
|
+
if (!Array.isArray(error.$exception_list)) return error;
|
|
45
|
+
return {
|
|
46
|
+
...error,
|
|
47
|
+
$exception_list: error.$exception_list.map((exception)=>({
|
|
48
|
+
...exception,
|
|
49
|
+
value: (0, external_mcp_payloads_js_namespaceObject.sanitizeCapturedValue)(exception.value)
|
|
50
|
+
}))
|
|
51
|
+
};
|
|
52
|
+
}
|
|
42
53
|
function sanitizeResponse(response) {
|
|
43
54
|
if (null == response || 'object' != typeof response) return (0, external_mcp_payloads_js_namespaceObject.sanitizeCapturedValue)(response);
|
|
44
55
|
const sanitized = (0, external_mcp_payloads_js_namespaceObject.sanitizeCapturedValue)(response);
|
|
@@ -9,8 +9,19 @@ function sanitizeEvent(event) {
|
|
|
9
9
|
if (null != result.response) result.response = sanitizeResponse(result.response);
|
|
10
10
|
if (null != result.parameters) result.parameters = sanitizeParameters(result.parameters);
|
|
11
11
|
if (null != result.userIntent) result.userIntent = sanitizeCapturedValue(result.userIntent);
|
|
12
|
+
if (null != result.error) result.error = sanitizeExceptionValues(result.error);
|
|
12
13
|
return result;
|
|
13
14
|
}
|
|
15
|
+
function sanitizeExceptionValues(error) {
|
|
16
|
+
if (!Array.isArray(error.$exception_list)) return error;
|
|
17
|
+
return {
|
|
18
|
+
...error,
|
|
19
|
+
$exception_list: error.$exception_list.map((exception)=>({
|
|
20
|
+
...exception,
|
|
21
|
+
value: sanitizeCapturedValue(exception.value)
|
|
22
|
+
}))
|
|
23
|
+
};
|
|
24
|
+
}
|
|
14
25
|
function sanitizeResponse(response) {
|
|
15
26
|
if (null == response || 'object' != typeof response) return sanitizeCapturedValue(response);
|
|
16
27
|
const sanitized = sanitizeCapturedValue(response);
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.10.
|
|
1
|
+
export declare const version = "0.10.3";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -26,7 +26,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
27
|
version: ()=>version
|
|
28
28
|
});
|
|
29
|
-
const version = '0.10.
|
|
29
|
+
const version = '0.10.3';
|
|
30
30
|
exports.version = __webpack_exports__.version;
|
|
31
31
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
32
32
|
"version"
|
package/dist/version.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const version = '0.10.
|
|
1
|
+
const version = '0.10.3';
|
|
2
2
|
export { version };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/mcp",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"bugs": {
|
|
5
5
|
"url": "https://github.com/PostHog/posthog-js/issues"
|
|
6
6
|
},
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"module": "dist/index.mjs",
|
|
29
29
|
"types": "dist/index.d.ts",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@posthog/core": "^1.
|
|
31
|
+
"@posthog/core": "^1.46.2"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@babel/preset-env": "^7.27.1",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"@types/node": "^20.0.0",
|
|
40
40
|
"jest": "29.7.0",
|
|
41
41
|
"zod": "^3.25.0",
|
|
42
|
-
"
|
|
43
|
-
"posthog-
|
|
42
|
+
"posthog-node": "^5.47.4",
|
|
43
|
+
"@posthog-tooling/tsconfig-base": "1.1.1"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@modelcontextprotocol/sdk": ">=1.26.0",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface AnalyticsInjectableJsonSchema {
|
|
2
|
+
additionalProperties?: boolean
|
|
3
|
+
allOf?: unknown
|
|
4
|
+
anyOf?: unknown
|
|
5
|
+
oneOf?: unknown
|
|
6
|
+
properties?: Record<string, unknown>
|
|
7
|
+
required?: string[]
|
|
8
|
+
type?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function hasAnalyticsParameter(
|
|
12
|
+
schema: AnalyticsInjectableJsonSchema | undefined,
|
|
13
|
+
parameterName: string
|
|
14
|
+
): boolean {
|
|
15
|
+
return !!schema?.properties && Object.prototype.hasOwnProperty.call(schema.properties, parameterName)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function canInjectAnalyticsParameter(
|
|
19
|
+
schema: AnalyticsInjectableJsonSchema | undefined,
|
|
20
|
+
parameterName: string
|
|
21
|
+
): boolean {
|
|
22
|
+
return !hasAnalyticsParameter(schema, parameterName) && !schema?.oneOf && !schema?.allOf && !schema?.anyOf
|
|
23
|
+
}
|
|
@@ -4,21 +4,16 @@
|
|
|
4
4
|
// Licensed under the MIT License: https://github.com/agentcathq/agentcat-typescript-sdk/blob/main/LICENSE
|
|
5
5
|
|
|
6
6
|
import type { MCPAnalyticsOptions } from '../types'
|
|
7
|
+
import {
|
|
8
|
+
canInjectAnalyticsParameter,
|
|
9
|
+
hasAnalyticsParameter,
|
|
10
|
+
type AnalyticsInjectableJsonSchema,
|
|
11
|
+
} from './analytics-parameters'
|
|
7
12
|
import { DEFAULT_CONTEXT_PARAMETER_DESCRIPTION } from './constants'
|
|
8
13
|
import { log } from './logger'
|
|
9
14
|
|
|
10
|
-
interface JsonSchema {
|
|
11
|
-
additionalProperties?: boolean
|
|
12
|
-
allOf?: unknown
|
|
13
|
-
anyOf?: unknown
|
|
14
|
-
oneOf?: unknown
|
|
15
|
-
properties?: Record<string, unknown>
|
|
16
|
-
required?: string[]
|
|
17
|
-
type?: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
15
|
export interface ContextInjectableTool {
|
|
21
|
-
inputSchema?:
|
|
16
|
+
inputSchema?: AnalyticsInjectableJsonSchema
|
|
22
17
|
name?: string
|
|
23
18
|
[key: string]: unknown
|
|
24
19
|
}
|
|
@@ -48,17 +43,14 @@ export function addContextParameterToTool<TTool extends ContextInjectableTool>(
|
|
|
48
43
|
// Create a shallow copy of the tool to avoid modifying the original
|
|
49
44
|
const modifiedTool = { ...tool }
|
|
50
45
|
const toolName = tool.name || 'unknown'
|
|
51
|
-
const schema = modifiedTool.inputSchema as
|
|
52
|
-
|
|
53
|
-
// Check if tool already has context parameter - skip to avoid collision
|
|
54
|
-
if (schema?.properties?.context) {
|
|
55
|
-
log(`WARN: Tool "${toolName}" already has 'context' parameter. Skipping context injection.`)
|
|
56
|
-
return modifiedTool
|
|
57
|
-
}
|
|
46
|
+
const schema = modifiedTool.inputSchema as AnalyticsInjectableJsonSchema | undefined
|
|
58
47
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
if (!canInjectAnalyticsParameter(schema, 'context')) {
|
|
49
|
+
if (hasAnalyticsParameter(schema, 'context')) {
|
|
50
|
+
log(`WARN: Tool "${toolName}" already has 'context' parameter. Skipping context injection.`)
|
|
51
|
+
} else {
|
|
52
|
+
log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping context injection.`)
|
|
53
|
+
}
|
|
62
54
|
return modifiedTool
|
|
63
55
|
}
|
|
64
56
|
|
|
@@ -77,9 +69,9 @@ export function addContextParameterToTool<TTool extends ContextInjectableTool>(
|
|
|
77
69
|
const contextDescription = contextDescriptionOverride || DEFAULT_CONTEXT_PARAMETER_DESCRIPTION
|
|
78
70
|
|
|
79
71
|
// Deep copy the inputSchema to avoid mutations
|
|
80
|
-
modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema)) as
|
|
72
|
+
modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema)) as AnalyticsInjectableJsonSchema
|
|
81
73
|
|
|
82
|
-
const inputSchema = modifiedTool.inputSchema as
|
|
74
|
+
const inputSchema = modifiedTool.inputSchema as AnalyticsInjectableJsonSchema
|
|
83
75
|
|
|
84
76
|
// Ensure properties object exists
|
|
85
77
|
if (!inputSchema.properties) {
|
|
@@ -4,24 +4,19 @@
|
|
|
4
4
|
// Licensed under the MIT License: https://github.com/agentcathq/agentcat-typescript-sdk/blob/main/LICENSE
|
|
5
5
|
|
|
6
6
|
import { uuidv7 } from '@posthog/core'
|
|
7
|
+
import {
|
|
8
|
+
canInjectAnalyticsParameter,
|
|
9
|
+
hasAnalyticsParameter,
|
|
10
|
+
type AnalyticsInjectableJsonSchema,
|
|
11
|
+
} from './analytics-parameters'
|
|
7
12
|
import { DEFAULT_CONVERSATION_ID_DESCRIPTION } from './constants'
|
|
8
13
|
import { log } from './logger'
|
|
9
14
|
import { GET_MORE_TOOLS_NAME } from './tools'
|
|
10
15
|
|
|
11
16
|
export const CONVERSATION_ID_PARAM_NAME = 'conversation_id'
|
|
12
17
|
|
|
13
|
-
interface JsonSchema {
|
|
14
|
-
additionalProperties?: boolean
|
|
15
|
-
allOf?: unknown
|
|
16
|
-
anyOf?: unknown
|
|
17
|
-
oneOf?: unknown
|
|
18
|
-
properties?: Record<string, unknown>
|
|
19
|
-
required?: string[]
|
|
20
|
-
type?: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
18
|
export interface ConversationIdInjectableTool {
|
|
24
|
-
inputSchema?:
|
|
19
|
+
inputSchema?: AnalyticsInjectableJsonSchema
|
|
25
20
|
name?: string
|
|
26
21
|
[key: string]: unknown
|
|
27
22
|
}
|
|
@@ -29,17 +24,16 @@ export interface ConversationIdInjectableTool {
|
|
|
29
24
|
export function addConversationIdToTool<TTool extends ConversationIdInjectableTool>(tool: TTool): TTool {
|
|
30
25
|
const modifiedTool = { ...tool }
|
|
31
26
|
const toolName = tool.name || 'unknown'
|
|
32
|
-
const schema = modifiedTool.inputSchema as
|
|
33
|
-
|
|
34
|
-
if (schema
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`)
|
|
27
|
+
const schema = modifiedTool.inputSchema as AnalyticsInjectableJsonSchema | undefined
|
|
28
|
+
|
|
29
|
+
if (!canInjectAnalyticsParameter(schema, CONVERSATION_ID_PARAM_NAME)) {
|
|
30
|
+
if (hasAnalyticsParameter(schema, CONVERSATION_ID_PARAM_NAME)) {
|
|
31
|
+
log(
|
|
32
|
+
`WARN: Tool "${toolName}" already has '${CONVERSATION_ID_PARAM_NAME}' parameter. Skipping conversation_id injection.`
|
|
33
|
+
)
|
|
34
|
+
} else {
|
|
35
|
+
log(`WARN: Tool "${toolName}" has complex schema (oneOf/allOf/anyOf). Skipping conversation_id injection.`)
|
|
36
|
+
}
|
|
43
37
|
return modifiedTool
|
|
44
38
|
}
|
|
45
39
|
|
|
@@ -51,9 +45,9 @@ export function addConversationIdToTool<TTool extends ConversationIdInjectableTo
|
|
|
51
45
|
}
|
|
52
46
|
}
|
|
53
47
|
|
|
54
|
-
modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema)) as
|
|
48
|
+
modifiedTool.inputSchema = JSON.parse(JSON.stringify(modifiedTool.inputSchema)) as AnalyticsInjectableJsonSchema
|
|
55
49
|
|
|
56
|
-
const inputSchema = modifiedTool.inputSchema as
|
|
50
|
+
const inputSchema = modifiedTool.inputSchema as AnalyticsInjectableJsonSchema
|
|
57
51
|
|
|
58
52
|
if (!inputSchema.properties) {
|
|
59
53
|
inputSchema.properties = {}
|
|
@@ -11,11 +11,19 @@ import type {
|
|
|
11
11
|
RegisteredTool,
|
|
12
12
|
ToolCallback,
|
|
13
13
|
} from '../types'
|
|
14
|
+
import { canInjectAnalyticsParameter } from './analytics-parameters'
|
|
14
15
|
import { stripConversationId } from './conversation-id'
|
|
16
|
+
import { isContextEnabled } from './context-parameters'
|
|
15
17
|
import { MCPAnalyticsEventType } from './event-types'
|
|
16
18
|
import { getServerTrackingData } from './internal'
|
|
17
19
|
import { log } from './logger'
|
|
18
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
createWrappedTool,
|
|
22
|
+
getObjectShape,
|
|
23
|
+
getToolFunction,
|
|
24
|
+
hasToolFunction,
|
|
25
|
+
isZodRawShapeCompat,
|
|
26
|
+
} from './mcp-sdk-compat'
|
|
19
27
|
import { handleReportMissing, resolveMissingCapabilityToolName } from './tools'
|
|
20
28
|
import {
|
|
21
29
|
handleInitializeRequest,
|
|
@@ -44,6 +52,41 @@ function isCallbackUpdate(value: unknown): value is { callback: ToolCallback } {
|
|
|
44
52
|
return !!value && typeof value === 'object' && 'callback' in value && typeof value.callback === 'function'
|
|
45
53
|
}
|
|
46
54
|
|
|
55
|
+
function analyticsOwnsParameter(inputSchema: unknown, parameterName: string): boolean {
|
|
56
|
+
if (!inputSchema || typeof inputSchema !== 'object') {
|
|
57
|
+
return canInjectAnalyticsParameter(undefined, parameterName)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (isZodRawShapeCompat(inputSchema)) {
|
|
61
|
+
return canInjectAnalyticsParameter({ properties: inputSchema }, parameterName)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const shape = getObjectShape(inputSchema)
|
|
65
|
+
if (shape) {
|
|
66
|
+
return canInjectAnalyticsParameter({ properties: shape }, parameterName)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const schema = inputSchema as Record<string, unknown>
|
|
70
|
+
if ('_def' in schema || '_zod' in schema || '~standard' in schema) {
|
|
71
|
+
// The MCP SDK advertises non-object schemas as an empty object schema.
|
|
72
|
+
return canInjectAnalyticsParameter(undefined, parameterName)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return canInjectAnalyticsParameter(schema, parameterName)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function stripOwnedAnalyticsArguments(
|
|
79
|
+
args: unknown,
|
|
80
|
+
ownership: { context: boolean; conversationId: boolean }
|
|
81
|
+
): unknown {
|
|
82
|
+
let cleanedArgs = args
|
|
83
|
+
if (ownership.context && cleanedArgs && typeof cleanedArgs === 'object' && 'context' in cleanedArgs) {
|
|
84
|
+
const { context: _context, ...rest } = cleanedArgs
|
|
85
|
+
cleanedArgs = rest
|
|
86
|
+
}
|
|
87
|
+
return ownership.conversationId ? stripConversationId(cleanedArgs) : cleanedArgs
|
|
88
|
+
}
|
|
89
|
+
|
|
47
90
|
function addTracingToToolRegistry(
|
|
48
91
|
tools: Record<string, RegisteredTool>,
|
|
49
92
|
server: HighLevelMCPServerLike
|
|
@@ -78,7 +121,10 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
78
121
|
return Reflect.set(target, property, value)
|
|
79
122
|
}
|
|
80
123
|
|
|
81
|
-
|
|
124
|
+
// The MCP SDK's registry copy is currently stale after update(), but keep this lookup lazy so
|
|
125
|
+
// ownership follows the current schema once the registry reflects live tool state.
|
|
126
|
+
const getCurrentInputSchema = () => value.inputSchema
|
|
127
|
+
const nextValue = addTracingToToolCallbackInternal(value, property, server, getCurrentInputSchema)
|
|
82
128
|
|
|
83
129
|
if (typeof nextValue.update === 'function') {
|
|
84
130
|
const originalUpdate = nextValue.update
|
|
@@ -89,7 +135,8 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
89
135
|
const wrappedTool = addTracingToToolCallbackInternal(
|
|
90
136
|
{ callback: updateObj.callback },
|
|
91
137
|
property,
|
|
92
|
-
server
|
|
138
|
+
server,
|
|
139
|
+
getCurrentInputSchema
|
|
93
140
|
)
|
|
94
141
|
updateObj.callback = getToolFunction(wrappedTool)
|
|
95
142
|
}
|
|
@@ -141,12 +188,12 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
141
188
|
function addTracingToToolCallbackInternal(
|
|
142
189
|
tool: RegisteredTool,
|
|
143
190
|
toolName: string,
|
|
144
|
-
server: HighLevelMCPServerLike
|
|
191
|
+
server: HighLevelMCPServerLike,
|
|
192
|
+
getCurrentInputSchema: () => unknown = () => tool.inputSchema
|
|
145
193
|
): RegisteredTool {
|
|
146
194
|
const originalCallback = getToolFunction(tool)
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
)
|
|
195
|
+
const options = getServerTrackingData(server.server as MCPServerLike)?.options
|
|
196
|
+
const missingToolName = resolveMissingCapabilityToolName(options)
|
|
150
197
|
|
|
151
198
|
if (wrappedCallbacks.has(originalCallback)) {
|
|
152
199
|
log(`Tool ${toolName} callback already wrapped, skipping re-wrap`)
|
|
@@ -170,15 +217,17 @@ function addTracingToToolCallbackInternal(
|
|
|
170
217
|
extra = params[0] as CompatibleRequestHandlerExtra
|
|
171
218
|
}
|
|
172
219
|
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
220
|
+
const inputSchema = getCurrentInputSchema()
|
|
221
|
+
const cleanedArgs = stripOwnedAnalyticsArguments(args, {
|
|
222
|
+
context:
|
|
223
|
+
toolName !== missingToolName &&
|
|
224
|
+
isContextEnabled(options?.context) &&
|
|
225
|
+
analyticsOwnsParameter(inputSchema, 'context'),
|
|
226
|
+
conversationId:
|
|
227
|
+
toolName !== missingToolName &&
|
|
228
|
+
options?.enableConversationId === true &&
|
|
229
|
+
analyticsOwnsParameter(inputSchema, 'conversation_id'),
|
|
230
|
+
})
|
|
182
231
|
|
|
183
232
|
try {
|
|
184
233
|
if (cleanedArgs === undefined) {
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
const CONTEXT_ARGUMENT_NAME = 'context'
|
|
7
7
|
const REDACTED_VALUE = '[redacted]'
|
|
8
|
+
const BINARY_REDACTED_VALUE = '[binary data redacted - not supported by PostHog MCP analytics]'
|
|
8
9
|
const BASE64_PATTERN = /^[A-Za-z0-9+/\n\r]+=*$/
|
|
10
|
+
const BASE64URL_PATTERN = /^[A-Za-z0-9_-]+={0,2}$/
|
|
11
|
+
const BASE64URL_SPECIFIC_CHAR_PATTERN = /[-_]/
|
|
12
|
+
const BASE64_DATA_URL_PREFIX_PATTERN = /^data:[^,\s]*;base64,/i
|
|
13
|
+
const BASE64_DATA_URL_PAYLOAD_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/
|
|
9
14
|
const SIZE_GATE = 10_240
|
|
10
15
|
const POSTHOG_TOKEN_PATTERN = /\bph[a-z]_[A-Za-z0-9_-]{20,}\b/g
|
|
11
16
|
const SENSITIVE_KEY_PATTERN =
|
|
@@ -21,9 +26,30 @@ function shouldRedactKey(key: string): boolean {
|
|
|
21
26
|
return SENSITIVE_KEY_PATTERN.test(key)
|
|
22
27
|
}
|
|
23
28
|
|
|
29
|
+
function isBase64DataUrl(value: string): boolean {
|
|
30
|
+
const prefix = BASE64_DATA_URL_PREFIX_PATTERN.exec(value)
|
|
31
|
+
if (!prefix) {
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let payload: string
|
|
36
|
+
try {
|
|
37
|
+
payload = decodeURIComponent(value.slice(prefix[0].length))
|
|
38
|
+
} catch {
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return BASE64_DATA_URL_PAYLOAD_PATTERN.test(payload.replace(/[\r\n]/g, ''))
|
|
43
|
+
}
|
|
44
|
+
|
|
24
45
|
function sanitizeString(value: string): string {
|
|
25
|
-
if (
|
|
26
|
-
|
|
46
|
+
if (
|
|
47
|
+
value.length >= SIZE_GATE &&
|
|
48
|
+
(BASE64_PATTERN.test(value) ||
|
|
49
|
+
isBase64DataUrl(value) ||
|
|
50
|
+
(BASE64URL_SPECIFIC_CHAR_PATTERN.test(value) && BASE64URL_PATTERN.test(value)))
|
|
51
|
+
) {
|
|
52
|
+
return BINARY_REDACTED_VALUE
|
|
27
53
|
}
|
|
28
54
|
return value.replace(POSTHOG_TOKEN_PATTERN, REDACTED_VALUE)
|
|
29
55
|
}
|
|
@@ -97,6 +97,21 @@ export function isZ4Schema(schema: unknown): boolean {
|
|
|
97
97
|
return !!(schema as ZodV4Internal)._zod
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
function isZodTypeLike(value: unknown): boolean {
|
|
101
|
+
return (
|
|
102
|
+
!!value &&
|
|
103
|
+
typeof value === 'object' &&
|
|
104
|
+
'parse' in value &&
|
|
105
|
+
typeof value.parse === 'function' &&
|
|
106
|
+
'safeParse' in value &&
|
|
107
|
+
typeof value.safeParse === 'function'
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function isZodRawShapeCompat(schema: unknown): schema is Record<string, unknown> {
|
|
112
|
+
return !!schema && typeof schema === 'object' && Object.values(schema).some(isZodTypeLike)
|
|
113
|
+
}
|
|
114
|
+
|
|
100
115
|
export function getObjectShape(schema: unknown): Record<string, unknown> | undefined {
|
|
101
116
|
if (!schema || typeof schema !== 'object') {
|
|
102
117
|
return
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Copyright (c) 2025 AgentCat, Inc. (formerly MCPcat)
|
|
4
4
|
// Licensed under the MIT License: https://github.com/agentcathq/agentcat-typescript-sdk/blob/main/LICENSE
|
|
5
5
|
|
|
6
|
-
import type { Event, McpEvent } from '../types'
|
|
6
|
+
import type { ErrorProperties, Event, McpEvent } from '../types'
|
|
7
7
|
import { sanitizeCapturedValue } from './mcp-payloads'
|
|
8
8
|
|
|
9
9
|
type SanitizedRecord = Record<string, unknown>
|
|
@@ -39,9 +39,31 @@ export function sanitizeEvent<T extends Event | McpEvent>(event: T): T {
|
|
|
39
39
|
result.userIntent = sanitizeCapturedValue(result.userIntent) as string
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
if (result.error != null) {
|
|
43
|
+
result.error = sanitizeExceptionValues(result.error)
|
|
44
|
+
}
|
|
45
|
+
|
|
42
46
|
return result
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Sanitizes exception messages before they fan out to both the primary MCP
|
|
51
|
+
* event's error-message property and the `$exception` sibling.
|
|
52
|
+
*/
|
|
53
|
+
function sanitizeExceptionValues(error: ErrorProperties): ErrorProperties {
|
|
54
|
+
if (!Array.isArray(error.$exception_list)) {
|
|
55
|
+
return error
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
...error,
|
|
60
|
+
$exception_list: error.$exception_list.map((exception) => ({
|
|
61
|
+
...exception,
|
|
62
|
+
value: sanitizeCapturedValue(exception.value) as string,
|
|
63
|
+
})),
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
45
67
|
/**
|
|
46
68
|
* Sanitizes response content blocks by replacing non-text content types
|
|
47
69
|
* with informative redaction messages.
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.10.
|
|
1
|
+
export const version = '0.10.3'
|