@posthog/mcp 0.4.1 → 0.4.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/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-highlevel.js +11 -29
- package/dist/extensions/instrument-highlevel.mjs +13 -31
- package/dist/extensions/instrument-lowlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-lowlevel.js +5 -2
- package/dist/extensions/instrument-lowlevel.mjs +6 -3
- package/dist/extensions/instrumentation.d.ts +31 -9
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +42 -42
- package/dist/extensions/instrumentation.mjs +34 -37
- 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/instrument-highlevel.ts +19 -46
- package/src/extensions/instrument-lowlevel.ts +12 -3
- package/src/extensions/instrumentation.ts +69 -66
- package/src/version.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-highlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-highlevel.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAiC,sBAAsB,EAAiC,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"instrument-highlevel.d.ts","sourceRoot":"","sources":["../../src/extensions/instrument-highlevel.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAiC,sBAAsB,EAAiC,MAAM,UAAU,CAAA;AAqPpH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAwB9E"}
|
|
@@ -63,7 +63,6 @@ function setupListenerToRegisteredTools(server) {
|
|
|
63
63
|
return Reflect.set(target, property, value);
|
|
64
64
|
}
|
|
65
65
|
const nextValue = addTracingToToolCallbackInternal(value, property, server);
|
|
66
|
-
(0, external_instrumentation_js_namespaceObject.instrumentToolsListHandler)(server.server);
|
|
67
66
|
if ('function' == typeof nextValue.update) {
|
|
68
67
|
const originalUpdate = nextValue.update;
|
|
69
68
|
nextValue.update = function(...updateArgs) {
|
|
@@ -151,32 +150,11 @@ function addTracingToToolCallbackInternal(tool, toolName, server) {
|
|
|
151
150
|
wrappedTool[MCP_ANALYTICS_PROCESSED] = true;
|
|
152
151
|
return wrappedTool;
|
|
153
152
|
}
|
|
154
|
-
function
|
|
155
|
-
const lowLevelServer = server.server;
|
|
156
|
-
const existingHandler = lowLevelServer._requestHandlers.get('tools/call');
|
|
157
|
-
if (existingHandler) {
|
|
158
|
-
const wrappedHandler = createToolsCallWrapper(existingHandler, lowLevelServer);
|
|
159
|
-
lowLevelServer._requestHandlers.set('tools/call', wrappedHandler);
|
|
160
|
-
}
|
|
161
|
-
const originalSetRequestHandler = lowLevelServer.setRequestHandler.bind(lowLevelServer);
|
|
162
|
-
lowLevelServer.setRequestHandler = (requestSchema, handler)=>{
|
|
163
|
-
const shape = (0, external_mcp_sdk_compat_js_namespaceObject.getObjectShape)(requestSchema);
|
|
164
|
-
const method = shape?.method ? (0, external_mcp_sdk_compat_js_namespaceObject.getLiteralValue)(shape.method) : void 0;
|
|
165
|
-
if ('tools/call' === method) {
|
|
166
|
-
const wrappedHandler = createToolsCallWrapper(handler, lowLevelServer);
|
|
167
|
-
return originalSetRequestHandler(requestSchema, wrappedHandler);
|
|
168
|
-
}
|
|
169
|
-
return originalSetRequestHandler(requestSchema, handler);
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
function createToolsCallWrapper(originalHandler, server) {
|
|
173
|
-
return async (request, extra)=>await handleWrappedToolsCall(originalHandler, server, request, extra);
|
|
174
|
-
}
|
|
175
|
-
async function handleWrappedToolsCall(originalHandler, server, request, extra) {
|
|
153
|
+
async function handleToolCallRequest(server, originalCallToolHandler, request, extra) {
|
|
176
154
|
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
|
|
177
155
|
if (!data) {
|
|
178
156
|
(0, external_logger_js_namespaceObject.log)('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');
|
|
179
|
-
return await
|
|
157
|
+
return await originalCallToolHandler(request, extra);
|
|
180
158
|
}
|
|
181
159
|
if (request.params?.name === (0, external_tools_js_namespaceObject.resolveMissingCapabilityToolName)(data.options)) {
|
|
182
160
|
const context = (0, external_tracing_helpers_js_namespaceObject.getContextArgument)(request) || '';
|
|
@@ -197,7 +175,7 @@ async function handleWrappedToolsCall(originalHandler, server, request, extra) {
|
|
|
197
175
|
data,
|
|
198
176
|
request,
|
|
199
177
|
extra,
|
|
200
|
-
execute: ()=>
|
|
178
|
+
execute: ()=>originalCallToolHandler(request, extra),
|
|
201
179
|
takeCapturedError: ()=>{
|
|
202
180
|
const captured = extra?.__mcp_analytics_error;
|
|
203
181
|
if (extra) extra.__mcp_analytics_error = void 0;
|
|
@@ -207,15 +185,19 @@ async function handleWrappedToolsCall(originalHandler, server, request, extra) {
|
|
|
207
185
|
}
|
|
208
186
|
function instrumentHighLevelServer(server) {
|
|
209
187
|
try {
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
188
|
+
const lowLevelServer = server.server;
|
|
189
|
+
const mcpAnalyticsData = (0, external_internal_js_namespaceObject.getServerTrackingData)(lowLevelServer);
|
|
190
|
+
const handlers = {
|
|
191
|
+
initialize: external_instrumentation_js_namespaceObject.handleInitializeRequest,
|
|
192
|
+
'tools/list': external_instrumentation_js_namespaceObject.handleListToolsRequest,
|
|
193
|
+
'tools/call': handleToolCallRequest
|
|
194
|
+
};
|
|
195
|
+
(0, external_instrumentation_js_namespaceObject.patchRequestHandlers)(lowLevelServer, handlers);
|
|
213
196
|
server._registeredTools = addTracingToToolRegistry(server._registeredTools, server);
|
|
214
197
|
if (mcpAnalyticsData) {
|
|
215
198
|
seedToolDescriptionsFromRegistry(mcpAnalyticsData.toolDescriptions, server._registeredTools);
|
|
216
199
|
seedToolCategoriesFromRegistry(mcpAnalyticsData.toolCategories, server._registeredTools);
|
|
217
200
|
}
|
|
218
|
-
(0, external_instrumentation_js_namespaceObject.instrumentToolsListHandler)(server.server);
|
|
219
201
|
setupListenerToRegisteredTools(server);
|
|
220
202
|
} catch (error) {
|
|
221
203
|
(0, external_logger_js_namespaceObject.log)(`Warning: Failed to setup tool call instrumentation - ${error}`);
|
|
@@ -2,9 +2,9 @@ import { stripConversationId } from "./conversation-id.mjs";
|
|
|
2
2
|
import { MCPAnalyticsEventType } from "./event-types.mjs";
|
|
3
3
|
import { getServerTrackingData } from "./internal.mjs";
|
|
4
4
|
import { log } from "./logger.mjs";
|
|
5
|
-
import { createWrappedTool,
|
|
5
|
+
import { createWrappedTool, getToolFunction, hasToolFunction } from "./mcp-sdk-compat.mjs";
|
|
6
6
|
import { handleReportMissing, resolveMissingCapabilityToolName } from "./tools.mjs";
|
|
7
|
-
import { captureToolCall,
|
|
7
|
+
import { captureToolCall, handleInitializeRequest, handleListToolsRequest, patchRequestHandlers, readToolMetaCategory } from "./instrumentation.mjs";
|
|
8
8
|
import { getContextArgument } from "./tracing-helpers.mjs";
|
|
9
9
|
const wrappedCallbacks = new WeakMap();
|
|
10
10
|
const MCP_ANALYTICS_PROCESSED = Symbol('__posthog_mcp_analytics_processed__');
|
|
@@ -35,7 +35,6 @@ function setupListenerToRegisteredTools(server) {
|
|
|
35
35
|
return Reflect.set(target, property, value);
|
|
36
36
|
}
|
|
37
37
|
const nextValue = addTracingToToolCallbackInternal(value, property, server);
|
|
38
|
-
instrumentToolsListHandler(server.server);
|
|
39
38
|
if ('function' == typeof nextValue.update) {
|
|
40
39
|
const originalUpdate = nextValue.update;
|
|
41
40
|
nextValue.update = function(...updateArgs) {
|
|
@@ -123,32 +122,11 @@ function addTracingToToolCallbackInternal(tool, toolName, server) {
|
|
|
123
122
|
wrappedTool[MCP_ANALYTICS_PROCESSED] = true;
|
|
124
123
|
return wrappedTool;
|
|
125
124
|
}
|
|
126
|
-
function
|
|
127
|
-
const lowLevelServer = server.server;
|
|
128
|
-
const existingHandler = lowLevelServer._requestHandlers.get('tools/call');
|
|
129
|
-
if (existingHandler) {
|
|
130
|
-
const wrappedHandler = createToolsCallWrapper(existingHandler, lowLevelServer);
|
|
131
|
-
lowLevelServer._requestHandlers.set('tools/call', wrappedHandler);
|
|
132
|
-
}
|
|
133
|
-
const originalSetRequestHandler = lowLevelServer.setRequestHandler.bind(lowLevelServer);
|
|
134
|
-
lowLevelServer.setRequestHandler = (requestSchema, handler)=>{
|
|
135
|
-
const shape = getObjectShape(requestSchema);
|
|
136
|
-
const method = shape?.method ? getLiteralValue(shape.method) : void 0;
|
|
137
|
-
if ('tools/call' === method) {
|
|
138
|
-
const wrappedHandler = createToolsCallWrapper(handler, lowLevelServer);
|
|
139
|
-
return originalSetRequestHandler(requestSchema, wrappedHandler);
|
|
140
|
-
}
|
|
141
|
-
return originalSetRequestHandler(requestSchema, handler);
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
function createToolsCallWrapper(originalHandler, server) {
|
|
145
|
-
return async (request, extra)=>await handleWrappedToolsCall(originalHandler, server, request, extra);
|
|
146
|
-
}
|
|
147
|
-
async function handleWrappedToolsCall(originalHandler, server, request, extra) {
|
|
125
|
+
async function handleToolCallRequest(server, originalCallToolHandler, request, extra) {
|
|
148
126
|
const data = getServerTrackingData(server);
|
|
149
127
|
if (!data) {
|
|
150
128
|
log('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');
|
|
151
|
-
return await
|
|
129
|
+
return await originalCallToolHandler(request, extra);
|
|
152
130
|
}
|
|
153
131
|
if (request.params?.name === resolveMissingCapabilityToolName(data.options)) {
|
|
154
132
|
const context = getContextArgument(request) || '';
|
|
@@ -169,7 +147,7 @@ async function handleWrappedToolsCall(originalHandler, server, request, extra) {
|
|
|
169
147
|
data,
|
|
170
148
|
request,
|
|
171
149
|
extra,
|
|
172
|
-
execute: ()=>
|
|
150
|
+
execute: ()=>originalCallToolHandler(request, extra),
|
|
173
151
|
takeCapturedError: ()=>{
|
|
174
152
|
const captured = extra?.__mcp_analytics_error;
|
|
175
153
|
if (extra) extra.__mcp_analytics_error = void 0;
|
|
@@ -179,15 +157,19 @@ async function handleWrappedToolsCall(originalHandler, server, request, extra) {
|
|
|
179
157
|
}
|
|
180
158
|
function instrumentHighLevelServer(server) {
|
|
181
159
|
try {
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
160
|
+
const lowLevelServer = server.server;
|
|
161
|
+
const mcpAnalyticsData = getServerTrackingData(lowLevelServer);
|
|
162
|
+
const handlers = {
|
|
163
|
+
initialize: handleInitializeRequest,
|
|
164
|
+
'tools/list': handleListToolsRequest,
|
|
165
|
+
'tools/call': handleToolCallRequest
|
|
166
|
+
};
|
|
167
|
+
patchRequestHandlers(lowLevelServer, handlers);
|
|
185
168
|
server._registeredTools = addTracingToToolRegistry(server._registeredTools, server);
|
|
186
169
|
if (mcpAnalyticsData) {
|
|
187
170
|
seedToolDescriptionsFromRegistry(mcpAnalyticsData.toolDescriptions, server._registeredTools);
|
|
188
171
|
seedToolCategoriesFromRegistry(mcpAnalyticsData.toolCategories, server._registeredTools);
|
|
189
172
|
}
|
|
190
|
-
instrumentToolsListHandler(server.server);
|
|
191
173
|
setupListenerToRegisteredTools(server);
|
|
192
174
|
} catch (error) {
|
|
193
175
|
log(`Warning: Failed to setup tool call instrumentation - ${error}`);
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAmB5F;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAkBpE"}
|
|
@@ -35,8 +35,11 @@ const external_instrumentation_js_namespaceObject = require("./instrumentation.j
|
|
|
35
35
|
const external_tracing_helpers_js_namespaceObject = require("./tracing-helpers.js");
|
|
36
36
|
function instrumentLowLevelServer(server) {
|
|
37
37
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const handlers = {
|
|
39
|
+
initialize: external_instrumentation_js_namespaceObject.handleInitializeRequest,
|
|
40
|
+
'tools/list': external_instrumentation_js_namespaceObject.handleListToolsRequest
|
|
41
|
+
};
|
|
42
|
+
(0, external_instrumentation_js_namespaceObject.patchRequestHandlers)(server, handlers);
|
|
40
43
|
const originalCallToolHandler = server._requestHandlers.get('tools/call');
|
|
41
44
|
server.setRequestHandler(types_js_namespaceObject.CallToolRequestSchema, async (request, extra)=>await handleToolCallRequest(server, originalCallToolHandler, request, extra));
|
|
42
45
|
} catch (error) {
|
|
@@ -3,12 +3,15 @@ import { MCPAnalyticsEventType } from "./event-types.mjs";
|
|
|
3
3
|
import { getServerTrackingData } from "./internal.mjs";
|
|
4
4
|
import { log } from "./logger.mjs";
|
|
5
5
|
import { handleReportMissing, resolveMissingCapabilityToolName } from "./tools.mjs";
|
|
6
|
-
import { captureToolCall,
|
|
6
|
+
import { captureToolCall, handleInitializeRequest, handleListToolsRequest, patchRequestHandlers } from "./instrumentation.mjs";
|
|
7
7
|
import { getContextArgument } from "./tracing-helpers.mjs";
|
|
8
8
|
function instrumentLowLevelServer(server) {
|
|
9
9
|
try {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const handlers = {
|
|
11
|
+
initialize: handleInitializeRequest,
|
|
12
|
+
'tools/list': handleListToolsRequest
|
|
13
|
+
};
|
|
14
|
+
patchRequestHandlers(server, handlers);
|
|
12
15
|
const originalCallToolHandler = server._requestHandlers.get('tools/call');
|
|
13
16
|
server.setRequestHandler(CallToolRequestSchema, async (request, extra)=>await handleToolCallRequest(server, originalCallToolHandler, request, extra));
|
|
14
17
|
} catch (error) {
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ListToolsResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import type { CompatibleRequestHandlerExtra, MCPAnalyticsData, MCPRequestLike, MCPServerLike } from '../types';
|
|
3
3
|
import { MCPAnalyticsEventType } from './event-types';
|
|
4
|
+
/**
|
|
5
|
+
* Single instrumentation core shared by the low-level (`Server`) and high-level
|
|
6
|
+
* (`McpServer`) wrappers. The two entrypoints differ only in how they reach the
|
|
7
|
+
* underlying tool — they both funnel the tool-call lifecycle through
|
|
8
|
+
* {@link captureToolCall}, so error handling, conversation-id minting, session
|
|
9
|
+
* attribution, and event capture are defined exactly once.
|
|
10
|
+
*/
|
|
11
|
+
type MCPRequestHandler = (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Promise<unknown>;
|
|
4
12
|
/**
|
|
5
13
|
* Runs the underlying tool. Receives the request with the SDK-injected
|
|
6
14
|
* `conversation_id` stripped; an adapter is free to ignore it (the high-level
|
|
@@ -43,12 +51,26 @@ interface TraceToolCallParams {
|
|
|
43
51
|
*/
|
|
44
52
|
export declare function captureToolCall(params: TraceToolCallParams): Promise<unknown>;
|
|
45
53
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
|
|
54
|
+
* A method's patch: runs the original handler and captures analytics. `server`
|
|
55
|
+
* and `originalHandler` are bound by {@link patchRequestHandlers}; the SDK
|
|
56
|
+
* supplies `request` and `extra` per call.
|
|
57
|
+
*/
|
|
58
|
+
export type HandlerPatch = (server: MCPServerLike, originalHandler: MCPRequestHandler, request: MCPRequestLike, extra: CompatibleRequestHandlerExtra | undefined) => Promise<unknown>;
|
|
59
|
+
/**
|
|
60
|
+
* Applies the `patches` (keyed by method, e.g. `initialize`, `tools/list`) to the
|
|
61
|
+
* handlers already registered, and patches `setRequestHandler` so matching
|
|
62
|
+
* handlers registered later are patched too. The latter is what makes adapters
|
|
63
|
+
* that register handlers post-construction work — e.g. `@rekog/mcp-nest` hands a
|
|
64
|
+
* bare server to instrument() and only then registers its handlers.
|
|
65
|
+
*/
|
|
66
|
+
export declare function patchRequestHandlers(server: MCPServerLike, patches: Record<string, HandlerPatch>): void;
|
|
67
|
+
/**
|
|
68
|
+
* Captures each `tools/list` and injects the SDK-managed tools (context
|
|
69
|
+
* parameter, conversation id, `get_more_tools`) into the returned list.
|
|
50
70
|
*/
|
|
51
|
-
export declare function
|
|
71
|
+
export declare function handleListToolsRequest(server: MCPServerLike, originalListToolsHandler: MCPRequestHandler, request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra): Promise<{
|
|
72
|
+
tools: ListToolsResult['tools'];
|
|
73
|
+
}>;
|
|
52
74
|
export declare function cacheToolDescriptions(cache: Map<string, string>, tools: ListToolsResult['tools'] | undefined): void;
|
|
53
75
|
/**
|
|
54
76
|
* Category declared on a tool's `_meta` block (the MCP spec allows arbitrary
|
|
@@ -58,9 +80,9 @@ export declare function cacheToolDescriptions(cache: Map<string, string>, tools:
|
|
|
58
80
|
export declare function readToolMetaCategory(meta: unknown): string | undefined;
|
|
59
81
|
export declare function cacheToolCategories(cache: Map<string, string>, tools: ListToolsResult['tools'] | undefined): void;
|
|
60
82
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
83
|
+
* Captures the connection handshake (and resolves identity) on `initialize`
|
|
84
|
+
* before the original handler runs.
|
|
63
85
|
*/
|
|
64
|
-
export declare function
|
|
86
|
+
export declare function handleInitializeRequest(server: MCPServerLike, originalInitializeHandler: MCPRequestHandler, request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra): Promise<unknown>;
|
|
65
87
|
export {};
|
|
66
88
|
//# sourceMappingURL=instrumentation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/extensions/instrumentation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAY,MAAM,UAAU,CAAA;AAWxH,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAWrD;;;;;;GAMG;AAEH,KAAK,iBAAiB,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,6BAA6B,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE7G;;;;GAIG;AACH,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;;;;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,CAuCnF;AAgHD;;;;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;AAErB;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CAqBvG;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,aAAa,EACrB,wBAAwB,EAAE,iBAAiB,EAC3C,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC;IAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAwC9C;AAwDD,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;AAID;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,aAAa,EACrB,yBAAyB,EAAE,iBAAiB,EAC5C,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,6BAA6B,GACpC,OAAO,CAAC,OAAO,CAAC,CA0BlB"}
|
|
@@ -27,11 +27,11 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
27
27
|
readToolMetaCategory: ()=>readToolMetaCategory,
|
|
28
28
|
cacheToolDescriptions: ()=>cacheToolDescriptions,
|
|
29
29
|
cacheToolCategories: ()=>cacheToolCategories,
|
|
30
|
+
handleInitializeRequest: ()=>handleInitializeRequest,
|
|
30
31
|
captureToolCall: ()=>captureToolCall,
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
handleListToolsRequest: ()=>handleListToolsRequest,
|
|
33
|
+
patchRequestHandlers: ()=>patchRequestHandlers
|
|
33
34
|
});
|
|
34
|
-
const types_js_namespaceObject = require("@modelcontextprotocol/sdk/types.js");
|
|
35
35
|
const external_context_parameters_js_namespaceObject = require("./context-parameters.js");
|
|
36
36
|
const external_conversation_id_js_namespaceObject = require("./conversation-id.js");
|
|
37
37
|
const external_capture_js_namespaceObject = require("./capture.js");
|
|
@@ -41,6 +41,7 @@ const external_intent_js_namespaceObject = require("./intent.js");
|
|
|
41
41
|
const external_internal_js_namespaceObject = require("./internal.js");
|
|
42
42
|
const external_logger_js_namespaceObject = require("./logger.js");
|
|
43
43
|
const external_mcp_payloads_js_namespaceObject = require("./mcp-payloads.js");
|
|
44
|
+
const external_mcp_sdk_compat_js_namespaceObject = require("./mcp-sdk-compat.js");
|
|
44
45
|
const external_session_js_namespaceObject = require("./session.js");
|
|
45
46
|
const external_tools_js_namespaceObject = require("./tools.js");
|
|
46
47
|
const external_tracing_helpers_js_namespaceObject = require("./tracing-helpers.js");
|
|
@@ -118,18 +119,19 @@ function publishFailedToolEvent(server, event, error, startTime, conversation) {
|
|
|
118
119
|
(0, external_logger_js_namespaceObject.log)(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`);
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const originalListToolsHandler = server._requestHandlers.get('tools/list');
|
|
126
|
-
if (!originalListToolsHandler) return;
|
|
127
|
-
try {
|
|
128
|
-
server.setRequestHandler(types_js_namespaceObject.ListToolsRequestSchema, async (request, extra)=>await handleListToolsRequest(server, originalListToolsHandler, request, extra));
|
|
129
|
-
listToolsTracingSetup.set(server, true);
|
|
130
|
-
} catch (error) {
|
|
131
|
-
(0, external_logger_js_namespaceObject.log)(`Warning: Failed to override list tools handler - ${error}`);
|
|
122
|
+
function patchRequestHandlers(server, patches) {
|
|
123
|
+
for (const [handlerName, patch] of Object.entries(patches)){
|
|
124
|
+
const originalHandler = server._requestHandlers.get(handlerName);
|
|
125
|
+
if (originalHandler) server._requestHandlers.set(handlerName, (request, extra)=>patch(server, originalHandler, request, extra));
|
|
132
126
|
}
|
|
127
|
+
const originalSetRequestHandler = server.setRequestHandler.bind(server);
|
|
128
|
+
server.setRequestHandler = (requestSchema, originalHandler)=>{
|
|
129
|
+
const shape = (0, external_mcp_sdk_compat_js_namespaceObject.getObjectShape)(requestSchema);
|
|
130
|
+
const handlerName = shape?.method ? (0, external_mcp_sdk_compat_js_namespaceObject.getLiteralValue)(shape.method) : void 0;
|
|
131
|
+
const patch = 'string' == typeof handlerName ? patches[handlerName] : void 0;
|
|
132
|
+
if (!patch) return originalSetRequestHandler(requestSchema, originalHandler);
|
|
133
|
+
return originalSetRequestHandler(requestSchema, (request, extra)=>patch(server, originalHandler, request, extra));
|
|
134
|
+
};
|
|
133
135
|
}
|
|
134
136
|
async function handleListToolsRequest(server, originalListToolsHandler, request, extra) {
|
|
135
137
|
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
|
|
@@ -215,43 +217,41 @@ function cacheToolCategories(cache, tools) {
|
|
|
215
217
|
if (category) cache.set(tool.name, category);
|
|
216
218
|
}
|
|
217
219
|
}
|
|
218
|
-
function
|
|
219
|
-
const
|
|
220
|
-
if (!
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
event.response = result;
|
|
239
|
-
(0, external_capture_js_namespaceObject.captureEvent)(server, event);
|
|
240
|
-
return result;
|
|
241
|
-
});
|
|
220
|
+
async function handleInitializeRequest(server, originalInitializeHandler, request, extra) {
|
|
221
|
+
const data = (0, external_internal_js_namespaceObject.getServerTrackingData)(server);
|
|
222
|
+
if (!data) {
|
|
223
|
+
(0, external_logger_js_namespaceObject.log)('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');
|
|
224
|
+
return await originalInitializeHandler(request, extra);
|
|
225
|
+
}
|
|
226
|
+
const sessionId = (0, external_session_js_namespaceObject.getServerSessionId)(server, extra);
|
|
227
|
+
await (0, external_internal_js_namespaceObject.handleIdentify)(server, data, sessionId, request, extra);
|
|
228
|
+
const event = {
|
|
229
|
+
sessionId,
|
|
230
|
+
resourceName: request.params?.name || 'Unknown Tool Name',
|
|
231
|
+
eventType: external_event_types_js_namespaceObject.MCPAnalyticsEventType.mcpInitialize,
|
|
232
|
+
parameters: (0, external_mcp_payloads_js_namespaceObject.buildCapturedMcpParameters)(request),
|
|
233
|
+
timestamp: new Date()
|
|
234
|
+
};
|
|
235
|
+
await (0, external_tracing_helpers_js_namespaceObject.applyResolvedMetadata)(event, data, request, extra);
|
|
236
|
+
const result = await originalInitializeHandler(request, extra);
|
|
237
|
+
event.response = result;
|
|
238
|
+
(0, external_capture_js_namespaceObject.captureEvent)(server, event);
|
|
239
|
+
return result;
|
|
242
240
|
}
|
|
243
241
|
exports.cacheToolCategories = __webpack_exports__.cacheToolCategories;
|
|
244
242
|
exports.cacheToolDescriptions = __webpack_exports__.cacheToolDescriptions;
|
|
245
243
|
exports.captureToolCall = __webpack_exports__.captureToolCall;
|
|
246
|
-
exports.
|
|
247
|
-
exports.
|
|
244
|
+
exports.handleInitializeRequest = __webpack_exports__.handleInitializeRequest;
|
|
245
|
+
exports.handleListToolsRequest = __webpack_exports__.handleListToolsRequest;
|
|
246
|
+
exports.patchRequestHandlers = __webpack_exports__.patchRequestHandlers;
|
|
248
247
|
exports.readToolMetaCategory = __webpack_exports__.readToolMetaCategory;
|
|
249
248
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
250
249
|
"cacheToolCategories",
|
|
251
250
|
"cacheToolDescriptions",
|
|
252
251
|
"captureToolCall",
|
|
253
|
-
"
|
|
254
|
-
"
|
|
252
|
+
"handleInitializeRequest",
|
|
253
|
+
"handleListToolsRequest",
|
|
254
|
+
"patchRequestHandlers",
|
|
255
255
|
"readToolMetaCategory"
|
|
256
256
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
257
257
|
Object.defineProperty(exports, '__esModule', {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { InitializeRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2
1
|
import { addContextParameterToTools, getContextDescription, isContextEnabled } from "./context-parameters.mjs";
|
|
3
2
|
import { addConversationIdToTools, canInjectConversationIdPromptBack, cloneRequestWithoutConversationId, injectConversationIdPromptBack, resolveConversationId } from "./conversation-id.mjs";
|
|
4
3
|
import { captureEvent } from "./capture.mjs";
|
|
@@ -8,6 +7,7 @@ import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from
|
|
|
8
7
|
import { getServerTrackingData, handleIdentify } from "./internal.mjs";
|
|
9
8
|
import { log } from "./logger.mjs";
|
|
10
9
|
import { buildCapturedMcpParameters } from "./mcp-payloads.mjs";
|
|
10
|
+
import { getLiteralValue, getObjectShape } from "./mcp-sdk-compat.mjs";
|
|
11
11
|
import { getServerSessionId } from "./session.mjs";
|
|
12
12
|
import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from "./tools.mjs";
|
|
13
13
|
import { applyResolvedMetadata, isToolResultError } from "./tracing-helpers.mjs";
|
|
@@ -85,18 +85,19 @@ function publishFailedToolEvent(server, event, error, startTime, conversation) {
|
|
|
85
85
|
log(`Warning: PostHog MCP analytics failed to publish failed tool event - ${publishError}`);
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const originalListToolsHandler = server._requestHandlers.get('tools/list');
|
|
93
|
-
if (!originalListToolsHandler) return;
|
|
94
|
-
try {
|
|
95
|
-
server.setRequestHandler(ListToolsRequestSchema, async (request, extra)=>await handleListToolsRequest(server, originalListToolsHandler, request, extra));
|
|
96
|
-
listToolsTracingSetup.set(server, true);
|
|
97
|
-
} catch (error) {
|
|
98
|
-
log(`Warning: Failed to override list tools handler - ${error}`);
|
|
88
|
+
function patchRequestHandlers(server, patches) {
|
|
89
|
+
for (const [handlerName, patch] of Object.entries(patches)){
|
|
90
|
+
const originalHandler = server._requestHandlers.get(handlerName);
|
|
91
|
+
if (originalHandler) server._requestHandlers.set(handlerName, (request, extra)=>patch(server, originalHandler, request, extra));
|
|
99
92
|
}
|
|
93
|
+
const originalSetRequestHandler = server.setRequestHandler.bind(server);
|
|
94
|
+
server.setRequestHandler = (requestSchema, originalHandler)=>{
|
|
95
|
+
const shape = getObjectShape(requestSchema);
|
|
96
|
+
const handlerName = shape?.method ? getLiteralValue(shape.method) : void 0;
|
|
97
|
+
const patch = 'string' == typeof handlerName ? patches[handlerName] : void 0;
|
|
98
|
+
if (!patch) return originalSetRequestHandler(requestSchema, originalHandler);
|
|
99
|
+
return originalSetRequestHandler(requestSchema, (request, extra)=>patch(server, originalHandler, request, extra));
|
|
100
|
+
};
|
|
100
101
|
}
|
|
101
102
|
async function handleListToolsRequest(server, originalListToolsHandler, request, extra) {
|
|
102
103
|
const data = getServerTrackingData(server);
|
|
@@ -182,29 +183,25 @@ function cacheToolCategories(cache, tools) {
|
|
|
182
183
|
if (category) cache.set(tool.name, category);
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
|
-
function
|
|
186
|
-
const
|
|
187
|
-
if (!
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
event.response = result;
|
|
206
|
-
captureEvent(server, event);
|
|
207
|
-
return result;
|
|
208
|
-
});
|
|
186
|
+
async function handleInitializeRequest(server, originalInitializeHandler, request, extra) {
|
|
187
|
+
const data = getServerTrackingData(server);
|
|
188
|
+
if (!data) {
|
|
189
|
+
log('Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.');
|
|
190
|
+
return await originalInitializeHandler(request, extra);
|
|
191
|
+
}
|
|
192
|
+
const sessionId = getServerSessionId(server, extra);
|
|
193
|
+
await handleIdentify(server, data, sessionId, request, extra);
|
|
194
|
+
const event = {
|
|
195
|
+
sessionId,
|
|
196
|
+
resourceName: request.params?.name || 'Unknown Tool Name',
|
|
197
|
+
eventType: MCPAnalyticsEventType.mcpInitialize,
|
|
198
|
+
parameters: buildCapturedMcpParameters(request),
|
|
199
|
+
timestamp: new Date()
|
|
200
|
+
};
|
|
201
|
+
await applyResolvedMetadata(event, data, request, extra);
|
|
202
|
+
const result = await originalInitializeHandler(request, extra);
|
|
203
|
+
event.response = result;
|
|
204
|
+
captureEvent(server, event);
|
|
205
|
+
return result;
|
|
209
206
|
}
|
|
210
|
-
export { cacheToolCategories, cacheToolDescriptions, captureToolCall,
|
|
207
|
+
export { cacheToolCategories, cacheToolDescriptions, captureToolCall, handleInitializeRequest, handleListToolsRequest, patchRequestHandlers, readToolMetaCategory };
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.4.
|
|
1
|
+
export declare const version = "0.4.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.4.
|
|
29
|
+
const version = '0.4.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.4.
|
|
1
|
+
const version = '0.4.3';
|
|
2
2
|
export { version };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/mcp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.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.38.0"
|
|
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.38.5",
|
|
43
|
+
"@posthog-tooling/tsconfig-base": "1.1.1"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@modelcontextprotocol/sdk": ">=1.26.0",
|
|
@@ -8,11 +8,12 @@ import { stripConversationId } from './conversation-id'
|
|
|
8
8
|
import { MCPAnalyticsEventType } from './event-types'
|
|
9
9
|
import { getServerTrackingData } from './internal'
|
|
10
10
|
import { log } from './logger'
|
|
11
|
-
import { createWrappedTool,
|
|
11
|
+
import { createWrappedTool, getToolFunction, hasToolFunction } from './mcp-sdk-compat'
|
|
12
12
|
import { handleReportMissing, resolveMissingCapabilityToolName } from './tools'
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
handleInitializeRequest,
|
|
15
|
+
handleListToolsRequest,
|
|
16
|
+
patchRequestHandlers,
|
|
16
17
|
captureToolCall,
|
|
17
18
|
readToolMetaCategory,
|
|
18
19
|
} from './instrumentation'
|
|
@@ -72,8 +73,6 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
72
73
|
|
|
73
74
|
const nextValue = addTracingToToolCallbackInternal(value, property, server)
|
|
74
75
|
|
|
75
|
-
instrumentToolsListHandler(server.server as MCPServerLike)
|
|
76
|
-
|
|
77
76
|
if (typeof nextValue.update === 'function') {
|
|
78
77
|
const originalUpdate = nextValue.update
|
|
79
78
|
nextValue.update = function (...updateArgs: unknown[]) {
|
|
@@ -130,7 +129,7 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
130
129
|
* (the high-level SDK turns thrown errors into `isError` results otherwise).
|
|
131
130
|
*
|
|
132
131
|
* This is purely the tool-facing concern; event capture lives in
|
|
133
|
-
* {@link captureToolCall} via {@link
|
|
132
|
+
* {@link captureToolCall} via {@link handleToolCallRequest}.
|
|
134
133
|
*/
|
|
135
134
|
function addTracingToToolCallbackInternal(
|
|
136
135
|
tool: RegisteredTool,
|
|
@@ -202,38 +201,9 @@ function addTracingToToolCallbackInternal(
|
|
|
202
201
|
return wrappedTool
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
function
|
|
206
|
-
const lowLevelServer = server.server as MCPServerLike
|
|
207
|
-
|
|
208
|
-
const existingHandler = lowLevelServer._requestHandlers.get('tools/call')
|
|
209
|
-
if (existingHandler) {
|
|
210
|
-
const wrappedHandler = createToolsCallWrapper(existingHandler, lowLevelServer)
|
|
211
|
-
lowLevelServer._requestHandlers.set('tools/call', wrappedHandler)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const originalSetRequestHandler = lowLevelServer.setRequestHandler.bind(lowLevelServer)
|
|
215
|
-
|
|
216
|
-
lowLevelServer.setRequestHandler = ((requestSchema: unknown, handler: MCPRequestHandler) => {
|
|
217
|
-
const shape = getObjectShape(requestSchema)
|
|
218
|
-
const method = shape?.method ? getLiteralValue(shape.method) : undefined
|
|
219
|
-
|
|
220
|
-
if (method === 'tools/call') {
|
|
221
|
-
const wrappedHandler = createToolsCallWrapper(handler, lowLevelServer)
|
|
222
|
-
return originalSetRequestHandler(requestSchema, wrappedHandler)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return originalSetRequestHandler(requestSchema, handler)
|
|
226
|
-
}) as MCPServerLike['setRequestHandler']
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function createToolsCallWrapper(originalHandler: MCPRequestHandler, server: MCPServerLike): MCPRequestHandler {
|
|
230
|
-
return async (request: MCPRequest, extra: MCPRequestExtra) =>
|
|
231
|
-
await handleWrappedToolsCall(originalHandler, server, request, extra)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
async function handleWrappedToolsCall(
|
|
235
|
-
originalHandler: MCPRequestHandler,
|
|
204
|
+
async function handleToolCallRequest(
|
|
236
205
|
server: MCPServerLike,
|
|
206
|
+
originalCallToolHandler: MCPRequestHandler,
|
|
237
207
|
request: MCPRequest,
|
|
238
208
|
extra: MCPRequestExtra
|
|
239
209
|
): Promise<unknown> {
|
|
@@ -242,7 +212,7 @@ async function handleWrappedToolsCall(
|
|
|
242
212
|
log(
|
|
243
213
|
'Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.'
|
|
244
214
|
)
|
|
245
|
-
return await
|
|
215
|
+
return await originalCallToolHandler(request, extra)
|
|
246
216
|
}
|
|
247
217
|
|
|
248
218
|
if (request.params?.name === resolveMissingCapabilityToolName(data.options)) {
|
|
@@ -267,7 +237,7 @@ async function handleWrappedToolsCall(
|
|
|
267
237
|
data,
|
|
268
238
|
request,
|
|
269
239
|
extra,
|
|
270
|
-
execute: () =>
|
|
240
|
+
execute: () => originalCallToolHandler(request, extra),
|
|
271
241
|
takeCapturedError: () => {
|
|
272
242
|
const captured = extra?.__mcp_analytics_error
|
|
273
243
|
if (extra) {
|
|
@@ -280,11 +250,16 @@ async function handleWrappedToolsCall(
|
|
|
280
250
|
|
|
281
251
|
export function instrumentHighLevelServer(server: HighLevelMCPServerLike): void {
|
|
282
252
|
try {
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
253
|
+
const lowLevelServer = server.server
|
|
254
|
+
const mcpAnalyticsData = getServerTrackingData(lowLevelServer)
|
|
255
|
+
|
|
256
|
+
// Patch already existing handlers, and patch setRequestHandler to capture dynamically created handlers.
|
|
257
|
+
const handlers = {
|
|
258
|
+
initialize: handleInitializeRequest,
|
|
259
|
+
'tools/list': handleListToolsRequest,
|
|
260
|
+
'tools/call': handleToolCallRequest,
|
|
261
|
+
}
|
|
262
|
+
patchRequestHandlers(lowLevelServer, handlers)
|
|
288
263
|
|
|
289
264
|
server._registeredTools = addTracingToToolRegistry(server._registeredTools, server)
|
|
290
265
|
|
|
@@ -293,8 +268,6 @@ export function instrumentHighLevelServer(server: HighLevelMCPServerLike): void
|
|
|
293
268
|
seedToolCategoriesFromRegistry(mcpAnalyticsData.toolCategories, server._registeredTools)
|
|
294
269
|
}
|
|
295
270
|
|
|
296
|
-
instrumentToolsListHandler(server.server)
|
|
297
|
-
|
|
298
271
|
setupListenerToRegisteredTools(server)
|
|
299
272
|
} catch (error) {
|
|
300
273
|
log(`Warning: Failed to setup tool call instrumentation - ${error}`)
|
|
@@ -8,7 +8,12 @@ import { MCPAnalyticsEventType } from './event-types'
|
|
|
8
8
|
import { getServerTrackingData } from './internal'
|
|
9
9
|
import { log } from './logger'
|
|
10
10
|
import { handleReportMissing, resolveMissingCapabilityToolName } from './tools'
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
handleInitializeRequest,
|
|
13
|
+
handleListToolsRequest,
|
|
14
|
+
patchRequestHandlers,
|
|
15
|
+
captureToolCall,
|
|
16
|
+
} from './instrumentation'
|
|
12
17
|
import { getContextArgument } from './tracing-helpers'
|
|
13
18
|
|
|
14
19
|
type MCPRequestHandler = NonNullable<
|
|
@@ -24,8 +29,12 @@ type MCPRequestExtra = Parameters<MCPRequestHandler>[1]
|
|
|
24
29
|
*/
|
|
25
30
|
export function instrumentLowLevelServer(server: MCPServerLike): void {
|
|
26
31
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
// Patch already existing handlers, and patch setRequestHandler to capture dynamically created handlers.
|
|
33
|
+
const handlers = {
|
|
34
|
+
initialize: handleInitializeRequest,
|
|
35
|
+
'tools/list': handleListToolsRequest,
|
|
36
|
+
}
|
|
37
|
+
patchRequestHandlers(server, handlers)
|
|
29
38
|
|
|
30
39
|
const originalCallToolHandler = server._requestHandlers.get('tools/call')
|
|
31
40
|
server.setRequestHandler(
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
// Copyright (c) 2025 MCPcat
|
|
3
3
|
// Licensed under the MIT License: https://github.com/MCPCat/mcpcat-typescript-sdk/blob/main/LICENSE
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
InitializeRequestSchema,
|
|
7
|
-
ListToolsRequestSchema,
|
|
8
|
-
type ListToolsResult,
|
|
9
|
-
} from '@modelcontextprotocol/sdk/types.js'
|
|
5
|
+
import type { ListToolsResult } from '@modelcontextprotocol/sdk/types.js'
|
|
10
6
|
import type { CompatibleRequestHandlerExtra, MCPAnalyticsData, MCPRequestLike, MCPServerLike, McpEvent } from '../types'
|
|
11
7
|
import { addContextParameterToTools, getContextDescription, isContextEnabled } from './context-parameters'
|
|
12
8
|
import {
|
|
@@ -24,6 +20,7 @@ import { resolveToolCallIntent, setEventIntent, setExplicitContextIntent } from
|
|
|
24
20
|
import { getServerTrackingData, handleIdentify } from './internal'
|
|
25
21
|
import { log } from './logger'
|
|
26
22
|
import { buildCapturedMcpParameters } from './mcp-payloads'
|
|
23
|
+
import { getLiteralValue, getObjectShape } from './mcp-sdk-compat'
|
|
27
24
|
import { getServerSessionId } from './session'
|
|
28
25
|
import { getReportMissingToolDescriptor, resolveMissingCapabilityToolName } from './tools'
|
|
29
26
|
import { applyResolvedMetadata, isToolResultError } from './tracing-helpers'
|
|
@@ -231,45 +228,53 @@ function publishFailedToolEvent(
|
|
|
231
228
|
|
|
232
229
|
// --- tools/list -----------------------------------------------------------
|
|
233
230
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
231
|
+
/**
|
|
232
|
+
* A method's patch: runs the original handler and captures analytics. `server`
|
|
233
|
+
* and `originalHandler` are bound by {@link patchRequestHandlers}; the SDK
|
|
234
|
+
* supplies `request` and `extra` per call.
|
|
235
|
+
*/
|
|
236
|
+
export type HandlerPatch = (
|
|
237
|
+
server: MCPServerLike,
|
|
238
|
+
originalHandler: MCPRequestHandler,
|
|
239
|
+
request: MCPRequestLike,
|
|
240
|
+
extra: CompatibleRequestHandlerExtra | undefined
|
|
241
|
+
) => Promise<unknown>
|
|
241
242
|
|
|
242
243
|
/**
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
244
|
+
* Applies the `patches` (keyed by method, e.g. `initialize`, `tools/list`) to the
|
|
245
|
+
* handlers already registered, and patches `setRequestHandler` so matching
|
|
246
|
+
* handlers registered later are patched too. The latter is what makes adapters
|
|
247
|
+
* that register handlers post-construction work — e.g. `@rekog/mcp-nest` hands a
|
|
248
|
+
* bare server to instrument() and only then registers its handlers.
|
|
247
249
|
*/
|
|
248
|
-
export function
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
250
|
+
export function patchRequestHandlers(server: MCPServerLike, patches: Record<string, HandlerPatch>): void {
|
|
251
|
+
// Monkey patch existing handlers.
|
|
252
|
+
for (const [handlerName, patch] of Object.entries(patches)) {
|
|
253
|
+
const originalHandler = server._requestHandlers.get(handlerName)
|
|
254
|
+
if (originalHandler) {
|
|
255
|
+
server._requestHandlers.set(handlerName, (request, extra) => patch(server, originalHandler, request, extra))
|
|
256
|
+
}
|
|
254
257
|
}
|
|
255
258
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
// Monkey patch dynamically added handlers (registered after instrument()).
|
|
260
|
+
const originalSetRequestHandler = server.setRequestHandler.bind(server)
|
|
261
|
+
server.setRequestHandler = ((requestSchema: unknown, originalHandler: MCPRequestHandler) => {
|
|
262
|
+
const shape = getObjectShape(requestSchema)
|
|
263
|
+
const handlerName = shape?.method ? getLiteralValue(shape.method) : undefined
|
|
264
|
+
const patch = typeof handlerName === 'string' ? patches[handlerName] : undefined
|
|
265
|
+
if (!patch) {
|
|
266
|
+
return originalSetRequestHandler(requestSchema, originalHandler)
|
|
267
|
+
}
|
|
260
268
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
ListToolsRequestSchema,
|
|
264
|
-
async (request, extra) => await handleListToolsRequest(server, originalListToolsHandler, request, extra)
|
|
265
|
-
)
|
|
266
|
-
listToolsTracingSetup.set(server, true)
|
|
267
|
-
} catch (error) {
|
|
268
|
-
log(`Warning: Failed to override list tools handler - ${error}`)
|
|
269
|
-
}
|
|
269
|
+
return originalSetRequestHandler(requestSchema, (request, extra) => patch(server, originalHandler, request, extra))
|
|
270
|
+
}) as MCPServerLike['setRequestHandler']
|
|
270
271
|
}
|
|
271
272
|
|
|
272
|
-
|
|
273
|
+
/**
|
|
274
|
+
* Captures each `tools/list` and injects the SDK-managed tools (context
|
|
275
|
+
* parameter, conversation id, `get_more_tools`) into the returned list.
|
|
276
|
+
*/
|
|
277
|
+
export async function handleListToolsRequest(
|
|
273
278
|
server: MCPServerLike,
|
|
274
279
|
originalListToolsHandler: MCPRequestHandler,
|
|
275
280
|
request: MCPRequestLike,
|
|
@@ -406,40 +411,38 @@ export function cacheToolCategories(cache: Map<string, string>, tools: ListTools
|
|
|
406
411
|
// --- initialize -----------------------------------------------------------
|
|
407
412
|
|
|
408
413
|
/**
|
|
409
|
-
*
|
|
410
|
-
*
|
|
414
|
+
* Captures the connection handshake (and resolves identity) on `initialize`
|
|
415
|
+
* before the original handler runs.
|
|
411
416
|
*/
|
|
412
|
-
export function
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
417
|
+
export async function handleInitializeRequest(
|
|
418
|
+
server: MCPServerLike,
|
|
419
|
+
originalInitializeHandler: MCPRequestHandler,
|
|
420
|
+
request: MCPRequestLike,
|
|
421
|
+
extra?: CompatibleRequestHandlerExtra
|
|
422
|
+
): Promise<unknown> {
|
|
423
|
+
const data = getServerTrackingData(server)
|
|
424
|
+
if (!data) {
|
|
425
|
+
log(
|
|
426
|
+
'Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.'
|
|
427
|
+
)
|
|
428
|
+
return await originalInitializeHandler(request, extra)
|
|
416
429
|
}
|
|
417
430
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (!data) {
|
|
421
|
-
log(
|
|
422
|
-
'Warning: PostHog MCP analytics is unable to find server tracking data. Please ensure you have called instrument(server, options) before using tool calls.'
|
|
423
|
-
)
|
|
424
|
-
return await originalInitializeHandler(request, extra)
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const sessionId = getServerSessionId(server, extra)
|
|
428
|
-
await handleIdentify(server, data, sessionId, request, extra)
|
|
431
|
+
const sessionId = getServerSessionId(server, extra)
|
|
432
|
+
await handleIdentify(server, data, sessionId, request, extra)
|
|
429
433
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
434
|
+
const event: McpEvent = {
|
|
435
|
+
sessionId,
|
|
436
|
+
resourceName: request.params?.name || 'Unknown Tool Name',
|
|
437
|
+
eventType: MCPAnalyticsEventType.mcpInitialize,
|
|
438
|
+
parameters: buildCapturedMcpParameters(request),
|
|
439
|
+
timestamp: new Date(),
|
|
440
|
+
}
|
|
437
441
|
|
|
438
|
-
|
|
442
|
+
await applyResolvedMetadata(event, data, request, extra)
|
|
439
443
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
})
|
|
444
|
+
const result = await originalInitializeHandler(request, extra)
|
|
445
|
+
event.response = result
|
|
446
|
+
captureEvent(server, event)
|
|
447
|
+
return result
|
|
445
448
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.4.
|
|
1
|
+
export const version = '0.4.3'
|