@tambo-ai/react 0.49.0 → 0.53.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/__tests__/use-component-state.test.js +4 -1
- package/dist/hooks/__tests__/use-component-state.test.js.map +1 -1
- package/dist/hooks/__tests__/use-message-images.test.d.ts +2 -0
- package/dist/hooks/__tests__/use-message-images.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/use-message-images.test.js +66 -0
- package/dist/hooks/__tests__/use-message-images.test.js.map +1 -0
- package/dist/hooks/__tests__/use-tambo-threads.test.js +1 -1
- package/dist/hooks/__tests__/use-tambo-threads.test.js.map +1 -1
- package/dist/hooks/use-component-state.js +3 -3
- package/dist/hooks/use-component-state.js.map +1 -1
- package/dist/hooks/use-message-images.d.ts +25 -0
- package/dist/hooks/use-message-images.d.ts.map +1 -0
- package/dist/hooks/use-message-images.js +66 -0
- package/dist/hooks/use-message-images.js.map +1 -0
- package/dist/hooks/use-suggestions.js +4 -2
- package/dist/hooks/use-suggestions.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/__tests__/mcp-client.test.d.ts +2 -0
- package/dist/mcp/__tests__/mcp-client.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/mcp-client.test.js +502 -0
- package/dist/mcp/__tests__/mcp-client.test.js.map +1 -0
- package/dist/mcp/mcp-client.d.ts +77 -3
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +184 -19
- package/dist/mcp/mcp-client.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts +1 -0
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +1 -0
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/tambo-interactable.d.ts +1 -1
- package/dist/model/tambo-interactable.d.ts.map +1 -1
- package/dist/model/tambo-interactable.js.map +1 -1
- package/dist/providers/__tests__/tambo-interactable-provider-partial-updates.test.d.ts +2 -0
- package/dist/providers/__tests__/tambo-interactable-provider-partial-updates.test.d.ts.map +1 -0
- package/dist/providers/__tests__/tambo-interactable-provider-partial-updates.test.js +677 -0
- package/dist/providers/__tests__/tambo-interactable-provider-partial-updates.test.js.map +1 -0
- package/dist/providers/__tests__/tambo-stubs.test.js +6 -2
- package/dist/providers/__tests__/tambo-stubs.test.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider.test.js +14 -14
- package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +26 -24
- package/dist/providers/tambo-interactable-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 +1 -0
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +11 -0
- package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-input-provider.js +63 -12
- package/dist/providers/tambo-thread-input-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts +1 -0
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +9 -5
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/setupTests.d.ts +0 -1
- package/dist/setupTests.d.ts.map +1 -1
- package/dist/setupTests.js +0 -1
- package/dist/setupTests.js.map +1 -1
- package/dist/util/__tests__/message-builder.test.d.ts +2 -0
- package/dist/util/__tests__/message-builder.test.d.ts.map +1 -0
- package/dist/util/__tests__/message-builder.test.js +191 -0
- package/dist/util/__tests__/message-builder.test.js.map +1 -0
- package/dist/util/message-builder.d.ts +10 -0
- package/dist/util/message-builder.d.ts.map +1 -0
- package/dist/util/message-builder.js +31 -0
- package/dist/util/message-builder.js.map +1 -0
- package/esm/hooks/__tests__/use-component-state.test.js +4 -1
- package/esm/hooks/__tests__/use-component-state.test.js.map +1 -1
- package/esm/hooks/__tests__/use-message-images.test.d.ts +2 -0
- package/esm/hooks/__tests__/use-message-images.test.d.ts.map +1 -0
- package/esm/hooks/__tests__/use-message-images.test.js +64 -0
- package/esm/hooks/__tests__/use-message-images.test.js.map +1 -0
- package/esm/hooks/__tests__/use-tambo-threads.test.js +1 -1
- package/esm/hooks/__tests__/use-tambo-threads.test.js.map +1 -1
- package/esm/hooks/use-component-state.js +3 -3
- package/esm/hooks/use-component-state.js.map +1 -1
- package/esm/hooks/use-message-images.d.ts +25 -0
- package/esm/hooks/use-message-images.d.ts.map +1 -0
- package/esm/hooks/use-message-images.js +63 -0
- package/esm/hooks/use-message-images.js.map +1 -0
- package/esm/hooks/use-suggestions.js +4 -2
- package/esm/hooks/use-suggestions.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/mcp/__tests__/mcp-client.test.d.ts +2 -0
- package/esm/mcp/__tests__/mcp-client.test.d.ts.map +1 -0
- package/esm/mcp/__tests__/mcp-client.test.js +500 -0
- package/esm/mcp/__tests__/mcp-client.test.js.map +1 -0
- package/esm/mcp/mcp-client.d.ts +77 -3
- package/esm/mcp/mcp-client.d.ts.map +1 -1
- package/esm/mcp/mcp-client.js +184 -19
- package/esm/mcp/mcp-client.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts +1 -0
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +1 -0
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/tambo-interactable.d.ts +1 -1
- package/esm/model/tambo-interactable.d.ts.map +1 -1
- package/esm/model/tambo-interactable.js.map +1 -1
- package/esm/providers/__tests__/tambo-interactable-provider-partial-updates.test.d.ts +2 -0
- package/esm/providers/__tests__/tambo-interactable-provider-partial-updates.test.d.ts.map +1 -0
- package/esm/providers/__tests__/tambo-interactable-provider-partial-updates.test.js +672 -0
- package/esm/providers/__tests__/tambo-interactable-provider-partial-updates.test.js.map +1 -0
- package/esm/providers/__tests__/tambo-stubs.test.js +6 -2
- package/esm/providers/__tests__/tambo-stubs.test.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider.test.js +14 -14
- package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +26 -24
- package/esm/providers/tambo-interactable-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 +1 -0
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +11 -0
- package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-input-provider.js +63 -12
- package/esm/providers/tambo-thread-input-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts +1 -0
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +9 -5
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/setupTests.d.ts +0 -1
- package/esm/setupTests.d.ts.map +1 -1
- package/esm/setupTests.js +0 -1
- package/esm/setupTests.js.map +1 -1
- package/esm/util/__tests__/message-builder.test.d.ts +2 -0
- package/esm/util/__tests__/message-builder.test.d.ts.map +1 -0
- package/esm/util/__tests__/message-builder.test.js +189 -0
- package/esm/util/__tests__/message-builder.test.js.map +1 -0
- package/esm/util/message-builder.d.ts +10 -0
- package/esm/util/message-builder.d.ts.map +1 -0
- package/esm/util/message-builder.js +28 -0
- package/esm/util/message-builder.js.map +1 -0
- package/package.json +7 -7
package/dist/mcp/mcp-client.d.ts
CHANGED
|
@@ -16,10 +16,48 @@ export declare enum MCPTransport {
|
|
|
16
16
|
export declare class MCPClient {
|
|
17
17
|
private client;
|
|
18
18
|
private transport;
|
|
19
|
+
private transportType;
|
|
20
|
+
private endpoint;
|
|
21
|
+
private headers;
|
|
22
|
+
/**
|
|
23
|
+
* Tracks an in-flight reconnect so concurrent triggers coalesce
|
|
24
|
+
* (single-flight). When set, additional calls to `reconnect()` or
|
|
25
|
+
* the automatic `onclose` handler will await the same Promise instead of
|
|
26
|
+
* starting another reconnect sequence.
|
|
27
|
+
*/
|
|
28
|
+
private reconnecting?;
|
|
29
|
+
/**
|
|
30
|
+
* Timer id for a scheduled automatic reconnect (used by `onclose`).
|
|
31
|
+
* Present only while waiting for the backoff delay to elapse.
|
|
32
|
+
*/
|
|
33
|
+
private reconnectTimer?;
|
|
34
|
+
/**
|
|
35
|
+
* Count of consecutive automatic reconnect failures used to compute
|
|
36
|
+
* exponential backoff. Reset to 0 after a successful connection.
|
|
37
|
+
*/
|
|
38
|
+
private backoffAttempts;
|
|
39
|
+
/**
|
|
40
|
+
* Backoff policy (discoverable constants)
|
|
41
|
+
* - BACKOFF_INITIAL_MS: initial delay for the first automatic retry
|
|
42
|
+
* - BACKOFF_MULTIPLIER: exponential growth factor for each failed attempt
|
|
43
|
+
* - BACKOFF_MAX_MS: upper bound for the delay
|
|
44
|
+
* - BACKOFF_JITTER_RATIO: jitter range as a fraction of the base delay
|
|
45
|
+
*
|
|
46
|
+
* Jitter is applied symmetrically in [-ratio, +ratio]. For example, with a
|
|
47
|
+
* 500ms base delay and 0.2 ratio, the actual delay is in [400ms, 600ms].
|
|
48
|
+
*
|
|
49
|
+
* The backoff applies only to automatic reconnects started from the
|
|
50
|
+
* `onclose` handler. Explicit/manual calls to `reconnect()` run immediately
|
|
51
|
+
* (no backoff), and will preempt any scheduled automatic attempt.
|
|
52
|
+
*/
|
|
53
|
+
static readonly BACKOFF_INITIAL_MS = 500;
|
|
54
|
+
static readonly BACKOFF_MULTIPLIER = 2;
|
|
55
|
+
static readonly BACKOFF_MAX_MS = 30000;
|
|
56
|
+
static readonly BACKOFF_JITTER_RATIO = 0.2;
|
|
19
57
|
/**
|
|
20
58
|
* Private constructor to enforce using the static create method.
|
|
21
59
|
* @param endpoint - The URL of the MCP server to connect to
|
|
22
|
-
* @param
|
|
60
|
+
* @param transportType - The transport to use for the MCP client
|
|
23
61
|
* @param headers - Optional custom headers to include in requests
|
|
24
62
|
*/
|
|
25
63
|
private constructor();
|
|
@@ -28,12 +66,48 @@ export declare class MCPClient {
|
|
|
28
66
|
* This is the recommended way to create an MCPClient as it handles both
|
|
29
67
|
* instantiation and connection setup.
|
|
30
68
|
* @param endpoint - The URL of the MCP server to connect to
|
|
31
|
-
* @param
|
|
69
|
+
* @param transportType - The transport type to use for the MCP client. Defaults to HTTP.
|
|
32
70
|
* @param headers - Optional custom headers to include in requests
|
|
33
71
|
* @returns A connected MCPClient instance ready for use
|
|
34
72
|
* @throws Will throw an error if connection fails
|
|
35
73
|
*/
|
|
36
|
-
static create(endpoint: string,
|
|
74
|
+
static create(endpoint: string, transportType?: MCPTransport, headers?: Record<string, string>): Promise<MCPClient>;
|
|
75
|
+
/**
|
|
76
|
+
* Reconnects to the MCP server, optionally retaining the same session ID.
|
|
77
|
+
*
|
|
78
|
+
* Single‑flight semantics:
|
|
79
|
+
* - If a reconnect is already in progress (triggered either manually or by
|
|
80
|
+
* the automatic `onclose` handler), additional calls will await the
|
|
81
|
+
* in-flight reconnect rather than start another one.
|
|
82
|
+
* - If an automatic reconnect has been scheduled but not yet started (i.e.,
|
|
83
|
+
* we are waiting in a backoff delay), calling `reconnect()` manually will
|
|
84
|
+
* cancel the scheduled attempt and perform an immediate reconnect.
|
|
85
|
+
*
|
|
86
|
+
* Backoff policy:
|
|
87
|
+
* - Backoff delays with jitter are applied only for automatic reconnects
|
|
88
|
+
* (via `onclose`). Manual calls to `reconnect()` do not use backoff.
|
|
89
|
+
* @param newSession - Whether to create a new session (true) or reuse existing session ID (false)
|
|
90
|
+
* @param reportErrorOnClose - Whether to report errors when closing the client
|
|
91
|
+
* Note that only StreamableHTTPClientTransport supports session IDs.
|
|
92
|
+
*/
|
|
93
|
+
reconnect(newSession?: boolean, reportErrorOnClose?: boolean): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Called by the underlying MCP SDK when the connection closes.
|
|
96
|
+
* Schedules an automatic reconnect with bounded exponential backoff and
|
|
97
|
+
* jitter. If a reconnect is already scheduled or running, this is a no-op.
|
|
98
|
+
*/
|
|
99
|
+
private onclose;
|
|
100
|
+
/**
|
|
101
|
+
* Compute the next backoff delay with symmetric jitter.
|
|
102
|
+
*/
|
|
103
|
+
private computeBackoffDelayMs;
|
|
104
|
+
/**
|
|
105
|
+
* Schedule an automatic reconnect attempt if one is not already scheduled
|
|
106
|
+
* or running. Uses the backoff policy and self-reschedules on failure.
|
|
107
|
+
*/
|
|
108
|
+
private scheduleAutoReconnect;
|
|
109
|
+
private initializeTransport;
|
|
110
|
+
private initializeClient;
|
|
37
111
|
/**
|
|
38
112
|
* Retrieves a complete list of all available tools from the MCP server.
|
|
39
113
|
* Handles pagination automatically by following cursors until all tools are fetched.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,oBAAY,YAAY;IACtB,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;AACD;;;;;;;;;GASG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAqD;
|
|
1
|
+
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,oBAAY,YAAY;IACtB,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;AACD;;;;;;;;;GASG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAqD;IACtE,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAyB;IACxC;;;;;OAKG;IACH,OAAO,CAAC,YAAY,CAAC,CAAgB;IACrC;;;OAGG;IACH,OAAO,CAAC,cAAc,CAAC,CAAgC;IACvD;;;OAGG;IACH,OAAO,CAAC,eAAe,CAAK;IAE5B;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,OAAO;IACzC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,KAAK;IACvC,MAAM,CAAC,QAAQ,CAAC,cAAc,SAAU;IACxC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,OAAO;IAE3C;;;;;OAKG;IACH,OAAO;IAYP;;;;;;;;;OASG;WACU,MAAM,CACjB,QAAQ,EAAE,MAAM,EAChB,aAAa,GAAE,YAAgC,EAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAKrB;;;;;;;;;;;;;;;;;OAiBG;IACG,SAAS,CAAC,UAAU,UAAQ,EAAE,kBAAkB,UAAO;IAmD7D;;;;OAIG;IACH,OAAO,CAAC,OAAO;IAIf;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAY7B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,gBAAgB;IASxB;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAiCzC;;;;;;OAMG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAO3D;AASD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B"}
|
package/dist/mcp/mcp-client.js
CHANGED
|
@@ -22,43 +22,208 @@ var MCPTransport;
|
|
|
22
22
|
class MCPClient {
|
|
23
23
|
client;
|
|
24
24
|
transport;
|
|
25
|
+
transportType;
|
|
26
|
+
endpoint;
|
|
27
|
+
headers;
|
|
28
|
+
/**
|
|
29
|
+
* Tracks an in-flight reconnect so concurrent triggers coalesce
|
|
30
|
+
* (single-flight). When set, additional calls to `reconnect()` or
|
|
31
|
+
* the automatic `onclose` handler will await the same Promise instead of
|
|
32
|
+
* starting another reconnect sequence.
|
|
33
|
+
*/
|
|
34
|
+
reconnecting;
|
|
35
|
+
/**
|
|
36
|
+
* Timer id for a scheduled automatic reconnect (used by `onclose`).
|
|
37
|
+
* Present only while waiting for the backoff delay to elapse.
|
|
38
|
+
*/
|
|
39
|
+
reconnectTimer;
|
|
40
|
+
/**
|
|
41
|
+
* Count of consecutive automatic reconnect failures used to compute
|
|
42
|
+
* exponential backoff. Reset to 0 after a successful connection.
|
|
43
|
+
*/
|
|
44
|
+
backoffAttempts = 0;
|
|
45
|
+
/**
|
|
46
|
+
* Backoff policy (discoverable constants)
|
|
47
|
+
* - BACKOFF_INITIAL_MS: initial delay for the first automatic retry
|
|
48
|
+
* - BACKOFF_MULTIPLIER: exponential growth factor for each failed attempt
|
|
49
|
+
* - BACKOFF_MAX_MS: upper bound for the delay
|
|
50
|
+
* - BACKOFF_JITTER_RATIO: jitter range as a fraction of the base delay
|
|
51
|
+
*
|
|
52
|
+
* Jitter is applied symmetrically in [-ratio, +ratio]. For example, with a
|
|
53
|
+
* 500ms base delay and 0.2 ratio, the actual delay is in [400ms, 600ms].
|
|
54
|
+
*
|
|
55
|
+
* The backoff applies only to automatic reconnects started from the
|
|
56
|
+
* `onclose` handler. Explicit/manual calls to `reconnect()` run immediately
|
|
57
|
+
* (no backoff), and will preempt any scheduled automatic attempt.
|
|
58
|
+
*/
|
|
59
|
+
static BACKOFF_INITIAL_MS = 500;
|
|
60
|
+
static BACKOFF_MULTIPLIER = 2;
|
|
61
|
+
static BACKOFF_MAX_MS = 30_000;
|
|
62
|
+
static BACKOFF_JITTER_RATIO = 0.2;
|
|
25
63
|
/**
|
|
26
64
|
* Private constructor to enforce using the static create method.
|
|
27
65
|
* @param endpoint - The URL of the MCP server to connect to
|
|
28
|
-
* @param
|
|
66
|
+
* @param transportType - The transport to use for the MCP client
|
|
29
67
|
* @param headers - Optional custom headers to include in requests
|
|
30
68
|
*/
|
|
31
|
-
constructor(endpoint,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
else {
|
|
38
|
-
this.transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(endpoint), {
|
|
39
|
-
requestInit: { headers },
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
this.client = new index_js_1.Client({
|
|
43
|
-
name: "tambo-mcp-client",
|
|
44
|
-
version: "1.0.0",
|
|
45
|
-
});
|
|
69
|
+
constructor(endpoint, transportType, headers = {}) {
|
|
70
|
+
this.endpoint = endpoint;
|
|
71
|
+
this.headers = headers;
|
|
72
|
+
this.transportType = transportType;
|
|
73
|
+
this.transport = this.initializeTransport(undefined);
|
|
74
|
+
this.client = this.initializeClient();
|
|
46
75
|
}
|
|
47
76
|
/**
|
|
48
77
|
* Creates and initializes a new MCPClient instance.
|
|
49
78
|
* This is the recommended way to create an MCPClient as it handles both
|
|
50
79
|
* instantiation and connection setup.
|
|
51
80
|
* @param endpoint - The URL of the MCP server to connect to
|
|
52
|
-
* @param
|
|
81
|
+
* @param transportType - The transport type to use for the MCP client. Defaults to HTTP.
|
|
53
82
|
* @param headers - Optional custom headers to include in requests
|
|
54
83
|
* @returns A connected MCPClient instance ready for use
|
|
55
84
|
* @throws Will throw an error if connection fails
|
|
56
85
|
*/
|
|
57
|
-
static async create(endpoint,
|
|
58
|
-
const mcpClient = new MCPClient(endpoint,
|
|
86
|
+
static async create(endpoint, transportType = MCPTransport.HTTP, headers) {
|
|
87
|
+
const mcpClient = new MCPClient(endpoint, transportType, headers);
|
|
59
88
|
await mcpClient.client.connect(mcpClient.transport);
|
|
60
89
|
return mcpClient;
|
|
61
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Reconnects to the MCP server, optionally retaining the same session ID.
|
|
93
|
+
*
|
|
94
|
+
* Single‑flight semantics:
|
|
95
|
+
* - If a reconnect is already in progress (triggered either manually or by
|
|
96
|
+
* the automatic `onclose` handler), additional calls will await the
|
|
97
|
+
* in-flight reconnect rather than start another one.
|
|
98
|
+
* - If an automatic reconnect has been scheduled but not yet started (i.e.,
|
|
99
|
+
* we are waiting in a backoff delay), calling `reconnect()` manually will
|
|
100
|
+
* cancel the scheduled attempt and perform an immediate reconnect.
|
|
101
|
+
*
|
|
102
|
+
* Backoff policy:
|
|
103
|
+
* - Backoff delays with jitter are applied only for automatic reconnects
|
|
104
|
+
* (via `onclose`). Manual calls to `reconnect()` do not use backoff.
|
|
105
|
+
* @param newSession - Whether to create a new session (true) or reuse existing session ID (false)
|
|
106
|
+
* @param reportErrorOnClose - Whether to report errors when closing the client
|
|
107
|
+
* Note that only StreamableHTTPClientTransport supports session IDs.
|
|
108
|
+
*/
|
|
109
|
+
async reconnect(newSession = false, reportErrorOnClose = true) {
|
|
110
|
+
// If a reconnect is already running, coalesce into it.
|
|
111
|
+
if (this.reconnecting) {
|
|
112
|
+
return await this.reconnecting;
|
|
113
|
+
}
|
|
114
|
+
// Manual reconnect preempts any scheduled automatic attempt.
|
|
115
|
+
if (this.reconnectTimer) {
|
|
116
|
+
clearTimeout(this.reconnectTimer);
|
|
117
|
+
this.reconnectTimer = undefined;
|
|
118
|
+
}
|
|
119
|
+
const doReconnect = async () => {
|
|
120
|
+
const sessionId = newSession
|
|
121
|
+
? undefined
|
|
122
|
+
: "sessionId" in this.transport
|
|
123
|
+
? this.transport.sessionId
|
|
124
|
+
: undefined;
|
|
125
|
+
// Prevent re-entrant onclose during deliberate close by detaching
|
|
126
|
+
// the handler from the previous client instance.
|
|
127
|
+
const prevClient = this.client;
|
|
128
|
+
// Prevent re-entrant onclose callbacks from the previous client
|
|
129
|
+
prevClient.onclose = undefined;
|
|
130
|
+
try {
|
|
131
|
+
await prevClient.close();
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (reportErrorOnClose) {
|
|
135
|
+
console.error("Error closing Tambo MCP Client:", error);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
this.transport = this.initializeTransport(sessionId);
|
|
139
|
+
this.client = this.initializeClient();
|
|
140
|
+
await this.client.connect(this.transport);
|
|
141
|
+
};
|
|
142
|
+
this.reconnecting = (async () => {
|
|
143
|
+
try {
|
|
144
|
+
await doReconnect();
|
|
145
|
+
// Successful manual reconnect: reset backoff.
|
|
146
|
+
this.backoffAttempts = 0;
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
this.reconnecting = undefined;
|
|
150
|
+
}
|
|
151
|
+
})();
|
|
152
|
+
return await this.reconnecting;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Called by the underlying MCP SDK when the connection closes.
|
|
156
|
+
* Schedules an automatic reconnect with bounded exponential backoff and
|
|
157
|
+
* jitter. If a reconnect is already scheduled or running, this is a no-op.
|
|
158
|
+
*/
|
|
159
|
+
onclose() {
|
|
160
|
+
this.scheduleAutoReconnect();
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Compute the next backoff delay with symmetric jitter.
|
|
164
|
+
*/
|
|
165
|
+
computeBackoffDelayMs() {
|
|
166
|
+
const base = Math.min(MCPClient.BACKOFF_MAX_MS, MCPClient.BACKOFF_INITIAL_MS *
|
|
167
|
+
Math.pow(MCPClient.BACKOFF_MULTIPLIER, this.backoffAttempts));
|
|
168
|
+
const jitterRange = MCPClient.BACKOFF_JITTER_RATIO * base;
|
|
169
|
+
const jitter = (Math.random() * 2 - 1) * jitterRange; // [-range, +range]
|
|
170
|
+
const ms = Math.max(0, Math.round(base + jitter));
|
|
171
|
+
return ms;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Schedule an automatic reconnect attempt if one is not already scheduled
|
|
175
|
+
* or running. Uses the backoff policy and self-reschedules on failure.
|
|
176
|
+
*/
|
|
177
|
+
scheduleAutoReconnect() {
|
|
178
|
+
if (this.reconnecting || this.reconnectTimer) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const delayMs = this.computeBackoffDelayMs();
|
|
182
|
+
console.warn("Tambo MCP Client closed; attempting automatic reconnect in", `${delayMs}ms`);
|
|
183
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
184
|
+
this.reconnectTimer = undefined;
|
|
185
|
+
// Start the actual reconnect (single-flight)
|
|
186
|
+
const inFlight = (this.reconnecting = this.reconnect(false, false));
|
|
187
|
+
try {
|
|
188
|
+
await inFlight;
|
|
189
|
+
// Success: reset attempts
|
|
190
|
+
this.backoffAttempts = 0;
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
// Failure: increase attempts; scheduling occurs in finally below so the
|
|
194
|
+
// new timer isn't blocked by `this.reconnecting` being truthy.
|
|
195
|
+
this.backoffAttempts += 1;
|
|
196
|
+
console.warn("Automatic reconnect failed; will retry with backoff.", err);
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
this.reconnecting = undefined;
|
|
200
|
+
if (this.backoffAttempts > 0) {
|
|
201
|
+
this.scheduleAutoReconnect();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}, delayMs);
|
|
205
|
+
}
|
|
206
|
+
initializeTransport(sessionId) {
|
|
207
|
+
if (this.transportType === MCPTransport.SSE) {
|
|
208
|
+
return new sse_js_1.SSEClientTransport(new URL(this.endpoint), {
|
|
209
|
+
requestInit: { headers: this.headers },
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
return new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(this.endpoint), {
|
|
214
|
+
sessionId,
|
|
215
|
+
requestInit: { headers: this.headers },
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
initializeClient() {
|
|
220
|
+
const client = new index_js_1.Client({
|
|
221
|
+
name: "tambo-mcp-client",
|
|
222
|
+
version: "1.0.0",
|
|
223
|
+
});
|
|
224
|
+
client.onclose = this.onclose.bind(this);
|
|
225
|
+
return client;
|
|
226
|
+
}
|
|
62
227
|
/**
|
|
63
228
|
* Retrieves a complete list of all available tools from the MCP server.
|
|
64
229
|
* Handles pagination automatically by following cursors until all tools are fetched.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../../src/mcp/mcp-client.ts"],"names":[],"mappings":";;;AAAA,wEAAmE;AACnE,oEAA6E;AAC7E,0FAAmG;AAGnG,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,2BAAW,CAAA;IACX,6BAAa,CAAA;AACf,CAAC,EAHW,YAAY,4BAAZ,YAAY,QAGvB;AACD;;;;;;;;;GASG;AACH,MAAa,SAAS;IACZ,MAAM,CAAS;IACf,SAAS,CAAqD;IAEtE;;;;;OAKG;IACH,YACE,QAAgB,EAChB,SAAuB,EACvB,OAAgC;QAEhC,IAAI,SAAS,KAAK,YAAY,CAAC,GAAG,EAAE,CAAC;YACnC,IAAI,CAAC,SAAS,GAAG,IAAI,2BAAkB,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE;gBACzD,WAAW,EAAE,EAAE,OAAO,EAAE;aACzB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,GAAG,IAAI,iDAA6B,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE;gBACpE,WAAW,EAAE,EAAE,OAAO,EAAE;aACzB,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,iBAAM,CAAC;YACvB,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CACjB,QAAgB,EAChB,YAA0B,YAAY,CAAC,IAAI,EAC3C,OAAgC;QAEhC,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9D,MAAM,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACpD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,QAAQ,GAAkB,EAAE,CAAC;QACnC,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,IAAI,MAAM,GAAuB,SAAS,CAAC;QAE3C,OAAO,OAAO,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;YAC7D,QAAQ,CAAC,IAAI,CACX,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAe,EAAE;gBAC1C,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACvC,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,CAAC,IAAI,mBAAmB,CACtD,CAAC;gBACJ,CAAC;gBAED,OAAO;oBACL,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,WAAW,EAAE,IAAI,CAAC,WAA0B;iBAC7C,CAAC;YACJ,CAAC,CAAC,CACH,CAAC;YAEF,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACxB,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,KAAK,CAAC;YAClB,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAA6B;QACxD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YACxC,IAAI;YACJ,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAvGD,8BAuGC","sourcesContent":["import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { JSONSchema7 } from \"json-schema\";\n\nexport enum MCPTransport {\n SSE = \"sse\",\n HTTP = \"http\",\n}\n/**\n * A client for interacting with MCP (Model Context Protocol) servers.\n * Provides a simple interface for listing and calling tools exposed by the server.\n * @example\n * ```typescript\n * const mcp = await MCPClient.create('https://api.example.com/mcp');\n * const tools = await mcp.listTools();\n * const result = await mcp.callTool('toolName', { arg1: 'value1' });\n * ```\n */\nexport class MCPClient {\n private client: Client;\n private transport: SSEClientTransport | StreamableHTTPClientTransport;\n\n /**\n * Private constructor to enforce using the static create method.\n * @param endpoint - The URL of the MCP server to connect to\n * @param transport - The transport to use for the MCP client\n * @param headers - Optional custom headers to include in requests\n */\n private constructor(\n endpoint: string,\n transport: MCPTransport,\n headers?: Record<string, string>,\n ) {\n if (transport === MCPTransport.SSE) {\n this.transport = new SSEClientTransport(new URL(endpoint), {\n requestInit: { headers },\n });\n } else {\n this.transport = new StreamableHTTPClientTransport(new URL(endpoint), {\n requestInit: { headers },\n });\n }\n this.client = new Client({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n }\n\n /**\n * Creates and initializes a new MCPClient instance.\n * This is the recommended way to create an MCPClient as it handles both\n * instantiation and connection setup.\n * @param endpoint - The URL of the MCP server to connect to\n * @param transport - The transport type to use for the MCP client. Defaults to HTTP.\n * @param headers - Optional custom headers to include in requests\n * @returns A connected MCPClient instance ready for use\n * @throws Will throw an error if connection fails\n */\n static async create(\n endpoint: string,\n transport: MCPTransport = MCPTransport.HTTP,\n headers?: Record<string, string>,\n ): Promise<MCPClient> {\n const mcpClient = new MCPClient(endpoint, transport, headers);\n await mcpClient.client.connect(mcpClient.transport);\n return mcpClient;\n }\n\n /**\n * Retrieves a complete list of all available tools from the MCP server.\n * Handles pagination automatically by following cursors until all tools are fetched.\n * @returns A complete list of all available tools and their descriptions\n * @throws Will throw an error if any server request fails during pagination\n */\n async listTools(): Promise<MCPToolSpec[]> {\n const allTools: MCPToolSpec[] = [];\n let hasMore = true;\n let cursor: string | undefined = undefined;\n\n while (hasMore) {\n const response = await this.client.listTools({ cursor }, {});\n allTools.push(\n ...response.tools.map((tool): MCPToolSpec => {\n if (tool.inputSchema.type !== \"object\") {\n throw new Error(\n `Input schema for tool ${tool.name} is not an object`,\n );\n }\n\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema as JSONSchema7,\n };\n }),\n );\n\n if (response.nextCursor) {\n cursor = response.nextCursor;\n } else {\n hasMore = false;\n }\n }\n\n return allTools;\n }\n\n /**\n * Calls a specific tool on the MCP server with the provided arguments.\n * @param name - The name of the tool to call\n * @param args - Arguments to pass to the tool, must match the tool's expected schema\n * @returns The result from the tool execution\n * @throws Will throw an error if the tool call fails or if arguments are invalid\n */\n async callTool(name: string, args: Record<string, unknown>) {\n const result = await this.client.callTool({\n name,\n arguments: args,\n });\n return result;\n }\n}\n\n// Example usage:\n/*\nconst mcp = await MCPClient.create('https://api.example.com/mcp', MCPTransport.HTTP);\nconst tools = await mcp.listTools();\nconst result = await mcp.callTool('toolName', { arg1: 'value1' });\n*/\n\nexport interface MCPToolSpec {\n name: string;\n description?: string;\n inputSchema?: JSONSchema7;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../../src/mcp/mcp-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { JSONSchema7 } from \"json-schema\";\n\nexport enum MCPTransport {\n SSE = \"sse\",\n HTTP = \"http\",\n}\n/**\n * A client for interacting with MCP (Model Context Protocol) servers.\n * Provides a simple interface for listing and calling tools exposed by the server.\n * @example\n * ```typescript\n * const mcp = await MCPClient.create('https://api.example.com/mcp');\n * const tools = await mcp.listTools();\n * const result = await mcp.callTool('toolName', { arg1: 'value1' });\n * ```\n */\nexport class MCPClient {\n private client: Client;\n private transport: SSEClientTransport | StreamableHTTPClientTransport;\n private transportType: MCPTransport;\n private endpoint: string;\n private headers: Record<string, string>;\n /**\n * Tracks an in-flight reconnect so concurrent triggers coalesce\n * (single-flight). When set, additional calls to `reconnect()` or\n * the automatic `onclose` handler will await the same Promise instead of\n * starting another reconnect sequence.\n */\n private reconnecting?: Promise<void>;\n /**\n * Timer id for a scheduled automatic reconnect (used by `onclose`).\n * Present only while waiting for the backoff delay to elapse.\n */\n private reconnectTimer?: ReturnType<typeof setTimeout>;\n /**\n * Count of consecutive automatic reconnect failures used to compute\n * exponential backoff. Reset to 0 after a successful connection.\n */\n private backoffAttempts = 0;\n\n /**\n * Backoff policy (discoverable constants)\n * - BACKOFF_INITIAL_MS: initial delay for the first automatic retry\n * - BACKOFF_MULTIPLIER: exponential growth factor for each failed attempt\n * - BACKOFF_MAX_MS: upper bound for the delay\n * - BACKOFF_JITTER_RATIO: jitter range as a fraction of the base delay\n *\n * Jitter is applied symmetrically in [-ratio, +ratio]. For example, with a\n * 500ms base delay and 0.2 ratio, the actual delay is in [400ms, 600ms].\n *\n * The backoff applies only to automatic reconnects started from the\n * `onclose` handler. Explicit/manual calls to `reconnect()` run immediately\n * (no backoff), and will preempt any scheduled automatic attempt.\n */\n static readonly BACKOFF_INITIAL_MS = 500;\n static readonly BACKOFF_MULTIPLIER = 2;\n static readonly BACKOFF_MAX_MS = 30_000;\n static readonly BACKOFF_JITTER_RATIO = 0.2;\n\n /**\n * Private constructor to enforce using the static create method.\n * @param endpoint - The URL of the MCP server to connect to\n * @param transportType - The transport to use for the MCP client\n * @param headers - Optional custom headers to include in requests\n */\n private constructor(\n endpoint: string,\n transportType: MCPTransport,\n headers: Record<string, string> = {},\n ) {\n this.endpoint = endpoint;\n this.headers = headers;\n this.transportType = transportType;\n this.transport = this.initializeTransport(undefined);\n this.client = this.initializeClient();\n }\n\n /**\n * Creates and initializes a new MCPClient instance.\n * This is the recommended way to create an MCPClient as it handles both\n * instantiation and connection setup.\n * @param endpoint - The URL of the MCP server to connect to\n * @param transportType - The transport type to use for the MCP client. Defaults to HTTP.\n * @param headers - Optional custom headers to include in requests\n * @returns A connected MCPClient instance ready for use\n * @throws Will throw an error if connection fails\n */\n static async create(\n endpoint: string,\n transportType: MCPTransport = MCPTransport.HTTP,\n headers?: Record<string, string>,\n ): Promise<MCPClient> {\n const mcpClient = new MCPClient(endpoint, transportType, headers);\n await mcpClient.client.connect(mcpClient.transport);\n return mcpClient;\n }\n /**\n * Reconnects to the MCP server, optionally retaining the same session ID.\n *\n * Single‑flight semantics:\n * - If a reconnect is already in progress (triggered either manually or by\n * the automatic `onclose` handler), additional calls will await the\n * in-flight reconnect rather than start another one.\n * - If an automatic reconnect has been scheduled but not yet started (i.e.,\n * we are waiting in a backoff delay), calling `reconnect()` manually will\n * cancel the scheduled attempt and perform an immediate reconnect.\n *\n * Backoff policy:\n * - Backoff delays with jitter are applied only for automatic reconnects\n * (via `onclose`). Manual calls to `reconnect()` do not use backoff.\n * @param newSession - Whether to create a new session (true) or reuse existing session ID (false)\n * @param reportErrorOnClose - Whether to report errors when closing the client\n * Note that only StreamableHTTPClientTransport supports session IDs.\n */\n async reconnect(newSession = false, reportErrorOnClose = true) {\n // If a reconnect is already running, coalesce into it.\n if (this.reconnecting) {\n return await this.reconnecting;\n }\n\n // Manual reconnect preempts any scheduled automatic attempt.\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n\n const doReconnect = async () => {\n const sessionId = newSession\n ? undefined\n : \"sessionId\" in this.transport\n ? this.transport.sessionId\n : undefined;\n\n // Prevent re-entrant onclose during deliberate close by detaching\n // the handler from the previous client instance.\n const prevClient = this.client;\n // Prevent re-entrant onclose callbacks from the previous client\n prevClient.onclose = undefined;\n\n try {\n await prevClient.close();\n } catch (error) {\n if (reportErrorOnClose) {\n console.error(\"Error closing Tambo MCP Client:\", error);\n }\n }\n\n this.transport = this.initializeTransport(sessionId);\n this.client = this.initializeClient();\n await this.client.connect(this.transport);\n };\n\n this.reconnecting = (async () => {\n try {\n await doReconnect();\n // Successful manual reconnect: reset backoff.\n this.backoffAttempts = 0;\n } finally {\n this.reconnecting = undefined;\n }\n })();\n\n return await this.reconnecting;\n }\n\n /**\n * Called by the underlying MCP SDK when the connection closes.\n * Schedules an automatic reconnect with bounded exponential backoff and\n * jitter. If a reconnect is already scheduled or running, this is a no-op.\n */\n private onclose() {\n this.scheduleAutoReconnect();\n }\n\n /**\n * Compute the next backoff delay with symmetric jitter.\n */\n private computeBackoffDelayMs(): number {\n const base = Math.min(\n MCPClient.BACKOFF_MAX_MS,\n MCPClient.BACKOFF_INITIAL_MS *\n Math.pow(MCPClient.BACKOFF_MULTIPLIER, this.backoffAttempts),\n );\n const jitterRange = MCPClient.BACKOFF_JITTER_RATIO * base;\n const jitter = (Math.random() * 2 - 1) * jitterRange; // [-range, +range]\n const ms = Math.max(0, Math.round(base + jitter));\n return ms;\n }\n\n /**\n * Schedule an automatic reconnect attempt if one is not already scheduled\n * or running. Uses the backoff policy and self-reschedules on failure.\n */\n private scheduleAutoReconnect() {\n if (this.reconnecting || this.reconnectTimer) {\n return;\n }\n\n const delayMs = this.computeBackoffDelayMs();\n console.warn(\n \"Tambo MCP Client closed; attempting automatic reconnect in\",\n `${delayMs}ms`,\n );\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = undefined;\n // Start the actual reconnect (single-flight)\n const inFlight = (this.reconnecting = this.reconnect(false, false));\n try {\n await inFlight;\n // Success: reset attempts\n this.backoffAttempts = 0;\n } catch (err) {\n // Failure: increase attempts; scheduling occurs in finally below so the\n // new timer isn't blocked by `this.reconnecting` being truthy.\n this.backoffAttempts += 1;\n console.warn(\n \"Automatic reconnect failed; will retry with backoff.\",\n err,\n );\n } finally {\n this.reconnecting = undefined;\n if (this.backoffAttempts > 0) {\n this.scheduleAutoReconnect();\n }\n }\n }, delayMs);\n }\n\n private initializeTransport(sessionId: string | undefined) {\n if (this.transportType === MCPTransport.SSE) {\n return new SSEClientTransport(new URL(this.endpoint), {\n requestInit: { headers: this.headers },\n });\n } else {\n return new StreamableHTTPClientTransport(new URL(this.endpoint), {\n sessionId,\n requestInit: { headers: this.headers },\n });\n }\n }\n\n private initializeClient() {\n const client = new Client({\n name: \"tambo-mcp-client\",\n version: \"1.0.0\",\n });\n client.onclose = this.onclose.bind(this);\n return client;\n }\n\n /**\n * Retrieves a complete list of all available tools from the MCP server.\n * Handles pagination automatically by following cursors until all tools are fetched.\n * @returns A complete list of all available tools and their descriptions\n * @throws Will throw an error if any server request fails during pagination\n */\n async listTools(): Promise<MCPToolSpec[]> {\n const allTools: MCPToolSpec[] = [];\n let hasMore = true;\n let cursor: string | undefined = undefined;\n\n while (hasMore) {\n const response = await this.client.listTools({ cursor }, {});\n allTools.push(\n ...response.tools.map((tool): MCPToolSpec => {\n if (tool.inputSchema.type !== \"object\") {\n throw new Error(\n `Input schema for tool ${tool.name} is not an object`,\n );\n }\n\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema as JSONSchema7,\n };\n }),\n );\n\n if (response.nextCursor) {\n cursor = response.nextCursor;\n } else {\n hasMore = false;\n }\n }\n\n return allTools;\n }\n\n /**\n * Calls a specific tool on the MCP server with the provided arguments.\n * @param name - The name of the tool to call\n * @param args - Arguments to pass to the tool, must match the tool's expected schema\n * @returns The result from the tool execution\n * @throws Will throw an error if the tool call fails or if arguments are invalid\n */\n async callTool(name: string, args: Record<string, unknown>) {\n const result = await this.client.callTool({\n name,\n arguments: args,\n });\n return result;\n }\n}\n\n// Example usage:\n/*\nconst mcp = await MCPClient.create('https://api.example.com/mcp', MCPTransport.HTTP);\nconst tools = await mcp.listTools();\nconst result = await mcp.callTool('toolName', { arg1: 'value1' });\n*/\n\nexport interface MCPToolSpec {\n name: string;\n description?: string;\n inputSchema?: JSONSchema7;\n}\n"]}
|
|
@@ -4,6 +4,7 @@ import { MCPTransport } from "./mcp-client";
|
|
|
4
4
|
* Extracts error message from MCP tool result content.
|
|
5
5
|
* Handles both array and string content formats.
|
|
6
6
|
* Always returns a string, even for invalid/null inputs.
|
|
7
|
+
* @returns The extracted error message as a string
|
|
7
8
|
*/
|
|
8
9
|
export declare function extractErrorMessage(content: unknown): string;
|
|
9
10
|
export interface McpServerInfo {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-mcp-provider.d.ts","sourceRoot":"","sources":["../../src/mcp/tambo-mcp-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAa,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvD
|
|
1
|
+
{"version":3,"file":"tambo-mcp-provider.d.ts","sourceRoot":"","sources":["../../src/mcp/tambo-mcp-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAa,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAsB5D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AACD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC;IAChC,UAAU,EAAE,CAAC,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC;IACvC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAkEA,CAAC"}
|
|
@@ -9,6 +9,7 @@ const mcp_client_1 = require("./mcp-client");
|
|
|
9
9
|
* Extracts error message from MCP tool result content.
|
|
10
10
|
* Handles both array and string content formats.
|
|
11
11
|
* Always returns a string, even for invalid/null inputs.
|
|
12
|
+
* @returns The extracted error message as a string
|
|
12
13
|
*/
|
|
13
14
|
function extractErrorMessage(content) {
|
|
14
15
|
if (content === undefined || content === null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-mcp-provider.js","sourceRoot":"","sources":["../../src/mcp/tambo-mcp-provider.tsx"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"tambo-mcp-provider.js","sourceRoot":"","sources":["../../src/mcp/tambo-mcp-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["import { FC, useEffect } from \"react\";\nimport { TamboTool } from \"../model/component-metadata\";\nimport { useTamboRegistry } from \"../providers/tambo-registry-provider\";\nimport { MCPClient, MCPTransport } from \"./mcp-client\";\n\n/**\n * Extracts error message from MCP tool result content.\n * Handles both array and string content formats.\n * Always returns a string, even for invalid/null inputs.\n * @returns The extracted error message as a string\n */\nexport function extractErrorMessage(content: unknown): string {\n if (content === undefined || content === null) {\n return \"Unknown error occurred\";\n }\n\n if (Array.isArray(content)) {\n const textItems = content\n .filter(\n (item) => item && item.type === \"text\" && typeof item.text === \"string\",\n )\n .map((item) => item.text);\n\n return textItems.length > 0\n ? textItems.join(\" \")\n : \"Error occurred but no details provided\";\n }\n\n if (typeof content === \"object\") {\n return JSON.stringify(content);\n }\n\n return `${content}`;\n}\n\nexport interface McpServerInfo {\n name?: string;\n url: string;\n description?: string;\n transport?: MCPTransport;\n customHeaders?: Record<string, string>;\n}\n/**\n * This provider is used to register tools from MCP servers.\n * @returns the wrapped children\n */\nexport const TamboMcpProvider: FC<{\n mcpServers: (McpServerInfo | string)[];\n children: React.ReactNode;\n}> = ({ mcpServers, children }) => {\n const { registerTool } = useTamboRegistry();\n\n useEffect(() => {\n if (!mcpServers) {\n return;\n }\n async function registerMcpServers(mcpServers: (McpServerInfo | string)[]) {\n // Maps tool names to the MCP client that registered them\n const mcpServerMap = new Map<string, MCPClient>();\n const serverToolLists = mcpServers.map(async (mcpServer) => {\n const server =\n typeof mcpServer === \"string\"\n ? { url: mcpServer, transport: MCPTransport.SSE }\n : mcpServer;\n const { url, transport = MCPTransport.SSE, customHeaders } = server;\n const mcpClient = await MCPClient.create(url, transport, customHeaders);\n const tools = await mcpClient.listTools();\n tools.forEach((tool) => {\n mcpServerMap.set(tool.name, mcpClient);\n });\n return tools;\n });\n const toolResults = await Promise.allSettled(serverToolLists);\n\n // Just log the failed tools, we can't do anything about them\n const failedTools = toolResults.filter(\n (result) => result.status === \"rejected\",\n );\n if (failedTools.length > 0) {\n console.error(\n \"Failed to register tools from MCP servers:\",\n failedTools.map((result) => result.reason),\n );\n }\n\n // Register the successful tools\n const allTools = toolResults\n .filter((result) => result.status === \"fulfilled\")\n .map((result) => result.value)\n .flat();\n allTools.forEach((tool) => {\n registerTool({\n description: tool.description ?? \"\",\n name: tool.name,\n tool: async (args: Record<string, unknown>) => {\n const mcpServer = mcpServerMap.get(tool.name);\n if (!mcpServer) {\n // should never happen\n throw new Error(`MCP server for tool ${tool.name} not found`);\n }\n const result = await mcpServer.callTool(tool.name, args);\n if (result.isError) {\n const errorMessage = extractErrorMessage(result.content);\n throw new Error(errorMessage);\n }\n return result.content;\n },\n toolSchema: tool.inputSchema as TamboTool[\"toolSchema\"],\n });\n });\n }\n registerMcpServers(mcpServers);\n }, [mcpServers, registerTool]);\n\n return children;\n};\n"]}
|
|
@@ -13,7 +13,7 @@ export interface TamboInteractableContext {
|
|
|
13
13
|
/** Remove an interactable component by ID */
|
|
14
14
|
removeInteractableComponent: (id: string) => void;
|
|
15
15
|
/** Update an interactable component's props */
|
|
16
|
-
updateInteractableComponentProps: (id: string, newProps: Record<string, any>) =>
|
|
16
|
+
updateInteractableComponentProps: (id: string, newProps: Record<string, any>) => string;
|
|
17
17
|
/** Get an interactable component by ID */
|
|
18
18
|
getInteractableComponent: (id: string) => TamboInteractableComponent | undefined;
|
|
19
19
|
/** Get all interactable components by component name */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-interactable.d.ts","sourceRoot":"","sources":["../../src/model/tambo-interactable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,0BAA2B,SAAQ,cAAc;IAChE,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,sBAAsB,EAAE,0BAA0B,EAAE,CAAC;IACrD,uCAAuC;IACvC,wBAAwB,EAAE,CACxB,SAAS,EAAE,IAAI,CAAC,0BAA0B,EAAE,IAAI,GAAG,WAAW,CAAC,KAC5D,MAAM,CAAC;IACZ,6CAA6C;IAC7C,2BAA2B,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,+CAA+C;IAC/C,gCAAgC,EAAE,CAChC,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAC1B,
|
|
1
|
+
{"version":3,"file":"tambo-interactable.d.ts","sourceRoot":"","sources":["../../src/model/tambo-interactable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,0BAA2B,SAAQ,cAAc;IAChE,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,sBAAsB,EAAE,0BAA0B,EAAE,CAAC;IACrD,uCAAuC;IACvC,wBAAwB,EAAE,CACxB,SAAS,EAAE,IAAI,CAAC,0BAA0B,EAAE,IAAI,GAAG,WAAW,CAAC,KAC5D,MAAM,CAAC;IACZ,6CAA6C;IAC7C,2BAA2B,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,+CAA+C;IAC/C,gCAAgC,EAAE,CAChC,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAC1B,MAAM,CAAC;IACZ,0CAA0C;IAC1C,wBAAwB,EAAE,CACxB,EAAE,EAAE,MAAM,KACP,0BAA0B,GAAG,SAAS,CAAC;IAC5C,wDAAwD;IACxD,+BAA+B,EAAE,CAC/B,aAAa,EAAE,MAAM,KAClB,0BAA0B,EAAE,CAAC;IAClC,wCAAwC;IACxC,8BAA8B,EAAE,MAAM,IAAI,CAAC;CAC5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-interactable.js","sourceRoot":"","sources":["../../src/model/tambo-interactable.ts"],"names":[],"mappings":"","sourcesContent":["import { TamboComponent } from \"./component-metadata\";\n\nexport interface TamboInteractableComponent extends TamboComponent {\n /** Unique identifier for this component instance */\n id: string;\n /** Current props for the component */\n props: Record<string, any>;\n}\n\nexport interface TamboInteractableContext {\n /** List of all interactable components */\n interactableComponents: TamboInteractableComponent[];\n /** Add a new interactable component */\n addInteractableComponent: (\n component: Omit<TamboInteractableComponent, \"id\" | \"createdAt\">,\n ) => string;\n /** Remove an interactable component by ID */\n removeInteractableComponent: (id: string) => void;\n /** Update an interactable component's props */\n updateInteractableComponentProps: (\n id: string,\n newProps: Record<string, any>,\n ) =>
|
|
1
|
+
{"version":3,"file":"tambo-interactable.js","sourceRoot":"","sources":["../../src/model/tambo-interactable.ts"],"names":[],"mappings":"","sourcesContent":["import { TamboComponent } from \"./component-metadata\";\n\nexport interface TamboInteractableComponent extends TamboComponent {\n /** Unique identifier for this component instance */\n id: string;\n /** Current props for the component */\n props: Record<string, any>;\n}\n\nexport interface TamboInteractableContext {\n /** List of all interactable components */\n interactableComponents: TamboInteractableComponent[];\n /** Add a new interactable component */\n addInteractableComponent: (\n component: Omit<TamboInteractableComponent, \"id\" | \"createdAt\">,\n ) => string;\n /** Remove an interactable component by ID */\n removeInteractableComponent: (id: string) => void;\n /** Update an interactable component's props */\n updateInteractableComponentProps: (\n id: string,\n newProps: Record<string, any>,\n ) => string;\n /** Get an interactable component by ID */\n getInteractableComponent: (\n id: string,\n ) => TamboInteractableComponent | undefined;\n /** Get all interactable components by component name */\n getInteractableComponentsByName: (\n componentName: string,\n ) => TamboInteractableComponent[];\n /** Clear all interactable components */\n clearAllInteractableComponents: () => void;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tambo-interactable-provider-partial-updates.test.d.ts","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-interactable-provider-partial-updates.test.tsx"],"names":[],"mappings":""}
|