@posthog/mcp 0.10.8 → 0.10.9
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/instrument-lowlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-lowlevel.js +6 -5
- package/dist/extensions/instrument-lowlevel.mjs +7 -6
- package/dist/extensions/instrumentation.d.ts +22 -0
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +13 -7
- package/dist/extensions/instrumentation.mjs +11 -8
- package/dist/extensions/mcp-sdk-compat.d.ts +10 -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/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +1 -1
- package/src/extensions/instrument-lowlevel.ts +14 -9
- package/src/extensions/instrumentation.ts +53 -9
- package/src/extensions/mcp-sdk-compat.ts +18 -0
- package/src/version.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-lowlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-lowlevel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"instrument-lowlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-lowlevel.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAiD,aAAa,EAAE,MAAM,UAAU,CAAA;AAG5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAmBxC;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CA0BtF"}
|
|
@@ -26,7 +26,6 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
27
|
instrumentLowLevelServer: ()=>instrumentLowLevelServer
|
|
28
28
|
});
|
|
29
|
-
const types_js_namespaceObject = require("@modelcontextprotocol/sdk/types.js");
|
|
30
29
|
const external_event_types_js_namespaceObject = require("./event-types.js");
|
|
31
30
|
const external_internal_js_namespaceObject = require("./internal.js");
|
|
32
31
|
const external_tools_js_namespaceObject = require("./tools.js");
|
|
@@ -35,20 +34,22 @@ const external_tracing_helpers_js_namespaceObject = require("./tracing-helpers.j
|
|
|
35
34
|
function instrumentLowLevelServer(server, logger) {
|
|
36
35
|
try {
|
|
37
36
|
const hadCallToolHandler = server._requestHandlers.has('tools/call');
|
|
37
|
+
const traceToolCall = (server, originalHandler, request, extra)=>handleToolCallRequest(server, originalHandler, request, extra, logger);
|
|
38
38
|
const handlers = {
|
|
39
39
|
initialize: (server, originalHandler, request, extra)=>(0, external_instrumentation_js_namespaceObject.handleInitializeRequest)(server, originalHandler, request, extra, logger),
|
|
40
40
|
'tools/list': (server, originalHandler, request, extra)=>(0, external_instrumentation_js_namespaceObject.handleListToolsRequest)(server, originalHandler, request, extra, logger),
|
|
41
|
-
'tools/call':
|
|
41
|
+
'tools/call': traceToolCall
|
|
42
42
|
};
|
|
43
43
|
(0, external_instrumentation_js_namespaceObject.patchRequestHandlers)(server, handlers);
|
|
44
|
-
if (!hadCallToolHandler)
|
|
45
|
-
throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
|
|
46
|
-
});
|
|
44
|
+
if (!hadCallToolHandler) (0, external_instrumentation_js_namespaceObject.registerFallbackRequestHandler)(server, 'tools/call', unknownToolHandler, traceToolCall);
|
|
47
45
|
} catch (error) {
|
|
48
46
|
logger(`Warning: Failed to setup tool call instrumentation - ${error}`);
|
|
49
47
|
throw error;
|
|
50
48
|
}
|
|
51
49
|
}
|
|
50
|
+
async function unknownToolHandler(request) {
|
|
51
|
+
throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
|
|
52
|
+
}
|
|
52
53
|
async function handleToolCallRequest(server, originalCallToolHandler, request, extra, logger) {
|
|
53
54
|
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
|
|
54
55
|
if (!data) {
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import { CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2
1
|
import { MCPAnalyticsEventType } from "./event-types.mjs";
|
|
3
2
|
import { getServerTrackingData } from "./internal.mjs";
|
|
4
3
|
import { handleReportMissing, resolveMissingCapabilityToolName } from "./tools.mjs";
|
|
5
|
-
import { captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers } from "./instrumentation.mjs";
|
|
4
|
+
import { captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, registerFallbackRequestHandler } from "./instrumentation.mjs";
|
|
6
5
|
import { getContextArgument } from "./tracing-helpers.mjs";
|
|
7
6
|
function instrumentLowLevelServer(server, logger) {
|
|
8
7
|
try {
|
|
9
8
|
const hadCallToolHandler = server._requestHandlers.has('tools/call');
|
|
9
|
+
const traceToolCall = (server, originalHandler, request, extra)=>handleToolCallRequest(server, originalHandler, request, extra, logger);
|
|
10
10
|
const handlers = {
|
|
11
11
|
initialize: (server, originalHandler, request, extra)=>handleInitializeRequest(server, originalHandler, request, extra, logger),
|
|
12
12
|
'tools/list': (server, originalHandler, request, extra)=>handleListToolsRequest(server, originalHandler, request, extra, logger),
|
|
13
|
-
'tools/call':
|
|
13
|
+
'tools/call': traceToolCall
|
|
14
14
|
};
|
|
15
15
|
patchRequestHandlers(server, handlers);
|
|
16
|
-
if (!hadCallToolHandler) server
|
|
17
|
-
throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
|
|
18
|
-
});
|
|
16
|
+
if (!hadCallToolHandler) registerFallbackRequestHandler(server, 'tools/call', unknownToolHandler, traceToolCall);
|
|
19
17
|
} catch (error) {
|
|
20
18
|
logger(`Warning: Failed to setup tool call instrumentation - ${error}`);
|
|
21
19
|
throw error;
|
|
22
20
|
}
|
|
23
21
|
}
|
|
22
|
+
async function unknownToolHandler(request) {
|
|
23
|
+
throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`);
|
|
24
|
+
}
|
|
24
25
|
async function handleToolCallRequest(server, originalCallToolHandler, request, extra, logger) {
|
|
25
26
|
const data = getServerTrackingData(server);
|
|
26
27
|
if (!data) {
|
|
@@ -55,6 +55,28 @@ export declare function captureToolCall(params: TraceToolCallParams): Promise<un
|
|
|
55
55
|
* supplies `request` and `extra` per call.
|
|
56
56
|
*/
|
|
57
57
|
export type HandlerPatch = (server: MCPServerLike, originalHandler: MCPRequestHandler, request: MCPRequestLike, extra: CompatibleRequestHandlerExtra | undefined) => Promise<unknown>;
|
|
58
|
+
/**
|
|
59
|
+
* Registers a synthetic fallback handler for `handlerName`, already wrapped in
|
|
60
|
+
* `patch`, by writing straight into `_requestHandlers` instead of going through
|
|
61
|
+
* `setRequestHandler`.
|
|
62
|
+
*
|
|
63
|
+
* Bypassing the SDK setter is deliberate, on three counts:
|
|
64
|
+
*
|
|
65
|
+
* - **Capability assertion.** `setRequestHandler` refuses a method the server
|
|
66
|
+
* never declared a capability for, so instrumenting a low-level server built
|
|
67
|
+
* without `capabilities.tools` used to throw `Server does not support tools`
|
|
68
|
+
* and leave instrumentation half-applied. Our fallback is not a capability the
|
|
69
|
+
* server offers — it exists only so a call for a tool nobody claims is still
|
|
70
|
+
* captured — so the assertion has nothing to protect here.
|
|
71
|
+
* - **Schema validation.** The setter also wraps the handler in request/result
|
|
72
|
+
* parsing, which a handler that can only ever throw `Unknown tool` never needs.
|
|
73
|
+
* - **Portability.** The setter's first argument is a Zod schema on SDK v1 and a
|
|
74
|
+
* method string on v2; the map key is the same string on both, so this is the
|
|
75
|
+
* one registration form that does not need to know which major it is talking
|
|
76
|
+
* to — and it drops the last runtime `@modelcontextprotocol/sdk` import from
|
|
77
|
+
* the shipped bundle.
|
|
78
|
+
*/
|
|
79
|
+
export declare function registerFallbackRequestHandler(server: MCPServerLike, handlerName: string, fallbackHandler: MCPRequestHandler, patch: HandlerPatch): void;
|
|
58
80
|
export declare function patchRequestHandlers(server: MCPServerLike, patches: Record<string, HandlerPatch>): void;
|
|
59
81
|
/**
|
|
60
82
|
* Checks the server's raw listing for a real owner of a candidate virtual tool.
|
|
@@ -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,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,
|
|
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;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,iBAAiB,EAClC,KAAK,EAAE,YAAY,GAClB,IAAI,CAGN;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CA2CvG;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"}
|
|
@@ -31,6 +31,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
31
31
|
readToolMetaCategory: ()=>readToolMetaCategory,
|
|
32
32
|
cacheToolCategories: ()=>cacheToolCategories,
|
|
33
33
|
handleListToolsRequest: ()=>handleListToolsRequest,
|
|
34
|
+
registerFallbackRequestHandler: ()=>registerFallbackRequestHandler,
|
|
34
35
|
patchRequestHandlers: ()=>patchRequestHandlers
|
|
35
36
|
});
|
|
36
37
|
const external_analytics_parameters_js_namespaceObject = require("./analytics-parameters.js");
|
|
@@ -174,6 +175,10 @@ function rememberOriginalRequestHandler(server, handlerName, originalHandler) {
|
|
|
174
175
|
}
|
|
175
176
|
handlers.set(handlerName, originalHandler);
|
|
176
177
|
}
|
|
178
|
+
function registerFallbackRequestHandler(server, handlerName, fallbackHandler, patch) {
|
|
179
|
+
rememberOriginalRequestHandler(server, handlerName, fallbackHandler);
|
|
180
|
+
server._requestHandlers.set(handlerName, (request, extra)=>patch(server, fallbackHandler, request, extra));
|
|
181
|
+
}
|
|
177
182
|
function patchRequestHandlers(server, patches) {
|
|
178
183
|
for (const [handlerName, patch] of Object.entries(patches)){
|
|
179
184
|
const originalHandler = server._requestHandlers.get(handlerName);
|
|
@@ -183,12 +188,11 @@ function patchRequestHandlers(server, patches) {
|
|
|
183
188
|
}
|
|
184
189
|
}
|
|
185
190
|
const originalSetRequestHandler = server.setRequestHandler.bind(server);
|
|
186
|
-
server.setRequestHandler = (
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const result = originalSetRequestHandler(requestSchema, originalHandler);
|
|
191
|
+
server.setRequestHandler = (...args)=>{
|
|
192
|
+
const handlerName = (0, external_mcp_sdk_compat_js_namespaceObject.readRequestHandlerMethod)(args[0]);
|
|
193
|
+
const patch = void 0 !== handlerName && Object.prototype.hasOwnProperty.call(patches, handlerName) ? patches[handlerName] : void 0;
|
|
194
|
+
if (void 0 === handlerName || !patch) return originalSetRequestHandler(...args);
|
|
195
|
+
const result = originalSetRequestHandler(...args);
|
|
192
196
|
const registeredHandler = server._requestHandlers.get(handlerName);
|
|
193
197
|
if (registeredHandler) {
|
|
194
198
|
rememberOriginalRequestHandler(server, handlerName, registeredHandler);
|
|
@@ -429,6 +433,7 @@ exports.handleListToolsRequest = __webpack_exports__.handleListToolsRequest;
|
|
|
429
433
|
exports.isToolAdvertised = __webpack_exports__.isToolAdvertised;
|
|
430
434
|
exports.patchRequestHandlers = __webpack_exports__.patchRequestHandlers;
|
|
431
435
|
exports.readToolMetaCategory = __webpack_exports__.readToolMetaCategory;
|
|
436
|
+
exports.registerFallbackRequestHandler = __webpack_exports__.registerFallbackRequestHandler;
|
|
432
437
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
433
438
|
"cacheToolCategories",
|
|
434
439
|
"cacheToolDescriptions",
|
|
@@ -437,7 +442,8 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
|
437
442
|
"handleListToolsRequest",
|
|
438
443
|
"isToolAdvertised",
|
|
439
444
|
"patchRequestHandlers",
|
|
440
|
-
"readToolMetaCategory"
|
|
445
|
+
"readToolMetaCategory",
|
|
446
|
+
"registerFallbackRequestHandler"
|
|
441
447
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
442
448
|
Object.defineProperty(exports, '__esModule', {
|
|
443
449
|
value: true
|
|
@@ -9,7 +9,7 @@ import { captureException } from "./exceptions.mjs";
|
|
|
9
9
|
import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from "./intent.mjs";
|
|
10
10
|
import { getServerTrackingData, handleIdentify, setServerTrackingData, withIdentity } from "./internal.mjs";
|
|
11
11
|
import { buildCapturedMcpParameters } from "./mcp-payloads.mjs";
|
|
12
|
-
import {
|
|
12
|
+
import { readRequestHandlerMethod } from "./mcp-sdk-compat.mjs";
|
|
13
13
|
import { getSessionId, getSessionInfo, newSessionId } from "./session.mjs";
|
|
14
14
|
import { encodeSessionId, readMcpSessionHeader, writeSessionIdToTransport } from "./session-token.mjs";
|
|
15
15
|
import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from "./tools.mjs";
|
|
@@ -139,6 +139,10 @@ function rememberOriginalRequestHandler(server, handlerName, originalHandler) {
|
|
|
139
139
|
}
|
|
140
140
|
handlers.set(handlerName, originalHandler);
|
|
141
141
|
}
|
|
142
|
+
function registerFallbackRequestHandler(server, handlerName, fallbackHandler, patch) {
|
|
143
|
+
rememberOriginalRequestHandler(server, handlerName, fallbackHandler);
|
|
144
|
+
server._requestHandlers.set(handlerName, (request, extra)=>patch(server, fallbackHandler, request, extra));
|
|
145
|
+
}
|
|
142
146
|
function patchRequestHandlers(server, patches) {
|
|
143
147
|
for (const [handlerName, patch] of Object.entries(patches)){
|
|
144
148
|
const originalHandler = server._requestHandlers.get(handlerName);
|
|
@@ -148,12 +152,11 @@ function patchRequestHandlers(server, patches) {
|
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
const originalSetRequestHandler = server.setRequestHandler.bind(server);
|
|
151
|
-
server.setRequestHandler = (
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const result = originalSetRequestHandler(requestSchema, originalHandler);
|
|
155
|
+
server.setRequestHandler = (...args)=>{
|
|
156
|
+
const handlerName = readRequestHandlerMethod(args[0]);
|
|
157
|
+
const patch = void 0 !== handlerName && Object.prototype.hasOwnProperty.call(patches, handlerName) ? patches[handlerName] : void 0;
|
|
158
|
+
if (void 0 === handlerName || !patch) return originalSetRequestHandler(...args);
|
|
159
|
+
const result = originalSetRequestHandler(...args);
|
|
157
160
|
const registeredHandler = server._requestHandlers.get(handlerName);
|
|
158
161
|
if (registeredHandler) {
|
|
159
162
|
rememberOriginalRequestHandler(server, handlerName, registeredHandler);
|
|
@@ -386,4 +389,4 @@ function readProtocolVersion(result, request) {
|
|
|
386
389
|
const requested = request.params?.protocolVersion;
|
|
387
390
|
return 'string' == typeof requested && requested.length > 0 ? requested : void 0;
|
|
388
391
|
}
|
|
389
|
-
export { cacheToolCategories, cacheToolDescriptions, captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, readToolMetaCategory };
|
|
392
|
+
export { cacheToolCategories, cacheToolDescriptions, captureToolCall, handleInitializeRequest, handleListToolsRequest, isToolAdvertised, patchRequestHandlers, readToolMetaCategory, registerFallbackRequestHandler };
|
|
@@ -30,5 +30,15 @@ export declare function createWrappedTool(originalTool: RegisteredTool, wrappedF
|
|
|
30
30
|
export declare function isZ4Schema(schema: unknown): boolean;
|
|
31
31
|
export declare function isZodRawShapeCompat(schema: unknown): schema is Record<string, unknown>;
|
|
32
32
|
export declare function getObjectShape(schema: unknown): Record<string, unknown> | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Reads the method name a `setRequestHandler` registration is for.
|
|
35
|
+
*
|
|
36
|
+
* The two SDK majors disagree on what the first argument is: v1 passes the Zod
|
|
37
|
+
* schema for the request and carries the method as a literal on its shape, v2
|
|
38
|
+
* passes the method string itself. A registration we cannot name is one we
|
|
39
|
+
* cannot match against a patch — which is how a handler registered after
|
|
40
|
+
* `instrument()` on v2 ends up replacing our wrapper instead of being wrapped.
|
|
41
|
+
*/
|
|
42
|
+
export declare function readRequestHandlerMethod(requestSchema: unknown): string | undefined;
|
|
33
43
|
export declare function getLiteralValue(schema: unknown): unknown;
|
|
34
44
|
//# 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;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"}
|
|
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;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOnF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAkCxD"}
|
|
@@ -31,7 +31,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
31
31
|
getToolFunctionKey: ()=>getToolFunctionKey,
|
|
32
32
|
hasToolFunction: ()=>hasToolFunction,
|
|
33
33
|
isZ4Schema: ()=>isZ4Schema,
|
|
34
|
-
isZodRawShapeCompat: ()=>isZodRawShapeCompat
|
|
34
|
+
isZodRawShapeCompat: ()=>isZodRawShapeCompat,
|
|
35
|
+
readRequestHandlerMethod: ()=>readRequestHandlerMethod
|
|
35
36
|
});
|
|
36
37
|
function getToolFunction(tool) {
|
|
37
38
|
if ('handler' in tool && 'function' == typeof tool.handler) return tool.handler;
|
|
@@ -82,6 +83,12 @@ function getObjectShape(schema) {
|
|
|
82
83
|
}
|
|
83
84
|
return rawShape;
|
|
84
85
|
}
|
|
86
|
+
function readRequestHandlerMethod(requestSchema) {
|
|
87
|
+
if ('string' == typeof requestSchema) return requestSchema;
|
|
88
|
+
const shape = getObjectShape(requestSchema);
|
|
89
|
+
const method = shape?.method ? getLiteralValue(shape.method) : void 0;
|
|
90
|
+
return 'string' == typeof method ? method : void 0;
|
|
91
|
+
}
|
|
85
92
|
function getLiteralValue(schema) {
|
|
86
93
|
if (!schema || 'object' != typeof schema) return;
|
|
87
94
|
if (isZ4Schema(schema)) {
|
|
@@ -106,6 +113,7 @@ exports.getToolFunctionKey = __webpack_exports__.getToolFunctionKey;
|
|
|
106
113
|
exports.hasToolFunction = __webpack_exports__.hasToolFunction;
|
|
107
114
|
exports.isZ4Schema = __webpack_exports__.isZ4Schema;
|
|
108
115
|
exports.isZodRawShapeCompat = __webpack_exports__.isZodRawShapeCompat;
|
|
116
|
+
exports.readRequestHandlerMethod = __webpack_exports__.readRequestHandlerMethod;
|
|
109
117
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
110
118
|
"createWrappedTool",
|
|
111
119
|
"getLiteralValue",
|
|
@@ -114,7 +122,8 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
|
114
122
|
"getToolFunctionKey",
|
|
115
123
|
"hasToolFunction",
|
|
116
124
|
"isZ4Schema",
|
|
117
|
-
"isZodRawShapeCompat"
|
|
125
|
+
"isZodRawShapeCompat",
|
|
126
|
+
"readRequestHandlerMethod"
|
|
118
127
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
119
128
|
Object.defineProperty(exports, '__esModule', {
|
|
120
129
|
value: true
|
|
@@ -47,6 +47,12 @@ function getObjectShape(schema) {
|
|
|
47
47
|
}
|
|
48
48
|
return rawShape;
|
|
49
49
|
}
|
|
50
|
+
function readRequestHandlerMethod(requestSchema) {
|
|
51
|
+
if ('string' == typeof requestSchema) return requestSchema;
|
|
52
|
+
const shape = getObjectShape(requestSchema);
|
|
53
|
+
const method = shape?.method ? getLiteralValue(shape.method) : void 0;
|
|
54
|
+
return 'string' == typeof method ? method : void 0;
|
|
55
|
+
}
|
|
50
56
|
function getLiteralValue(schema) {
|
|
51
57
|
if (!schema || 'object' != typeof schema) return;
|
|
52
58
|
if (isZ4Schema(schema)) {
|
|
@@ -63,4 +69,4 @@ function getLiteralValue(schema) {
|
|
|
63
69
|
const directValue = schema.value;
|
|
64
70
|
if (void 0 !== directValue) return directValue;
|
|
65
71
|
}
|
|
66
|
-
export { createWrappedTool, getLiteralValue, getObjectShape, getToolFunction, getToolFunctionKey, hasToolFunction, isZ4Schema, isZodRawShapeCompat };
|
|
72
|
+
export { createWrappedTool, getLiteralValue, getObjectShape, getToolFunction, getToolFunctionKey, hasToolFunction, isZ4Schema, isZodRawShapeCompat, readRequestHandlerMethod };
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.10.
|
|
1
|
+
export declare const version = "0.10.9";
|
|
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.9';
|
|
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.9';
|
|
2
2
|
export { version };
|
package/package.json
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
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 { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'
|
|
7
6
|
import type { CompatibleRequestHandlerExtra, MCPRequestLike, MCPServerLike } from '../types'
|
|
8
7
|
import { MCPAnalyticsEventType } from './event-types'
|
|
9
8
|
import { getServerTrackingData } from './internal'
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
handleInitializeRequest,
|
|
14
13
|
handleListToolsRequest,
|
|
15
14
|
patchRequestHandlers,
|
|
15
|
+
registerFallbackRequestHandler,
|
|
16
16
|
captureToolCall,
|
|
17
17
|
isToolAdvertised,
|
|
18
18
|
type HandlerPatch,
|
|
@@ -34,23 +34,23 @@ export function instrumentLowLevelServer(server: MCPServerLike, logger: LoggerFn
|
|
|
34
34
|
try {
|
|
35
35
|
// Patch already existing handlers, and patch setRequestHandler to capture dynamically created handlers.
|
|
36
36
|
const hadCallToolHandler = server._requestHandlers.has('tools/call')
|
|
37
|
+
const traceToolCall: HandlerPatch = (server, originalHandler, request, extra) =>
|
|
38
|
+
handleToolCallRequest(server, originalHandler, request, extra, logger)
|
|
37
39
|
const handlers: Record<string, HandlerPatch> = {
|
|
38
40
|
initialize: (server, originalHandler, request, extra) =>
|
|
39
41
|
handleInitializeRequest(server, originalHandler, request, extra, logger),
|
|
40
42
|
'tools/list': (server, originalHandler, request, extra) =>
|
|
41
43
|
handleListToolsRequest(server, originalHandler, request, extra, logger),
|
|
42
|
-
'tools/call':
|
|
43
|
-
handleToolCallRequest(server, originalHandler, request, extra, logger),
|
|
44
|
+
'tools/call': traceToolCall,
|
|
44
45
|
}
|
|
45
46
|
patchRequestHandlers(server, handlers)
|
|
46
47
|
|
|
47
48
|
if (!hadCallToolHandler) {
|
|
48
|
-
// Register a raw fallback
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
})
|
|
49
|
+
// Register a raw fallback so reportMissing works even before an application
|
|
50
|
+
// dispatcher is attached. A later registration replaces it and is wrapped by
|
|
51
|
+
// the patched setRequestHandler. Written into the handler map directly — see
|
|
52
|
+
// registerFallbackRequestHandler for why the SDK setter is the wrong door.
|
|
53
|
+
registerFallbackRequestHandler(server, 'tools/call', unknownToolHandler, traceToolCall)
|
|
54
54
|
}
|
|
55
55
|
} catch (error) {
|
|
56
56
|
logger(`Warning: Failed to setup tool call instrumentation - ${error}`)
|
|
@@ -58,6 +58,11 @@ export function instrumentLowLevelServer(server: MCPServerLike, logger: LoggerFn
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/** Stands in for an application dispatcher that has not been attached yet. */
|
|
62
|
+
async function unknownToolHandler(request: MCPRequestLike): Promise<never> {
|
|
63
|
+
throw new Error(`Unknown tool: ${request.params?.name || 'unknown'}`)
|
|
64
|
+
}
|
|
65
|
+
|
|
61
66
|
async function handleToolCallRequest(
|
|
62
67
|
server: MCPServerLike,
|
|
63
68
|
originalCallToolHandler: MCPRequestHandler | undefined,
|
|
@@ -32,7 +32,7 @@ import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from
|
|
|
32
32
|
import { getServerTrackingData, handleIdentify, setServerTrackingData, withIdentity } from './internal'
|
|
33
33
|
import type { LoggerFn } from './logger'
|
|
34
34
|
import { buildCapturedMcpParameters } from './mcp-payloads'
|
|
35
|
-
import {
|
|
35
|
+
import { readRequestHandlerMethod } from './mcp-sdk-compat'
|
|
36
36
|
import { getSessionId, getSessionInfo, newSessionId } from './session'
|
|
37
37
|
import { encodeSessionId, readMcpSessionHeader, writeSessionIdToTransport } from './session-token'
|
|
38
38
|
import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from './tools'
|
|
@@ -386,6 +386,37 @@ function rememberOriginalRequestHandler(
|
|
|
386
386
|
handlers.set(handlerName, originalHandler)
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Registers a synthetic fallback handler for `handlerName`, already wrapped in
|
|
391
|
+
* `patch`, by writing straight into `_requestHandlers` instead of going through
|
|
392
|
+
* `setRequestHandler`.
|
|
393
|
+
*
|
|
394
|
+
* Bypassing the SDK setter is deliberate, on three counts:
|
|
395
|
+
*
|
|
396
|
+
* - **Capability assertion.** `setRequestHandler` refuses a method the server
|
|
397
|
+
* never declared a capability for, so instrumenting a low-level server built
|
|
398
|
+
* without `capabilities.tools` used to throw `Server does not support tools`
|
|
399
|
+
* and leave instrumentation half-applied. Our fallback is not a capability the
|
|
400
|
+
* server offers — it exists only so a call for a tool nobody claims is still
|
|
401
|
+
* captured — so the assertion has nothing to protect here.
|
|
402
|
+
* - **Schema validation.** The setter also wraps the handler in request/result
|
|
403
|
+
* parsing, which a handler that can only ever throw `Unknown tool` never needs.
|
|
404
|
+
* - **Portability.** The setter's first argument is a Zod schema on SDK v1 and a
|
|
405
|
+
* method string on v2; the map key is the same string on both, so this is the
|
|
406
|
+
* one registration form that does not need to know which major it is talking
|
|
407
|
+
* to — and it drops the last runtime `@modelcontextprotocol/sdk` import from
|
|
408
|
+
* the shipped bundle.
|
|
409
|
+
*/
|
|
410
|
+
export function registerFallbackRequestHandler(
|
|
411
|
+
server: MCPServerLike,
|
|
412
|
+
handlerName: string,
|
|
413
|
+
fallbackHandler: MCPRequestHandler,
|
|
414
|
+
patch: HandlerPatch
|
|
415
|
+
): void {
|
|
416
|
+
rememberOriginalRequestHandler(server, handlerName, fallbackHandler)
|
|
417
|
+
server._requestHandlers.set(handlerName, (request, extra) => patch(server, fallbackHandler, request, extra))
|
|
418
|
+
}
|
|
419
|
+
|
|
389
420
|
export function patchRequestHandlers(server: MCPServerLike, patches: Record<string, HandlerPatch>): void {
|
|
390
421
|
// Monkey patch existing handlers.
|
|
391
422
|
for (const [handlerName, patch] of Object.entries(patches)) {
|
|
@@ -397,18 +428,31 @@ export function patchRequestHandlers(server: MCPServerLike, patches: Record<stri
|
|
|
397
428
|
}
|
|
398
429
|
|
|
399
430
|
// Monkey patch dynamically added handlers (registered after instrument()).
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
431
|
+
//
|
|
432
|
+
// Variadic, and every argument is forwarded verbatim. The registration form is
|
|
433
|
+
// the SDK's business, not ours — only *that* a registration happened is ours.
|
|
434
|
+
// SDK v2 has a three-argument form for custom methods,
|
|
435
|
+
// `setRequestHandler(method, { params, result }, handler)`, and a two-parameter
|
|
436
|
+
// wrapper drops the handler: the SDK then sees the schemas object where the
|
|
437
|
+
// handler should be and throws `setRequestHandler: handler is required`, which
|
|
438
|
+
// takes down the host server rather than just our instrumentation.
|
|
439
|
+
const originalSetRequestHandler = server.setRequestHandler.bind(server) as (...args: unknown[]) => unknown
|
|
440
|
+
server.setRequestHandler = ((...args: unknown[]) => {
|
|
441
|
+
const handlerName = readRequestHandlerMethod(args[0])
|
|
442
|
+
// `hasOwnProperty`, not a bare index: `handlerName` is now an arbitrary
|
|
443
|
+
// caller-supplied string, and a custom method named `toString` would
|
|
444
|
+
// otherwise resolve to an inherited function and be treated as a patch.
|
|
445
|
+
const patch =
|
|
446
|
+
handlerName !== undefined && Object.prototype.hasOwnProperty.call(patches, handlerName)
|
|
447
|
+
? patches[handlerName]
|
|
448
|
+
: undefined
|
|
449
|
+
if (handlerName === undefined || !patch) {
|
|
450
|
+
return originalSetRequestHandler(...args)
|
|
407
451
|
}
|
|
408
452
|
|
|
409
453
|
// Register first so the MCP SDK's request/result validation stays inside
|
|
410
454
|
// our analytics wrapper, matching handlers that existed before instrument().
|
|
411
|
-
const result = originalSetRequestHandler(
|
|
455
|
+
const result = originalSetRequestHandler(...args)
|
|
412
456
|
const registeredHandler = server._requestHandlers.get(handlerName)
|
|
413
457
|
if (registeredHandler) {
|
|
414
458
|
rememberOriginalRequestHandler(server, handlerName, registeredHandler)
|
|
@@ -143,6 +143,24 @@ export function getObjectShape(schema: unknown): Record<string, unknown> | undef
|
|
|
143
143
|
return rawShape
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Reads the method name a `setRequestHandler` registration is for.
|
|
148
|
+
*
|
|
149
|
+
* The two SDK majors disagree on what the first argument is: v1 passes the Zod
|
|
150
|
+
* schema for the request and carries the method as a literal on its shape, v2
|
|
151
|
+
* passes the method string itself. A registration we cannot name is one we
|
|
152
|
+
* cannot match against a patch — which is how a handler registered after
|
|
153
|
+
* `instrument()` on v2 ends up replacing our wrapper instead of being wrapped.
|
|
154
|
+
*/
|
|
155
|
+
export function readRequestHandlerMethod(requestSchema: unknown): string | undefined {
|
|
156
|
+
if (typeof requestSchema === 'string') {
|
|
157
|
+
return requestSchema
|
|
158
|
+
}
|
|
159
|
+
const shape = getObjectShape(requestSchema)
|
|
160
|
+
const method = shape?.method ? getLiteralValue(shape.method) : undefined
|
|
161
|
+
return typeof method === 'string' ? method : undefined
|
|
162
|
+
}
|
|
163
|
+
|
|
146
164
|
export function getLiteralValue(schema: unknown): unknown {
|
|
147
165
|
if (!schema || typeof schema !== 'object') {
|
|
148
166
|
return
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.10.
|
|
1
|
+
export const version = '0.10.9'
|