@tambo-ai/react 0.64.1 → 0.65.2
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/README.md +304 -327
- package/dist/hooks/use-tambo-threads.d.ts +0 -12
- package/dist/hooks/use-tambo-threads.d.ts.map +1 -1
- package/dist/hooks/use-tambo-threads.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/__tests__/elicitation.test.js +7 -3
- package/dist/mcp/__tests__/elicitation.test.js.map +1 -1
- package/dist/mcp/__tests__/mcp-hooks.test.js +149 -123
- package/dist/mcp/__tests__/mcp-hooks.test.js.map +1 -1
- package/dist/mcp/__tests__/tambo-mcp-provider.test.js +176 -120
- package/dist/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -1
- package/dist/mcp/__tests__/use-mcp-servers.test.js +12 -9
- package/dist/mcp/__tests__/use-mcp-servers.test.js.map +1 -1
- package/dist/mcp/elicitation.d.ts +4 -40
- package/dist/mcp/elicitation.d.ts.map +1 -1
- package/dist/mcp/elicitation.js +1 -1
- package/dist/mcp/elicitation.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-client.d.ts +14 -26
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +4 -7
- package/dist/mcp/mcp-client.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts +27 -78
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts +27 -45
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +36 -87
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/mcp-server-info.d.ts +74 -0
- package/dist/model/mcp-server-info.d.ts.map +1 -0
- package/dist/model/mcp-server-info.js +29 -0
- package/dist/model/mcp-server-info.js.map +1 -0
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.js +22 -8
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider.test.js +318 -129
- package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/tambo-client-provider.d.ts +4 -0
- package/dist/providers/tambo-client-provider.d.ts.map +1 -1
- package/dist/providers/tambo-client-provider.js +3 -0
- package/dist/providers/tambo-client-provider.js.map +1 -1
- package/dist/providers/tambo-mcp-token-provider.d.ts +3 -0
- package/dist/providers/tambo-mcp-token-provider.d.ts.map +1 -1
- package/dist/providers/tambo-mcp-token-provider.js +11 -3
- package/dist/providers/tambo-mcp-token-provider.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +1 -0
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +10 -5
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-registry-provider.d.ts +37 -0
- package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
- package/dist/providers/tambo-registry-provider.js +162 -2
- package/dist/providers/tambo-registry-provider.js.map +1 -1
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +10 -1
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/esm/hooks/use-tambo-threads.d.ts +0 -12
- package/esm/hooks/use-tambo-threads.d.ts.map +1 -1
- package/esm/hooks/use-tambo-threads.js.map +1 -1
- package/esm/index.d.ts +3 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +3 -2
- package/esm/index.js.map +1 -1
- package/esm/mcp/__tests__/elicitation.test.js +8 -4
- package/esm/mcp/__tests__/elicitation.test.js.map +1 -1
- package/esm/mcp/__tests__/mcp-hooks.test.js +149 -123
- package/esm/mcp/__tests__/mcp-hooks.test.js.map +1 -1
- package/esm/mcp/__tests__/tambo-mcp-provider.test.js +178 -122
- package/esm/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -1
- package/esm/mcp/__tests__/use-mcp-servers.test.js +12 -9
- package/esm/mcp/__tests__/use-mcp-servers.test.js.map +1 -1
- package/esm/mcp/elicitation.d.ts +4 -40
- package/esm/mcp/elicitation.d.ts.map +1 -1
- package/esm/mcp/elicitation.js +2 -2
- package/esm/mcp/elicitation.js.map +1 -1
- package/esm/mcp/index.d.ts +2 -1
- package/esm/mcp/index.d.ts.map +1 -1
- package/esm/mcp/index.js +1 -1
- package/esm/mcp/index.js.map +1 -1
- package/esm/mcp/mcp-client.d.ts +14 -26
- package/esm/mcp/mcp-client.d.ts.map +1 -1
- package/esm/mcp/mcp-client.js +3 -5
- package/esm/mcp/mcp-client.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts +27 -78
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts +27 -45
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +35 -86
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/mcp-server-info.d.ts +74 -0
- package/esm/model/mcp-server-info.d.ts.map +1 -0
- package/esm/model/mcp-server-info.js +25 -0
- package/esm/model/mcp-server-info.js.map +1 -0
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.js +23 -9
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider.test.js +319 -130
- package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/esm/providers/index.d.ts +1 -1
- package/esm/providers/index.d.ts.map +1 -1
- package/esm/providers/index.js +1 -1
- package/esm/providers/index.js.map +1 -1
- package/esm/providers/tambo-client-provider.d.ts +4 -0
- package/esm/providers/tambo-client-provider.d.ts.map +1 -1
- package/esm/providers/tambo-client-provider.js +3 -0
- package/esm/providers/tambo-client-provider.js.map +1 -1
- package/esm/providers/tambo-mcp-token-provider.d.ts +3 -0
- package/esm/providers/tambo-mcp-token-provider.d.ts.map +1 -1
- package/esm/providers/tambo-mcp-token-provider.js +13 -5
- package/esm/providers/tambo-mcp-token-provider.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts +1 -0
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +11 -6
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.d.ts +37 -0
- package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
- package/esm/providers/tambo-registry-provider.js +161 -2
- package/esm/providers/tambo-registry-provider.js.map +1 -1
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +10 -1
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { render, waitFor } from "@testing-library/react";
|
|
2
2
|
import React, { useEffect } from "react";
|
|
3
|
-
import { useTamboClient } from "../../providers/tambo-client-provider";
|
|
3
|
+
import { TamboClientContext, useTamboClient, } from "../../providers/tambo-client-provider";
|
|
4
4
|
import { TamboMcpTokenProvider } from "../../providers/tambo-mcp-token-provider";
|
|
5
|
-
import { useTamboRegistry } from "../../providers/tambo-registry-provider";
|
|
5
|
+
import { TamboRegistryProvider, useTamboRegistry, } from "../../providers/tambo-registry-provider";
|
|
6
6
|
import { MCPClient, MCPTransport } from "../mcp-client";
|
|
7
7
|
import { extractErrorMessage, TamboMcpProvider, useTamboMcpServers, } from "../tambo-mcp-provider";
|
|
8
8
|
// Import the private function for testing by re-exporting it for tests only
|
|
@@ -25,13 +25,34 @@ jest.mock("../mcp-client", () => ({
|
|
|
25
25
|
},
|
|
26
26
|
}));
|
|
27
27
|
// Mock the registry provider to avoid dependency issues
|
|
28
|
-
jest.mock("../../providers/tambo-registry-provider", () =>
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
jest.mock("../../providers/tambo-registry-provider", () => {
|
|
29
|
+
const actual = jest.requireActual("../../providers/tambo-registry-provider");
|
|
30
|
+
return {
|
|
31
|
+
...actual,
|
|
32
|
+
useTamboRegistry: jest.fn(),
|
|
33
|
+
};
|
|
34
|
+
});
|
|
31
35
|
// Mock the client provider to avoid dependency issues
|
|
32
|
-
jest.mock("../../providers/tambo-client-provider", () =>
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
jest.mock("../../providers/tambo-client-provider", () => {
|
|
37
|
+
return {
|
|
38
|
+
useTamboClient: jest.fn(),
|
|
39
|
+
TamboClientContext: React.createContext(undefined),
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
// Helper to wrap tests with all required providers (used across multiple describe blocks)
|
|
43
|
+
const TestWrapper = ({ mcpServers, handlers, children }) => {
|
|
44
|
+
const client = useTamboClient();
|
|
45
|
+
return (React.createElement(TamboClientContext.Provider, { value: {
|
|
46
|
+
client,
|
|
47
|
+
queryClient: {},
|
|
48
|
+
isUpdatingToken: false,
|
|
49
|
+
mcpAccessToken: null,
|
|
50
|
+
setMcpAccessToken: () => { },
|
|
51
|
+
} },
|
|
52
|
+
React.createElement(TamboRegistryProvider, { mcpServers: mcpServers },
|
|
53
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
54
|
+
React.createElement(TamboMcpProvider, { handlers: handlers }, children)))));
|
|
55
|
+
};
|
|
35
56
|
describe("extractErrorMessage", () => {
|
|
36
57
|
describe("Array content handling", () => {
|
|
37
58
|
it("should extract text from array content with multiple text items", () => {
|
|
@@ -156,17 +177,33 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
156
177
|
};
|
|
157
178
|
it("adds a new server when the list grows", async () => {
|
|
158
179
|
let latest = [];
|
|
159
|
-
const { rerender, getByTestId } = render(React.createElement(
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
const { rerender, getByTestId } = render(React.createElement(TamboClientContext.Provider, { value: {
|
|
181
|
+
client: useTamboClient(),
|
|
182
|
+
queryClient: {},
|
|
183
|
+
isUpdatingToken: false,
|
|
184
|
+
mcpAccessToken: null,
|
|
185
|
+
setMcpAccessToken: () => { },
|
|
186
|
+
} },
|
|
187
|
+
React.createElement(TamboRegistryProvider, { mcpServers: ["https://a.example"] },
|
|
188
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
189
|
+
React.createElement(TamboMcpProvider, null,
|
|
190
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))))));
|
|
162
191
|
// Wait for initial connection
|
|
163
192
|
await waitFor(() => {
|
|
164
193
|
expect(latest.length).toBe(1);
|
|
165
194
|
});
|
|
166
195
|
// Add new server
|
|
167
|
-
rerender(React.createElement(
|
|
168
|
-
|
|
169
|
-
|
|
196
|
+
rerender(React.createElement(TamboClientContext.Provider, { value: {
|
|
197
|
+
client: useTamboClient(),
|
|
198
|
+
queryClient: {},
|
|
199
|
+
isUpdatingToken: false,
|
|
200
|
+
mcpAccessToken: null,
|
|
201
|
+
setMcpAccessToken: () => { },
|
|
202
|
+
} },
|
|
203
|
+
React.createElement(TamboRegistryProvider, { mcpServers: ["https://a.example", "https://b.example"] },
|
|
204
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
205
|
+
React.createElement(TamboMcpProvider, null,
|
|
206
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))))));
|
|
170
207
|
await waitFor(() => {
|
|
171
208
|
expect(latest.length).toBe(2);
|
|
172
209
|
const urls = getByTestId("urls").textContent || "";
|
|
@@ -176,16 +213,32 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
176
213
|
});
|
|
177
214
|
it("removes a server when the list shrinks", async () => {
|
|
178
215
|
let latest = [];
|
|
179
|
-
const { rerender, getByTestId } = render(React.createElement(
|
|
180
|
-
|
|
181
|
-
|
|
216
|
+
const { rerender, getByTestId } = render(React.createElement(TamboClientContext.Provider, { value: {
|
|
217
|
+
client: useTamboClient(),
|
|
218
|
+
queryClient: {},
|
|
219
|
+
isUpdatingToken: false,
|
|
220
|
+
mcpAccessToken: null,
|
|
221
|
+
setMcpAccessToken: () => { },
|
|
222
|
+
} },
|
|
223
|
+
React.createElement(TamboRegistryProvider, { mcpServers: ["https://a.example", "https://b.example"] },
|
|
224
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
225
|
+
React.createElement(TamboMcpProvider, null,
|
|
226
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))))));
|
|
182
227
|
await waitFor(() => {
|
|
183
228
|
expect(latest.length).toBe(2);
|
|
184
229
|
});
|
|
185
230
|
// Remove one server
|
|
186
|
-
rerender(React.createElement(
|
|
187
|
-
|
|
188
|
-
|
|
231
|
+
rerender(React.createElement(TamboClientContext.Provider, { value: {
|
|
232
|
+
client: useTamboClient(),
|
|
233
|
+
queryClient: {},
|
|
234
|
+
isUpdatingToken: false,
|
|
235
|
+
mcpAccessToken: null,
|
|
236
|
+
setMcpAccessToken: () => { },
|
|
237
|
+
} },
|
|
238
|
+
React.createElement(TamboRegistryProvider, { mcpServers: ["https://a.example"] },
|
|
239
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
240
|
+
React.createElement(TamboMcpProvider, null,
|
|
241
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))))));
|
|
189
242
|
await waitFor(() => {
|
|
190
243
|
expect(latest.length).toBe(1);
|
|
191
244
|
const urls = getByTestId("urls").textContent || "";
|
|
@@ -199,9 +252,8 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
199
252
|
{ url: "https://a.example", transport: MCPTransport.SSE },
|
|
200
253
|
{ url: "https://b.example", transport: MCPTransport.SSE },
|
|
201
254
|
];
|
|
202
|
-
const { rerender } = render(React.createElement(
|
|
203
|
-
React.createElement(
|
|
204
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
255
|
+
const { rerender } = render(React.createElement(TestWrapper, { mcpServers: initial },
|
|
256
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
205
257
|
await waitFor(() => {
|
|
206
258
|
expect(latest.length).toBe(2);
|
|
207
259
|
});
|
|
@@ -210,9 +262,8 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
210
262
|
{ url: "https://a.example", transport: MCPTransport.SSE },
|
|
211
263
|
{ url: "https://b.example", transport: MCPTransport.SSE },
|
|
212
264
|
];
|
|
213
|
-
rerender(React.createElement(
|
|
214
|
-
React.createElement(
|
|
215
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
265
|
+
rerender(React.createElement(TestWrapper, { mcpServers: same },
|
|
266
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
216
267
|
await waitFor(() => {
|
|
217
268
|
expect(latest.length).toBe(2);
|
|
218
269
|
const urls = latest.map((s) => s.url).sort();
|
|
@@ -227,9 +278,8 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
227
278
|
MCPClient.create = createSpy;
|
|
228
279
|
let latest = [];
|
|
229
280
|
const initial = [{ url: "https://a.example", transport: MCPTransport.SSE }];
|
|
230
|
-
const { rerender } = render(React.createElement(
|
|
231
|
-
React.createElement(
|
|
232
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
281
|
+
const { rerender } = render(React.createElement(TestWrapper, { mcpServers: initial },
|
|
282
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
233
283
|
await waitFor(() => {
|
|
234
284
|
expect(latest.length).toBe(1);
|
|
235
285
|
});
|
|
@@ -238,9 +288,8 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
238
288
|
const firstClient = latest[0].client;
|
|
239
289
|
// Pass a new array with same server
|
|
240
290
|
const same = [{ url: "https://a.example", transport: MCPTransport.SSE }];
|
|
241
|
-
rerender(React.createElement(
|
|
242
|
-
React.createElement(
|
|
243
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
291
|
+
rerender(React.createElement(TestWrapper, { mcpServers: same },
|
|
292
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
244
293
|
await waitFor(() => {
|
|
245
294
|
expect(latest.length).toBe(1);
|
|
246
295
|
});
|
|
@@ -257,17 +306,33 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
257
306
|
});
|
|
258
307
|
MCPClient.create = createSpy;
|
|
259
308
|
let latest = [];
|
|
260
|
-
const { rerender } = render(React.createElement(
|
|
261
|
-
|
|
262
|
-
|
|
309
|
+
const { rerender } = render(React.createElement(TamboClientContext.Provider, { value: {
|
|
310
|
+
client: useTamboClient(),
|
|
311
|
+
queryClient: {},
|
|
312
|
+
isUpdatingToken: false,
|
|
313
|
+
mcpAccessToken: null,
|
|
314
|
+
setMcpAccessToken: () => { },
|
|
315
|
+
} },
|
|
316
|
+
React.createElement(TamboRegistryProvider, { mcpServers: ["https://a.example", "https://b.example"] },
|
|
317
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
318
|
+
React.createElement(TamboMcpProvider, null,
|
|
319
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))))));
|
|
263
320
|
await waitFor(() => {
|
|
264
321
|
expect(latest.length).toBe(2);
|
|
265
322
|
});
|
|
266
323
|
expect(closeSpy).not.toHaveBeenCalled();
|
|
267
324
|
// Remove one server
|
|
268
|
-
rerender(React.createElement(
|
|
269
|
-
|
|
270
|
-
|
|
325
|
+
rerender(React.createElement(TamboClientContext.Provider, { value: {
|
|
326
|
+
client: useTamboClient(),
|
|
327
|
+
queryClient: {},
|
|
328
|
+
isUpdatingToken: false,
|
|
329
|
+
mcpAccessToken: null,
|
|
330
|
+
setMcpAccessToken: () => { },
|
|
331
|
+
} },
|
|
332
|
+
React.createElement(TamboRegistryProvider, { mcpServers: ["https://a.example"] },
|
|
333
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
334
|
+
React.createElement(TamboMcpProvider, null,
|
|
335
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))))));
|
|
271
336
|
await waitFor(() => {
|
|
272
337
|
expect(latest.length).toBe(1);
|
|
273
338
|
});
|
|
@@ -282,9 +347,17 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
282
347
|
});
|
|
283
348
|
MCPClient.create = createSpy;
|
|
284
349
|
let latest = [];
|
|
285
|
-
const { unmount } = render(React.createElement(
|
|
286
|
-
|
|
287
|
-
|
|
350
|
+
const { unmount } = render(React.createElement(TamboClientContext.Provider, { value: {
|
|
351
|
+
client: useTamboClient(),
|
|
352
|
+
queryClient: {},
|
|
353
|
+
isUpdatingToken: false,
|
|
354
|
+
mcpAccessToken: null,
|
|
355
|
+
setMcpAccessToken: () => { },
|
|
356
|
+
} },
|
|
357
|
+
React.createElement(TamboRegistryProvider, { mcpServers: ["https://a.example", "https://b.example"] },
|
|
358
|
+
React.createElement(TamboMcpTokenProvider, null,
|
|
359
|
+
React.createElement(TamboMcpProvider, null,
|
|
360
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))))));
|
|
288
361
|
await waitFor(() => {
|
|
289
362
|
expect(latest.length).toBe(2);
|
|
290
363
|
});
|
|
@@ -307,15 +380,14 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
307
380
|
});
|
|
308
381
|
MCPClient.create = createSpy;
|
|
309
382
|
let latest = [];
|
|
310
|
-
const { rerender } = render(React.createElement(
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
383
|
+
const { rerender } = render(React.createElement(TestWrapper, { mcpServers: [
|
|
384
|
+
{
|
|
385
|
+
url: "https://a.example",
|
|
386
|
+
transport: MCPTransport.SSE,
|
|
387
|
+
customHeaders: { Authorization: "Bearer token1" },
|
|
388
|
+
},
|
|
389
|
+
] },
|
|
390
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
319
391
|
await waitFor(() => {
|
|
320
392
|
expect(latest.length).toBe(1);
|
|
321
393
|
expect(createSpy).toHaveBeenCalledTimes(1);
|
|
@@ -323,15 +395,14 @@ describe("TamboMcpProvider server list changes", () => {
|
|
|
323
395
|
const firstClientId = latest[0].client?.id;
|
|
324
396
|
expect(firstClientId).toBe(1);
|
|
325
397
|
// Change the customHeaders
|
|
326
|
-
rerender(React.createElement(
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
398
|
+
rerender(React.createElement(TestWrapper, { mcpServers: [
|
|
399
|
+
{
|
|
400
|
+
url: "https://a.example",
|
|
401
|
+
transport: MCPTransport.SSE,
|
|
402
|
+
customHeaders: { Authorization: "Bearer token2" },
|
|
403
|
+
},
|
|
404
|
+
] },
|
|
405
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
335
406
|
// Wait for old client to be closed and new client to be created
|
|
336
407
|
await waitFor(() => {
|
|
337
408
|
expect(closeSpy).toHaveBeenCalledTimes(1);
|
|
@@ -383,13 +454,12 @@ describe("TamboMcpProvider handler support", () => {
|
|
|
383
454
|
elicitation: mockElicitationHandler,
|
|
384
455
|
};
|
|
385
456
|
let latest = [];
|
|
386
|
-
render(React.createElement(
|
|
387
|
-
React.createElement(
|
|
388
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
457
|
+
render(React.createElement(TestWrapper, { mcpServers: ["https://test.example"], handlers: handlers },
|
|
458
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
389
459
|
await waitFor(() => {
|
|
390
460
|
expect(latest.length).toBe(1);
|
|
391
461
|
});
|
|
392
|
-
// Verify MCPClient.create was called
|
|
462
|
+
// Verify MCPClient.create was called with an HTTP transport and wrapped handler
|
|
393
463
|
expect(createSpy).toHaveBeenCalledWith("https://test.example", MCPTransport.HTTP, undefined, undefined, undefined, expect.objectContaining({
|
|
394
464
|
elicitation: expect.any(Function),
|
|
395
465
|
}));
|
|
@@ -405,7 +475,7 @@ describe("TamboMcpProvider handler support", () => {
|
|
|
405
475
|
await passedHandlers.elicitation(mockRequest, mockExtra);
|
|
406
476
|
expect(mockElicitationHandler).toHaveBeenCalledWith(mockRequest, mockExtra, expect.objectContaining({
|
|
407
477
|
url: "https://test.example",
|
|
408
|
-
|
|
478
|
+
serverKey: "test",
|
|
409
479
|
}));
|
|
410
480
|
});
|
|
411
481
|
it("should pass provider-level sampling handler to MCPClient.create", async () => {
|
|
@@ -419,13 +489,12 @@ describe("TamboMcpProvider handler support", () => {
|
|
|
419
489
|
sampling: mockSamplingHandler,
|
|
420
490
|
};
|
|
421
491
|
let latest = [];
|
|
422
|
-
render(React.createElement(
|
|
423
|
-
React.createElement(
|
|
424
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
492
|
+
render(React.createElement(TestWrapper, { mcpServers: ["https://test.example"], handlers: handlers },
|
|
493
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
425
494
|
await waitFor(() => {
|
|
426
495
|
expect(latest.length).toBe(1);
|
|
427
496
|
});
|
|
428
|
-
// Verify MCPClient.create was called with sampling handler
|
|
497
|
+
// Verify MCPClient.create was called with HTTP transport and sampling handler
|
|
429
498
|
expect(createSpy).toHaveBeenCalledWith("https://test.example", MCPTransport.HTTP, undefined, undefined, undefined, expect.objectContaining({
|
|
430
499
|
sampling: expect.any(Function),
|
|
431
500
|
}));
|
|
@@ -442,7 +511,7 @@ describe("TamboMcpProvider handler support", () => {
|
|
|
442
511
|
await passedHandlers.sampling(mockRequest, mockExtra);
|
|
443
512
|
expect(mockSamplingHandler).toHaveBeenCalledWith(mockRequest, mockExtra, expect.objectContaining({
|
|
444
513
|
url: "https://test.example",
|
|
445
|
-
|
|
514
|
+
serverKey: "test",
|
|
446
515
|
}));
|
|
447
516
|
});
|
|
448
517
|
it("should allow per-server handlers to override provider-level handlers", async () => {
|
|
@@ -456,16 +525,15 @@ describe("TamboMcpProvider handler support", () => {
|
|
|
456
525
|
elicitation: providerElicitationHandler,
|
|
457
526
|
};
|
|
458
527
|
let latest = [];
|
|
459
|
-
render(React.createElement(
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
elicitation: serverElicitationHandler,
|
|
465
|
-
},
|
|
528
|
+
render(React.createElement(TestWrapper, { mcpServers: [
|
|
529
|
+
{
|
|
530
|
+
url: "https://test.example",
|
|
531
|
+
handlers: {
|
|
532
|
+
elicitation: serverElicitationHandler,
|
|
466
533
|
},
|
|
467
|
-
|
|
468
|
-
|
|
534
|
+
},
|
|
535
|
+
], handlers: handlers },
|
|
536
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
469
537
|
await waitFor(() => {
|
|
470
538
|
expect(latest.length).toBe(1);
|
|
471
539
|
});
|
|
@@ -481,12 +549,11 @@ describe("TamboMcpProvider handler support", () => {
|
|
|
481
549
|
elicitation: mockElicitationHandler,
|
|
482
550
|
};
|
|
483
551
|
let latest = [];
|
|
484
|
-
render(React.createElement(
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
552
|
+
render(React.createElement(TestWrapper, { mcpServers: [
|
|
553
|
+
{ url: "https://server-a.example", name: "Server A" },
|
|
554
|
+
{ url: "https://server-b.example", name: "Server B" },
|
|
555
|
+
], handlers: handlers },
|
|
556
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
490
557
|
await waitFor(() => {
|
|
491
558
|
expect(latest.length).toBe(2);
|
|
492
559
|
});
|
|
@@ -522,16 +589,14 @@ describe("TamboMcpProvider handler support", () => {
|
|
|
522
589
|
content: [{ type: "text", text: "updated" }],
|
|
523
590
|
});
|
|
524
591
|
let latest = [];
|
|
525
|
-
const { rerender } = render(React.createElement(
|
|
526
|
-
React.createElement(
|
|
527
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
592
|
+
const { rerender } = render(React.createElement(TestWrapper, { mcpServers: ["https://test.example"], handlers: { elicitation: initialHandler } },
|
|
593
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
528
594
|
await waitFor(() => {
|
|
529
595
|
expect(latest.length).toBe(1);
|
|
530
596
|
});
|
|
531
597
|
// Update the handlers
|
|
532
|
-
rerender(React.createElement(
|
|
533
|
-
React.createElement(
|
|
534
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
598
|
+
rerender(React.createElement(TestWrapper, { mcpServers: ["https://test.example"], handlers: { elicitation: updatedHandler } },
|
|
599
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
535
600
|
await waitFor(() => {
|
|
536
601
|
expect(mockClient.updateElicitationHandler).toHaveBeenCalled();
|
|
537
602
|
});
|
|
@@ -564,9 +629,8 @@ describe("TamboMcpProvider serverKey derivation and tool prefixing", () => {
|
|
|
564
629
|
close: jest.fn(),
|
|
565
630
|
});
|
|
566
631
|
let latest = [];
|
|
567
|
-
render(React.createElement(
|
|
568
|
-
React.createElement(
|
|
569
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
632
|
+
render(React.createElement(TestWrapper, { mcpServers: ["https://mcp.linear.app/mcp"] },
|
|
633
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
570
634
|
await waitFor(() => {
|
|
571
635
|
expect(latest.length).toBe(1);
|
|
572
636
|
expect(latest[0].serverKey).toBe("linear");
|
|
@@ -578,14 +642,13 @@ describe("TamboMcpProvider serverKey derivation and tool prefixing", () => {
|
|
|
578
642
|
close: jest.fn(),
|
|
579
643
|
});
|
|
580
644
|
let latest = [];
|
|
581
|
-
render(React.createElement(
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
645
|
+
render(React.createElement(TestWrapper, { mcpServers: [
|
|
646
|
+
{
|
|
647
|
+
url: "https://mcp.linear.app/mcp",
|
|
648
|
+
serverKey: "custom-key",
|
|
649
|
+
},
|
|
650
|
+
] },
|
|
651
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
589
652
|
await waitFor(() => {
|
|
590
653
|
expect(latest.length).toBe(1);
|
|
591
654
|
expect(latest[0].serverKey).toBe("custom-key");
|
|
@@ -605,9 +668,8 @@ describe("TamboMcpProvider serverKey derivation and tool prefixing", () => {
|
|
|
605
668
|
];
|
|
606
669
|
for (const { url, expected } of testCases) {
|
|
607
670
|
let latest = [];
|
|
608
|
-
const { unmount } = render(React.createElement(
|
|
609
|
-
React.createElement(
|
|
610
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
671
|
+
const { unmount } = render(React.createElement(TestWrapper, { mcpServers: [url] },
|
|
672
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
611
673
|
await waitFor(() => {
|
|
612
674
|
expect(latest.length).toBe(1);
|
|
613
675
|
expect(latest[0].serverKey).toBe(expected);
|
|
@@ -627,9 +689,8 @@ describe("TamboMcpProvider serverKey derivation and tool prefixing", () => {
|
|
|
627
689
|
close: jest.fn(),
|
|
628
690
|
});
|
|
629
691
|
let latest = [];
|
|
630
|
-
render(React.createElement(
|
|
631
|
-
React.createElement(
|
|
632
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
692
|
+
render(React.createElement(TestWrapper, { mcpServers: ["https://mcp.linear.app/mcp"] },
|
|
693
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
633
694
|
await waitFor(() => {
|
|
634
695
|
expect(latest.length).toBe(1);
|
|
635
696
|
expect(mockRegisterTool).toHaveBeenCalledWith(expect.objectContaining({
|
|
@@ -647,12 +708,8 @@ describe("TamboMcpProvider serverKey derivation and tool prefixing", () => {
|
|
|
647
708
|
close: jest.fn(),
|
|
648
709
|
});
|
|
649
710
|
let latest = [];
|
|
650
|
-
render(React.createElement(
|
|
651
|
-
React.createElement(
|
|
652
|
-
"https://mcp.linear.app/mcp",
|
|
653
|
-
"https://api.github.com",
|
|
654
|
-
] },
|
|
655
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
711
|
+
render(React.createElement(TestWrapper, { mcpServers: ["https://mcp.linear.app/mcp", "https://api.github.com"] },
|
|
712
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
656
713
|
await waitFor(() => {
|
|
657
714
|
expect(latest.length).toBe(2);
|
|
658
715
|
// Check that tools are registered with prefixed names
|
|
@@ -676,15 +733,14 @@ describe("TamboMcpProvider serverKey derivation and tool prefixing", () => {
|
|
|
676
733
|
close: jest.fn(),
|
|
677
734
|
});
|
|
678
735
|
let latest = [];
|
|
679
|
-
render(React.createElement(
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
React.createElement(Capture, { onUpdate: (s) => (latest = s) }))));
|
|
736
|
+
render(React.createElement(TestWrapper, { mcpServers: [
|
|
737
|
+
{
|
|
738
|
+
url: "https://mcp.linear.app/mcp",
|
|
739
|
+
serverKey: "my-server",
|
|
740
|
+
},
|
|
741
|
+
"https://api.github.com",
|
|
742
|
+
] },
|
|
743
|
+
React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
|
|
688
744
|
await waitFor(() => {
|
|
689
745
|
expect(latest.length).toBe(2);
|
|
690
746
|
const calls = mockRegisterTool.mock.calls;
|