@posthog/mcp 0.10.2 → 0.10.4
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 +17 -0
- package/dist/extensions/analytics-parameters.d.ts.map +1 -0
- package/dist/extensions/analytics-parameters.js +98 -0
- package/dist/extensions/analytics-parameters.mjs +52 -0
- package/dist/extensions/context-parameters.d.ts +3 -12
- 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 -17
- package/dist/extensions/conversation-id.d.ts.map +1 -1
- package/dist/extensions/conversation-id.js +6 -23
- package/dist/extensions/conversation-id.mjs +4 -19
- package/dist/extensions/instrument-highlevel.d.ts.map +1 -1
- package/dist/extensions/instrument-highlevel.js +19 -16
- package/dist/extensions/instrument-highlevel.mjs +19 -16
- package/dist/extensions/instrumentation.d.ts +4 -6
- package/dist/extensions/instrumentation.d.ts.map +1 -1
- package/dist/extensions/instrumentation.js +32 -6
- package/dist/extensions/instrumentation.mjs +33 -7
- package/dist/extensions/intent.d.ts +1 -1
- package/dist/extensions/intent.d.ts.map +1 -1
- package/dist/extensions/intent.js +2 -2
- package/dist/extensions/intent.mjs +2 -2
- 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/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +4 -4
- package/src/extensions/analytics-parameters.ts +89 -0
- package/src/extensions/context-parameters.ts +16 -24
- package/src/extensions/conversation-id.ts +18 -43
- package/src/extensions/instrument-highlevel.ts +42 -22
- package/src/extensions/instrumentation.ts +71 -11
- package/src/extensions/intent.ts +7 -1
- package/src/extensions/mcp-sdk-compat.ts +15 -0
- package/src/index.ts +1 -0
- package/src/types.ts +6 -0
- package/src/version.ts +1 -1
|
@@ -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/$ref). 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 = {}
|
|
@@ -137,25 +131,6 @@ export function extractConversationId(args: unknown): string | undefined {
|
|
|
137
131
|
return trimmed.length > 0 ? trimmed : undefined
|
|
138
132
|
}
|
|
139
133
|
|
|
140
|
-
export function cloneRequestWithoutConversationId<
|
|
141
|
-
TRequest extends { params?: { arguments?: unknown; [k: string]: unknown } },
|
|
142
|
-
>(request: TRequest): TRequest {
|
|
143
|
-
if (!request.params || typeof request.params !== 'object') {
|
|
144
|
-
return request
|
|
145
|
-
}
|
|
146
|
-
const args = request.params.arguments
|
|
147
|
-
if (!(args && typeof args === 'object')) {
|
|
148
|
-
return request
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
...request,
|
|
152
|
-
params: {
|
|
153
|
-
...request.params,
|
|
154
|
-
arguments: stripConversationId(args) as typeof request.params.arguments,
|
|
155
|
-
},
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
134
|
export function stripConversationId(args: unknown): unknown {
|
|
160
135
|
if (!args || typeof args !== 'object' || !(CONVERSATION_ID_PARAM_NAME in (args as Record<string, unknown>))) {
|
|
161
136
|
return args
|
|
@@ -11,7 +11,12 @@ import type {
|
|
|
11
11
|
RegisteredTool,
|
|
12
12
|
ToolCallback,
|
|
13
13
|
} from '../types'
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
analyticsOwnsParameter,
|
|
16
|
+
getAnalyticsParameterOwnership,
|
|
17
|
+
stripOwnedAnalyticsArguments,
|
|
18
|
+
} from './analytics-parameters'
|
|
19
|
+
import { isContextEnabled } from './context-parameters'
|
|
15
20
|
import { MCPAnalyticsEventType } from './event-types'
|
|
16
21
|
import { getServerTrackingData } from './internal'
|
|
17
22
|
import { log } from './logger'
|
|
@@ -78,7 +83,10 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
78
83
|
return Reflect.set(target, property, value)
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
|
|
86
|
+
// The MCP SDK's registry copy is currently stale after update(), but keep this lookup lazy so
|
|
87
|
+
// ownership follows the current schema once the registry reflects live tool state.
|
|
88
|
+
const getCurrentInputSchema = () => value.inputSchema
|
|
89
|
+
const nextValue = addTracingToToolCallbackInternal(value, property, server, getCurrentInputSchema)
|
|
82
90
|
|
|
83
91
|
if (typeof nextValue.update === 'function') {
|
|
84
92
|
const originalUpdate = nextValue.update
|
|
@@ -89,7 +97,8 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
89
97
|
const wrappedTool = addTracingToToolCallbackInternal(
|
|
90
98
|
{ callback: updateObj.callback },
|
|
91
99
|
property,
|
|
92
|
-
server
|
|
100
|
+
server,
|
|
101
|
+
getCurrentInputSchema
|
|
93
102
|
)
|
|
94
103
|
updateObj.callback = getToolFunction(wrappedTool)
|
|
95
104
|
}
|
|
@@ -141,12 +150,12 @@ function setupListenerToRegisteredTools(server: HighLevelMCPServerLike): void {
|
|
|
141
150
|
function addTracingToToolCallbackInternal(
|
|
142
151
|
tool: RegisteredTool,
|
|
143
152
|
toolName: string,
|
|
144
|
-
server: HighLevelMCPServerLike
|
|
153
|
+
server: HighLevelMCPServerLike,
|
|
154
|
+
getCurrentInputSchema: () => unknown = () => tool.inputSchema
|
|
145
155
|
): RegisteredTool {
|
|
146
156
|
const originalCallback = getToolFunction(tool)
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
)
|
|
157
|
+
const options = getServerTrackingData(server.server as MCPServerLike)?.options
|
|
158
|
+
const missingToolName = resolveMissingCapabilityToolName(options)
|
|
150
159
|
|
|
151
160
|
if (wrappedCallbacks.has(originalCallback)) {
|
|
152
161
|
log(`Tool ${toolName} callback already wrapped, skipping re-wrap`)
|
|
@@ -170,15 +179,17 @@ function addTracingToToolCallbackInternal(
|
|
|
170
179
|
extra = params[0] as CompatibleRequestHandlerExtra
|
|
171
180
|
}
|
|
172
181
|
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
+
const inputSchema = getCurrentInputSchema()
|
|
183
|
+
const cleanedArgs = stripOwnedAnalyticsArguments(args, {
|
|
184
|
+
context:
|
|
185
|
+
toolName !== missingToolName &&
|
|
186
|
+
isContextEnabled(options?.context) &&
|
|
187
|
+
analyticsOwnsParameter(inputSchema, 'context'),
|
|
188
|
+
conversationId:
|
|
189
|
+
toolName !== missingToolName &&
|
|
190
|
+
options?.enableConversationId === true &&
|
|
191
|
+
analyticsOwnsParameter(inputSchema, 'conversation_id'),
|
|
192
|
+
})
|
|
182
193
|
|
|
183
194
|
try {
|
|
184
195
|
if (cleanedArgs === undefined) {
|
|
@@ -209,6 +220,7 @@ function addTracingToToolCallbackInternal(
|
|
|
209
220
|
}
|
|
210
221
|
|
|
211
222
|
async function handleToolCallRequest(
|
|
223
|
+
highLevelServer: HighLevelMCPServerLike,
|
|
212
224
|
server: MCPServerLike,
|
|
213
225
|
originalCallToolHandler: MCPRequestHandler,
|
|
214
226
|
request: MCPRequest,
|
|
@@ -235,16 +247,19 @@ async function handleToolCallRequest(
|
|
|
235
247
|
})
|
|
236
248
|
}
|
|
237
249
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
//
|
|
250
|
+
const toolName = request.params?.name
|
|
251
|
+
const registeredTool = toolName ? highLevelServer._registeredTools[toolName] : undefined
|
|
252
|
+
|
|
253
|
+
// Strip SDK-owned arguments before the MCP SDK validates the registered Zod
|
|
254
|
+
// schema. The callback wrapper repeats the ownership-aware cleanup as a
|
|
255
|
+
// defensive fallback for direct callback invocation.
|
|
242
256
|
return await captureToolCall({
|
|
243
257
|
server,
|
|
244
258
|
data,
|
|
245
259
|
request,
|
|
246
260
|
extra,
|
|
247
|
-
execute: () => originalCallToolHandler(
|
|
261
|
+
execute: (downstreamRequest) => originalCallToolHandler(downstreamRequest as MCPRequest, extra),
|
|
262
|
+
parameterOwnership: registeredTool ? getAnalyticsParameterOwnership(registeredTool.inputSchema) : undefined,
|
|
248
263
|
takeCapturedError: () => {
|
|
249
264
|
const captured = extra?.__mcp_analytics_error
|
|
250
265
|
if (extra) {
|
|
@@ -264,7 +279,12 @@ export function instrumentHighLevelServer(server: HighLevelMCPServerLike): void
|
|
|
264
279
|
const handlers = {
|
|
265
280
|
initialize: handleInitializeRequest,
|
|
266
281
|
'tools/list': handleListToolsRequest,
|
|
267
|
-
'tools/call':
|
|
282
|
+
'tools/call': (
|
|
283
|
+
trackedServer: MCPServerLike,
|
|
284
|
+
originalHandler: MCPRequestHandler,
|
|
285
|
+
request: MCPRequest,
|
|
286
|
+
extra: MCPRequestExtra
|
|
287
|
+
) => handleToolCallRequest(server, trackedServer, originalHandler, request, extra),
|
|
268
288
|
}
|
|
269
289
|
patchRequestHandlers(lowLevelServer, handlers)
|
|
270
290
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { ListToolsResult } from '@modelcontextprotocol/sdk/types.js'
|
|
7
7
|
import type {
|
|
8
|
+
AnalyticsParameterOwnership,
|
|
8
9
|
CompatibleRequestHandlerExtra,
|
|
9
10
|
MCPAnalyticsData,
|
|
10
11
|
MCPRequestLike,
|
|
@@ -12,12 +13,12 @@ import type {
|
|
|
12
13
|
McpEvent,
|
|
13
14
|
ServerClientInfoLike,
|
|
14
15
|
} from '../types'
|
|
16
|
+
import { getAnalyticsParameterOwnership, stripOwnedAnalyticsArguments } from './analytics-parameters'
|
|
15
17
|
import { addContextParameterToTools, getContextDescription, isContextEnabled } from './context-parameters'
|
|
16
18
|
import {
|
|
17
19
|
addConversationIdToTools,
|
|
18
20
|
type ConversationIdResolution,
|
|
19
21
|
canInjectConversationIdPromptBack,
|
|
20
|
-
cloneRequestWithoutConversationId,
|
|
21
22
|
injectConversationIdPromptBack,
|
|
22
23
|
resolveConversationId,
|
|
23
24
|
} from './conversation-id'
|
|
@@ -45,11 +46,7 @@ import { applyResolvedMetadata, isToolResultError } from './tracing-helpers'
|
|
|
45
46
|
|
|
46
47
|
type MCPRequestHandler = (request: MCPRequestLike, extra?: CompatibleRequestHandlerExtra) => Promise<unknown>
|
|
47
48
|
|
|
48
|
-
/**
|
|
49
|
-
* Runs the underlying tool. Receives the request with the SDK-injected
|
|
50
|
-
* `conversation_id` stripped; an adapter is free to ignore it (the high-level
|
|
51
|
-
* path strips arguments inside the wrapped callback instead).
|
|
52
|
-
*/
|
|
49
|
+
/** Runs the underlying tool with SDK-owned analytics arguments removed. */
|
|
53
50
|
type ToolExecutor = (downstreamRequest: MCPRequestLike) => Promise<unknown>
|
|
54
51
|
|
|
55
52
|
interface TraceToolCallParams {
|
|
@@ -58,6 +55,8 @@ interface TraceToolCallParams {
|
|
|
58
55
|
request: MCPRequestLike
|
|
59
56
|
extra?: CompatibleRequestHandlerExtra
|
|
60
57
|
execute: ToolExecutor
|
|
58
|
+
/** Optional schema-derived ownership override for adapters with direct registry access. */
|
|
59
|
+
parameterOwnership?: AnalyticsParameterOwnership
|
|
61
60
|
/**
|
|
62
61
|
* Event type to capture. Defaults to a tool call; the `get_more_tools` virtual
|
|
63
62
|
* tool passes `mcpMissingCapability` so it records a capability gap rather than
|
|
@@ -88,15 +87,26 @@ interface TraceToolCallParams {
|
|
|
88
87
|
* throws, and the tool's own errors are always re-thrown to the caller.
|
|
89
88
|
*/
|
|
90
89
|
export async function captureToolCall(params: TraceToolCallParams): Promise<unknown> {
|
|
91
|
-
const {
|
|
92
|
-
|
|
90
|
+
const {
|
|
91
|
+
server,
|
|
92
|
+
data,
|
|
93
|
+
request,
|
|
94
|
+
extra,
|
|
95
|
+
execute,
|
|
96
|
+
parameterOwnership,
|
|
97
|
+
eventType,
|
|
98
|
+
explicitContextIntent,
|
|
99
|
+
takeCapturedError,
|
|
100
|
+
} = params
|
|
101
|
+
|
|
102
|
+
const ownership = getActiveAnalyticsParameterOwnership(data, request.params?.name, parameterOwnership)
|
|
93
103
|
const conversation = resolveConversationId(
|
|
94
|
-
|
|
104
|
+
ownership.conversationId,
|
|
95
105
|
request.params?.arguments,
|
|
96
106
|
request.params?.name,
|
|
97
107
|
resolveMissingCapabilityToolName(data.options)
|
|
98
108
|
)
|
|
99
|
-
const downstreamRequest =
|
|
109
|
+
const downstreamRequest = cloneRequestWithoutOwnedAnalyticsArguments(request, ownership)
|
|
100
110
|
|
|
101
111
|
// Prepare the event in isolation: if identity/metadata/intent resolution
|
|
102
112
|
// throws, we drop instrumentation for this call but still run the tool.
|
|
@@ -109,6 +119,7 @@ export async function captureToolCall(params: TraceToolCallParams): Promise<unkn
|
|
|
109
119
|
extra,
|
|
110
120
|
startTime,
|
|
111
121
|
conversation,
|
|
122
|
+
ownership,
|
|
112
123
|
eventType ?? MCPAnalyticsEventType.mcpToolsCall
|
|
113
124
|
)
|
|
114
125
|
if (event && explicitContextIntent) {
|
|
@@ -128,6 +139,38 @@ export async function captureToolCall(params: TraceToolCallParams): Promise<unkn
|
|
|
128
139
|
return finalResult
|
|
129
140
|
}
|
|
130
141
|
|
|
142
|
+
function getActiveAnalyticsParameterOwnership(
|
|
143
|
+
data: MCPAnalyticsData,
|
|
144
|
+
toolName: string | undefined,
|
|
145
|
+
override?: AnalyticsParameterOwnership
|
|
146
|
+
): AnalyticsParameterOwnership {
|
|
147
|
+
const ownership = override ?? (toolName ? data.toolAnalyticsParameterOwnership.get(toolName) : undefined)
|
|
148
|
+
const isMissingCapabilityTool = toolName === resolveMissingCapabilityToolName(data.options)
|
|
149
|
+
return {
|
|
150
|
+
context: !isMissingCapabilityTool && isContextEnabled(data.options.context) && ownership?.context === true,
|
|
151
|
+
conversationId:
|
|
152
|
+
!isMissingCapabilityTool && data.options.enableConversationId === true && ownership?.conversationId === true,
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function cloneRequestWithoutOwnedAnalyticsArguments(
|
|
157
|
+
request: MCPRequestLike,
|
|
158
|
+
ownership: AnalyticsParameterOwnership
|
|
159
|
+
): MCPRequestLike {
|
|
160
|
+
const args = request.params?.arguments
|
|
161
|
+
const cleanedArgs = stripOwnedAnalyticsArguments(args, ownership)
|
|
162
|
+
if (cleanedArgs === args || !request.params) {
|
|
163
|
+
return request
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
...request,
|
|
167
|
+
params: {
|
|
168
|
+
...request.params,
|
|
169
|
+
arguments: cleanedArgs as typeof request.params.arguments,
|
|
170
|
+
},
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
131
174
|
async function prepareToolCallEvent(
|
|
132
175
|
server: MCPServerLike,
|
|
133
176
|
data: MCPAnalyticsData,
|
|
@@ -136,6 +179,7 @@ async function prepareToolCallEvent(
|
|
|
136
179
|
extra: CompatibleRequestHandlerExtra | undefined,
|
|
137
180
|
startTime: Date,
|
|
138
181
|
conversation: ConversationIdResolution,
|
|
182
|
+
ownership: AnalyticsParameterOwnership,
|
|
139
183
|
eventType: MCPAnalyticsEventType
|
|
140
184
|
): Promise<McpEvent | null> {
|
|
141
185
|
try {
|
|
@@ -159,7 +203,7 @@ async function prepareToolCallEvent(
|
|
|
159
203
|
stampMetaClientInfo(event, request)
|
|
160
204
|
|
|
161
205
|
await applyResolvedMetadata(event, data, request, extra)
|
|
162
|
-
setEventIntent(event, await resolveToolCallIntent(data, request, extra))
|
|
206
|
+
setEventIntent(event, await resolveToolCallIntent(data, request, ownership.context, extra))
|
|
163
207
|
return event
|
|
164
208
|
} catch (error) {
|
|
165
209
|
log(
|
|
@@ -336,6 +380,18 @@ export async function handleListToolsRequest(
|
|
|
336
380
|
return { tools }
|
|
337
381
|
}
|
|
338
382
|
|
|
383
|
+
function cacheToolAnalyticsParameterOwnership(
|
|
384
|
+
cache: Map<string, AnalyticsParameterOwnership>,
|
|
385
|
+
tools: ListToolsResult['tools']
|
|
386
|
+
): void {
|
|
387
|
+
// Merge pages and concurrent enumerations; repeated tool names overwrite stale schemas.
|
|
388
|
+
for (const tool of tools) {
|
|
389
|
+
if (tool?.name) {
|
|
390
|
+
cache.set(tool.name, getAnalyticsParameterOwnership(tool.inputSchema))
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
339
395
|
function collectListedToolNames(tools: ListToolsResult['tools'] | undefined): string[] | undefined {
|
|
340
396
|
if (!tools || tools.length === 0) {
|
|
341
397
|
return
|
|
@@ -356,6 +412,10 @@ async function getTracedToolsList(
|
|
|
356
412
|
const originalResponse = (await originalListToolsHandler(request, extra)) as ListToolsResult
|
|
357
413
|
let tools = originalResponse.tools || []
|
|
358
414
|
|
|
415
|
+
if (data) {
|
|
416
|
+
cacheToolAnalyticsParameterOwnership(data.toolAnalyticsParameterOwnership, tools)
|
|
417
|
+
}
|
|
418
|
+
|
|
359
419
|
if (data && isContextEnabled(data.options.context)) {
|
|
360
420
|
tools = addContextParameterToTools(tools, getContextDescription(data.options.context))
|
|
361
421
|
}
|
package/src/extensions/intent.ts
CHANGED
|
@@ -53,10 +53,16 @@ async function runIntentFallback(
|
|
|
53
53
|
export async function resolveToolCallIntent(
|
|
54
54
|
data: MCPAnalyticsData,
|
|
55
55
|
request: MCPRequestLike,
|
|
56
|
+
analyticsOwnsContext: boolean,
|
|
56
57
|
extra?: CompatibleRequestHandlerExtra
|
|
57
58
|
): Promise<ResolvedIntent | null> {
|
|
58
59
|
const contextArgument = getContextArgument(request)
|
|
59
|
-
if (
|
|
60
|
+
if (
|
|
61
|
+
analyticsOwnsContext &&
|
|
62
|
+
isContextEnabled(data.options.context) &&
|
|
63
|
+
request.params?.name !== 'get_more_tools' &&
|
|
64
|
+
contextArgument
|
|
65
|
+
) {
|
|
60
66
|
return { intent: contextArgument, source: 'context_parameter' }
|
|
61
67
|
}
|
|
62
68
|
|
|
@@ -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
|
package/src/index.ts
CHANGED
|
@@ -143,6 +143,7 @@ function buildTrackingData(
|
|
|
143
143
|
sessionId: newSessionId(),
|
|
144
144
|
lastActivity: new Date(),
|
|
145
145
|
identifiedSessions: new IdentityCache(),
|
|
146
|
+
toolAnalyticsParameterOwnership: new Map(),
|
|
146
147
|
toolCategories: new Map<string, string>(),
|
|
147
148
|
toolDescriptions: new Map<string, string>(),
|
|
148
149
|
sessionInfo: getSessionInfo(lowLevelServer, undefined),
|
package/src/types.ts
CHANGED
|
@@ -271,6 +271,11 @@ export interface SessionInfo {
|
|
|
271
271
|
serverVersion?: string
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
export interface AnalyticsParameterOwnership {
|
|
275
|
+
context: boolean
|
|
276
|
+
conversationId: boolean
|
|
277
|
+
}
|
|
278
|
+
|
|
274
279
|
export interface MCPAnalyticsData {
|
|
275
280
|
sink: McpEventSink | undefined
|
|
276
281
|
identifiedSessions: IdentityCache
|
|
@@ -280,6 +285,7 @@ export interface MCPAnalyticsData {
|
|
|
280
285
|
sessionInfo: SessionInfo
|
|
281
286
|
/** `token` = recovered from a self-encoded `Mcp-Session-Id` token (see session-token.ts). */
|
|
282
287
|
sessionSource: 'generated' | 'mcp' | 'token'
|
|
288
|
+
toolAnalyticsParameterOwnership: Map<string, AnalyticsParameterOwnership>
|
|
283
289
|
toolCategories: Map<string, string>
|
|
284
290
|
toolDescriptions: Map<string, string>
|
|
285
291
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.10.
|
|
1
|
+
export const version = '0.10.4'
|