@tambo-ai/react 0.58.0 → 0.59.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/hooks/use-tambo-stream-status.js +1 -1
- package/dist/hooks/use-tambo-stream-status.js.map +1 -1
- package/dist/mcp/__tests__/mcp-client.test.js +0 -266
- package/dist/mcp/__tests__/mcp-client.test.js.map +1 -1
- package/dist/mcp/__tests__/tambo-mcp-provider.test.js +218 -12
- package/dist/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -1
- package/dist/mcp/__tests__/use-mcp-servers.test.js +34 -9
- package/dist/mcp/__tests__/use-mcp-servers.test.js.map +1 -1
- package/dist/mcp/index.d.ts +3 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +4 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-client.d.ts +12 -79
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +22 -159
- package/dist/mcp/mcp-client.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts +93 -0
- package/dist/mcp/mcp-hooks.d.ts.map +1 -0
- package/dist/mcp/mcp-hooks.js +56 -0
- package/dist/mcp/mcp-hooks.js.map +1 -0
- package/dist/mcp/tambo-mcp-provider.d.ts +30 -2
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +127 -17
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/component-metadata.d.ts +1 -1
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.js +3 -1
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider.test.js +395 -8
- package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/dist/providers/tambo-mcp-token-provider.d.ts +34 -0
- package/dist/providers/tambo-mcp-token-provider.d.ts.map +1 -0
- package/dist/providers/tambo-mcp-token-provider.js +69 -0
- package/dist/providers/tambo-mcp-token-provider.js.map +1 -0
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +7 -5
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +20 -8
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/testing/tools.d.ts +1 -1
- package/esm/hooks/use-tambo-stream-status.js +1 -1
- package/esm/hooks/use-tambo-stream-status.js.map +1 -1
- package/esm/mcp/__tests__/mcp-client.test.js +0 -266
- package/esm/mcp/__tests__/mcp-client.test.js.map +1 -1
- package/esm/mcp/__tests__/tambo-mcp-provider.test.js +218 -12
- package/esm/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -1
- package/esm/mcp/__tests__/use-mcp-servers.test.js +34 -9
- package/esm/mcp/__tests__/use-mcp-servers.test.js.map +1 -1
- package/esm/mcp/index.d.ts +3 -1
- package/esm/mcp/index.d.ts.map +1 -1
- package/esm/mcp/index.js +1 -0
- package/esm/mcp/index.js.map +1 -1
- package/esm/mcp/mcp-client.d.ts +12 -79
- package/esm/mcp/mcp-client.d.ts.map +1 -1
- package/esm/mcp/mcp-client.js +22 -159
- package/esm/mcp/mcp-client.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts +93 -0
- package/esm/mcp/mcp-hooks.d.ts.map +1 -0
- package/esm/mcp/mcp-hooks.js +52 -0
- package/esm/mcp/mcp-hooks.js.map +1 -0
- package/esm/mcp/tambo-mcp-provider.d.ts +30 -2
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +128 -18
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/component-metadata.d.ts +1 -1
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.js +3 -1
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider.test.js +395 -8
- package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/esm/providers/tambo-mcp-token-provider.d.ts +34 -0
- package/esm/providers/tambo-mcp-token-provider.d.ts.map +1 -0
- package/esm/providers/tambo-mcp-token-provider.js +31 -0
- package/esm/providers/tambo-mcp-token-provider.js.map +1 -0
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +7 -5
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +20 -8
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/testing/tools.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { render, waitFor } from "@testing-library/react";
|
|
2
2
|
import React, { useEffect } from "react";
|
|
3
|
+
import { useTamboClient } from "../../providers/tambo-client-provider";
|
|
4
|
+
import { TamboMcpTokenProvider } from "../../providers/tambo-mcp-token-provider";
|
|
3
5
|
import { useTamboRegistry } from "../../providers/tambo-registry-provider";
|
|
4
6
|
import { MCPClient, MCPTransport } from "../mcp-client";
|
|
5
7
|
import { extractErrorMessage, TamboMcpProvider, useTamboMcpServers, } from "../tambo-mcp-provider";
|
|
@@ -15,6 +17,10 @@ jest.mock("../mcp-client", () => ({
|
|
|
15
17
|
jest.mock("../../providers/tambo-registry-provider", () => ({
|
|
16
18
|
useTamboRegistry: jest.fn(),
|
|
17
19
|
}));
|
|
20
|
+
// Mock the client provider to avoid dependency issues
|
|
21
|
+
jest.mock("../../providers/tambo-client-provider", () => ({
|
|
22
|
+
useTamboClient: jest.fn(),
|
|
23
|
+
}));
|
|
18
24
|
describe("extractErrorMessage", () => {
|
|
19
25
|
describe("Array content handling", () => {
|
|
20
26
|
it("should extract text from array content with multiple text items", () => {
|
|
@@ -120,6 +126,10 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
120
126
|
useTamboRegistry.mockReturnValue({
|
|
121
127
|
registerTool: jest.fn(),
|
|
122
128
|
});
|
|
129
|
+
// Mock client with baseURL
|
|
130
|
+
useTamboClient.mockReturnValue({
|
|
131
|
+
baseURL: "https://api.tambo.co",
|
|
132
|
+
});
|
|
123
133
|
// Ensure MCPClient.create exists and returns a fake client with listTools
|
|
124
134
|
MCPClient.create = jest
|
|
125
135
|
.fn()
|
|
@@ -134,15 +144,17 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
134
144
|
};
|
|
135
145
|
it("adds a new server when the list grows", async () => {
|
|
136
146
|
let latest = [];
|
|
137
|
-
const { rerender, getByTestId } = render(React.createElement(
|
|
138
|
-
React.createElement(
|
|
147
|
+
const { rerender, getByTestId } = render(React.createElement(TamboMcpTokenProvider, null,
|
|
148
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example"] },
|
|
149
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
139
150
|
// Wait for initial connection
|
|
140
151
|
await waitFor(() => {
|
|
141
152
|
expect(latest.length).toBe(1);
|
|
142
153
|
});
|
|
143
154
|
// Add new server
|
|
144
|
-
rerender(React.createElement(
|
|
145
|
-
React.createElement(
|
|
155
|
+
rerender(React.createElement(TamboMcpTokenProvider, null,
|
|
156
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example", "https://b.example"] },
|
|
157
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
146
158
|
await waitFor(() => {
|
|
147
159
|
expect(latest.length).toBe(2);
|
|
148
160
|
const urls = getByTestId("urls").textContent || "";
|
|
@@ -152,14 +164,16 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
152
164
|
});
|
|
153
165
|
it("removes a server when the list shrinks", async () => {
|
|
154
166
|
let latest = [];
|
|
155
|
-
const { rerender, getByTestId } = render(React.createElement(
|
|
156
|
-
React.createElement(
|
|
167
|
+
const { rerender, getByTestId } = render(React.createElement(TamboMcpTokenProvider, null,
|
|
168
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example", "https://b.example"] },
|
|
169
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
157
170
|
await waitFor(() => {
|
|
158
171
|
expect(latest.length).toBe(2);
|
|
159
172
|
});
|
|
160
173
|
// Remove one server
|
|
161
|
-
rerender(React.createElement(
|
|
162
|
-
React.createElement(
|
|
174
|
+
rerender(React.createElement(TamboMcpTokenProvider, null,
|
|
175
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example"] },
|
|
176
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
163
177
|
await waitFor(() => {
|
|
164
178
|
expect(latest.length).toBe(1);
|
|
165
179
|
const urls = getByTestId("urls").textContent || "";
|
|
@@ -173,8 +187,9 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
173
187
|
{ url: "https://a.example", transport: MCPTransport.SSE },
|
|
174
188
|
{ url: "https://b.example", transport: MCPTransport.SSE },
|
|
175
189
|
];
|
|
176
|
-
const { rerender } = render(React.createElement(
|
|
177
|
-
React.createElement(
|
|
190
|
+
const { rerender } = render(React.createElement(TamboMcpTokenProvider, null,
|
|
191
|
+
React.createElement(TamboMcpProvider, { mcpServers: initial },
|
|
192
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
178
193
|
await waitFor(() => {
|
|
179
194
|
expect(latest.length).toBe(2);
|
|
180
195
|
});
|
|
@@ -183,8 +198,9 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
183
198
|
{ url: "https://a.example", transport: MCPTransport.SSE },
|
|
184
199
|
{ url: "https://b.example", transport: MCPTransport.SSE },
|
|
185
200
|
];
|
|
186
|
-
rerender(React.createElement(
|
|
187
|
-
React.createElement(
|
|
201
|
+
rerender(React.createElement(TamboMcpTokenProvider, null,
|
|
202
|
+
React.createElement(TamboMcpProvider, { mcpServers: same },
|
|
203
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
188
204
|
await waitFor(() => {
|
|
189
205
|
expect(latest.length).toBe(2);
|
|
190
206
|
const urls = latest.map((s) => s.url).sort();
|
|
@@ -192,4 +208,194 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
192
208
|
});
|
|
193
209
|
});
|
|
194
210
|
});
|
|
211
|
+
describe("TamboMcpProvider handler support", () => {
|
|
212
|
+
let mockClient;
|
|
213
|
+
let createSpy;
|
|
214
|
+
beforeEach(() => {
|
|
215
|
+
// Mock registry so tool registration is a no-op
|
|
216
|
+
useTamboRegistry.mockReturnValue({
|
|
217
|
+
registerTool: jest.fn(),
|
|
218
|
+
});
|
|
219
|
+
// Mock client with baseURL
|
|
220
|
+
useTamboClient.mockReturnValue({
|
|
221
|
+
baseURL: "https://api.tambo.co",
|
|
222
|
+
});
|
|
223
|
+
// Create a mock client with update methods
|
|
224
|
+
mockClient = {
|
|
225
|
+
listTools: jest.fn().mockResolvedValue([]),
|
|
226
|
+
updateElicitationHandler: jest.fn(),
|
|
227
|
+
updateSamplingHandler: jest.fn(),
|
|
228
|
+
};
|
|
229
|
+
// Mock MCPClient.create to return our mock client
|
|
230
|
+
createSpy = jest.fn().mockResolvedValue(mockClient);
|
|
231
|
+
MCPClient.create = createSpy;
|
|
232
|
+
});
|
|
233
|
+
const Capture = ({ onUpdate, }) => {
|
|
234
|
+
const servers = useTamboMcpServers();
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
onUpdate(servers);
|
|
237
|
+
}, [servers, onUpdate]);
|
|
238
|
+
return null;
|
|
239
|
+
};
|
|
240
|
+
it("should pass provider-level elicitation handler to MCPClient.create", async () => {
|
|
241
|
+
const mockElicitationHandler = jest.fn().mockResolvedValue({
|
|
242
|
+
content: [{ type: "text", text: "test" }],
|
|
243
|
+
});
|
|
244
|
+
const handlers = {
|
|
245
|
+
elicitation: mockElicitationHandler,
|
|
246
|
+
};
|
|
247
|
+
let latest = [];
|
|
248
|
+
render(React.createElement(TamboMcpTokenProvider, null,
|
|
249
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://test.example"], handlers: handlers },
|
|
250
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
251
|
+
await waitFor(() => {
|
|
252
|
+
expect(latest.length).toBe(1);
|
|
253
|
+
});
|
|
254
|
+
// Verify MCPClient.create was called
|
|
255
|
+
expect(createSpy).toHaveBeenCalledWith("https://test.example", MCPTransport.SSE, undefined, undefined, undefined, expect.objectContaining({
|
|
256
|
+
elicitation: expect.any(Function),
|
|
257
|
+
}));
|
|
258
|
+
// Get the actual handler that was passed
|
|
259
|
+
const passedHandlers = createSpy.mock.calls[0][5];
|
|
260
|
+
expect(passedHandlers.elicitation).toBeDefined();
|
|
261
|
+
// Call the wrapped handler and verify it receives serverInfo
|
|
262
|
+
const mockRequest = {
|
|
263
|
+
method: "sampling/createMessage",
|
|
264
|
+
params: {},
|
|
265
|
+
};
|
|
266
|
+
await passedHandlers.elicitation(mockRequest);
|
|
267
|
+
expect(mockElicitationHandler).toHaveBeenCalledWith(mockRequest, expect.objectContaining({
|
|
268
|
+
url: "https://test.example",
|
|
269
|
+
transport: MCPTransport.SSE,
|
|
270
|
+
}));
|
|
271
|
+
});
|
|
272
|
+
it("should pass provider-level sampling handler to MCPClient.create", async () => {
|
|
273
|
+
const mockSamplingHandler = jest.fn().mockResolvedValue({
|
|
274
|
+
model: "test-model",
|
|
275
|
+
stopReason: "endTurn",
|
|
276
|
+
role: "assistant",
|
|
277
|
+
content: { type: "text", text: "response" },
|
|
278
|
+
});
|
|
279
|
+
const handlers = {
|
|
280
|
+
sampling: mockSamplingHandler,
|
|
281
|
+
};
|
|
282
|
+
let latest = [];
|
|
283
|
+
render(React.createElement(TamboMcpTokenProvider, null,
|
|
284
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://test.example"], handlers: handlers },
|
|
285
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
286
|
+
await waitFor(() => {
|
|
287
|
+
expect(latest.length).toBe(1);
|
|
288
|
+
});
|
|
289
|
+
// Verify MCPClient.create was called with sampling handler
|
|
290
|
+
expect(createSpy).toHaveBeenCalledWith("https://test.example", MCPTransport.SSE, undefined, undefined, undefined, expect.objectContaining({
|
|
291
|
+
sampling: expect.any(Function),
|
|
292
|
+
}));
|
|
293
|
+
// Get the actual handler and verify it receives serverInfo
|
|
294
|
+
const passedHandlers = createSpy.mock.calls[0][5];
|
|
295
|
+
const mockRequest = {
|
|
296
|
+
method: "sampling/createMessage",
|
|
297
|
+
params: {
|
|
298
|
+
messages: [],
|
|
299
|
+
modelPreferences: {},
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
await passedHandlers.sampling(mockRequest);
|
|
303
|
+
expect(mockSamplingHandler).toHaveBeenCalledWith(mockRequest, expect.objectContaining({
|
|
304
|
+
url: "https://test.example",
|
|
305
|
+
transport: MCPTransport.SSE,
|
|
306
|
+
}));
|
|
307
|
+
});
|
|
308
|
+
it("should allow per-server handlers to override provider-level handlers", async () => {
|
|
309
|
+
const providerElicitationHandler = jest.fn().mockResolvedValue({
|
|
310
|
+
content: [{ type: "text", text: "provider" }],
|
|
311
|
+
});
|
|
312
|
+
const serverElicitationHandler = jest.fn().mockResolvedValue({
|
|
313
|
+
content: [{ type: "text", text: "server" }],
|
|
314
|
+
});
|
|
315
|
+
const handlers = {
|
|
316
|
+
elicitation: providerElicitationHandler,
|
|
317
|
+
};
|
|
318
|
+
let latest = [];
|
|
319
|
+
render(React.createElement(TamboMcpTokenProvider, null,
|
|
320
|
+
React.createElement(TamboMcpProvider, { mcpServers: [
|
|
321
|
+
{
|
|
322
|
+
url: "https://test.example",
|
|
323
|
+
handlers: {
|
|
324
|
+
elicitation: serverElicitationHandler,
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
], handlers: handlers },
|
|
328
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
329
|
+
await waitFor(() => {
|
|
330
|
+
expect(latest.length).toBe(1);
|
|
331
|
+
});
|
|
332
|
+
// Verify the per-server handler was used, not the provider handler
|
|
333
|
+
const passedHandlers = createSpy.mock.calls[0][5];
|
|
334
|
+
expect(passedHandlers.elicitation).toBe(serverElicitationHandler);
|
|
335
|
+
});
|
|
336
|
+
it("should pass different serverInfo to handlers for different servers", async () => {
|
|
337
|
+
const mockElicitationHandler = jest.fn().mockResolvedValue({
|
|
338
|
+
content: [{ type: "text", text: "test" }],
|
|
339
|
+
});
|
|
340
|
+
const handlers = {
|
|
341
|
+
elicitation: mockElicitationHandler,
|
|
342
|
+
};
|
|
343
|
+
let latest = [];
|
|
344
|
+
render(React.createElement(TamboMcpTokenProvider, null,
|
|
345
|
+
React.createElement(TamboMcpProvider, { mcpServers: [
|
|
346
|
+
{ url: "https://server-a.example", name: "Server A" },
|
|
347
|
+
{ url: "https://server-b.example", name: "Server B" },
|
|
348
|
+
], handlers: handlers },
|
|
349
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
350
|
+
await waitFor(() => {
|
|
351
|
+
expect(latest.length).toBe(2);
|
|
352
|
+
});
|
|
353
|
+
// Verify both servers got handlers
|
|
354
|
+
expect(createSpy).toHaveBeenCalledTimes(2);
|
|
355
|
+
// Get handlers for both servers
|
|
356
|
+
const serverAHandlers = createSpy.mock.calls[0][5];
|
|
357
|
+
const serverBHandlers = createSpy.mock.calls[1][5];
|
|
358
|
+
const mockRequest = {
|
|
359
|
+
method: "sampling/createMessage",
|
|
360
|
+
params: {},
|
|
361
|
+
};
|
|
362
|
+
// Call handler for server A
|
|
363
|
+
await serverAHandlers.elicitation(mockRequest);
|
|
364
|
+
expect(mockElicitationHandler).toHaveBeenCalledWith(mockRequest, expect.objectContaining({
|
|
365
|
+
url: "https://server-a.example",
|
|
366
|
+
name: "Server A",
|
|
367
|
+
}));
|
|
368
|
+
mockElicitationHandler.mockClear();
|
|
369
|
+
// Call handler for server B
|
|
370
|
+
await serverBHandlers.elicitation(mockRequest);
|
|
371
|
+
expect(mockElicitationHandler).toHaveBeenCalledWith(mockRequest, expect.objectContaining({
|
|
372
|
+
url: "https://server-b.example",
|
|
373
|
+
name: "Server B",
|
|
374
|
+
}));
|
|
375
|
+
});
|
|
376
|
+
it("should update handlers when provider handlers change", async () => {
|
|
377
|
+
const initialHandler = jest.fn().mockResolvedValue({
|
|
378
|
+
content: [{ type: "text", text: "initial" }],
|
|
379
|
+
});
|
|
380
|
+
const updatedHandler = jest.fn().mockResolvedValue({
|
|
381
|
+
content: [{ type: "text", text: "updated" }],
|
|
382
|
+
});
|
|
383
|
+
let latest = [];
|
|
384
|
+
const { rerender } = render(React.createElement(TamboMcpTokenProvider, null,
|
|
385
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://test.example"], handlers: { elicitation: initialHandler } },
|
|
386
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
387
|
+
await waitFor(() => {
|
|
388
|
+
expect(latest.length).toBe(1);
|
|
389
|
+
});
|
|
390
|
+
// Update the handlers
|
|
391
|
+
rerender(React.createElement(TamboMcpTokenProvider, null,
|
|
392
|
+
React.createElement(TamboMcpProvider, { mcpServers: ["https://test.example"], handlers: { elicitation: updatedHandler } },
|
|
393
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
394
|
+
await waitFor(() => {
|
|
395
|
+
expect(mockClient.updateElicitationHandler).toHaveBeenCalled();
|
|
396
|
+
});
|
|
397
|
+
// Verify the handler was updated
|
|
398
|
+
expect(mockClient.updateElicitationHandler).toHaveBeenCalledWith(expect.any(Function));
|
|
399
|
+
});
|
|
400
|
+
});
|
|
195
401
|
//# sourceMappingURL=tambo-mcp-provider.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-mcp-provider.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/tambo-mcp-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { render, waitFor } from \"@testing-library/react\";\nimport React, { useEffect } from \"react\";\nimport { useTamboRegistry } from \"../../providers/tambo-registry-provider\";\nimport { MCPClient, MCPTransport } from \"../mcp-client\";\nimport {\n extractErrorMessage,\n TamboMcpProvider,\n useTamboMcpServers,\n type McpServer,\n} from \"../tambo-mcp-provider\";\n\n// Mock the MCP client to avoid ES module issues\njest.mock(\"../mcp-client\", () => ({\n MCPClient: jest.fn(),\n MCPTransport: {\n SSE: \"sse\",\n HTTP: \"http\",\n },\n}));\n\n// Mock the registry provider to avoid dependency issues\njest.mock(\"../../providers/tambo-registry-provider\", () => ({\n useTamboRegistry: jest.fn(),\n}));\n\ndescribe(\"extractErrorMessage\", () => {\n describe(\"Array content handling\", () => {\n it(\"should extract text from array content with multiple text items\", () => {\n const content = [\n { type: \"text\", text: \"Error:\" },\n { type: \"text\", text: \"Tool execution failed\" },\n { type: \"image\", url: \"http://example.com/error.png\" }, // Should be filtered out\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error: Tool execution failed\");\n });\n\n it(\"should extract text from array content with single text item\", () => {\n const content = [{ type: \"text\", text: \"Simple error message\" }];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Simple error message\");\n });\n\n it(\"should return fallback message for array content with no text items\", () => {\n const content = [\n { type: \"image\", url: \"http://example.com/error.png\" },\n { type: \"resource\", uri: \"file://error.log\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should return fallback message for empty array content\", () => {\n const content: any[] = [];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should handle array content with mixed types correctly\", () => {\n const content = [\n { type: \"resource\", uri: \"file://log.txt\" },\n { type: \"text\", text: \"First error\" },\n { type: \"image\", url: \"http://example.com/img.png\" },\n { type: \"text\", text: \"Second error\" },\n { type: \"unknown\", data: \"something\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"First error Second error\");\n });\n\n it(\"should handle array content with malformed items\", () => {\n const content = [\n null,\n { type: \"text\", text: \"Valid error\" },\n { type: \"text\" }, // Missing text property\n { type: \"text\", text: null }, // Invalid text type\n { type: \"text\", text: \"Another valid error\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Valid error Another valid error\");\n });\n });\n\n describe(\"Non-array content handling\", () => {\n it(\"should return string content as-is\", () => {\n const content = \"Direct error message\";\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Direct error message\");\n });\n\n it(\"should handle null content\", () => {\n const content = null;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle undefined content\", () => {\n const content = undefined;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle number content\", () => {\n const content = 42;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"42\");\n });\n\n it(\"should handle boolean content\", () => {\n const content = false;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"false\");\n });\n\n it(\"should handle object content\", () => {\n const content = { error: \"Something went wrong\" };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe('{\"error\":\"Something went wrong\"}');\n });\n\n it(\"should handle complex object content\", () => {\n const content = {\n error: \"Something went wrong\",\n code: 500,\n details: { message: \"Internal server error\" },\n };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\n '{\"error\":\"Something went wrong\",\"code\":500,\"details\":{\"message\":\"Internal server error\"}}',\n );\n });\n\n it(\"should handle empty object content\", () => {\n const content = {};\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"{}\");\n });\n });\n});\n\ndescribe(\"TamboMcpProvider server list changes\", () => {\n beforeEach(() => {\n // Mock registry so tool registration is a no-op\n (useTamboRegistry as unknown as jest.Mock).mockReturnValue({\n registerTool: jest.fn(),\n });\n\n // Ensure MCPClient.create exists and returns a fake client with listTools\n (MCPClient as unknown as any).create = jest\n .fn()\n .mockResolvedValue({ listTools: jest.fn().mockResolvedValue([]) });\n });\n\n const Capture: React.FC<{ onUpdate: (servers: McpServer[]) => void }> = ({\n onUpdate,\n }) => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n onUpdate(servers);\n }, [servers, onUpdate]);\n return <div data-testid=\"urls\">{servers.map((s) => s.url).join(\",\")}</div>;\n };\n\n it(\"adds a new server when the list grows\", async () => {\n let latest: McpServer[] = [];\n const { rerender, getByTestId } = render(\n <TamboMcpProvider mcpServers={[\"https://a.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n // Wait for initial connection\n await waitFor(() => {\n expect(latest.length).toBe(1);\n });\n\n // Add new server\n rerender(\n <TamboMcpProvider mcpServers={[\"https://a.example\", \"https://b.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://a.example\");\n expect(urls).toContain(\"https://b.example\");\n });\n });\n\n it(\"removes a server when the list shrinks\", async () => {\n let latest: McpServer[] = [];\n const { rerender, getByTestId } = render(\n <TamboMcpProvider mcpServers={[\"https://a.example\", \"https://b.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n });\n\n // Remove one server\n rerender(\n <TamboMcpProvider mcpServers={[\"https://a.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://a.example\");\n expect(urls).not.toContain(\"https://b.example\");\n });\n });\n\n it(\"does not duplicate when a new copy of the same list is passed\", async () => {\n let latest: McpServer[] = [];\n const initial = [\n { url: \"https://a.example\", transport: MCPTransport.SSE },\n { url: \"https://b.example\", transport: MCPTransport.SSE },\n ];\n\n const { rerender } = render(\n <TamboMcpProvider mcpServers={initial}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n });\n\n // Pass a new array instance with the same logical servers\n const same = [\n { url: \"https://a.example\", transport: MCPTransport.SSE },\n { url: \"https://b.example\", transport: MCPTransport.SSE },\n ];\n rerender(\n <TamboMcpProvider mcpServers={same}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n const urls = latest.map((s) => s.url).sort();\n expect(urls).toEqual([\"https://a.example\", \"https://b.example\"].sort());\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"tambo-mcp-provider.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/tambo-mcp-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { render, waitFor } from \"@testing-library/react\";\nimport React, { useEffect } from \"react\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { TamboMcpTokenProvider } from \"../../providers/tambo-mcp-token-provider\";\nimport { useTamboRegistry } from \"../../providers/tambo-registry-provider\";\nimport { MCPClient, MCPTransport } from \"../mcp-client\";\nimport {\n extractErrorMessage,\n TamboMcpProvider,\n useTamboMcpServers,\n type McpServer,\n type ProviderMCPHandlers,\n} from \"../tambo-mcp-provider\";\n\n// Mock the MCP client to avoid ES module issues\njest.mock(\"../mcp-client\", () => ({\n MCPClient: jest.fn(),\n MCPTransport: {\n SSE: \"sse\",\n HTTP: \"http\",\n },\n}));\n\n// Mock the registry provider to avoid dependency issues\njest.mock(\"../../providers/tambo-registry-provider\", () => ({\n useTamboRegistry: jest.fn(),\n}));\n\n// Mock the client provider to avoid dependency issues\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n}));\n\ndescribe(\"extractErrorMessage\", () => {\n describe(\"Array content handling\", () => {\n it(\"should extract text from array content with multiple text items\", () => {\n const content = [\n { type: \"text\", text: \"Error:\" },\n { type: \"text\", text: \"Tool execution failed\" },\n { type: \"image\", url: \"http://example.com/error.png\" }, // Should be filtered out\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error: Tool execution failed\");\n });\n\n it(\"should extract text from array content with single text item\", () => {\n const content = [{ type: \"text\", text: \"Simple error message\" }];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Simple error message\");\n });\n\n it(\"should return fallback message for array content with no text items\", () => {\n const content = [\n { type: \"image\", url: \"http://example.com/error.png\" },\n { type: \"resource\", uri: \"file://error.log\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should return fallback message for empty array content\", () => {\n const content: any[] = [];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should handle array content with mixed types correctly\", () => {\n const content = [\n { type: \"resource\", uri: \"file://log.txt\" },\n { type: \"text\", text: \"First error\" },\n { type: \"image\", url: \"http://example.com/img.png\" },\n { type: \"text\", text: \"Second error\" },\n { type: \"unknown\", data: \"something\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"First error Second error\");\n });\n\n it(\"should handle array content with malformed items\", () => {\n const content = [\n null,\n { type: \"text\", text: \"Valid error\" },\n { type: \"text\" }, // Missing text property\n { type: \"text\", text: null }, // Invalid text type\n { type: \"text\", text: \"Another valid error\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Valid error Another valid error\");\n });\n });\n\n describe(\"Non-array content handling\", () => {\n it(\"should return string content as-is\", () => {\n const content = \"Direct error message\";\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Direct error message\");\n });\n\n it(\"should handle null content\", () => {\n const content = null;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle undefined content\", () => {\n const content = undefined;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle number content\", () => {\n const content = 42;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"42\");\n });\n\n it(\"should handle boolean content\", () => {\n const content = false;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"false\");\n });\n\n it(\"should handle object content\", () => {\n const content = { error: \"Something went wrong\" };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe('{\"error\":\"Something went wrong\"}');\n });\n\n it(\"should handle complex object content\", () => {\n const content = {\n error: \"Something went wrong\",\n code: 500,\n details: { message: \"Internal server error\" },\n };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\n '{\"error\":\"Something went wrong\",\"code\":500,\"details\":{\"message\":\"Internal server error\"}}',\n );\n });\n\n it(\"should handle empty object content\", () => {\n const content = {};\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"{}\");\n });\n });\n});\n\ndescribe(\"TamboMcpProvider server list changes\", () => {\n beforeEach(() => {\n // Mock registry so tool registration is a no-op\n (useTamboRegistry as unknown as jest.Mock).mockReturnValue({\n registerTool: jest.fn(),\n });\n\n // Mock client with baseURL\n (useTamboClient as unknown as jest.Mock).mockReturnValue({\n baseURL: \"https://api.tambo.co\",\n });\n\n // Ensure MCPClient.create exists and returns a fake client with listTools\n (MCPClient as unknown as any).create = jest\n .fn()\n .mockResolvedValue({ listTools: jest.fn().mockResolvedValue([]) });\n });\n\n const Capture: React.FC<{ onUpdate: (servers: McpServer[]) => void }> = ({\n onUpdate,\n }) => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n onUpdate(servers);\n }, [servers, onUpdate]);\n return <div data-testid=\"urls\">{servers.map((s) => s.url).join(\",\")}</div>;\n };\n\n it(\"adds a new server when the list grows\", async () => {\n let latest: McpServer[] = [];\n const { rerender, getByTestId } = render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider mcpServers={[\"https://a.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n // Wait for initial connection\n await waitFor(() => {\n expect(latest.length).toBe(1);\n });\n\n // Add new server\n rerender(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\"https://a.example\", \"https://b.example\"]}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://a.example\");\n expect(urls).toContain(\"https://b.example\");\n });\n });\n\n it(\"removes a server when the list shrinks\", async () => {\n let latest: McpServer[] = [];\n const { rerender, getByTestId } = render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\"https://a.example\", \"https://b.example\"]}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n });\n\n // Remove one server\n rerender(\n <TamboMcpTokenProvider>\n <TamboMcpProvider mcpServers={[\"https://a.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://a.example\");\n expect(urls).not.toContain(\"https://b.example\");\n });\n });\n\n it(\"does not duplicate when a new copy of the same list is passed\", async () => {\n let latest: McpServer[] = [];\n const initial = [\n { url: \"https://a.example\", transport: MCPTransport.SSE },\n { url: \"https://b.example\", transport: MCPTransport.SSE },\n ];\n\n const { rerender } = render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider mcpServers={initial}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n });\n\n // Pass a new array instance with the same logical servers\n const same = [\n { url: \"https://a.example\", transport: MCPTransport.SSE },\n { url: \"https://b.example\", transport: MCPTransport.SSE },\n ];\n rerender(\n <TamboMcpTokenProvider>\n <TamboMcpProvider mcpServers={same}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n const urls = latest.map((s) => s.url).sort();\n expect(urls).toEqual([\"https://a.example\", \"https://b.example\"].sort());\n });\n });\n});\n\ndescribe(\"TamboMcpProvider handler support\", () => {\n let mockClient: any;\n let createSpy: jest.Mock;\n\n beforeEach(() => {\n // Mock registry so tool registration is a no-op\n (useTamboRegistry as unknown as jest.Mock).mockReturnValue({\n registerTool: jest.fn(),\n });\n\n // Mock client with baseURL\n (useTamboClient as unknown as jest.Mock).mockReturnValue({\n baseURL: \"https://api.tambo.co\",\n });\n\n // Create a mock client with update methods\n mockClient = {\n listTools: jest.fn().mockResolvedValue([]),\n updateElicitationHandler: jest.fn(),\n updateSamplingHandler: jest.fn(),\n };\n\n // Mock MCPClient.create to return our mock client\n createSpy = jest.fn().mockResolvedValue(mockClient);\n (MCPClient as unknown as any).create = createSpy;\n });\n\n const Capture: React.FC<{ onUpdate: (servers: McpServer[]) => void }> = ({\n onUpdate,\n }) => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n onUpdate(servers);\n }, [servers, onUpdate]);\n return null;\n };\n\n it(\"should pass provider-level elicitation handler to MCPClient.create\", async () => {\n const mockElicitationHandler = jest.fn().mockResolvedValue({\n content: [{ type: \"text\", text: \"test\" }],\n });\n\n const handlers: ProviderMCPHandlers = {\n elicitation: mockElicitationHandler,\n };\n\n let latest: McpServer[] = [];\n render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\"https://test.example\"]}\n handlers={handlers}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n });\n\n // Verify MCPClient.create was called\n expect(createSpy).toHaveBeenCalledWith(\n \"https://test.example\",\n MCPTransport.SSE,\n undefined,\n undefined,\n undefined,\n expect.objectContaining({\n elicitation: expect.any(Function),\n }),\n );\n\n // Get the actual handler that was passed\n const passedHandlers = createSpy.mock.calls[0][5];\n expect(passedHandlers.elicitation).toBeDefined();\n\n // Call the wrapped handler and verify it receives serverInfo\n const mockRequest = {\n method: \"sampling/createMessage\" as const,\n params: {},\n };\n await passedHandlers.elicitation(mockRequest);\n\n expect(mockElicitationHandler).toHaveBeenCalledWith(\n mockRequest,\n expect.objectContaining({\n url: \"https://test.example\",\n transport: MCPTransport.SSE,\n }),\n );\n });\n\n it(\"should pass provider-level sampling handler to MCPClient.create\", async () => {\n const mockSamplingHandler = jest.fn().mockResolvedValue({\n model: \"test-model\",\n stopReason: \"endTurn\",\n role: \"assistant\",\n content: { type: \"text\", text: \"response\" },\n });\n\n const handlers: ProviderMCPHandlers = {\n sampling: mockSamplingHandler,\n };\n\n let latest: McpServer[] = [];\n render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\"https://test.example\"]}\n handlers={handlers}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n });\n\n // Verify MCPClient.create was called with sampling handler\n expect(createSpy).toHaveBeenCalledWith(\n \"https://test.example\",\n MCPTransport.SSE,\n undefined,\n undefined,\n undefined,\n expect.objectContaining({\n sampling: expect.any(Function),\n }),\n );\n\n // Get the actual handler and verify it receives serverInfo\n const passedHandlers = createSpy.mock.calls[0][5];\n const mockRequest = {\n method: \"sampling/createMessage\" as const,\n params: {\n messages: [],\n modelPreferences: {},\n },\n };\n await passedHandlers.sampling(mockRequest);\n\n expect(mockSamplingHandler).toHaveBeenCalledWith(\n mockRequest,\n expect.objectContaining({\n url: \"https://test.example\",\n transport: MCPTransport.SSE,\n }),\n );\n });\n\n it(\"should allow per-server handlers to override provider-level handlers\", async () => {\n const providerElicitationHandler = jest.fn().mockResolvedValue({\n content: [{ type: \"text\", text: \"provider\" }],\n });\n\n const serverElicitationHandler = jest.fn().mockResolvedValue({\n content: [{ type: \"text\", text: \"server\" }],\n });\n\n const handlers: ProviderMCPHandlers = {\n elicitation: providerElicitationHandler,\n };\n\n let latest: McpServer[] = [];\n render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\n {\n url: \"https://test.example\",\n handlers: {\n elicitation: serverElicitationHandler,\n },\n },\n ]}\n handlers={handlers}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n });\n\n // Verify the per-server handler was used, not the provider handler\n const passedHandlers = createSpy.mock.calls[0][5];\n expect(passedHandlers.elicitation).toBe(serverElicitationHandler);\n });\n\n it(\"should pass different serverInfo to handlers for different servers\", async () => {\n const mockElicitationHandler = jest.fn().mockResolvedValue({\n content: [{ type: \"text\", text: \"test\" }],\n });\n\n const handlers: ProviderMCPHandlers = {\n elicitation: mockElicitationHandler,\n };\n\n let latest: McpServer[] = [];\n render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\n { url: \"https://server-a.example\", name: \"Server A\" },\n { url: \"https://server-b.example\", name: \"Server B\" },\n ]}\n handlers={handlers}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n });\n\n // Verify both servers got handlers\n expect(createSpy).toHaveBeenCalledTimes(2);\n\n // Get handlers for both servers\n const serverAHandlers = createSpy.mock.calls[0][5];\n const serverBHandlers = createSpy.mock.calls[1][5];\n\n const mockRequest = {\n method: \"sampling/createMessage\" as const,\n params: {},\n };\n\n // Call handler for server A\n await serverAHandlers.elicitation(mockRequest);\n expect(mockElicitationHandler).toHaveBeenCalledWith(\n mockRequest,\n expect.objectContaining({\n url: \"https://server-a.example\",\n name: \"Server A\",\n }),\n );\n\n mockElicitationHandler.mockClear();\n\n // Call handler for server B\n await serverBHandlers.elicitation(mockRequest);\n expect(mockElicitationHandler).toHaveBeenCalledWith(\n mockRequest,\n expect.objectContaining({\n url: \"https://server-b.example\",\n name: \"Server B\",\n }),\n );\n });\n\n it(\"should update handlers when provider handlers change\", async () => {\n const initialHandler = jest.fn().mockResolvedValue({\n content: [{ type: \"text\", text: \"initial\" }],\n });\n\n const updatedHandler = jest.fn().mockResolvedValue({\n content: [{ type: \"text\", text: \"updated\" }],\n });\n\n let latest: McpServer[] = [];\n const { rerender } = render(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\"https://test.example\"]}\n handlers={{ elicitation: initialHandler }}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n });\n\n // Update the handlers\n rerender(\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\"https://test.example\"]}\n handlers={{ elicitation: updatedHandler }}\n >\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>,\n );\n\n await waitFor(() => {\n expect(mockClient.updateElicitationHandler).toHaveBeenCalled();\n });\n\n // Verify the handler was updated\n expect(mockClient.updateElicitationHandler).toHaveBeenCalledWith(\n expect.any(Function),\n );\n });\n});\n"]}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { render, waitFor } from "@testing-library/react";
|
|
2
2
|
import React, { useEffect } from "react";
|
|
3
|
+
import { TamboMcpTokenProvider } from "../../providers/tambo-mcp-token-provider";
|
|
3
4
|
import { TamboRegistryProvider } from "../../providers/tambo-registry-provider";
|
|
5
|
+
import { TamboClientContext } from "../../providers/tambo-client-provider";
|
|
6
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
4
7
|
import { TamboMcpProvider, useTamboMcpServers, } from "../tambo-mcp-provider";
|
|
5
8
|
// Mock the registry to provide a no-op registerTool
|
|
6
9
|
// Do not mock the registry; use the real provider in render
|
|
10
|
+
// Provide a minimal client context instead of mocking the hook
|
|
7
11
|
// Mock the MCP client; use a mutable implementation to avoid TDZ issues
|
|
8
12
|
let createImpl = jest.fn();
|
|
9
13
|
jest.mock("../mcp-client", () => ({
|
|
@@ -24,9 +28,18 @@ describe("useTamboMcpServers + TamboMcpProvider", () => {
|
|
|
24
28
|
React.createElement("div", { "data-testid": "count" }, servers.length),
|
|
25
29
|
React.createElement("div", { "data-testid": "urls" }, servers.map((s) => s.url).join(","))));
|
|
26
30
|
};
|
|
27
|
-
const { getByTestId } = render(React.createElement(
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
const { getByTestId } = render(React.createElement(TamboClientContext.Provider, { value: {
|
|
32
|
+
client: { baseURL: "https://api.tambo.co" },
|
|
33
|
+
queryClient: new QueryClient(),
|
|
34
|
+
isUpdatingToken: false,
|
|
35
|
+
} },
|
|
36
|
+
React.createElement(TamboRegistryProvider, null,
|
|
37
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
38
|
+
React.createElement(TamboMcpProvider, { mcpServers: [
|
|
39
|
+
{ url: "https://one.example" },
|
|
40
|
+
"https://two.example",
|
|
41
|
+
] },
|
|
42
|
+
React.createElement(Inner, null))))));
|
|
30
43
|
await waitFor(() => {
|
|
31
44
|
expect(getByTestId("count").textContent).toBe("2");
|
|
32
45
|
const urls = getByTestId("urls").textContent || "";
|
|
@@ -45,9 +58,15 @@ describe("useTamboMcpServers + TamboMcpProvider", () => {
|
|
|
45
58
|
}, [servers]);
|
|
46
59
|
return null;
|
|
47
60
|
};
|
|
48
|
-
render(React.createElement(
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
render(React.createElement(TamboClientContext.Provider, { value: {
|
|
62
|
+
client: { baseURL: "https://api.tambo.co" },
|
|
63
|
+
queryClient: new QueryClient(),
|
|
64
|
+
isUpdatingToken: false,
|
|
65
|
+
} },
|
|
66
|
+
React.createElement(TamboRegistryProvider, null,
|
|
67
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
68
|
+
React.createElement(TamboMcpProvider, { mcpServers: [{ url: "https://ok.example" }] },
|
|
69
|
+
React.createElement(Capture, null))))));
|
|
51
70
|
await waitFor(() => {
|
|
52
71
|
expect(latest.length).toBe(1);
|
|
53
72
|
expect("client" in latest[0]).toBe(true);
|
|
@@ -67,9 +86,15 @@ describe("useTamboMcpServers + TamboMcpProvider", () => {
|
|
|
67
86
|
}, [servers]);
|
|
68
87
|
return null;
|
|
69
88
|
};
|
|
70
|
-
render(React.createElement(
|
|
71
|
-
|
|
72
|
-
|
|
89
|
+
render(React.createElement(TamboClientContext.Provider, { value: {
|
|
90
|
+
client: { baseURL: "https://api.tambo.co" },
|
|
91
|
+
queryClient: new QueryClient(),
|
|
92
|
+
isUpdatingToken: false,
|
|
93
|
+
} },
|
|
94
|
+
React.createElement(TamboRegistryProvider, null,
|
|
95
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
96
|
+
React.createElement(TamboMcpProvider, { mcpServers: [{ url: "https://fail.example" }] },
|
|
97
|
+
React.createElement(Capture, null))))));
|
|
73
98
|
await waitFor(() => {
|
|
74
99
|
expect(latest.length).toBe(1);
|
|
75
100
|
expect("client" in latest[0]).toBe(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-mcp-servers.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/use-mcp-servers.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EACL,gBAAgB,EAChB,kBAAkB,GAEnB,MAAM,uBAAuB,CAAC;AAE/B,oDAAoD;AACpD,4DAA4D;AAE5D,wEAAwE;AACxE,IAAI,UAAU,GAAwB,IAAI,CAAC,EAAE,EAAE,CAAC;AAChD,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC;IAChC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,EAAE;IAC9D,YAAY,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE;CAC3C,CAAC,CAAC,CAAC;AAEJ,qFAAqF;AAErF,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,UAAU,CAAC,GAAG,EAAE;QACd,UAAU,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,UAAU,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,EAAS,CAAC;QACzE,UAAU,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAEzC,MAAM,KAAK,GAAa,GAAG,EAAE;YAC3B,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;YACrC,OAAO,CACL;gBACE,4CAAiB,OAAO,IAAE,OAAO,CAAC,MAAM,CAAO;gBAC/C,4CAAiB,MAAM,IAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAO,CAC/D,CACP,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAC5B,oBAAC,qBAAqB;
|
|
1
|
+
{"version":3,"file":"use-mcp-servers.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/use-mcp-servers.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { render, waitFor } from \"@testing-library/react\";\nimport React, { useEffect } from \"react\";\nimport { TamboMcpTokenProvider } from \"../../providers/tambo-mcp-token-provider\";\nimport { TamboRegistryProvider } from \"../../providers/tambo-registry-provider\";\nimport { TamboClientContext } from \"../../providers/tambo-client-provider\";\nimport { QueryClient } from \"@tanstack/react-query\";\nimport {\n TamboMcpProvider,\n useTamboMcpServers,\n type McpServer,\n} from \"../tambo-mcp-provider\";\n\n// Mock the registry to provide a no-op registerTool\n// Do not mock the registry; use the real provider in render\n\n// Provide a minimal client context instead of mocking the hook\n\n// Mock the MCP client; use a mutable implementation to avoid TDZ issues\nlet createImpl: jest.Mock<any, any> = jest.fn();\njest.mock(\"../mcp-client\", () => ({\n MCPClient: { create: (...args: any[]) => createImpl(...args) },\n MCPTransport: { SSE: \"sse\", HTTP: \"http\" },\n}));\n\n// Import after mocks note: jest.mock calls are hoisted, so standard imports are fine\n\ndescribe(\"useTamboMcpServers + TamboMcpProvider\", () => {\n beforeEach(() => {\n createImpl = jest.fn();\n });\n\n it(\"provides normalized MCP server entries to inner components\", async () => {\n const fakeClient = { listTools: jest.fn().mockResolvedValue([]) } as any;\n createImpl.mockResolvedValue(fakeClient);\n\n const Inner: React.FC = () => {\n const servers = useTamboMcpServers();\n return (\n <div>\n <div data-testid=\"count\">{servers.length}</div>\n <div data-testid=\"urls\">{servers.map((s) => s.url).join(\",\")}</div>\n </div>\n );\n };\n\n const { getByTestId } = render(\n <TamboClientContext.Provider\n value={{\n client: { baseURL: \"https://api.tambo.co\" } as any,\n queryClient: new QueryClient(),\n isUpdatingToken: false,\n }}\n >\n <TamboRegistryProvider>\n <TamboMcpTokenProvider>\n <TamboMcpProvider\n mcpServers={[\n { url: \"https://one.example\" },\n \"https://two.example\",\n ]}\n >\n <Inner />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>\n </TamboRegistryProvider>\n </TamboClientContext.Provider>,\n );\n\n await waitFor(() => {\n expect(getByTestId(\"count\").textContent).toBe(\"2\");\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://one.example\");\n expect(urls).toContain(\"https://two.example\");\n });\n });\n\n it(\"marks a successfully connected server with a client instance\", async () => {\n const fakeClient = { listTools: jest.fn().mockResolvedValue([]) } as any;\n createImpl.mockResolvedValue(fakeClient);\n\n let latest: McpServer[] = [];\n const Capture: React.FC = () => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n latest = servers;\n }, [servers]);\n return null;\n };\n\n render(\n <TamboClientContext.Provider\n value={{\n client: { baseURL: \"https://api.tambo.co\" } as any,\n queryClient: new QueryClient(),\n isUpdatingToken: false,\n }}\n >\n <TamboRegistryProvider>\n <TamboMcpTokenProvider>\n <TamboMcpProvider mcpServers={[{ url: \"https://ok.example\" }]}>\n <Capture />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>\n </TamboRegistryProvider>\n </TamboClientContext.Provider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n expect(\"client\" in latest[0]).toBe(true);\n expect((latest[0] as any).client).toBe(fakeClient);\n // no connectionError on connected server\n expect((latest[0] as any).connectionError).toBeUndefined();\n });\n });\n\n it(\"marks a failed server with a connectionError and no client\", async () => {\n const boom = new Error(\"boom\");\n createImpl.mockRejectedValue(boom);\n\n let latest: McpServer[] = [];\n const Capture: React.FC = () => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n latest = servers;\n }, [servers]);\n return null;\n };\n\n render(\n <TamboClientContext.Provider\n value={{\n client: { baseURL: \"https://api.tambo.co\" } as any,\n queryClient: new QueryClient(),\n isUpdatingToken: false,\n }}\n >\n <TamboRegistryProvider>\n <TamboMcpTokenProvider>\n <TamboMcpProvider mcpServers={[{ url: \"https://fail.example\" }]}>\n <Capture />\n </TamboMcpProvider>\n </TamboMcpTokenProvider>\n </TamboRegistryProvider>\n </TamboClientContext.Provider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n expect(\"client\" in latest[0]).toBe(false);\n // @ts-expect-error narrowing at runtime\n expect(latest[0].connectionError).toBeInstanceOf(Error);\n // @ts-expect-error narrowing at runtime\n expect(latest[0].connectionError?.message).toBe(\"boom\");\n });\n });\n});\n"]}
|
package/esm/mcp/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { MCPTransport } from "./mcp-client";
|
|
2
|
-
export
|
|
2
|
+
export type { MCPHandlers } from "./mcp-client";
|
|
3
|
+
export { useTamboMcpPrompt, useTamboMcpPromptList } from "./mcp-hooks";
|
|
4
|
+
export { TamboMcpProvider, useTamboMcpServers, type ConnectedMcpServer, type FailedMcpServer, type McpServer, type McpServerInfo, type ProviderMCPHandlers, } from "./tambo-mcp-provider";
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
package/esm/mcp/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,mBAAmB,GACzB,MAAM,sBAAsB,CAAC"}
|
package/esm/mcp/index.js
CHANGED
package/esm/mcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EACL,gBAAgB,EAChB,kBAAkB,GAMnB,MAAM,sBAAsB,CAAC","sourcesContent":["export { MCPTransport } from \"./mcp-client\";\nexport type { MCPHandlers } from \"./mcp-client\";\nexport { useTamboMcpPrompt, useTamboMcpPromptList } from \"./mcp-hooks\";\nexport {\n TamboMcpProvider,\n useTamboMcpServers,\n type ConnectedMcpServer,\n type FailedMcpServer,\n type McpServer,\n type McpServerInfo,\n type ProviderMCPHandlers,\n} from \"./tambo-mcp-provider\";\n"]}
|