@agent-inspect/mcp 6.31.18 → 6.31.20

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 CHANGED
@@ -49,15 +49,94 @@ function baseMetadata(options, overrides = {}) {
49
49
  };
50
50
  return { ...options.metadata ?? {}, ...metadata };
51
51
  }
52
+ var SDK_REQUEST_OPTION_KEYS = [
53
+ "signal",
54
+ "timeout",
55
+ "onprogress",
56
+ "resetTimeoutOnProgress",
57
+ "maxTotalTimeout",
58
+ "relatedRequestId",
59
+ "resumptionToken",
60
+ "onresumptiontoken"
61
+ ];
62
+ function isSdkRequestOptions(value) {
63
+ if (!value || typeof value !== "object") return false;
64
+ const obj = value;
65
+ return SDK_REQUEST_OPTION_KEYS.some((key) => key in obj);
66
+ }
67
+ function isAgentInspectMetadataBag(value) {
68
+ if (!value || typeof value !== "object") return false;
69
+ if (isSdkRequestOptions(value)) return false;
70
+ const obj = value;
71
+ if (!("metadata" in obj)) return false;
72
+ if ("parse" in obj) return false;
73
+ return true;
74
+ }
75
+ function extractCallMetadata(bag) {
76
+ if (bag.metadata && typeof bag.metadata === "object") {
77
+ return bag.metadata;
78
+ }
79
+ return {};
80
+ }
81
+ function resolveCallToolArgs(resultSchemaOrOptions, maybeOptions) {
82
+ if (maybeOptions !== void 0) {
83
+ let callMetadata = {};
84
+ let requestOptions;
85
+ if (isAgentInspectMetadataBag(maybeOptions)) {
86
+ callMetadata = extractCallMetadata(maybeOptions);
87
+ requestOptions = void 0;
88
+ } else if (isSdkRequestOptions(maybeOptions) || maybeOptions === null) {
89
+ requestOptions = maybeOptions && typeof maybeOptions === "object" ? maybeOptions : void 0;
90
+ } else if (maybeOptions && typeof maybeOptions === "object") {
91
+ requestOptions = maybeOptions;
92
+ }
93
+ return {
94
+ resultSchema: resultSchemaOrOptions,
95
+ requestOptions,
96
+ callMetadata
97
+ };
98
+ }
99
+ if (isAgentInspectMetadataBag(resultSchemaOrOptions)) {
100
+ return {
101
+ resultSchema: void 0,
102
+ requestOptions: void 0,
103
+ callMetadata: extractCallMetadata(resultSchemaOrOptions)
104
+ };
105
+ }
106
+ if (isSdkRequestOptions(resultSchemaOrOptions)) {
107
+ return {
108
+ resultSchema: void 0,
109
+ requestOptions: resultSchemaOrOptions,
110
+ callMetadata: {}
111
+ };
112
+ }
113
+ return {
114
+ resultSchema: resultSchemaOrOptions,
115
+ requestOptions: void 0,
116
+ callMetadata: {}
117
+ };
118
+ }
119
+ function invokeCallTool(callToolImpl, params, resultSchema, requestOptions) {
120
+ const fn = callToolImpl;
121
+ if (requestOptions !== void 0) {
122
+ return fn(params, resultSchema, requestOptions);
123
+ }
124
+ if (resultSchema !== void 0) {
125
+ return fn(params, resultSchema);
126
+ }
127
+ return fn(params);
128
+ }
52
129
  function wrapMcpClient(client, options = {}) {
53
130
  const maxSummaryLength = options.maxSummaryLength ?? 240;
54
131
  const listToolsImpl = typeof client.listTools === "function" ? client.listTools.bind(client) : void 0;
55
132
  const callToolImpl = client.callTool.bind(client);
56
- const wrappedListTools = listToolsImpl ? async (params) => agentInspect.step(
133
+ const wrappedListTools = listToolsImpl ? async (params, requestOptions) => agentInspect.step(
57
134
  "mcp:tools/list",
58
135
  async () => {
59
- const result = await listToolsImpl(params);
60
- return result;
136
+ if (requestOptions !== void 0) {
137
+ return listToolsImpl(params, requestOptions);
138
+ }
139
+ return listToolsImpl(params);
61
140
  },
62
141
  {
63
142
  type: "tool",
@@ -67,21 +146,28 @@ function wrapMcpClient(client, options = {}) {
67
146
  })
68
147
  }
69
148
  ) : void 0;
70
- const wrappedCallTool = async (params) => agentInspect.step(
71
- `mcp:${params.name}`,
72
- async () => callToolImpl(params),
73
- {
74
- type: "tool",
75
- metadata: baseMetadata(options, {
76
- toolName: params.name,
77
- toolCallId: nextToolCallId(options.toolCallIdPrefix),
78
- argumentSummary: summarizeMcpValue(
79
- params.arguments ?? {},
80
- maxSummaryLength
81
- )
82
- })
83
- }
84
- );
149
+ const wrappedCallTool = async (params, resultSchemaOrOptions, maybeOptions) => {
150
+ const { resultSchema, requestOptions, callMetadata } = resolveCallToolArgs(
151
+ resultSchemaOrOptions,
152
+ maybeOptions
153
+ );
154
+ return agentInspect.step(
155
+ `mcp:${params.name}`,
156
+ async () => invokeCallTool(callToolImpl, params, resultSchema, requestOptions),
157
+ {
158
+ type: "tool",
159
+ metadata: baseMetadata(options, {
160
+ toolName: params.name,
161
+ toolCallId: nextToolCallId(options.toolCallIdPrefix),
162
+ argumentSummary: summarizeMcpValue(
163
+ params.arguments ?? {},
164
+ maxSummaryLength
165
+ ),
166
+ ...callMetadata
167
+ })
168
+ }
169
+ );
170
+ };
85
171
  return new Proxy(client, {
86
172
  get(target, property, receiver) {
87
173
  if (property === "listTools" && wrappedListTools !== void 0) {
@@ -104,6 +190,7 @@ function resetMcpToolCallIdsForTests() {
104
190
 
105
191
  exports.hashServerUrl = hashServerUrl;
106
192
  exports.resetMcpToolCallIdsForTests = resetMcpToolCallIdsForTests;
193
+ exports.resolveCallToolArgs = resolveCallToolArgs;
107
194
  exports.summarizeMcpValue = summarizeMcpValue;
108
195
  exports.wrapMcpClient = wrapMcpClient;
109
196
  //# sourceMappingURL=index.cjs.map
@@ -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 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/**\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 */\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) =>\n step(\n \"mcp:tools/list\",\n async () => {\n const result = await listToolsImpl(params);\n return result;\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 ) =>\n step(\n `mcp:${params.name}`,\n async () => callToolImpl(params),\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 }),\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":["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/**\n * Resolve SDK callTool arity:\n * callTool(params, resultSchema?, requestOptions?)\n * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.\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 let callMetadata: Record<string, unknown> = {};\n let requestOptions: McpRequestOptions | undefined;\n\n if (isAgentInspectMetadataBag(maybeOptions)) {\n callMetadata = extractCallMetadata(maybeOptions);\n // Remaining SDK keys (if any were mixed in) still forward — but AI bags exclude them.\n requestOptions = undefined;\n } else if (isSdkRequestOptions(maybeOptions) || maybeOptions === null) {\n requestOptions =\n maybeOptions && typeof maybeOptions === \"object\"\n ? (maybeOptions as McpRequestOptions)\n : undefined;\n } else if (maybeOptions && typeof maybeOptions === \"object\") {\n // Unknown object third arg — forward as RequestOptions to preserve caller intent.\n requestOptions = maybeOptions as McpRequestOptions;\n }\n\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions,\n 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 return {\n resultSchema: undefined,\n requestOptions: resultSchemaOrOptions,\n 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"]}
package/dist/index.d.cts CHANGED
@@ -15,13 +15,36 @@ interface McpCallToolResult {
15
15
  isError?: boolean;
16
16
  structuredContent?: unknown;
17
17
  }
18
+ /**
19
+ * Subset of MCP SDK `RequestOptions` forwarded by the wrapper.
20
+ * Compatible with @modelcontextprotocol/sdk without requiring it at runtime.
21
+ */
22
+ interface McpRequestOptions {
23
+ signal?: AbortSignal;
24
+ timeout?: number;
25
+ onprogress?: (...args: unknown[]) => void;
26
+ resetTimeoutOnProgress?: boolean;
27
+ maxTotalTimeout?: number;
28
+ relatedRequestId?: string;
29
+ resumptionToken?: string;
30
+ onresumptiontoken?: (...args: unknown[]) => void;
31
+ /** AgentInspect per-call metadata (optional; never consumes SDK option keys). */
32
+ metadata?: Record<string, unknown>;
33
+ [key: string]: unknown;
34
+ }
18
35
  /**
19
36
  * Minimal MCP client surface for local tracing. Compatible with common SDK
20
37
  * client shapes without requiring @modelcontextprotocol/sdk at runtime.
38
+ *
39
+ * Matches SDK arity: `callTool(params, resultSchema?, requestOptions?)` and
40
+ * `listTools(params?, requestOptions?)`. AgentInspect also accepts a
41
+ * `{ metadata }` bag in place of schema/options when it is not RequestOptions-shaped.
21
42
  */
22
43
  interface McpClientLike {
23
- listTools?: (params?: unknown) => Promise<McpListToolsResult>;
24
- callTool: (params: McpCallToolParams) => Promise<McpCallToolResult>;
44
+ listTools?: (params?: unknown, options?: McpRequestOptions) => Promise<McpListToolsResult>;
45
+ callTool: (params: McpCallToolParams, resultSchemaOrOptions?: unknown, options?: McpRequestOptions | {
46
+ metadata?: Record<string, unknown>;
47
+ }) => Promise<McpCallToolResult>;
25
48
  }
26
49
  interface McpClientTracerOptions {
27
50
  serverName?: string;
@@ -50,6 +73,16 @@ interface McpTraceMetadata {
50
73
  declare function summarizeMcpValue(value: unknown, maxLength?: number): string;
51
74
  declare function hashServerUrl(url: string): string;
52
75
 
76
+ /**
77
+ * Resolve SDK callTool arity:
78
+ * callTool(params, resultSchema?, requestOptions?)
79
+ * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.
80
+ */
81
+ declare function resolveCallToolArgs(resultSchemaOrOptions?: unknown, maybeOptions?: unknown): {
82
+ resultSchema: unknown;
83
+ requestOptions: McpRequestOptions | undefined;
84
+ callMetadata: Record<string, unknown>;
85
+ };
53
86
  /**
54
87
  * Wraps an MCP client so tools/list and tools/call emit local tool steps.
55
88
  * Telemetry only — does not proxy network behavior beyond the wrapped client.
@@ -57,9 +90,13 @@ declare function hashServerUrl(url: string): string;
57
90
  * Uses a Proxy over the original client so prototype methods (`connect`,
58
91
  * `close`, `listResources`, …), private SDK state, and `instanceof` stay intact.
59
92
  * A shallow object spread would drop prototype methods and copy private fields.
93
+ *
94
+ * Forwards the real SDK argument positions, including `RequestOptions`
95
+ * (`signal`, `timeout`, progress callbacks). Does not fake cancellation while
96
+ * still dispatching the underlying request.
60
97
  */
61
98
  declare function wrapMcpClient<T extends McpClientLike>(client: T, options?: McpClientTracerOptions): T;
62
99
  /** @internal resets tool call ids for deterministic tests */
63
100
  declare function resetMcpToolCallIdsForTests(): void;
64
101
 
65
- export { type McpCallToolParams, type McpCallToolResult, type McpClientLike, type McpClientTracerOptions, type McpListToolsResult, type McpToolDescriptor, type McpTraceMetadata, hashServerUrl, resetMcpToolCallIdsForTests, summarizeMcpValue, wrapMcpClient };
102
+ export { type McpCallToolParams, type McpCallToolResult, type McpClientLike, type McpClientTracerOptions, type McpListToolsResult, type McpRequestOptions, type McpToolDescriptor, type McpTraceMetadata, hashServerUrl, resetMcpToolCallIdsForTests, resolveCallToolArgs, summarizeMcpValue, wrapMcpClient };
package/dist/index.d.ts CHANGED
@@ -15,13 +15,36 @@ interface McpCallToolResult {
15
15
  isError?: boolean;
16
16
  structuredContent?: unknown;
17
17
  }
18
+ /**
19
+ * Subset of MCP SDK `RequestOptions` forwarded by the wrapper.
20
+ * Compatible with @modelcontextprotocol/sdk without requiring it at runtime.
21
+ */
22
+ interface McpRequestOptions {
23
+ signal?: AbortSignal;
24
+ timeout?: number;
25
+ onprogress?: (...args: unknown[]) => void;
26
+ resetTimeoutOnProgress?: boolean;
27
+ maxTotalTimeout?: number;
28
+ relatedRequestId?: string;
29
+ resumptionToken?: string;
30
+ onresumptiontoken?: (...args: unknown[]) => void;
31
+ /** AgentInspect per-call metadata (optional; never consumes SDK option keys). */
32
+ metadata?: Record<string, unknown>;
33
+ [key: string]: unknown;
34
+ }
18
35
  /**
19
36
  * Minimal MCP client surface for local tracing. Compatible with common SDK
20
37
  * client shapes without requiring @modelcontextprotocol/sdk at runtime.
38
+ *
39
+ * Matches SDK arity: `callTool(params, resultSchema?, requestOptions?)` and
40
+ * `listTools(params?, requestOptions?)`. AgentInspect also accepts a
41
+ * `{ metadata }` bag in place of schema/options when it is not RequestOptions-shaped.
21
42
  */
22
43
  interface McpClientLike {
23
- listTools?: (params?: unknown) => Promise<McpListToolsResult>;
24
- callTool: (params: McpCallToolParams) => Promise<McpCallToolResult>;
44
+ listTools?: (params?: unknown, options?: McpRequestOptions) => Promise<McpListToolsResult>;
45
+ callTool: (params: McpCallToolParams, resultSchemaOrOptions?: unknown, options?: McpRequestOptions | {
46
+ metadata?: Record<string, unknown>;
47
+ }) => Promise<McpCallToolResult>;
25
48
  }
26
49
  interface McpClientTracerOptions {
27
50
  serverName?: string;
@@ -50,6 +73,16 @@ interface McpTraceMetadata {
50
73
  declare function summarizeMcpValue(value: unknown, maxLength?: number): string;
51
74
  declare function hashServerUrl(url: string): string;
52
75
 
76
+ /**
77
+ * Resolve SDK callTool arity:
78
+ * callTool(params, resultSchema?, requestOptions?)
79
+ * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.
80
+ */
81
+ declare function resolveCallToolArgs(resultSchemaOrOptions?: unknown, maybeOptions?: unknown): {
82
+ resultSchema: unknown;
83
+ requestOptions: McpRequestOptions | undefined;
84
+ callMetadata: Record<string, unknown>;
85
+ };
53
86
  /**
54
87
  * Wraps an MCP client so tools/list and tools/call emit local tool steps.
55
88
  * Telemetry only — does not proxy network behavior beyond the wrapped client.
@@ -57,9 +90,13 @@ declare function hashServerUrl(url: string): string;
57
90
  * Uses a Proxy over the original client so prototype methods (`connect`,
58
91
  * `close`, `listResources`, …), private SDK state, and `instanceof` stay intact.
59
92
  * A shallow object spread would drop prototype methods and copy private fields.
93
+ *
94
+ * Forwards the real SDK argument positions, including `RequestOptions`
95
+ * (`signal`, `timeout`, progress callbacks). Does not fake cancellation while
96
+ * still dispatching the underlying request.
60
97
  */
61
98
  declare function wrapMcpClient<T extends McpClientLike>(client: T, options?: McpClientTracerOptions): T;
62
99
  /** @internal resets tool call ids for deterministic tests */
63
100
  declare function resetMcpToolCallIdsForTests(): void;
64
101
 
65
- export { type McpCallToolParams, type McpCallToolResult, type McpClientLike, type McpClientTracerOptions, type McpListToolsResult, type McpToolDescriptor, type McpTraceMetadata, hashServerUrl, resetMcpToolCallIdsForTests, summarizeMcpValue, wrapMcpClient };
102
+ export { type McpCallToolParams, type McpCallToolResult, type McpClientLike, type McpClientTracerOptions, type McpListToolsResult, type McpRequestOptions, type McpToolDescriptor, type McpTraceMetadata, hashServerUrl, resetMcpToolCallIdsForTests, resolveCallToolArgs, summarizeMcpValue, wrapMcpClient };
package/dist/index.mjs CHANGED
@@ -47,15 +47,94 @@ function baseMetadata(options, overrides = {}) {
47
47
  };
48
48
  return { ...options.metadata ?? {}, ...metadata };
49
49
  }
50
+ var SDK_REQUEST_OPTION_KEYS = [
51
+ "signal",
52
+ "timeout",
53
+ "onprogress",
54
+ "resetTimeoutOnProgress",
55
+ "maxTotalTimeout",
56
+ "relatedRequestId",
57
+ "resumptionToken",
58
+ "onresumptiontoken"
59
+ ];
60
+ function isSdkRequestOptions(value) {
61
+ if (!value || typeof value !== "object") return false;
62
+ const obj = value;
63
+ return SDK_REQUEST_OPTION_KEYS.some((key) => key in obj);
64
+ }
65
+ function isAgentInspectMetadataBag(value) {
66
+ if (!value || typeof value !== "object") return false;
67
+ if (isSdkRequestOptions(value)) return false;
68
+ const obj = value;
69
+ if (!("metadata" in obj)) return false;
70
+ if ("parse" in obj) return false;
71
+ return true;
72
+ }
73
+ function extractCallMetadata(bag) {
74
+ if (bag.metadata && typeof bag.metadata === "object") {
75
+ return bag.metadata;
76
+ }
77
+ return {};
78
+ }
79
+ function resolveCallToolArgs(resultSchemaOrOptions, maybeOptions) {
80
+ if (maybeOptions !== void 0) {
81
+ let callMetadata = {};
82
+ let requestOptions;
83
+ if (isAgentInspectMetadataBag(maybeOptions)) {
84
+ callMetadata = extractCallMetadata(maybeOptions);
85
+ requestOptions = void 0;
86
+ } else if (isSdkRequestOptions(maybeOptions) || maybeOptions === null) {
87
+ requestOptions = maybeOptions && typeof maybeOptions === "object" ? maybeOptions : void 0;
88
+ } else if (maybeOptions && typeof maybeOptions === "object") {
89
+ requestOptions = maybeOptions;
90
+ }
91
+ return {
92
+ resultSchema: resultSchemaOrOptions,
93
+ requestOptions,
94
+ callMetadata
95
+ };
96
+ }
97
+ if (isAgentInspectMetadataBag(resultSchemaOrOptions)) {
98
+ return {
99
+ resultSchema: void 0,
100
+ requestOptions: void 0,
101
+ callMetadata: extractCallMetadata(resultSchemaOrOptions)
102
+ };
103
+ }
104
+ if (isSdkRequestOptions(resultSchemaOrOptions)) {
105
+ return {
106
+ resultSchema: void 0,
107
+ requestOptions: resultSchemaOrOptions,
108
+ callMetadata: {}
109
+ };
110
+ }
111
+ return {
112
+ resultSchema: resultSchemaOrOptions,
113
+ requestOptions: void 0,
114
+ callMetadata: {}
115
+ };
116
+ }
117
+ function invokeCallTool(callToolImpl, params, resultSchema, requestOptions) {
118
+ const fn = callToolImpl;
119
+ if (requestOptions !== void 0) {
120
+ return fn(params, resultSchema, requestOptions);
121
+ }
122
+ if (resultSchema !== void 0) {
123
+ return fn(params, resultSchema);
124
+ }
125
+ return fn(params);
126
+ }
50
127
  function wrapMcpClient(client, options = {}) {
51
128
  const maxSummaryLength = options.maxSummaryLength ?? 240;
52
129
  const listToolsImpl = typeof client.listTools === "function" ? client.listTools.bind(client) : void 0;
53
130
  const callToolImpl = client.callTool.bind(client);
54
- const wrappedListTools = listToolsImpl ? async (params) => step(
131
+ const wrappedListTools = listToolsImpl ? async (params, requestOptions) => step(
55
132
  "mcp:tools/list",
56
133
  async () => {
57
- const result = await listToolsImpl(params);
58
- return result;
134
+ if (requestOptions !== void 0) {
135
+ return listToolsImpl(params, requestOptions);
136
+ }
137
+ return listToolsImpl(params);
59
138
  },
60
139
  {
61
140
  type: "tool",
@@ -65,21 +144,28 @@ function wrapMcpClient(client, options = {}) {
65
144
  })
66
145
  }
67
146
  ) : void 0;
68
- const wrappedCallTool = async (params) => step(
69
- `mcp:${params.name}`,
70
- async () => callToolImpl(params),
71
- {
72
- type: "tool",
73
- metadata: baseMetadata(options, {
74
- toolName: params.name,
75
- toolCallId: nextToolCallId(options.toolCallIdPrefix),
76
- argumentSummary: summarizeMcpValue(
77
- params.arguments ?? {},
78
- maxSummaryLength
79
- )
80
- })
81
- }
82
- );
147
+ const wrappedCallTool = async (params, resultSchemaOrOptions, maybeOptions) => {
148
+ const { resultSchema, requestOptions, callMetadata } = resolveCallToolArgs(
149
+ resultSchemaOrOptions,
150
+ maybeOptions
151
+ );
152
+ return step(
153
+ `mcp:${params.name}`,
154
+ async () => invokeCallTool(callToolImpl, params, resultSchema, requestOptions),
155
+ {
156
+ type: "tool",
157
+ metadata: baseMetadata(options, {
158
+ toolName: params.name,
159
+ toolCallId: nextToolCallId(options.toolCallIdPrefix),
160
+ argumentSummary: summarizeMcpValue(
161
+ params.arguments ?? {},
162
+ maxSummaryLength
163
+ ),
164
+ ...callMetadata
165
+ })
166
+ }
167
+ );
168
+ };
83
169
  return new Proxy(client, {
84
170
  get(target, property, receiver) {
85
171
  if (property === "listTools" && wrappedListTools !== void 0) {
@@ -100,6 +186,6 @@ function resetMcpToolCallIdsForTests() {
100
186
  toolCallCounter = 0;
101
187
  }
102
188
 
103
- export { hashServerUrl, resetMcpToolCallIdsForTests, summarizeMcpValue, wrapMcpClient };
189
+ export { hashServerUrl, resetMcpToolCallIdsForTests, resolveCallToolArgs, summarizeMcpValue, wrapMcpClient };
104
190
  //# sourceMappingURL=index.mjs.map
105
191
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
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 { step } from \"agent-inspect\";\n\nimport { hashServerUrl, summarizeMcpValue } from \"./summarize.js\";\nimport type {\n McpClientLike,\n McpClientTracerOptions,\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/**\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 */\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) =>\n step(\n \"mcp:tools/list\",\n async () => {\n const result = await listToolsImpl(params);\n return result;\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 ) =>\n step(\n `mcp:${params.name}`,\n async () => callToolImpl(params),\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 }),\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":";;;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;AAOO,SAAS,mBAAA,CACd,uBACA,YAAA,EAKA;AAEA,EAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,IAAA,IAAI,eAAwC,EAAC;AAC7C,IAAA,IAAI,cAAA;AAEJ,IAAA,IAAI,yBAAA,CAA0B,YAAY,CAAA,EAAG;AAC3C,MAAA,YAAA,GAAe,oBAAoB,YAAY,CAAA;AAE/C,MAAA,cAAA,GAAiB,MAAA;AAAA,IACnB,CAAA,MAAA,IAAW,mBAAA,CAAoB,YAAY,CAAA,IAAK,iBAAiB,IAAA,EAAM;AACrE,MAAA,cAAA,GACE,YAAA,IAAgB,OAAO,YAAA,KAAiB,QAAA,GACnC,YAAA,GACD,MAAA;AAAA,IACR,CAAA,MAAA,IAAW,YAAA,IAAgB,OAAO,YAAA,KAAiB,QAAA,EAAU;AAE3D,MAAA,cAAA,GAAiB,YAAA;AAAA,IACnB;AAEA,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,qBAAA;AAAA,MACd,cAAA;AAAA,MACA;AAAA,KACF;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,OAAO;AAAA,MACL,YAAA,EAAc,MAAA;AAAA,MACd,cAAA,EAAgB,qBAAA;AAAA,MAChB,cAAc;AAAC,KACjB;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/**\n * Resolve SDK callTool arity:\n * callTool(params, resultSchema?, requestOptions?)\n * plus AgentInspect overloads that peel `{ metadata }` without dropping RequestOptions.\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 let callMetadata: Record<string, unknown> = {};\n let requestOptions: McpRequestOptions | undefined;\n\n if (isAgentInspectMetadataBag(maybeOptions)) {\n callMetadata = extractCallMetadata(maybeOptions);\n // Remaining SDK keys (if any were mixed in) still forward — but AI bags exclude them.\n requestOptions = undefined;\n } else if (isSdkRequestOptions(maybeOptions) || maybeOptions === null) {\n requestOptions =\n maybeOptions && typeof maybeOptions === \"object\"\n ? (maybeOptions as McpRequestOptions)\n : undefined;\n } else if (maybeOptions && typeof maybeOptions === \"object\") {\n // Unknown object third arg — forward as RequestOptions to preserve caller intent.\n requestOptions = maybeOptions as McpRequestOptions;\n }\n\n return {\n resultSchema: resultSchemaOrOptions,\n requestOptions,\n 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 return {\n resultSchema: undefined,\n requestOptions: resultSchemaOrOptions,\n 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-inspect/mcp",
3
- "version": "6.31.18",
3
+ "version": "6.31.20",
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.18"
38
+ "agent-inspect": "6.31.20"
39
39
  },
40
40
  "publishConfig": {
41
41
  "access": "public"