@agent-inspect/mcp 6.31.24 → 6.31.26
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/index.cjs +48 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +49 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,37 @@ function hashServerUrl(url) {
|
|
|
34
34
|
return hash.toString(16).padStart(8, "0");
|
|
35
35
|
}
|
|
36
36
|
var toolCallCounter = 0;
|
|
37
|
+
function resultReportsToolError(value) {
|
|
38
|
+
if (!value || typeof value !== "object") return false;
|
|
39
|
+
const record = value;
|
|
40
|
+
if (record.isError === true) return true;
|
|
41
|
+
const nested = record.toolResult;
|
|
42
|
+
if (!nested || typeof nested !== "object") return false;
|
|
43
|
+
return nested.isError === true;
|
|
44
|
+
}
|
|
45
|
+
function boundedId(value) {
|
|
46
|
+
if (typeof value !== "string") return void 0;
|
|
47
|
+
const trimmed = value.trim();
|
|
48
|
+
if (trimmed === "" || trimmed.length > 200) return void 0;
|
|
49
|
+
return trimmed;
|
|
50
|
+
}
|
|
51
|
+
async function recordToolResultOutcome(toolName, toolCallId, result, callMetadata) {
|
|
52
|
+
if (!resultReportsToolError(result)) return;
|
|
53
|
+
const operationId = boundedId(callMetadata.operationId);
|
|
54
|
+
const attemptId = boundedId(callMetadata.attemptId);
|
|
55
|
+
await agentInspect.observeOutcome(`mcp:${toolName}:tool-result`, {
|
|
56
|
+
expectation: "MCP tool result is not an error",
|
|
57
|
+
status: "failed",
|
|
58
|
+
method: "custom",
|
|
59
|
+
evidence: {
|
|
60
|
+
toolFailure: true,
|
|
61
|
+
toolName,
|
|
62
|
+
toolCallId,
|
|
63
|
+
...operationId !== void 0 ? { operationId } : {},
|
|
64
|
+
...attemptId !== void 0 ? { attemptId } : {}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
37
68
|
function nextToolCallId(prefix) {
|
|
38
69
|
toolCallCounter += 1;
|
|
39
70
|
const base = prefix?.trim() || "mcp";
|
|
@@ -164,14 +195,29 @@ function wrapMcpClient(client, options = {}) {
|
|
|
164
195
|
resultSchemaOrOptions,
|
|
165
196
|
maybeOptions
|
|
166
197
|
);
|
|
198
|
+
const toolCallId = nextToolCallId(options.toolCallIdPrefix);
|
|
167
199
|
return agentInspect.step(
|
|
168
200
|
`mcp:${params.name}`,
|
|
169
|
-
async () =>
|
|
201
|
+
async () => {
|
|
202
|
+
const result = await invokeCallTool(
|
|
203
|
+
callToolImpl,
|
|
204
|
+
params,
|
|
205
|
+
resultSchema,
|
|
206
|
+
requestOptions
|
|
207
|
+
);
|
|
208
|
+
await recordToolResultOutcome(
|
|
209
|
+
params.name,
|
|
210
|
+
toolCallId,
|
|
211
|
+
result,
|
|
212
|
+
callMetadata
|
|
213
|
+
);
|
|
214
|
+
return result;
|
|
215
|
+
},
|
|
170
216
|
{
|
|
171
217
|
type: "tool",
|
|
172
218
|
metadata: baseMetadata(options, {
|
|
173
219
|
toolName: params.name,
|
|
174
|
-
toolCallId
|
|
220
|
+
toolCallId,
|
|
175
221
|
argumentSummary: summarizeMcpValue(
|
|
176
222
|
params.arguments ?? {},
|
|
177
223
|
maxSummaryLength
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/summarize.ts","../src/wrap.ts"],"names":["step"],"mappings":"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","file":"index.cjs","sourcesContent":["const DEFAULT_MAX_SUMMARY_LENGTH = 240;\n\nfunction fallbackString(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"[unserializable]\";\n }\n}\n\nexport function summarizeMcpValue(\n value: unknown,\n maxLength = DEFAULT_MAX_SUMMARY_LENGTH,\n): string {\n let text: string;\n try {\n if (typeof value === \"string\") {\n text = value;\n } else {\n // JSON.stringify returns undefined (not a string) for undefined,\n // functions, and symbols; falling through with undefined would crash\n // instrumentation at text.length below.\n const serialized = JSON.stringify(value);\n text = serialized === undefined ? fallbackString(value) : serialized;\n }\n } catch {\n text = fallbackString(value);\n }\n if (text.length <= maxLength) return text;\n return `${text.slice(0, Math.max(0, maxLength - 3))}...`;\n}\n\nexport function hashServerUrl(url: string): string {\n let hash = 0;\n for (let i = 0; i < url.length; i += 1) {\n hash = (hash * 31 + url.charCodeAt(i)) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n","import { step } from \"agent-inspect\";\n\nimport { hashServerUrl, summarizeMcpValue } from \"./summarize.js\";\nimport type {\n McpClientLike,\n McpClientTracerOptions,\n McpRequestOptions,\n McpTraceMetadata,\n} from \"./types.js\";\n\nlet toolCallCounter = 0;\n\nfunction nextToolCallId(prefix?: string): string {\n toolCallCounter += 1;\n const base = prefix?.trim() || \"mcp\";\n return `${base}-${toolCallCounter}`;\n}\n\nfunction baseMetadata(\n options: McpClientTracerOptions,\n overrides: Partial<McpTraceMetadata> = {},\n): Record<string, unknown> {\n const metadata: McpTraceMetadata = {\n source: { type: \"mcp-client\" },\n ...(options.serverName ? { mcpServerName: options.serverName } : {}),\n ...(options.serverUrl\n ? { mcpServerUrlHash: hashServerUrl(options.serverUrl) }\n : {}),\n ...(options.sessionId ? { sessionId: options.sessionId } : {}),\n ...overrides,\n };\n return { ...(options.metadata ?? {}), ...metadata };\n}\n\n/** SDK RequestOptions keys — must never be swallowed as AgentInspect metadata. */\nconst SDK_REQUEST_OPTION_KEYS = [\n \"signal\",\n \"timeout\",\n \"onprogress\",\n \"resetTimeoutOnProgress\",\n \"maxTotalTimeout\",\n \"relatedRequestId\",\n \"resumptionToken\",\n \"onresumptiontoken\",\n] as const;\n\nfunction isSdkRequestOptions(value: unknown): value is McpRequestOptions {\n if (!value || typeof value !== \"object\") return false;\n const obj = value as Record<string, unknown>;\n return SDK_REQUEST_OPTION_KEYS.some((key) => key in obj);\n}\n\n/**\n * AgentInspect per-call metadata bag: `{ metadata: {...} }` without SDK option keys.\n * Must not consume ordinary SDK RequestOptions that happen to be objects.\n */\nfunction isAgentInspectMetadataBag(\n value: unknown,\n): value is { metadata?: Record<string, unknown> } {\n if (!value || typeof value !== \"object\") return false;\n if (isSdkRequestOptions(value)) return false;\n const obj = value as Record<string, unknown>;\n if (!(\"metadata\" in obj)) return false;\n // Zod/result schemas expose parse — never treat those as AI bags.\n if (\"parse\" in obj) return false;\n return true;\n}\n\nfunction extractCallMetadata(bag: {\n metadata?: Record<string, unknown>;\n}): Record<string, unknown> {\n if (bag.metadata && typeof bag.metadata === \"object\") {\n return bag.metadata;\n }\n return {};\n}\n\n/** Peel AgentInspect `metadata` without consuming SDK RequestOptions keys. */\nfunction peelOptionsObject(value: unknown): {\n callMetadata: Record<string, unknown>;\n requestOptions: McpRequestOptions | undefined;\n} {\n if (value === null || value === undefined) {\n return { callMetadata: {}, requestOptions: undefined };\n }\n if (typeof value !== \"object\") {\n return { callMetadata: {}, requestOptions: undefined };\n }\n const obj = value as Record<string, unknown>;\n const callMetadata = extractCallMetadata(obj);\n\n // Pure AI bag — do not forward as SDK RequestOptions.\n if (isAgentInspectMetadataBag(value)) {\n return { callMetadata, requestOptions: undefined };\n }\n\n if (isSdkRequestOptions(value) || Object.keys(obj).length > 0) {\n const { metadata: _ignored, ...rest } = obj;\n return {\n callMetadata,\n requestOptions: rest as McpRequestOptions,\n };\n }\n\n return { callMetadata, requestOptions: undefined };\n}\n\n/**\n * Resolve SDK callTool arity:\n * callTool(params, resultSchema?, requestOptions?)\n * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.\n * Composed `{ timeout, metadata: { operationId, attemptId } }` keeps both sides.\n */\nexport function resolveCallToolArgs(\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n): {\n resultSchema: unknown;\n requestOptions: McpRequestOptions | undefined;\n callMetadata: Record<string, unknown>;\n} {\n // Three-arg form: (params, schema|undefined, options)\n if (maybeOptions !== undefined) {\n const peeled = peelOptionsObject(maybeOptions);\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n // Two-arg form: (params, schema) OR (params, { metadata }) OR (params, RequestOptions)\n if (isAgentInspectMetadataBag(resultSchemaOrOptions)) {\n return {\n resultSchema: undefined,\n requestOptions: undefined,\n callMetadata: extractCallMetadata(resultSchemaOrOptions),\n };\n }\n\n if (isSdkRequestOptions(resultSchemaOrOptions)) {\n const peeled = peelOptionsObject(resultSchemaOrOptions);\n return {\n resultSchema: undefined,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: undefined,\n callMetadata: {},\n };\n}\n\nfunction invokeCallTool(\n callToolImpl: McpClientLike[\"callTool\"],\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchema: unknown,\n requestOptions: McpRequestOptions | undefined,\n): Promise<unknown> {\n const fn = callToolImpl as (\n p: unknown,\n schema?: unknown,\n opts?: unknown,\n ) => Promise<unknown>;\n if (requestOptions !== undefined) {\n return fn(params, resultSchema, requestOptions);\n }\n if (resultSchema !== undefined) {\n return fn(params, resultSchema);\n }\n return fn(params);\n}\n\n/**\n * Wraps an MCP client so tools/list and tools/call emit local tool steps.\n * Telemetry only — does not proxy network behavior beyond the wrapped client.\n *\n * Uses a Proxy over the original client so prototype methods (`connect`,\n * `close`, `listResources`, …), private SDK state, and `instanceof` stay intact.\n * A shallow object spread would drop prototype methods and copy private fields.\n *\n * Forwards the real SDK argument positions, including `RequestOptions`\n * (`signal`, `timeout`, progress callbacks). Does not fake cancellation while\n * still dispatching the underlying request.\n */\nexport function wrapMcpClient<T extends McpClientLike>(\n client: T,\n options: McpClientTracerOptions = {},\n): T {\n const maxSummaryLength = options.maxSummaryLength ?? 240;\n\n const listToolsImpl =\n typeof client.listTools === \"function\"\n ? client.listTools.bind(client)\n : undefined;\n const callToolImpl = client.callTool.bind(client);\n\n const wrappedListTools = listToolsImpl\n ? async (params?: unknown, requestOptions?: McpRequestOptions) =>\n step(\n \"mcp:tools/list\",\n async () => {\n if (requestOptions !== undefined) {\n return (\n listToolsImpl as (\n p?: unknown,\n opts?: unknown,\n ) => Promise<unknown>\n )(params, requestOptions);\n }\n return listToolsImpl(params);\n },\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: \"tools/list\",\n toolCallId: nextToolCallId(options.toolCallIdPrefix),\n }),\n },\n )\n : undefined;\n\n const wrappedCallTool = async (\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n ) => {\n const { resultSchema, requestOptions, callMetadata } = resolveCallToolArgs(\n resultSchemaOrOptions,\n maybeOptions,\n );\n\n return step(\n `mcp:${params.name}`,\n async () =>\n invokeCallTool(callToolImpl, params, resultSchema, requestOptions),\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: params.name,\n toolCallId: nextToolCallId(options.toolCallIdPrefix),\n argumentSummary: summarizeMcpValue(\n params.arguments ?? {},\n maxSummaryLength,\n ),\n ...callMetadata,\n }),\n },\n );\n };\n\n return new Proxy(client, {\n get(target, property, receiver) {\n if (property === \"listTools\" && wrappedListTools !== undefined) {\n return wrappedListTools;\n }\n if (property === \"callTool\") {\n return wrappedCallTool;\n }\n const value = Reflect.get(target, property, receiver);\n if (typeof value === \"function\") {\n return value.bind(target);\n }\n return value;\n },\n }) as T;\n}\n\n/** @internal resets tool call ids for deterministic tests */\nexport function resetMcpToolCallIdsForTests(): void {\n toolCallCounter = 0;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/summarize.ts","../src/wrap.ts"],"names":["observeOutcome","step"],"mappings":"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","file":"index.cjs","sourcesContent":["const DEFAULT_MAX_SUMMARY_LENGTH = 240;\n\nfunction fallbackString(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"[unserializable]\";\n }\n}\n\nexport function summarizeMcpValue(\n value: unknown,\n maxLength = DEFAULT_MAX_SUMMARY_LENGTH,\n): string {\n let text: string;\n try {\n if (typeof value === \"string\") {\n text = value;\n } else {\n // JSON.stringify returns undefined (not a string) for undefined,\n // functions, and symbols; falling through with undefined would crash\n // instrumentation at text.length below.\n const serialized = JSON.stringify(value);\n text = serialized === undefined ? fallbackString(value) : serialized;\n }\n } catch {\n text = fallbackString(value);\n }\n if (text.length <= maxLength) return text;\n return `${text.slice(0, Math.max(0, maxLength - 3))}...`;\n}\n\nexport function hashServerUrl(url: string): string {\n let hash = 0;\n for (let i = 0; i < url.length; i += 1) {\n hash = (hash * 31 + url.charCodeAt(i)) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n","import { observeOutcome, step } from \"agent-inspect\";\n\nimport { hashServerUrl, summarizeMcpValue } from \"./summarize.js\";\nimport type {\n McpClientLike,\n McpClientTracerOptions,\n McpRequestOptions,\n McpTraceMetadata,\n} from \"./types.js\";\n\nlet toolCallCounter = 0;\n\nfunction resultReportsToolError(value: unknown): boolean {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n if (record.isError === true) return true;\n const nested = record.toolResult;\n if (!nested || typeof nested !== \"object\") return false;\n return (nested as Record<string, unknown>).isError === true;\n}\n\nfunction boundedId(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed === \"\" || trimmed.length > 200) return undefined;\n return trimmed;\n}\n\nasync function recordToolResultOutcome(\n toolName: string,\n toolCallId: string,\n result: unknown,\n callMetadata: Record<string, unknown>,\n): Promise<void> {\n if (!resultReportsToolError(result)) return;\n const operationId = boundedId(callMetadata.operationId);\n const attemptId = boundedId(callMetadata.attemptId);\n await observeOutcome(`mcp:${toolName}:tool-result`, {\n expectation: \"MCP tool result is not an error\",\n status: \"failed\",\n method: \"custom\",\n evidence: {\n toolFailure: true,\n toolName,\n toolCallId,\n ...(operationId !== undefined ? { operationId } : {}),\n ...(attemptId !== undefined ? { attemptId } : {}),\n },\n });\n}\n\nfunction nextToolCallId(prefix?: string): string {\n toolCallCounter += 1;\n const base = prefix?.trim() || \"mcp\";\n return `${base}-${toolCallCounter}`;\n}\n\nfunction baseMetadata(\n options: McpClientTracerOptions,\n overrides: Partial<McpTraceMetadata> = {},\n): Record<string, unknown> {\n const metadata: McpTraceMetadata = {\n source: { type: \"mcp-client\" },\n ...(options.serverName ? { mcpServerName: options.serverName } : {}),\n ...(options.serverUrl\n ? { mcpServerUrlHash: hashServerUrl(options.serverUrl) }\n : {}),\n ...(options.sessionId ? { sessionId: options.sessionId } : {}),\n ...overrides,\n };\n return { ...(options.metadata ?? {}), ...metadata };\n}\n\n/** SDK RequestOptions keys — must never be swallowed as AgentInspect metadata. */\nconst SDK_REQUEST_OPTION_KEYS = [\n \"signal\",\n \"timeout\",\n \"onprogress\",\n \"resetTimeoutOnProgress\",\n \"maxTotalTimeout\",\n \"relatedRequestId\",\n \"resumptionToken\",\n \"onresumptiontoken\",\n] as const;\n\nfunction isSdkRequestOptions(value: unknown): value is McpRequestOptions {\n if (!value || typeof value !== \"object\") return false;\n const obj = value as Record<string, unknown>;\n return SDK_REQUEST_OPTION_KEYS.some((key) => key in obj);\n}\n\n/**\n * AgentInspect per-call metadata bag: `{ metadata: {...} }` without SDK option keys.\n * Must not consume ordinary SDK RequestOptions that happen to be objects.\n */\nfunction isAgentInspectMetadataBag(\n value: unknown,\n): value is { metadata?: Record<string, unknown> } {\n if (!value || typeof value !== \"object\") return false;\n if (isSdkRequestOptions(value)) return false;\n const obj = value as Record<string, unknown>;\n if (!(\"metadata\" in obj)) return false;\n // Zod/result schemas expose parse — never treat those as AI bags.\n if (\"parse\" in obj) return false;\n return true;\n}\n\nfunction extractCallMetadata(bag: {\n metadata?: Record<string, unknown>;\n}): Record<string, unknown> {\n if (bag.metadata && typeof bag.metadata === \"object\") {\n return bag.metadata;\n }\n return {};\n}\n\n/** Peel AgentInspect `metadata` without consuming SDK RequestOptions keys. */\nfunction peelOptionsObject(value: unknown): {\n callMetadata: Record<string, unknown>;\n requestOptions: McpRequestOptions | undefined;\n} {\n if (value === null || value === undefined) {\n return { callMetadata: {}, requestOptions: undefined };\n }\n if (typeof value !== \"object\") {\n return { callMetadata: {}, requestOptions: undefined };\n }\n const obj = value as Record<string, unknown>;\n const callMetadata = extractCallMetadata(obj);\n\n // Pure AI bag — do not forward as SDK RequestOptions.\n if (isAgentInspectMetadataBag(value)) {\n return { callMetadata, requestOptions: undefined };\n }\n\n if (isSdkRequestOptions(value) || Object.keys(obj).length > 0) {\n const { metadata: _ignored, ...rest } = obj;\n return {\n callMetadata,\n requestOptions: rest as McpRequestOptions,\n };\n }\n\n return { callMetadata, requestOptions: undefined };\n}\n\n/**\n * Resolve SDK callTool arity:\n * callTool(params, resultSchema?, requestOptions?)\n * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.\n * Composed `{ timeout, metadata: { operationId, attemptId } }` keeps both sides.\n */\nexport function resolveCallToolArgs(\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n): {\n resultSchema: unknown;\n requestOptions: McpRequestOptions | undefined;\n callMetadata: Record<string, unknown>;\n} {\n // Three-arg form: (params, schema|undefined, options)\n if (maybeOptions !== undefined) {\n const peeled = peelOptionsObject(maybeOptions);\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n // Two-arg form: (params, schema) OR (params, { metadata }) OR (params, RequestOptions)\n if (isAgentInspectMetadataBag(resultSchemaOrOptions)) {\n return {\n resultSchema: undefined,\n requestOptions: undefined,\n callMetadata: extractCallMetadata(resultSchemaOrOptions),\n };\n }\n\n if (isSdkRequestOptions(resultSchemaOrOptions)) {\n const peeled = peelOptionsObject(resultSchemaOrOptions);\n return {\n resultSchema: undefined,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: undefined,\n callMetadata: {},\n };\n}\n\nfunction invokeCallTool(\n callToolImpl: McpClientLike[\"callTool\"],\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchema: unknown,\n requestOptions: McpRequestOptions | undefined,\n): Promise<unknown> {\n const fn = callToolImpl as (\n p: unknown,\n schema?: unknown,\n opts?: unknown,\n ) => Promise<unknown>;\n if (requestOptions !== undefined) {\n return fn(params, resultSchema, requestOptions);\n }\n if (resultSchema !== undefined) {\n return fn(params, resultSchema);\n }\n return fn(params);\n}\n\n/**\n * Wraps an MCP client so tools/list and tools/call emit local tool steps.\n * Telemetry only — does not proxy network behavior beyond the wrapped client.\n *\n * Uses a Proxy over the original client so prototype methods (`connect`,\n * `close`, `listResources`, …), private SDK state, and `instanceof` stay intact.\n * A shallow object spread would drop prototype methods and copy private fields.\n *\n * Forwards the real SDK argument positions, including `RequestOptions`\n * (`signal`, `timeout`, progress callbacks). Does not fake cancellation while\n * still dispatching the underlying request.\n */\nexport function wrapMcpClient<T extends McpClientLike>(\n client: T,\n options: McpClientTracerOptions = {},\n): T {\n const maxSummaryLength = options.maxSummaryLength ?? 240;\n\n const listToolsImpl =\n typeof client.listTools === \"function\"\n ? client.listTools.bind(client)\n : undefined;\n const callToolImpl = client.callTool.bind(client);\n\n const wrappedListTools = listToolsImpl\n ? async (params?: unknown, requestOptions?: McpRequestOptions) =>\n step(\n \"mcp:tools/list\",\n async () => {\n if (requestOptions !== undefined) {\n return (\n listToolsImpl as (\n p?: unknown,\n opts?: unknown,\n ) => Promise<unknown>\n )(params, requestOptions);\n }\n return listToolsImpl(params);\n },\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: \"tools/list\",\n toolCallId: nextToolCallId(options.toolCallIdPrefix),\n }),\n },\n )\n : undefined;\n\n const wrappedCallTool = async (\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n ) => {\n const { resultSchema, requestOptions, callMetadata } = resolveCallToolArgs(\n resultSchemaOrOptions,\n maybeOptions,\n );\n\n const toolCallId = nextToolCallId(options.toolCallIdPrefix);\n return step(\n `mcp:${params.name}`,\n async () => {\n const result = await invokeCallTool(\n callToolImpl,\n params,\n resultSchema,\n requestOptions,\n );\n await recordToolResultOutcome(\n params.name,\n toolCallId,\n result,\n callMetadata,\n );\n return result;\n },\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: params.name,\n toolCallId,\n argumentSummary: summarizeMcpValue(\n params.arguments ?? {},\n maxSummaryLength,\n ),\n ...callMetadata,\n }),\n },\n );\n };\n\n return new Proxy(client, {\n get(target, property, receiver) {\n if (property === \"listTools\" && wrappedListTools !== undefined) {\n return wrappedListTools;\n }\n if (property === \"callTool\") {\n return wrappedCallTool;\n }\n const value = Reflect.get(target, property, receiver);\n if (typeof value === \"function\") {\n return value.bind(target);\n }\n return value;\n },\n }) as T;\n}\n\n/** @internal resets tool call ids for deterministic tests */\nexport function resetMcpToolCallIdsForTests(): void {\n toolCallCounter = 0;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { step } from 'agent-inspect';
|
|
1
|
+
import { step, observeOutcome } from 'agent-inspect';
|
|
2
2
|
|
|
3
3
|
// packages/mcp/src/summarize.ts
|
|
4
4
|
var DEFAULT_MAX_SUMMARY_LENGTH = 240;
|
|
@@ -32,6 +32,37 @@ function hashServerUrl(url) {
|
|
|
32
32
|
return hash.toString(16).padStart(8, "0");
|
|
33
33
|
}
|
|
34
34
|
var toolCallCounter = 0;
|
|
35
|
+
function resultReportsToolError(value) {
|
|
36
|
+
if (!value || typeof value !== "object") return false;
|
|
37
|
+
const record = value;
|
|
38
|
+
if (record.isError === true) return true;
|
|
39
|
+
const nested = record.toolResult;
|
|
40
|
+
if (!nested || typeof nested !== "object") return false;
|
|
41
|
+
return nested.isError === true;
|
|
42
|
+
}
|
|
43
|
+
function boundedId(value) {
|
|
44
|
+
if (typeof value !== "string") return void 0;
|
|
45
|
+
const trimmed = value.trim();
|
|
46
|
+
if (trimmed === "" || trimmed.length > 200) return void 0;
|
|
47
|
+
return trimmed;
|
|
48
|
+
}
|
|
49
|
+
async function recordToolResultOutcome(toolName, toolCallId, result, callMetadata) {
|
|
50
|
+
if (!resultReportsToolError(result)) return;
|
|
51
|
+
const operationId = boundedId(callMetadata.operationId);
|
|
52
|
+
const attemptId = boundedId(callMetadata.attemptId);
|
|
53
|
+
await observeOutcome(`mcp:${toolName}:tool-result`, {
|
|
54
|
+
expectation: "MCP tool result is not an error",
|
|
55
|
+
status: "failed",
|
|
56
|
+
method: "custom",
|
|
57
|
+
evidence: {
|
|
58
|
+
toolFailure: true,
|
|
59
|
+
toolName,
|
|
60
|
+
toolCallId,
|
|
61
|
+
...operationId !== void 0 ? { operationId } : {},
|
|
62
|
+
...attemptId !== void 0 ? { attemptId } : {}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
35
66
|
function nextToolCallId(prefix) {
|
|
36
67
|
toolCallCounter += 1;
|
|
37
68
|
const base = prefix?.trim() || "mcp";
|
|
@@ -162,14 +193,29 @@ function wrapMcpClient(client, options = {}) {
|
|
|
162
193
|
resultSchemaOrOptions,
|
|
163
194
|
maybeOptions
|
|
164
195
|
);
|
|
196
|
+
const toolCallId = nextToolCallId(options.toolCallIdPrefix);
|
|
165
197
|
return step(
|
|
166
198
|
`mcp:${params.name}`,
|
|
167
|
-
async () =>
|
|
199
|
+
async () => {
|
|
200
|
+
const result = await invokeCallTool(
|
|
201
|
+
callToolImpl,
|
|
202
|
+
params,
|
|
203
|
+
resultSchema,
|
|
204
|
+
requestOptions
|
|
205
|
+
);
|
|
206
|
+
await recordToolResultOutcome(
|
|
207
|
+
params.name,
|
|
208
|
+
toolCallId,
|
|
209
|
+
result,
|
|
210
|
+
callMetadata
|
|
211
|
+
);
|
|
212
|
+
return result;
|
|
213
|
+
},
|
|
168
214
|
{
|
|
169
215
|
type: "tool",
|
|
170
216
|
metadata: baseMetadata(options, {
|
|
171
217
|
toolName: params.name,
|
|
172
|
-
toolCallId
|
|
218
|
+
toolCallId,
|
|
173
219
|
argumentSummary: summarizeMcpValue(
|
|
174
220
|
params.arguments ?? {},
|
|
175
221
|
maxSummaryLength
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/summarize.ts","../src/wrap.ts"],"names":[],"mappings":";;;AAAA,IAAM,0BAAA,GAA6B,GAAA;AAEnC,SAAS,eAAe,KAAA,EAAwB;AAC9C,EAAA,IAAI;AACF,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,kBAAA;AAAA,EACT;AACF;AAEO,SAAS,iBAAA,CACd,KAAA,EACA,SAAA,GAAY,0BAAA,EACJ;AACR,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,IAAA,GAAO,KAAA;AAAA,IACT,CAAA,MAAO;AAIL,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AACvC,MAAA,IAAA,GAAO,UAAA,KAAe,KAAA,CAAA,GAAY,cAAA,CAAe,KAAK,CAAA,GAAI,UAAA;AAAA,IAC5D;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,IAAA,GAAO,eAAe,KAAK,CAAA;AAAA,EAC7B;AACA,EAAA,IAAI,IAAA,CAAK,MAAA,IAAU,SAAA,EAAW,OAAO,IAAA;AACrC,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAG,SAAA,GAAY,CAAC,CAAC,CAAC,CAAA,GAAA,CAAA;AACrD;AAEO,SAAS,cAAc,GAAA,EAAqB;AACjD,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,KAAK,CAAA,EAAG;AACtC,IAAA,IAAA,GAAQ,IAAA,GAAO,EAAA,GAAK,GAAA,CAAI,UAAA,CAAW,CAAC,CAAA,KAAO,CAAA;AAAA,EAC7C;AACA,EAAA,OAAO,KAAK,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAC1C;AC5BA,IAAI,eAAA,GAAkB,CAAA;AAEtB,SAAS,eAAe,MAAA,EAAyB;AAC/C,EAAA,eAAA,IAAmB,CAAA;AACnB,EAAA,MAAM,IAAA,GAAO,MAAA,EAAQ,IAAA,EAAK,IAAK,KAAA;AAC/B,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,eAAe,CAAA,CAAA;AACnC;AAEA,SAAS,YAAA,CACP,OAAA,EACA,SAAA,GAAuC,EAAC,EACf;AACzB,EAAA,MAAM,QAAA,GAA6B;AAAA,IACjC,MAAA,EAAQ,EAAE,IAAA,EAAM,YAAA,EAAa;AAAA,IAC7B,GAAI,QAAQ,UAAA,GAAa,EAAE,eAAe,OAAA,CAAQ,UAAA,KAAe,EAAC;AAAA,IAClE,GAAI,OAAA,CAAQ,SAAA,GACR,EAAE,gBAAA,EAAkB,cAAc,OAAA,CAAQ,SAAS,CAAA,EAAE,GACrD,EAAC;AAAA,IACL,GAAI,QAAQ,SAAA,GAAY,EAAE,WAAW,OAAA,CAAQ,SAAA,KAAc,EAAC;AAAA,IAC5D,GAAG;AAAA,GACL;AACA,EAAA,OAAO,EAAE,GAAI,OAAA,CAAQ,YAAY,EAAC,EAAI,GAAG,QAAA,EAAS;AACpD;AAGA,IAAM,uBAAA,GAA0B;AAAA,EAC9B,QAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,wBAAA;AAAA,EACA,iBAAA;AAAA,EACA,kBAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,oBAAoB,KAAA,EAA4C;AACvE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,UAAU,OAAO,KAAA;AAChD,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,OAAO,uBAAA,CAAwB,IAAA,CAAK,CAAC,GAAA,KAAQ,OAAO,GAAG,CAAA;AACzD;AAMA,SAAS,0BACP,KAAA,EACiD;AACjD,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,UAAU,OAAO,KAAA;AAChD,EAAA,IAAI,mBAAA,CAAoB,KAAK,CAAA,EAAG,OAAO,KAAA;AACvC,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,IAAI,EAAE,UAAA,IAAc,GAAA,CAAA,EAAM,OAAO,KAAA;AAEjC,EAAA,IAAI,OAAA,IAAW,KAAK,OAAO,KAAA;AAC3B,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,oBAAoB,GAAA,EAED;AAC1B,EAAA,IAAI,GAAA,CAAI,QAAA,IAAY,OAAO,GAAA,CAAI,aAAa,QAAA,EAAU;AACpD,IAAA,OAAO,GAAA,CAAI,QAAA;AAAA,EACb;AACA,EAAA,OAAO,EAAC;AACV;AAGA,SAAS,kBAAkB,KAAA,EAGzB;AACA,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AACzC,IAAA,OAAO,EAAE,YAAA,EAAc,EAAC,EAAG,gBAAgB,MAAA,EAAU;AAAA,EACvD;AACA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,EAAE,YAAA,EAAc,EAAC,EAAG,gBAAgB,MAAA,EAAU;AAAA,EACvD;AACA,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,MAAM,YAAA,GAAe,oBAAoB,GAAG,CAAA;AAG5C,EAAA,IAAI,yBAAA,CAA0B,KAAK,CAAA,EAAG;AACpC,IAAA,OAAO,EAAE,YAAA,EAAc,cAAA,EAAgB,MAAA,EAAU;AAAA,EACnD;AAEA,EAAA,IAAI,mBAAA,CAAoB,KAAK,CAAA,IAAK,MAAA,CAAO,KAAK,GAAG,CAAA,CAAE,SAAS,CAAA,EAAG;AAC7D,IAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,GAAG,MAAK,GAAI,GAAA;AACxC,IAAA,OAAO;AAAA,MACL,YAAA;AAAA,MACA,cAAA,EAAgB;AAAA,KAClB;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,YAAA,EAAc,cAAA,EAAgB,MAAA,EAAU;AACnD;AAQO,SAAS,mBAAA,CACd,uBACA,YAAA,EAKA;AAEA,EAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,IAAA,MAAM,MAAA,GAAS,kBAAkB,YAAY,CAAA;AAC7C,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,qBAAA;AAAA,MACd,gBAAgB,MAAA,CAAO,cAAA;AAAA,MACvB,cAAc,MAAA,CAAO;AAAA,KACvB;AAAA,EACF;AAGA,EAAA,IAAI,yBAAA,CAA0B,qBAAqB,CAAA,EAAG;AACpD,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,MAAA;AAAA,MACd,cAAA,EAAgB,MAAA;AAAA,MAChB,YAAA,EAAc,oBAAoB,qBAAqB;AAAA,KACzD;AAAA,EACF;AAEA,EAAA,IAAI,mBAAA,CAAoB,qBAAqB,CAAA,EAAG;AAC9C,IAAA,MAAM,MAAA,GAAS,kBAAkB,qBAAqB,CAAA;AACtD,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,MAAA;AAAA,MACd,gBAAgB,MAAA,CAAO,cAAA;AAAA,MACvB,cAAc,MAAA,CAAO;AAAA,KACvB;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,qBAAA;AAAA,IACd,cAAA,EAAgB,MAAA;AAAA,IAChB,cAAc;AAAC,GACjB;AACF;AAEA,SAAS,cAAA,CACP,YAAA,EACA,MAAA,EACA,YAAA,EACA,cAAA,EACkB;AAClB,EAAA,MAAM,EAAA,GAAK,YAAA;AAKX,EAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,IAAA,OAAO,EAAA,CAAG,MAAA,EAAQ,YAAA,EAAc,cAAc,CAAA;AAAA,EAChD;AACA,EAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,IAAA,OAAO,EAAA,CAAG,QAAQ,YAAY,CAAA;AAAA,EAChC;AACA,EAAA,OAAO,GAAG,MAAM,CAAA;AAClB;AAcO,SAAS,aAAA,CACd,MAAA,EACA,OAAA,GAAkC,EAAC,EAChC;AACH,EAAA,MAAM,gBAAA,GAAmB,QAAQ,gBAAA,IAAoB,GAAA;AAErD,EAAA,MAAM,aAAA,GACJ,OAAO,MAAA,CAAO,SAAA,KAAc,aACxB,MAAA,CAAO,SAAA,CAAU,IAAA,CAAK,MAAM,CAAA,GAC5B,MAAA;AACN,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA;AAEhD,EAAA,MAAM,gBAAA,GAAmB,aAAA,GACrB,OAAO,MAAA,EAAkB,cAAA,KACvB,IAAA;AAAA,IACE,gBAAA;AAAA,IACA,YAAY;AACV,MAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,QAAA,OACE,aAAA,CAIA,QAAQ,cAAc,CAAA;AAAA,MAC1B;AACA,MAAA,OAAO,cAAc,MAAM,CAAA;AAAA,IAC7B,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAM,MAAA;AAAA,MACN,QAAA,EAAU,aAAa,OAAA,EAAS;AAAA,QAC9B,QAAA,EAAU,YAAA;AAAA,QACV,UAAA,EAAY,cAAA,CAAe,OAAA,CAAQ,gBAAgB;AAAA,OACpD;AAAA;AACH,GACF,GACF,MAAA;AAEJ,EAAA,MAAM,eAAA,GAAkB,OACtB,MAAA,EACA,qBAAA,EACA,YAAA,KACG;AACH,IAAA,MAAM,EAAE,YAAA,EAAc,cAAA,EAAgB,YAAA,EAAa,GAAI,mBAAA;AAAA,MACrD,qBAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,IAAA;AAAA,MACL,CAAA,IAAA,EAAO,OAAO,IAAI,CAAA,CAAA;AAAA,MAClB,YACE,cAAA,CAAe,YAAA,EAAc,MAAA,EAAQ,cAAc,cAAc,CAAA;AAAA,MACnE;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,QAAA,EAAU,aAAa,OAAA,EAAS;AAAA,UAC9B,UAAU,MAAA,CAAO,IAAA;AAAA,UACjB,UAAA,EAAY,cAAA,CAAe,OAAA,CAAQ,gBAAgB,CAAA;AAAA,UACnD,eAAA,EAAiB,iBAAA;AAAA,YACf,MAAA,CAAO,aAAa,EAAC;AAAA,YACrB;AAAA,WACF;AAAA,UACA,GAAG;AAAA,SACJ;AAAA;AACH,KACF;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,IAAI,MAAM,MAAA,EAAQ;AAAA,IACvB,GAAA,CAAI,MAAA,EAAQ,QAAA,EAAU,QAAA,EAAU;AAC9B,MAAA,IAAI,QAAA,KAAa,WAAA,IAAe,gBAAA,KAAqB,MAAA,EAAW;AAC9D,QAAA,OAAO,gBAAA;AAAA,MACT;AACA,MAAA,IAAI,aAAa,UAAA,EAAY;AAC3B,QAAA,OAAO,eAAA;AAAA,MACT;AACA,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,UAAU,QAAQ,CAAA;AACpD,MAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,QAAA,OAAO,KAAA,CAAM,KAAK,MAAM,CAAA;AAAA,MAC1B;AACA,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,GACD,CAAA;AACH;AAGO,SAAS,2BAAA,GAAoC;AAClD,EAAA,eAAA,GAAkB,CAAA;AACpB","file":"index.mjs","sourcesContent":["const DEFAULT_MAX_SUMMARY_LENGTH = 240;\n\nfunction fallbackString(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"[unserializable]\";\n }\n}\n\nexport function summarizeMcpValue(\n value: unknown,\n maxLength = DEFAULT_MAX_SUMMARY_LENGTH,\n): string {\n let text: string;\n try {\n if (typeof value === \"string\") {\n text = value;\n } else {\n // JSON.stringify returns undefined (not a string) for undefined,\n // functions, and symbols; falling through with undefined would crash\n // instrumentation at text.length below.\n const serialized = JSON.stringify(value);\n text = serialized === undefined ? fallbackString(value) : serialized;\n }\n } catch {\n text = fallbackString(value);\n }\n if (text.length <= maxLength) return text;\n return `${text.slice(0, Math.max(0, maxLength - 3))}...`;\n}\n\nexport function hashServerUrl(url: string): string {\n let hash = 0;\n for (let i = 0; i < url.length; i += 1) {\n hash = (hash * 31 + url.charCodeAt(i)) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n","import { step } from \"agent-inspect\";\n\nimport { hashServerUrl, summarizeMcpValue } from \"./summarize.js\";\nimport type {\n McpClientLike,\n McpClientTracerOptions,\n McpRequestOptions,\n McpTraceMetadata,\n} from \"./types.js\";\n\nlet toolCallCounter = 0;\n\nfunction nextToolCallId(prefix?: string): string {\n toolCallCounter += 1;\n const base = prefix?.trim() || \"mcp\";\n return `${base}-${toolCallCounter}`;\n}\n\nfunction baseMetadata(\n options: McpClientTracerOptions,\n overrides: Partial<McpTraceMetadata> = {},\n): Record<string, unknown> {\n const metadata: McpTraceMetadata = {\n source: { type: \"mcp-client\" },\n ...(options.serverName ? { mcpServerName: options.serverName } : {}),\n ...(options.serverUrl\n ? { mcpServerUrlHash: hashServerUrl(options.serverUrl) }\n : {}),\n ...(options.sessionId ? { sessionId: options.sessionId } : {}),\n ...overrides,\n };\n return { ...(options.metadata ?? {}), ...metadata };\n}\n\n/** SDK RequestOptions keys — must never be swallowed as AgentInspect metadata. */\nconst SDK_REQUEST_OPTION_KEYS = [\n \"signal\",\n \"timeout\",\n \"onprogress\",\n \"resetTimeoutOnProgress\",\n \"maxTotalTimeout\",\n \"relatedRequestId\",\n \"resumptionToken\",\n \"onresumptiontoken\",\n] as const;\n\nfunction isSdkRequestOptions(value: unknown): value is McpRequestOptions {\n if (!value || typeof value !== \"object\") return false;\n const obj = value as Record<string, unknown>;\n return SDK_REQUEST_OPTION_KEYS.some((key) => key in obj);\n}\n\n/**\n * AgentInspect per-call metadata bag: `{ metadata: {...} }` without SDK option keys.\n * Must not consume ordinary SDK RequestOptions that happen to be objects.\n */\nfunction isAgentInspectMetadataBag(\n value: unknown,\n): value is { metadata?: Record<string, unknown> } {\n if (!value || typeof value !== \"object\") return false;\n if (isSdkRequestOptions(value)) return false;\n const obj = value as Record<string, unknown>;\n if (!(\"metadata\" in obj)) return false;\n // Zod/result schemas expose parse — never treat those as AI bags.\n if (\"parse\" in obj) return false;\n return true;\n}\n\nfunction extractCallMetadata(bag: {\n metadata?: Record<string, unknown>;\n}): Record<string, unknown> {\n if (bag.metadata && typeof bag.metadata === \"object\") {\n return bag.metadata;\n }\n return {};\n}\n\n/** Peel AgentInspect `metadata` without consuming SDK RequestOptions keys. */\nfunction peelOptionsObject(value: unknown): {\n callMetadata: Record<string, unknown>;\n requestOptions: McpRequestOptions | undefined;\n} {\n if (value === null || value === undefined) {\n return { callMetadata: {}, requestOptions: undefined };\n }\n if (typeof value !== \"object\") {\n return { callMetadata: {}, requestOptions: undefined };\n }\n const obj = value as Record<string, unknown>;\n const callMetadata = extractCallMetadata(obj);\n\n // Pure AI bag — do not forward as SDK RequestOptions.\n if (isAgentInspectMetadataBag(value)) {\n return { callMetadata, requestOptions: undefined };\n }\n\n if (isSdkRequestOptions(value) || Object.keys(obj).length > 0) {\n const { metadata: _ignored, ...rest } = obj;\n return {\n callMetadata,\n requestOptions: rest as McpRequestOptions,\n };\n }\n\n return { callMetadata, requestOptions: undefined };\n}\n\n/**\n * Resolve SDK callTool arity:\n * callTool(params, resultSchema?, requestOptions?)\n * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.\n * Composed `{ timeout, metadata: { operationId, attemptId } }` keeps both sides.\n */\nexport function resolveCallToolArgs(\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n): {\n resultSchema: unknown;\n requestOptions: McpRequestOptions | undefined;\n callMetadata: Record<string, unknown>;\n} {\n // Three-arg form: (params, schema|undefined, options)\n if (maybeOptions !== undefined) {\n const peeled = peelOptionsObject(maybeOptions);\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n // Two-arg form: (params, schema) OR (params, { metadata }) OR (params, RequestOptions)\n if (isAgentInspectMetadataBag(resultSchemaOrOptions)) {\n return {\n resultSchema: undefined,\n requestOptions: undefined,\n callMetadata: extractCallMetadata(resultSchemaOrOptions),\n };\n }\n\n if (isSdkRequestOptions(resultSchemaOrOptions)) {\n const peeled = peelOptionsObject(resultSchemaOrOptions);\n return {\n resultSchema: undefined,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: undefined,\n callMetadata: {},\n };\n}\n\nfunction invokeCallTool(\n callToolImpl: McpClientLike[\"callTool\"],\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchema: unknown,\n requestOptions: McpRequestOptions | undefined,\n): Promise<unknown> {\n const fn = callToolImpl as (\n p: unknown,\n schema?: unknown,\n opts?: unknown,\n ) => Promise<unknown>;\n if (requestOptions !== undefined) {\n return fn(params, resultSchema, requestOptions);\n }\n if (resultSchema !== undefined) {\n return fn(params, resultSchema);\n }\n return fn(params);\n}\n\n/**\n * Wraps an MCP client so tools/list and tools/call emit local tool steps.\n * Telemetry only — does not proxy network behavior beyond the wrapped client.\n *\n * Uses a Proxy over the original client so prototype methods (`connect`,\n * `close`, `listResources`, …), private SDK state, and `instanceof` stay intact.\n * A shallow object spread would drop prototype methods and copy private fields.\n *\n * Forwards the real SDK argument positions, including `RequestOptions`\n * (`signal`, `timeout`, progress callbacks). Does not fake cancellation while\n * still dispatching the underlying request.\n */\nexport function wrapMcpClient<T extends McpClientLike>(\n client: T,\n options: McpClientTracerOptions = {},\n): T {\n const maxSummaryLength = options.maxSummaryLength ?? 240;\n\n const listToolsImpl =\n typeof client.listTools === \"function\"\n ? client.listTools.bind(client)\n : undefined;\n const callToolImpl = client.callTool.bind(client);\n\n const wrappedListTools = listToolsImpl\n ? async (params?: unknown, requestOptions?: McpRequestOptions) =>\n step(\n \"mcp:tools/list\",\n async () => {\n if (requestOptions !== undefined) {\n return (\n listToolsImpl as (\n p?: unknown,\n opts?: unknown,\n ) => Promise<unknown>\n )(params, requestOptions);\n }\n return listToolsImpl(params);\n },\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: \"tools/list\",\n toolCallId: nextToolCallId(options.toolCallIdPrefix),\n }),\n },\n )\n : undefined;\n\n const wrappedCallTool = async (\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n ) => {\n const { resultSchema, requestOptions, callMetadata } = resolveCallToolArgs(\n resultSchemaOrOptions,\n maybeOptions,\n );\n\n return step(\n `mcp:${params.name}`,\n async () =>\n invokeCallTool(callToolImpl, params, resultSchema, requestOptions),\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: params.name,\n toolCallId: nextToolCallId(options.toolCallIdPrefix),\n argumentSummary: summarizeMcpValue(\n params.arguments ?? {},\n maxSummaryLength,\n ),\n ...callMetadata,\n }),\n },\n );\n };\n\n return new Proxy(client, {\n get(target, property, receiver) {\n if (property === \"listTools\" && wrappedListTools !== undefined) {\n return wrappedListTools;\n }\n if (property === \"callTool\") {\n return wrappedCallTool;\n }\n const value = Reflect.get(target, property, receiver);\n if (typeof value === \"function\") {\n return value.bind(target);\n }\n return value;\n },\n }) as T;\n}\n\n/** @internal resets tool call ids for deterministic tests */\nexport function resetMcpToolCallIdsForTests(): void {\n toolCallCounter = 0;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/summarize.ts","../src/wrap.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["const DEFAULT_MAX_SUMMARY_LENGTH = 240;\n\nfunction fallbackString(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"[unserializable]\";\n }\n}\n\nexport function summarizeMcpValue(\n value: unknown,\n maxLength = DEFAULT_MAX_SUMMARY_LENGTH,\n): string {\n let text: string;\n try {\n if (typeof value === \"string\") {\n text = value;\n } else {\n // JSON.stringify returns undefined (not a string) for undefined,\n // functions, and symbols; falling through with undefined would crash\n // instrumentation at text.length below.\n const serialized = JSON.stringify(value);\n text = serialized === undefined ? fallbackString(value) : serialized;\n }\n } catch {\n text = fallbackString(value);\n }\n if (text.length <= maxLength) return text;\n return `${text.slice(0, Math.max(0, maxLength - 3))}...`;\n}\n\nexport function hashServerUrl(url: string): string {\n let hash = 0;\n for (let i = 0; i < url.length; i += 1) {\n hash = (hash * 31 + url.charCodeAt(i)) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n","import { observeOutcome, step } from \"agent-inspect\";\n\nimport { hashServerUrl, summarizeMcpValue } from \"./summarize.js\";\nimport type {\n McpClientLike,\n McpClientTracerOptions,\n McpRequestOptions,\n McpTraceMetadata,\n} from \"./types.js\";\n\nlet toolCallCounter = 0;\n\nfunction resultReportsToolError(value: unknown): boolean {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n if (record.isError === true) return true;\n const nested = record.toolResult;\n if (!nested || typeof nested !== \"object\") return false;\n return (nested as Record<string, unknown>).isError === true;\n}\n\nfunction boundedId(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed === \"\" || trimmed.length > 200) return undefined;\n return trimmed;\n}\n\nasync function recordToolResultOutcome(\n toolName: string,\n toolCallId: string,\n result: unknown,\n callMetadata: Record<string, unknown>,\n): Promise<void> {\n if (!resultReportsToolError(result)) return;\n const operationId = boundedId(callMetadata.operationId);\n const attemptId = boundedId(callMetadata.attemptId);\n await observeOutcome(`mcp:${toolName}:tool-result`, {\n expectation: \"MCP tool result is not an error\",\n status: \"failed\",\n method: \"custom\",\n evidence: {\n toolFailure: true,\n toolName,\n toolCallId,\n ...(operationId !== undefined ? { operationId } : {}),\n ...(attemptId !== undefined ? { attemptId } : {}),\n },\n });\n}\n\nfunction nextToolCallId(prefix?: string): string {\n toolCallCounter += 1;\n const base = prefix?.trim() || \"mcp\";\n return `${base}-${toolCallCounter}`;\n}\n\nfunction baseMetadata(\n options: McpClientTracerOptions,\n overrides: Partial<McpTraceMetadata> = {},\n): Record<string, unknown> {\n const metadata: McpTraceMetadata = {\n source: { type: \"mcp-client\" },\n ...(options.serverName ? { mcpServerName: options.serverName } : {}),\n ...(options.serverUrl\n ? { mcpServerUrlHash: hashServerUrl(options.serverUrl) }\n : {}),\n ...(options.sessionId ? { sessionId: options.sessionId } : {}),\n ...overrides,\n };\n return { ...(options.metadata ?? {}), ...metadata };\n}\n\n/** SDK RequestOptions keys — must never be swallowed as AgentInspect metadata. */\nconst SDK_REQUEST_OPTION_KEYS = [\n \"signal\",\n \"timeout\",\n \"onprogress\",\n \"resetTimeoutOnProgress\",\n \"maxTotalTimeout\",\n \"relatedRequestId\",\n \"resumptionToken\",\n \"onresumptiontoken\",\n] as const;\n\nfunction isSdkRequestOptions(value: unknown): value is McpRequestOptions {\n if (!value || typeof value !== \"object\") return false;\n const obj = value as Record<string, unknown>;\n return SDK_REQUEST_OPTION_KEYS.some((key) => key in obj);\n}\n\n/**\n * AgentInspect per-call metadata bag: `{ metadata: {...} }` without SDK option keys.\n * Must not consume ordinary SDK RequestOptions that happen to be objects.\n */\nfunction isAgentInspectMetadataBag(\n value: unknown,\n): value is { metadata?: Record<string, unknown> } {\n if (!value || typeof value !== \"object\") return false;\n if (isSdkRequestOptions(value)) return false;\n const obj = value as Record<string, unknown>;\n if (!(\"metadata\" in obj)) return false;\n // Zod/result schemas expose parse — never treat those as AI bags.\n if (\"parse\" in obj) return false;\n return true;\n}\n\nfunction extractCallMetadata(bag: {\n metadata?: Record<string, unknown>;\n}): Record<string, unknown> {\n if (bag.metadata && typeof bag.metadata === \"object\") {\n return bag.metadata;\n }\n return {};\n}\n\n/** Peel AgentInspect `metadata` without consuming SDK RequestOptions keys. */\nfunction peelOptionsObject(value: unknown): {\n callMetadata: Record<string, unknown>;\n requestOptions: McpRequestOptions | undefined;\n} {\n if (value === null || value === undefined) {\n return { callMetadata: {}, requestOptions: undefined };\n }\n if (typeof value !== \"object\") {\n return { callMetadata: {}, requestOptions: undefined };\n }\n const obj = value as Record<string, unknown>;\n const callMetadata = extractCallMetadata(obj);\n\n // Pure AI bag — do not forward as SDK RequestOptions.\n if (isAgentInspectMetadataBag(value)) {\n return { callMetadata, requestOptions: undefined };\n }\n\n if (isSdkRequestOptions(value) || Object.keys(obj).length > 0) {\n const { metadata: _ignored, ...rest } = obj;\n return {\n callMetadata,\n requestOptions: rest as McpRequestOptions,\n };\n }\n\n return { callMetadata, requestOptions: undefined };\n}\n\n/**\n * Resolve SDK callTool arity:\n * callTool(params, resultSchema?, requestOptions?)\n * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.\n * Composed `{ timeout, metadata: { operationId, attemptId } }` keeps both sides.\n */\nexport function resolveCallToolArgs(\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n): {\n resultSchema: unknown;\n requestOptions: McpRequestOptions | undefined;\n callMetadata: Record<string, unknown>;\n} {\n // Three-arg form: (params, schema|undefined, options)\n if (maybeOptions !== undefined) {\n const peeled = peelOptionsObject(maybeOptions);\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n // Two-arg form: (params, schema) OR (params, { metadata }) OR (params, RequestOptions)\n if (isAgentInspectMetadataBag(resultSchemaOrOptions)) {\n return {\n resultSchema: undefined,\n requestOptions: undefined,\n callMetadata: extractCallMetadata(resultSchemaOrOptions),\n };\n }\n\n if (isSdkRequestOptions(resultSchemaOrOptions)) {\n const peeled = peelOptionsObject(resultSchemaOrOptions);\n return {\n resultSchema: undefined,\n requestOptions: peeled.requestOptions,\n callMetadata: peeled.callMetadata,\n };\n }\n\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions: undefined,\n callMetadata: {},\n };\n}\n\nfunction invokeCallTool(\n callToolImpl: McpClientLike[\"callTool\"],\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchema: unknown,\n requestOptions: McpRequestOptions | undefined,\n): Promise<unknown> {\n const fn = callToolImpl as (\n p: unknown,\n schema?: unknown,\n opts?: unknown,\n ) => Promise<unknown>;\n if (requestOptions !== undefined) {\n return fn(params, resultSchema, requestOptions);\n }\n if (resultSchema !== undefined) {\n return fn(params, resultSchema);\n }\n return fn(params);\n}\n\n/**\n * Wraps an MCP client so tools/list and tools/call emit local tool steps.\n * Telemetry only — does not proxy network behavior beyond the wrapped client.\n *\n * Uses a Proxy over the original client so prototype methods (`connect`,\n * `close`, `listResources`, …), private SDK state, and `instanceof` stay intact.\n * A shallow object spread would drop prototype methods and copy private fields.\n *\n * Forwards the real SDK argument positions, including `RequestOptions`\n * (`signal`, `timeout`, progress callbacks). Does not fake cancellation while\n * still dispatching the underlying request.\n */\nexport function wrapMcpClient<T extends McpClientLike>(\n client: T,\n options: McpClientTracerOptions = {},\n): T {\n const maxSummaryLength = options.maxSummaryLength ?? 240;\n\n const listToolsImpl =\n typeof client.listTools === \"function\"\n ? client.listTools.bind(client)\n : undefined;\n const callToolImpl = client.callTool.bind(client);\n\n const wrappedListTools = listToolsImpl\n ? async (params?: unknown, requestOptions?: McpRequestOptions) =>\n step(\n \"mcp:tools/list\",\n async () => {\n if (requestOptions !== undefined) {\n return (\n listToolsImpl as (\n p?: unknown,\n opts?: unknown,\n ) => Promise<unknown>\n )(params, requestOptions);\n }\n return listToolsImpl(params);\n },\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: \"tools/list\",\n toolCallId: nextToolCallId(options.toolCallIdPrefix),\n }),\n },\n )\n : undefined;\n\n const wrappedCallTool = async (\n params: Parameters<McpClientLike[\"callTool\"]>[0],\n resultSchemaOrOptions?: unknown,\n maybeOptions?: unknown,\n ) => {\n const { resultSchema, requestOptions, callMetadata } = resolveCallToolArgs(\n resultSchemaOrOptions,\n maybeOptions,\n );\n\n const toolCallId = nextToolCallId(options.toolCallIdPrefix);\n return step(\n `mcp:${params.name}`,\n async () => {\n const result = await invokeCallTool(\n callToolImpl,\n params,\n resultSchema,\n requestOptions,\n );\n await recordToolResultOutcome(\n params.name,\n toolCallId,\n result,\n callMetadata,\n );\n return result;\n },\n {\n type: \"tool\",\n metadata: baseMetadata(options, {\n toolName: params.name,\n toolCallId,\n argumentSummary: summarizeMcpValue(\n params.arguments ?? {},\n maxSummaryLength,\n ),\n ...callMetadata,\n }),\n },\n );\n };\n\n return new Proxy(client, {\n get(target, property, receiver) {\n if (property === \"listTools\" && wrappedListTools !== undefined) {\n return wrappedListTools;\n }\n if (property === \"callTool\") {\n return wrappedCallTool;\n }\n const value = Reflect.get(target, property, receiver);\n if (typeof value === \"function\") {\n return value.bind(target);\n }\n return value;\n },\n }) as T;\n}\n\n/** @internal resets tool call ids for deterministic tests */\nexport function resetMcpToolCallIdsForTests(): void {\n toolCallCounter = 0;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-inspect/mcp",
|
|
3
|
-
"version": "6.31.
|
|
3
|
+
"version": "6.31.26",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Local MCP client tool-call tracing for AgentInspect",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dist"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"agent-inspect": "6.31.
|
|
38
|
+
"agent-inspect": "6.31.26"
|
|
39
39
|
},
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|