@tambo-ai/react 0.55.0 → 0.56.0
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/mcp/__tests__/mcp-client.test.js +52 -6
- package/dist/mcp/__tests__/mcp-client.test.js.map +1 -1
- package/dist/mcp/mcp-client.d.ts +34 -2
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +63 -4
- package/dist/mcp/mcp-client.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider.test.js +2 -6
- package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +2 -4
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/esm/mcp/__tests__/mcp-client.test.js +52 -6
- package/esm/mcp/__tests__/mcp-client.test.js.map +1 -1
- package/esm/mcp/mcp-client.d.ts +34 -2
- package/esm/mcp/mcp-client.d.ts.map +1 -1
- package/esm/mcp/mcp-client.js +63 -4
- package/esm/mcp/mcp-client.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider.test.js +2 -6
- package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +2 -4
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/package.json +11 -14
|
@@ -8,6 +8,8 @@ jest.mock("@modelcontextprotocol/sdk/client/index.js", () => ({
|
|
|
8
8
|
close: jest.fn(),
|
|
9
9
|
listTools: jest.fn(),
|
|
10
10
|
callTool: jest.fn(),
|
|
11
|
+
setRequestHandler: jest.fn(),
|
|
12
|
+
removeRequestHandler: jest.fn(),
|
|
11
13
|
onclose: null,
|
|
12
14
|
})),
|
|
13
15
|
}));
|
|
@@ -41,6 +43,8 @@ describe("MCPClient", () => {
|
|
|
41
43
|
close: jest.fn().mockResolvedValue(undefined),
|
|
42
44
|
listTools: jest.fn(),
|
|
43
45
|
callTool: jest.fn(),
|
|
46
|
+
setRequestHandler: jest.fn(),
|
|
47
|
+
removeRequestHandler: jest.fn(),
|
|
44
48
|
onclose: null,
|
|
45
49
|
};
|
|
46
50
|
mockTransportInstance = {
|
|
@@ -60,7 +64,7 @@ describe("MCPClient", () => {
|
|
|
60
64
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
61
65
|
name: "tambo-mcp-client",
|
|
62
66
|
version: "1.0.0",
|
|
63
|
-
});
|
|
67
|
+
}, { capabilities: {} });
|
|
64
68
|
expect(mockClientInstance.connect).toHaveBeenCalledWith(mockTransportInstance);
|
|
65
69
|
expect(client).toBeInstanceOf(mcp_client_1.MCPClient);
|
|
66
70
|
});
|
|
@@ -108,7 +112,7 @@ describe("MCPClient", () => {
|
|
|
108
112
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
109
113
|
name: "tambo-mcp-client",
|
|
110
114
|
version: "1.0.0",
|
|
111
|
-
});
|
|
115
|
+
}, { capabilities: {} });
|
|
112
116
|
// Verify new client's connect was called with new transport
|
|
113
117
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
114
118
|
});
|
|
@@ -172,7 +176,7 @@ describe("MCPClient", () => {
|
|
|
172
176
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
173
177
|
name: "tambo-mcp-client",
|
|
174
178
|
version: "1.0.0",
|
|
175
|
-
});
|
|
179
|
+
}, { capabilities: {} });
|
|
176
180
|
// Verify new client's connect was called with new transport
|
|
177
181
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
178
182
|
});
|
|
@@ -204,7 +208,7 @@ describe("MCPClient", () => {
|
|
|
204
208
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
205
209
|
name: "tambo-mcp-client",
|
|
206
210
|
version: "1.0.0",
|
|
207
|
-
});
|
|
211
|
+
}, { capabilities: {} });
|
|
208
212
|
// Verify new client's connect was called with new transport
|
|
209
213
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
210
214
|
});
|
|
@@ -247,7 +251,7 @@ describe("MCPClient", () => {
|
|
|
247
251
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
248
252
|
name: "tambo-mcp-client",
|
|
249
253
|
version: "1.0.0",
|
|
250
|
-
});
|
|
254
|
+
}, { capabilities: {} });
|
|
251
255
|
// Verify new client's connect was called with new transport
|
|
252
256
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
253
257
|
// Ensure only a single reconnect attempt occurred
|
|
@@ -489,7 +493,7 @@ describe("MCPClient", () => {
|
|
|
489
493
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
490
494
|
name: "tambo-mcp-client",
|
|
491
495
|
version: "1.0.0",
|
|
492
|
-
});
|
|
496
|
+
}, { capabilities: {} });
|
|
493
497
|
});
|
|
494
498
|
it("should set onclose handler", async () => {
|
|
495
499
|
const endpoint = "https://api.example.com/mcp";
|
|
@@ -498,5 +502,47 @@ describe("MCPClient", () => {
|
|
|
498
502
|
expect(typeof mockClientInstance.onclose).toBe("function");
|
|
499
503
|
});
|
|
500
504
|
});
|
|
505
|
+
describe("handlers (elicitation/sampling)", () => {
|
|
506
|
+
it("sets handlers on create when provided", async () => {
|
|
507
|
+
const endpoint = "https://api.example.com/mcp";
|
|
508
|
+
const elicitation = jest.fn(async () => ({}));
|
|
509
|
+
const sampling = jest.fn(async () => ({}));
|
|
510
|
+
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined, { elicitation, sampling });
|
|
511
|
+
expect(MockedClient).toHaveBeenLastCalledWith({
|
|
512
|
+
name: "tambo-mcp-client",
|
|
513
|
+
version: "1.0.0",
|
|
514
|
+
}, {
|
|
515
|
+
capabilities: {
|
|
516
|
+
elicitation: {},
|
|
517
|
+
sampling: {},
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
// Request handlers should be set for both
|
|
521
|
+
expect(mockClientInstance.setRequestHandler).toHaveBeenCalled();
|
|
522
|
+
expect(mockClientInstance.setRequestHandler.mock.calls.length).toBeGreaterThanOrEqual(2);
|
|
523
|
+
});
|
|
524
|
+
it("removes elicitation handler when set to undefined", async () => {
|
|
525
|
+
const endpoint = "https://api.example.com/mcp";
|
|
526
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined, {
|
|
527
|
+
elicitation: async () => ({}),
|
|
528
|
+
});
|
|
529
|
+
const removeSpy = mockClientInstance.removeRequestHandler;
|
|
530
|
+
// then remove
|
|
531
|
+
removeSpy.mockClear();
|
|
532
|
+
await client.updateElicitationHandler(undefined);
|
|
533
|
+
expect(removeSpy).toHaveBeenCalledWith(expect.any(String));
|
|
534
|
+
});
|
|
535
|
+
it("removes sampling handler when set to undefined", async () => {
|
|
536
|
+
const endpoint = "https://api.example.com/mcp";
|
|
537
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined, {
|
|
538
|
+
sampling: async () => ({}),
|
|
539
|
+
});
|
|
540
|
+
const removeSpy = mockClientInstance.removeRequestHandler;
|
|
541
|
+
// then remove
|
|
542
|
+
removeSpy.mockClear();
|
|
543
|
+
await client.updateSamplingHandler(undefined);
|
|
544
|
+
expect(removeSpy).toHaveBeenCalledWith(expect.any(String));
|
|
545
|
+
});
|
|
546
|
+
});
|
|
501
547
|
});
|
|
502
548
|
//# sourceMappingURL=mcp-client.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-client.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/mcp-client.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { MCPClient, MCPTransport } from \"../mcp-client\";\n\n// Mock the MCP SDK modules\njest.mock(\"@modelcontextprotocol/sdk/client/index.js\", () => ({\n Client: jest.fn().mockImplementation(() => ({\n connect: jest.fn(),\n close: jest.fn(),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n })),\n}));\n\njest.mock(\"@modelcontextprotocol/sdk/client/sse.js\", () => ({\n SSEClientTransport: jest.fn().mockImplementation(() => ({\n // SSE transport doesn't have sessionId\n })),\n}));\n\njest.mock(\"@modelcontextprotocol/sdk/client/streamableHttp.js\", () => ({\n StreamableHTTPClientTransport: jest\n .fn()\n .mockImplementation((url, options) => ({\n sessionId: options?.sessionId,\n })),\n}));\n\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\n// Type the mocked modules\nconst MockedClient = Client as jest.MockedClass<typeof Client>;\nconst MockedSSEClientTransport = SSEClientTransport as jest.MockedClass<\n typeof SSEClientTransport\n>;\nconst MockedStreamableHTTPClientTransport =\n StreamableHTTPClientTransport as jest.MockedClass<\n typeof StreamableHTTPClientTransport\n >;\n\ndescribe(\"MCPClient\", () => {\n let mockClientInstance: any;\n let mockTransportInstance: any;\n\n beforeEach(() => {\n jest.clearAllMocks();\n\n // Create mock instances\n mockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n mockTransportInstance = {\n sessionId: \"test-session-id\",\n };\n\n // Setup mocks\n MockedClient.mockImplementation(() => mockClientInstance);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => mockTransportInstance,\n );\n MockedSSEClientTransport.mockImplementation(\n () => ({}) as SSEClientTransport,\n );\n });\n\n describe(\"create\", () => {\n it(\"should create and connect an MCPClient with HTTP transport by default\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const headers = { Authorization: \"Bearer token\" };\n\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n headers,\n undefined,\n undefined,\n );\n\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers } },\n );\n expect(MockedClient).toHaveBeenCalledWith({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n expect(mockClientInstance.connect).toHaveBeenCalledWith(\n mockTransportInstance,\n );\n expect(client).toBeInstanceOf(MCPClient);\n });\n\n it(\"should create and connect an MCPClient with SSE transport\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.SSE,\n undefined,\n undefined,\n undefined,\n );\n\n expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {\n requestInit: { headers: {} },\n });\n expect(mockClientInstance.connect).toHaveBeenCalledWith({});\n expect(client).toBeInstanceOf(MCPClient);\n });\n\n it(\"should create client with default headers when none provided\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n\n await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers: {} } },\n );\n });\n });\n\n describe(\"reconnect\", () => {\n it(\"should create new transport and client instances and call connect when reconnect() is called (default behavior)\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls to focus on reconnect behavior\n jest.clearAllMocks();\n\n // Create new mock instances to verify new instances are created\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"new-session-id\",\n };\n\n // Mock the constructors to return new instances\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n await client.reconnect(); // Uses default parameters\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with preserved session ID (default behavior)\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: \"test-session-id\", requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n });\n\n it(\"should reconnect without session ID for SSE transport\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.SSE,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls\n jest.clearAllMocks();\n\n await client.reconnect();\n\n expect(mockClientInstance.close).toHaveBeenCalled();\n expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {\n requestInit: { headers: {} },\n });\n expect(mockClientInstance.connect).toHaveBeenCalledWith({});\n });\n\n it(\"should handle close errors when reportErrorOnClose is true\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n // Make close throw an error\n mockClientInstance.close.mockRejectedValue(new Error(\"Close failed\"));\n\n await client.reconnect(false, true);\n\n expect(consoleSpy).toHaveBeenCalledWith(\n \"Error closing Tambo MCP Client:\",\n expect.any(Error),\n );\n consoleSpy.mockRestore();\n });\n\n it(\"should not log close errors when reportErrorOnClose is false\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n // Make close throw an error\n mockClientInstance.close.mockRejectedValue(new Error(\"Close failed\"));\n\n await client.reconnect(false, false);\n\n expect(consoleSpy).not.toHaveBeenCalled();\n consoleSpy.mockRestore();\n });\n\n it(\"should create new session when newSession is true\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls to focus on reconnect behavior\n jest.clearAllMocks();\n\n // Create new mock instances to verify new instances are created\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"new-session-id\",\n };\n\n // Mock the constructors to return new instances\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n await client.reconnect(true, true); // newSession = true, reportErrorOnClose = true\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with undefined session ID (new session)\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n });\n\n it(\"should reuse existing session when newSession is false (default)\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls to focus on reconnect behavior\n jest.clearAllMocks();\n\n // Create new mock instances to verify new instances are created\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"reused-session-id\",\n };\n\n // Mock the constructors to return new instances\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n await client.reconnect(false, true); // newSession = false, reportErrorOnClose = true\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with preserved session ID\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: \"test-session-id\", requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n });\n });\n\n describe(\"onclose\", () => {\n it(\"should reconnect MCPClient when client is closed by external means (no backoff on manual preemption)\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n jest.useFakeTimers();\n const consoleSpy = jest.spyOn(console, \"warn\").mockImplementation();\n\n // Create new mock instances to verify reconnection creates new instances\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"reconnected-session-id\",\n };\n\n // Mock the constructors to return new instances for reconnection\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n // Reset counts after initial creation\n jest.clearAllMocks();\n\n // Trigger automatic onclose (schedules a delayed reconnect)\n (client as any).onclose();\n // Manual reconnect should preempt the scheduled automatic attempt\n const reconnectPromise = client.reconnect();\n // No timers should be pending after manual preemption\n await reconnectPromise;\n\n // Verify warning message is logged\n expect(consoleSpy).toHaveBeenCalled();\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with preserved session ID\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: \"test-session-id\", requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n\n // Ensure only a single reconnect attempt occurred\n expect(MockedClient).toHaveBeenCalledTimes(1);\n expect(newMockClientInstance.connect).toHaveBeenCalledTimes(1);\n\n consoleSpy.mockRestore();\n jest.useRealTimers();\n });\n });\n\n describe(\"reconnect re-entrancy and single-flight\", () => {\n it(\"prevents re-entrant onclose during deliberate close and coalesces concurrent calls\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Simulate an implementation where closing the client would call its own onclose handler\n const closeImpl = jest.fn(async () => {\n if (typeof mockClientInstance.onclose === \"function\") {\n // would cause recursion if not detached\n (mockClientInstance.onclose as unknown as () => void)();\n }\n return;\n });\n mockClientInstance.close = closeImpl;\n\n // Prepare new instances for the reconnect\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n\n // Reset counts after initial creation\n jest.clearAllMocks();\n\n // Trigger auto onclose and manual reconnect nearly simultaneously\n (client as any).onclose();\n await client.reconnect();\n\n // Should have detached onclose before calling close, avoiding recursion\n expect(closeImpl).toHaveBeenCalledTimes(1);\n expect(mockClientInstance.onclose).toBeUndefined();\n\n // Single-flight: only one new client/connect\n expect(MockedClient).toHaveBeenCalledTimes(1);\n expect(newMockClientInstance.connect).toHaveBeenCalledTimes(1);\n });\n });\n\n describe(\"backoff + jitter (automatic reconnect)\", () => {\n it(\"applies jitter and resets to initial delay after a successful reconnect (manual preempt)\", async () => {\n jest.useFakeTimers();\n const base = MCPClient.BACKOFF_INITIAL_MS;\n const ratio = MCPClient.BACKOFF_JITTER_RATIO;\n const min = Math.round(base * (1 - ratio));\n const max = Math.round(base * (1 + ratio));\n const setTimeoutSpy = jest.spyOn(global, \"setTimeout\");\n const randSpy = jest.spyOn(Math, \"random\").mockReturnValue(0.0); // extreme low jitter\n\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Prepare one attempt that will succeed to avoid rescheduling\n MockedClient.mockImplementation(\n () =>\n ({\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n }) as any,\n );\n\n // Trigger once to capture the delay\n (client as any).onclose();\n expect(setTimeoutSpy).toHaveBeenCalled();\n const numericDelays = setTimeoutSpy.mock.calls\n .map((c) => c[1])\n .filter((v) => typeof v === \"number\") as number[];\n expect(numericDelays.length).toBeGreaterThan(0);\n const d = numericDelays[0]!;\n expect(d).toBeGreaterThanOrEqual(min);\n expect(d).toBeLessThanOrEqual(max);\n\n // Manual reconnect succeeds and should reset backoff attempts\n await client.reconnect();\n\n // Trigger onclose again and ensure we start from initial range again\n (client as any).onclose();\n const numericDelays2 = setTimeoutSpy.mock.calls\n .map((c) => c[1])\n .filter((v) => typeof v === \"number\") as number[];\n expect(numericDelays2.length).toBeGreaterThanOrEqual(2);\n const dAgain = numericDelays2[1]!;\n expect(dAgain).toBeGreaterThanOrEqual(min);\n expect(dAgain).toBeLessThanOrEqual(max);\n\n jest.useRealTimers();\n setTimeoutSpy.mockRestore();\n randSpy.mockRestore();\n });\n });\n\n describe(\"listTools\", () => {\n it(\"should list all tools with pagination\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockTools = [\n {\n name: \"tool1\",\n description: \"First tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n {\n name: \"tool2\",\n description: \"Second tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg2: { type: \"number\" } },\n },\n },\n ];\n\n const mockResponse1 = {\n tools: [mockTools[0]],\n nextCursor: \"cursor1\",\n };\n\n const mockResponse2 = {\n tools: [mockTools[1]],\n nextCursor: undefined,\n };\n\n mockClientInstance.listTools\n .mockResolvedValueOnce(mockResponse1)\n .mockResolvedValueOnce(mockResponse2);\n\n const result = await client.listTools();\n\n expect(mockClientInstance.listTools).toHaveBeenCalledTimes(2);\n expect(mockClientInstance.listTools).toHaveBeenNthCalledWith(\n 1,\n { cursor: undefined },\n {},\n );\n expect(mockClientInstance.listTools).toHaveBeenNthCalledWith(\n 2,\n { cursor: \"cursor1\" },\n {},\n );\n expect(result).toEqual([\n {\n name: \"tool1\",\n description: \"First tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n {\n name: \"tool2\",\n description: \"Second tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg2: { type: \"number\" } },\n },\n },\n ]);\n });\n\n it(\"should handle single page of tools\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockTools = [\n {\n name: \"tool1\",\n description: \"Only tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n ];\n\n const mockResponse = {\n tools: mockTools,\n nextCursor: undefined,\n };\n\n mockClientInstance.listTools.mockResolvedValue(mockResponse);\n\n const result = await client.listTools();\n\n expect(mockClientInstance.listTools).toHaveBeenCalledTimes(1);\n expect(result).toEqual([\n {\n name: \"tool1\",\n description: \"Only tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n ]);\n });\n\n it(\"should throw error for invalid input schema\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockTools = [\n {\n name: \"invalid-tool\",\n description: \"Tool with invalid schema\",\n inputSchema: { type: \"string\" }, // Invalid - should be object\n },\n ];\n\n const mockResponse = {\n tools: mockTools,\n nextCursor: undefined,\n };\n\n mockClientInstance.listTools.mockResolvedValue(mockResponse);\n\n await expect(client.listTools()).rejects.toThrow(\n \"Input schema for tool invalid-tool is not an object\",\n );\n });\n });\n\n describe(\"callTool\", () => {\n it(\"should call a tool with arguments\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockResult = { success: true, data: \"test result\" };\n mockClientInstance.callTool.mockResolvedValue(mockResult);\n\n const result = await client.callTool(\"testTool\", {\n arg1: \"value1\",\n arg2: 42,\n });\n\n expect(mockClientInstance.callTool).toHaveBeenCalledWith({\n name: \"testTool\",\n arguments: { arg1: \"value1\", arg2: 42 },\n });\n expect(result).toBe(mockResult);\n });\n\n it(\"should handle tool call errors\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n const error = new Error(\"Tool call failed\");\n mockClientInstance.callTool.mockRejectedValue(error);\n\n await expect(client.callTool(\"testTool\", {})).rejects.toThrow(\n \"Tool call failed\",\n );\n });\n });\n\n describe(\"transport initialization\", () => {\n it(\"should initialize HTTP transport with session ID\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const headers = { Authorization: \"Bearer token\" };\n\n await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n headers,\n undefined,\n undefined,\n );\n\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers } },\n );\n });\n\n it(\"should initialize SSE transport without session ID\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const headers = { Authorization: \"Bearer token\" };\n\n await MCPClient.create(\n endpoint,\n MCPTransport.SSE,\n headers,\n undefined,\n undefined,\n );\n\n expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {\n requestInit: { headers },\n });\n });\n });\n\n describe(\"client initialization\", () => {\n it(\"should initialize client with correct name and version\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n\n await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n expect(MockedClient).toHaveBeenCalledWith({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n });\n\n it(\"should set onclose handler\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const _client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n expect(mockClientInstance.onclose).toBeDefined();\n expect(typeof mockClientInstance.onclose).toBe(\"function\");\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"mcp-client.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/mcp-client.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { MCPClient, MCPTransport } from \"../mcp-client\";\n\n// Mock the MCP SDK modules\njest.mock(\"@modelcontextprotocol/sdk/client/index.js\", () => ({\n Client: jest.fn().mockImplementation(() => ({\n connect: jest.fn(),\n close: jest.fn(),\n listTools: jest.fn(),\n callTool: jest.fn(),\n setRequestHandler: jest.fn(),\n removeRequestHandler: jest.fn(),\n onclose: null,\n })),\n}));\n\njest.mock(\"@modelcontextprotocol/sdk/client/sse.js\", () => ({\n SSEClientTransport: jest.fn().mockImplementation(() => ({\n // SSE transport doesn't have sessionId\n })),\n}));\n\njest.mock(\"@modelcontextprotocol/sdk/client/streamableHttp.js\", () => ({\n StreamableHTTPClientTransport: jest\n .fn()\n .mockImplementation((url, options) => ({\n sessionId: options?.sessionId,\n })),\n}));\n\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\n// Type the mocked modules\nconst MockedClient = Client as jest.MockedClass<typeof Client>;\nconst MockedSSEClientTransport = SSEClientTransport as jest.MockedClass<\n typeof SSEClientTransport\n>;\nconst MockedStreamableHTTPClientTransport =\n StreamableHTTPClientTransport as jest.MockedClass<\n typeof StreamableHTTPClientTransport\n >;\n\ndescribe(\"MCPClient\", () => {\n let mockClientInstance: any;\n let mockTransportInstance: any;\n\n beforeEach(() => {\n jest.clearAllMocks();\n\n // Create mock instances\n mockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n setRequestHandler: jest.fn(),\n removeRequestHandler: jest.fn(),\n onclose: null,\n };\n\n mockTransportInstance = {\n sessionId: \"test-session-id\",\n };\n\n // Setup mocks\n MockedClient.mockImplementation(() => mockClientInstance);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => mockTransportInstance,\n );\n MockedSSEClientTransport.mockImplementation(\n () => ({}) as SSEClientTransport,\n );\n });\n\n describe(\"create\", () => {\n it(\"should create and connect an MCPClient with HTTP transport by default\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const headers = { Authorization: \"Bearer token\" };\n\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n headers,\n undefined,\n undefined,\n );\n\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers } },\n );\n expect(MockedClient).toHaveBeenCalledWith(\n {\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n },\n { capabilities: {} },\n );\n expect(mockClientInstance.connect).toHaveBeenCalledWith(\n mockTransportInstance,\n );\n expect(client).toBeInstanceOf(MCPClient);\n });\n\n it(\"should create and connect an MCPClient with SSE transport\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.SSE,\n undefined,\n undefined,\n undefined,\n );\n\n expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {\n requestInit: { headers: {} },\n });\n expect(mockClientInstance.connect).toHaveBeenCalledWith({});\n expect(client).toBeInstanceOf(MCPClient);\n });\n\n it(\"should create client with default headers when none provided\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n\n await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers: {} } },\n );\n });\n });\n\n describe(\"reconnect\", () => {\n it(\"should create new transport and client instances and call connect when reconnect() is called (default behavior)\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls to focus on reconnect behavior\n jest.clearAllMocks();\n\n // Create new mock instances to verify new instances are created\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"new-session-id\",\n };\n\n // Mock the constructors to return new instances\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n await client.reconnect(); // Uses default parameters\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with preserved session ID (default behavior)\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: \"test-session-id\", requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith(\n {\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n },\n { capabilities: {} },\n );\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n });\n\n it(\"should reconnect without session ID for SSE transport\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.SSE,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls\n jest.clearAllMocks();\n\n await client.reconnect();\n\n expect(mockClientInstance.close).toHaveBeenCalled();\n expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {\n requestInit: { headers: {} },\n });\n expect(mockClientInstance.connect).toHaveBeenCalledWith({});\n });\n\n it(\"should handle close errors when reportErrorOnClose is true\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n // Make close throw an error\n mockClientInstance.close.mockRejectedValue(new Error(\"Close failed\"));\n\n await client.reconnect(false, true);\n\n expect(consoleSpy).toHaveBeenCalledWith(\n \"Error closing Tambo MCP Client:\",\n expect.any(Error),\n );\n consoleSpy.mockRestore();\n });\n\n it(\"should not log close errors when reportErrorOnClose is false\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n // Make close throw an error\n mockClientInstance.close.mockRejectedValue(new Error(\"Close failed\"));\n\n await client.reconnect(false, false);\n\n expect(consoleSpy).not.toHaveBeenCalled();\n consoleSpy.mockRestore();\n });\n\n it(\"should create new session when newSession is true\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls to focus on reconnect behavior\n jest.clearAllMocks();\n\n // Create new mock instances to verify new instances are created\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"new-session-id\",\n };\n\n // Mock the constructors to return new instances\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n await client.reconnect(true, true); // newSession = true, reportErrorOnClose = true\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with undefined session ID (new session)\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith(\n {\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n },\n { capabilities: {} },\n );\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n });\n\n it(\"should reuse existing session when newSession is false (default)\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Clear previous calls to focus on reconnect behavior\n jest.clearAllMocks();\n\n // Create new mock instances to verify new instances are created\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"reused-session-id\",\n };\n\n // Mock the constructors to return new instances\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n await client.reconnect(false, true); // newSession = false, reportErrorOnClose = true\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with preserved session ID\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: \"test-session-id\", requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith(\n {\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n },\n { capabilities: {} },\n );\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n });\n });\n\n describe(\"onclose\", () => {\n it(\"should reconnect MCPClient when client is closed by external means (no backoff on manual preemption)\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n jest.useFakeTimers();\n const consoleSpy = jest.spyOn(console, \"warn\").mockImplementation();\n\n // Create new mock instances to verify reconnection creates new instances\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n\n const newMockTransportInstance = {\n sessionId: \"reconnected-session-id\",\n };\n\n // Mock the constructors to return new instances for reconnection\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n MockedStreamableHTTPClientTransport.mockImplementation(\n () => newMockTransportInstance as any,\n );\n\n // Reset counts after initial creation\n jest.clearAllMocks();\n\n // Trigger automatic onclose (schedules a delayed reconnect)\n (client as any).onclose();\n // Manual reconnect should preempt the scheduled automatic attempt\n const reconnectPromise = client.reconnect();\n // No timers should be pending after manual preemption\n await reconnectPromise;\n\n // Verify warning message is logged\n expect(consoleSpy).toHaveBeenCalled();\n\n // Verify old client was closed\n expect(mockClientInstance.close).toHaveBeenCalled();\n\n // Verify new transport was created with preserved session ID\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: \"test-session-id\", requestInit: { headers: {} } },\n );\n\n // Verify new client was created\n expect(MockedClient).toHaveBeenCalledWith(\n {\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n },\n { capabilities: {} },\n );\n\n // Verify new client's connect was called with new transport\n expect(newMockClientInstance.connect).toHaveBeenCalledWith(\n newMockTransportInstance,\n );\n\n // Ensure only a single reconnect attempt occurred\n expect(MockedClient).toHaveBeenCalledTimes(1);\n expect(newMockClientInstance.connect).toHaveBeenCalledTimes(1);\n\n consoleSpy.mockRestore();\n jest.useRealTimers();\n });\n });\n\n describe(\"reconnect re-entrancy and single-flight\", () => {\n it(\"prevents re-entrant onclose during deliberate close and coalesces concurrent calls\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Simulate an implementation where closing the client would call its own onclose handler\n const closeImpl = jest.fn(async () => {\n if (typeof mockClientInstance.onclose === \"function\") {\n // would cause recursion if not detached\n (mockClientInstance.onclose as unknown as () => void)();\n }\n return;\n });\n mockClientInstance.close = closeImpl;\n\n // Prepare new instances for the reconnect\n const newMockClientInstance = {\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n };\n MockedClient.mockImplementation(() => newMockClientInstance as any);\n\n // Reset counts after initial creation\n jest.clearAllMocks();\n\n // Trigger auto onclose and manual reconnect nearly simultaneously\n (client as any).onclose();\n await client.reconnect();\n\n // Should have detached onclose before calling close, avoiding recursion\n expect(closeImpl).toHaveBeenCalledTimes(1);\n expect(mockClientInstance.onclose).toBeUndefined();\n\n // Single-flight: only one new client/connect\n expect(MockedClient).toHaveBeenCalledTimes(1);\n expect(newMockClientInstance.connect).toHaveBeenCalledTimes(1);\n });\n });\n\n describe(\"backoff + jitter (automatic reconnect)\", () => {\n it(\"applies jitter and resets to initial delay after a successful reconnect (manual preempt)\", async () => {\n jest.useFakeTimers();\n const base = MCPClient.BACKOFF_INITIAL_MS;\n const ratio = MCPClient.BACKOFF_JITTER_RATIO;\n const min = Math.round(base * (1 - ratio));\n const max = Math.round(base * (1 + ratio));\n const setTimeoutSpy = jest.spyOn(global, \"setTimeout\");\n const randSpy = jest.spyOn(Math, \"random\").mockReturnValue(0.0); // extreme low jitter\n\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n // Prepare one attempt that will succeed to avoid rescheduling\n MockedClient.mockImplementation(\n () =>\n ({\n connect: jest.fn().mockResolvedValue(undefined),\n close: jest.fn().mockResolvedValue(undefined),\n listTools: jest.fn(),\n callTool: jest.fn(),\n onclose: null,\n }) as any,\n );\n\n // Trigger once to capture the delay\n (client as any).onclose();\n expect(setTimeoutSpy).toHaveBeenCalled();\n const numericDelays = setTimeoutSpy.mock.calls\n .map((c) => c[1])\n .filter((v) => typeof v === \"number\") as number[];\n expect(numericDelays.length).toBeGreaterThan(0);\n const d = numericDelays[0]!;\n expect(d).toBeGreaterThanOrEqual(min);\n expect(d).toBeLessThanOrEqual(max);\n\n // Manual reconnect succeeds and should reset backoff attempts\n await client.reconnect();\n\n // Trigger onclose again and ensure we start from initial range again\n (client as any).onclose();\n const numericDelays2 = setTimeoutSpy.mock.calls\n .map((c) => c[1])\n .filter((v) => typeof v === \"number\") as number[];\n expect(numericDelays2.length).toBeGreaterThanOrEqual(2);\n const dAgain = numericDelays2[1]!;\n expect(dAgain).toBeGreaterThanOrEqual(min);\n expect(dAgain).toBeLessThanOrEqual(max);\n\n jest.useRealTimers();\n setTimeoutSpy.mockRestore();\n randSpy.mockRestore();\n });\n });\n\n describe(\"listTools\", () => {\n it(\"should list all tools with pagination\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockTools = [\n {\n name: \"tool1\",\n description: \"First tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n {\n name: \"tool2\",\n description: \"Second tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg2: { type: \"number\" } },\n },\n },\n ];\n\n const mockResponse1 = {\n tools: [mockTools[0]],\n nextCursor: \"cursor1\",\n };\n\n const mockResponse2 = {\n tools: [mockTools[1]],\n nextCursor: undefined,\n };\n\n mockClientInstance.listTools\n .mockResolvedValueOnce(mockResponse1)\n .mockResolvedValueOnce(mockResponse2);\n\n const result = await client.listTools();\n\n expect(mockClientInstance.listTools).toHaveBeenCalledTimes(2);\n expect(mockClientInstance.listTools).toHaveBeenNthCalledWith(\n 1,\n { cursor: undefined },\n {},\n );\n expect(mockClientInstance.listTools).toHaveBeenNthCalledWith(\n 2,\n { cursor: \"cursor1\" },\n {},\n );\n expect(result).toEqual([\n {\n name: \"tool1\",\n description: \"First tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n {\n name: \"tool2\",\n description: \"Second tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg2: { type: \"number\" } },\n },\n },\n ]);\n });\n\n it(\"should handle single page of tools\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockTools = [\n {\n name: \"tool1\",\n description: \"Only tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n ];\n\n const mockResponse = {\n tools: mockTools,\n nextCursor: undefined,\n };\n\n mockClientInstance.listTools.mockResolvedValue(mockResponse);\n\n const result = await client.listTools();\n\n expect(mockClientInstance.listTools).toHaveBeenCalledTimes(1);\n expect(result).toEqual([\n {\n name: \"tool1\",\n description: \"Only tool\",\n inputSchema: {\n type: \"object\",\n properties: { arg1: { type: \"string\" } },\n },\n },\n ]);\n });\n\n it(\"should throw error for invalid input schema\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockTools = [\n {\n name: \"invalid-tool\",\n description: \"Tool with invalid schema\",\n inputSchema: { type: \"string\" }, // Invalid - should be object\n },\n ];\n\n const mockResponse = {\n tools: mockTools,\n nextCursor: undefined,\n };\n\n mockClientInstance.listTools.mockResolvedValue(mockResponse);\n\n await expect(client.listTools()).rejects.toThrow(\n \"Input schema for tool invalid-tool is not an object\",\n );\n });\n });\n\n describe(\"callTool\", () => {\n it(\"should call a tool with arguments\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n const mockResult = { success: true, data: \"test result\" };\n mockClientInstance.callTool.mockResolvedValue(mockResult);\n\n const result = await client.callTool(\"testTool\", {\n arg1: \"value1\",\n arg2: 42,\n });\n\n expect(mockClientInstance.callTool).toHaveBeenCalledWith({\n name: \"testTool\",\n arguments: { arg1: \"value1\", arg2: 42 },\n });\n expect(result).toBe(mockResult);\n });\n\n it(\"should handle tool call errors\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n const error = new Error(\"Tool call failed\");\n mockClientInstance.callTool.mockRejectedValue(error);\n\n await expect(client.callTool(\"testTool\", {})).rejects.toThrow(\n \"Tool call failed\",\n );\n });\n });\n\n describe(\"transport initialization\", () => {\n it(\"should initialize HTTP transport with session ID\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const headers = { Authorization: \"Bearer token\" };\n\n await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n headers,\n undefined,\n undefined,\n );\n\n expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(\n new URL(endpoint),\n { sessionId: undefined, requestInit: { headers } },\n );\n });\n\n it(\"should initialize SSE transport without session ID\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const headers = { Authorization: \"Bearer token\" };\n\n await MCPClient.create(\n endpoint,\n MCPTransport.SSE,\n headers,\n undefined,\n undefined,\n );\n\n expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {\n requestInit: { headers },\n });\n });\n });\n\n describe(\"client initialization\", () => {\n it(\"should initialize client with correct name and version\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n\n await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n expect(MockedClient).toHaveBeenCalledWith(\n {\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n },\n { capabilities: {} },\n );\n });\n\n it(\"should set onclose handler\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const _client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n );\n\n expect(mockClientInstance.onclose).toBeDefined();\n expect(typeof mockClientInstance.onclose).toBe(\"function\");\n });\n });\n\n describe(\"handlers (elicitation/sampling)\", () => {\n it(\"sets handlers on create when provided\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const elicitation = jest.fn(async () => ({}) as any);\n const sampling = jest.fn(async () => ({}) as any);\n\n await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n { elicitation, sampling },\n );\n\n expect(MockedClient).toHaveBeenLastCalledWith(\n {\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n },\n {\n capabilities: {\n elicitation: {},\n sampling: {},\n },\n },\n );\n\n // Request handlers should be set for both\n expect(mockClientInstance.setRequestHandler).toHaveBeenCalled();\n expect(\n (mockClientInstance.setRequestHandler as jest.Mock).mock.calls.length,\n ).toBeGreaterThanOrEqual(2);\n });\n\n it(\"removes elicitation handler when set to undefined\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n {\n elicitation: async () => ({}) as any,\n },\n );\n\n const removeSpy = mockClientInstance.removeRequestHandler as jest.Mock;\n\n // then remove\n removeSpy.mockClear();\n await client.updateElicitationHandler(undefined);\n expect(removeSpy).toHaveBeenCalledWith(expect.any(String));\n });\n\n it(\"removes sampling handler when set to undefined\", async () => {\n const endpoint = \"https://api.example.com/mcp\";\n const client = await MCPClient.create(\n endpoint,\n MCPTransport.HTTP,\n undefined,\n undefined,\n undefined,\n {\n sampling: async () => ({}) as any,\n },\n );\n\n const removeSpy = mockClientInstance.removeRequestHandler as jest.Mock;\n\n // then remove\n removeSpy.mockClear();\n await client.updateSamplingHandler(undefined);\n expect(removeSpy).toHaveBeenCalledWith(expect.any(String));\n });\n });\n});\n"]}
|
package/dist/mcp/mcp-client.d.ts
CHANGED
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import { type OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
2
2
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
+
import { CreateMessageRequest, CreateMessageResult, ElicitRequest, ElicitResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
4
|
import { JSONSchema7 } from "json-schema";
|
|
4
5
|
export declare enum MCPTransport {
|
|
5
6
|
SSE = "sse",
|
|
6
7
|
HTTP = "http"
|
|
7
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Handlers for MCP requests - these are only used if the server supports the corresponding capabilities
|
|
11
|
+
* @param elicitation - Handler for elicitation requests
|
|
12
|
+
* @param sampling - Handler for sampling requests
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const mcp = await MCPClient.create(
|
|
16
|
+
* 'https://api.example.com/mcp',
|
|
17
|
+
* MCPTransport.HTTP,
|
|
18
|
+
* {},
|
|
19
|
+
* undefined,
|
|
20
|
+
* undefined,
|
|
21
|
+
* {
|
|
22
|
+
* elicitation: (e: ElicitRequest) => Promise.resolve({...}),
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
interface MCPHandlers {
|
|
28
|
+
elicitation?: (e: ElicitRequest) => Promise<ElicitResult>;
|
|
29
|
+
sampling?: (e: CreateMessageRequest) => Promise<CreateMessageResult>;
|
|
30
|
+
}
|
|
8
31
|
/**
|
|
9
32
|
* A client for interacting with MCP (Model Context Protocol) servers.
|
|
10
33
|
* Provides a simple interface for listing and calling tools exposed by the server.
|
|
@@ -23,6 +46,7 @@ export declare class MCPClient {
|
|
|
23
46
|
private endpoint;
|
|
24
47
|
private headers;
|
|
25
48
|
private authProvider?;
|
|
49
|
+
private handlers;
|
|
26
50
|
/**
|
|
27
51
|
* Tracks an in-flight reconnect so concurrent triggers coalesce
|
|
28
52
|
* (single-flight). When set, additional calls to `reconnect()` or
|
|
@@ -58,6 +82,7 @@ export declare class MCPClient {
|
|
|
58
82
|
static readonly BACKOFF_MULTIPLIER = 2;
|
|
59
83
|
static readonly BACKOFF_MAX_MS = 30000;
|
|
60
84
|
static readonly BACKOFF_JITTER_RATIO = 0.2;
|
|
85
|
+
elicitation: EventTarget;
|
|
61
86
|
/**
|
|
62
87
|
* Private constructor to enforce using the static create method.
|
|
63
88
|
* @param endpoint - The URL of the MCP server to connect to
|
|
@@ -78,7 +103,7 @@ export declare class MCPClient {
|
|
|
78
103
|
* @returns A connected MCPClient instance ready for use
|
|
79
104
|
* @throws {Error} Will throw an error if connection fails
|
|
80
105
|
*/
|
|
81
|
-
static create(endpoint: string, transportType: MCPTransport | undefined, headers: Record<string, string> | undefined, authProvider: OAuthClientProvider | undefined, sessionId: string | undefined): Promise<MCPClient>;
|
|
106
|
+
static create(endpoint: string, transportType: MCPTransport | undefined, headers: Record<string, string> | undefined, authProvider: OAuthClientProvider | undefined, sessionId: string | undefined, handlers?: MCPHandlers): Promise<MCPClient>;
|
|
82
107
|
/**
|
|
83
108
|
* Reconnects to the MCP server, optionally retaining the same session ID.
|
|
84
109
|
*
|
|
@@ -116,6 +141,10 @@ export declare class MCPClient {
|
|
|
116
141
|
*/
|
|
117
142
|
private scheduleAutoReconnect;
|
|
118
143
|
private initializeTransport;
|
|
144
|
+
/**
|
|
145
|
+
* Initializes the MCP client with the appropriate capabilities and handlers
|
|
146
|
+
* @returns The initialized MCP client
|
|
147
|
+
*/
|
|
119
148
|
private initializeClient;
|
|
120
149
|
/**
|
|
121
150
|
* Retrieves a complete list of all available tools from the MCP server.
|
|
@@ -159,7 +188,7 @@ export declare class MCPClient {
|
|
|
159
188
|
[x: string]: unknown;
|
|
160
189
|
src: string;
|
|
161
190
|
mimeType?: string | undefined;
|
|
162
|
-
sizes?: string | undefined;
|
|
191
|
+
sizes?: string[] | undefined;
|
|
163
192
|
}[] | undefined;
|
|
164
193
|
} | undefined;
|
|
165
194
|
getInstructions(): string | undefined;
|
|
@@ -171,6 +200,8 @@ export declare class MCPClient {
|
|
|
171
200
|
* @throws {Error} Will throw an error if the tool call fails or if arguments are invalid
|
|
172
201
|
*/
|
|
173
202
|
callTool(name: string, args: Record<string, unknown>): Promise<MCPToolCallResult>;
|
|
203
|
+
updateElicitationHandler(handler: ((e: ElicitRequest) => Promise<ElicitResult>) | undefined): void;
|
|
204
|
+
updateSamplingHandler(handler: ((e: CreateMessageRequest) => Promise<CreateMessageResult>) | undefined): void;
|
|
174
205
|
}
|
|
175
206
|
/**
|
|
176
207
|
* The result of a tool call.
|
|
@@ -182,4 +213,5 @@ export interface MCPToolSpec {
|
|
|
182
213
|
description?: string;
|
|
183
214
|
inputSchema?: JSONSchema7;
|
|
184
215
|
}
|
|
216
|
+
export {};
|
|
185
217
|
//# sourceMappingURL=mcp-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,oBAAY,YAAY;IACtB,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;
|
|
1
|
+
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-client.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/mcp-client.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.MCPClient = exports.MCPTransport = void 0;
|
|
|
4
4
|
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
5
5
|
const sse_js_1 = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
6
6
|
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
7
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
8
|
var MCPTransport;
|
|
8
9
|
(function (MCPTransport) {
|
|
9
10
|
MCPTransport["SSE"] = "sse";
|
|
@@ -27,6 +28,7 @@ class MCPClient {
|
|
|
27
28
|
endpoint;
|
|
28
29
|
headers;
|
|
29
30
|
authProvider;
|
|
31
|
+
handlers;
|
|
30
32
|
/**
|
|
31
33
|
* Tracks an in-flight reconnect so concurrent triggers coalesce
|
|
32
34
|
* (single-flight). When set, additional calls to `reconnect()` or
|
|
@@ -62,17 +64,19 @@ class MCPClient {
|
|
|
62
64
|
static BACKOFF_MULTIPLIER = 2;
|
|
63
65
|
static BACKOFF_MAX_MS = 30_000;
|
|
64
66
|
static BACKOFF_JITTER_RATIO = 0.2;
|
|
67
|
+
elicitation = new EventTarget();
|
|
65
68
|
/**
|
|
66
69
|
* Private constructor to enforce using the static create method.
|
|
67
70
|
* @param endpoint - The URL of the MCP server to connect to
|
|
68
71
|
* @param transportType - The transport to use for the MCP client
|
|
69
72
|
* @param headers - Optional custom headers to include in requests
|
|
70
73
|
*/
|
|
71
|
-
constructor(endpoint, transportType, headers, authProvider, sessionId) {
|
|
74
|
+
constructor(endpoint, transportType, headers, authProvider, sessionId, handlers = {}) {
|
|
72
75
|
this.endpoint = endpoint;
|
|
73
76
|
this.headers = headers ?? {};
|
|
74
77
|
this.authProvider = authProvider;
|
|
75
78
|
this.transportType = transportType;
|
|
79
|
+
this.handlers = handlers;
|
|
76
80
|
this.transport = this.initializeTransport(sessionId);
|
|
77
81
|
this.client = this.initializeClient();
|
|
78
82
|
}
|
|
@@ -89,8 +93,8 @@ class MCPClient {
|
|
|
89
93
|
* @returns A connected MCPClient instance ready for use
|
|
90
94
|
* @throws {Error} Will throw an error if connection fails
|
|
91
95
|
*/
|
|
92
|
-
static async create(endpoint, transportType = MCPTransport.HTTP, headers, authProvider, sessionId) {
|
|
93
|
-
const mcpClient = new MCPClient(endpoint, transportType, headers, authProvider, sessionId);
|
|
96
|
+
static async create(endpoint, transportType = MCPTransport.HTTP, headers, authProvider, sessionId, handlers = {}) {
|
|
97
|
+
const mcpClient = new MCPClient(endpoint, transportType, headers, authProvider, sessionId, handlers);
|
|
94
98
|
await mcpClient.client.connect(mcpClient.transport);
|
|
95
99
|
if ("sessionId" in mcpClient.transport) {
|
|
96
100
|
mcpClient.sessionId = mcpClient.transport.sessionId;
|
|
@@ -233,12 +237,31 @@ class MCPClient {
|
|
|
233
237
|
});
|
|
234
238
|
}
|
|
235
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Initializes the MCP client with the appropriate capabilities and handlers
|
|
242
|
+
* @returns The initialized MCP client
|
|
243
|
+
*/
|
|
236
244
|
initializeClient() {
|
|
245
|
+
const elicitationCapability = this.handlers.elicitation
|
|
246
|
+
? { elicitation: {} }
|
|
247
|
+
: {};
|
|
248
|
+
const samplingCapability = this.handlers.sampling ? { sampling: {} } : {};
|
|
237
249
|
const client = new index_js_1.Client({
|
|
238
250
|
name: "tambo-mcp-client",
|
|
239
251
|
version: "1.0.0",
|
|
252
|
+
}, {
|
|
253
|
+
capabilities: {
|
|
254
|
+
...elicitationCapability,
|
|
255
|
+
...samplingCapability,
|
|
256
|
+
},
|
|
240
257
|
});
|
|
241
258
|
client.onclose = this.onclose.bind(this);
|
|
259
|
+
if (this.handlers.elicitation) {
|
|
260
|
+
client.setRequestHandler(types_js_1.ElicitRequestSchema, this.handlers.elicitation);
|
|
261
|
+
}
|
|
262
|
+
if (this.handlers.sampling) {
|
|
263
|
+
client.setRequestHandler(types_js_1.CreateMessageRequestSchema, this.handlers.sampling);
|
|
264
|
+
}
|
|
242
265
|
return client;
|
|
243
266
|
}
|
|
244
267
|
/**
|
|
@@ -254,7 +277,9 @@ class MCPClient {
|
|
|
254
277
|
while (hasMore) {
|
|
255
278
|
const response = await this.client.listTools({ cursor }, {});
|
|
256
279
|
allTools.push(...response.tools.map((tool) => {
|
|
257
|
-
|
|
280
|
+
// make sure the right type is used
|
|
281
|
+
const inputSchemaType = tool.inputSchema.type;
|
|
282
|
+
if (inputSchemaType !== "object") {
|
|
258
283
|
throw new Error(`Input schema for tool ${tool.name} is not an object`);
|
|
259
284
|
}
|
|
260
285
|
return {
|
|
@@ -295,6 +320,40 @@ class MCPClient {
|
|
|
295
320
|
});
|
|
296
321
|
return result;
|
|
297
322
|
}
|
|
323
|
+
updateElicitationHandler(handler) {
|
|
324
|
+
// Because we advertise the elicitation capability on initial connection, we can only update
|
|
325
|
+
// an existing handler, not add it if we haven't set it yet.
|
|
326
|
+
if (handler && !this.handlers.elicitation) {
|
|
327
|
+
throw new Error("Elicitation handler must be set on create");
|
|
328
|
+
}
|
|
329
|
+
this.handlers = {
|
|
330
|
+
...this.handlers,
|
|
331
|
+
elicitation: handler,
|
|
332
|
+
};
|
|
333
|
+
if (!handler) {
|
|
334
|
+
const method = types_js_1.ElicitRequestSchema.shape.method.value;
|
|
335
|
+
this.client.removeRequestHandler(method);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
this.client.setRequestHandler(types_js_1.ElicitRequestSchema, handler);
|
|
339
|
+
}
|
|
340
|
+
updateSamplingHandler(handler) {
|
|
341
|
+
// Because we advertise the sampling capability on initial connection, we can only update
|
|
342
|
+
// an existing handler, not add it if we haven't set it yet.
|
|
343
|
+
if (handler && !this.handlers.sampling) {
|
|
344
|
+
throw new Error("Sampling handler must be set on create");
|
|
345
|
+
}
|
|
346
|
+
this.handlers = {
|
|
347
|
+
...this.handlers,
|
|
348
|
+
sampling: handler,
|
|
349
|
+
};
|
|
350
|
+
if (!handler) {
|
|
351
|
+
const method = types_js_1.CreateMessageRequestSchema.shape.method.value;
|
|
352
|
+
this.client.removeRequestHandler(method);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
this.client.setRequestHandler(types_js_1.CreateMessageRequestSchema, handler);
|
|
356
|
+
}
|
|
298
357
|
}
|
|
299
358
|
exports.MCPClient = MCPClient;
|
|
300
359
|
//# sourceMappingURL=mcp-client.js.map
|