agents 0.7.4 → 0.7.6
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/ai-chat-agent.js +3 -4
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.js +3 -4
- package/dist/ai-chat-v5-migration.js.map +1 -1
- package/dist/ai-react.js +3 -4
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.js +1 -2
- package/dist/ai-types.js.map +1 -1
- package/dist/cli/index.js +2 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/client-K8Z-u76l.js +1468 -0
- package/dist/client-K8Z-u76l.js.map +1 -0
- package/dist/client.js +1 -2
- package/dist/client.js.map +1 -1
- package/dist/codemode/ai.js +2 -2
- package/dist/do-oauth-client-provider-C2jurFjW.d.ts +78 -0
- package/dist/email-U_MG7UET.d.ts +157 -0
- package/dist/email.d.ts +16 -146
- package/dist/email.js +2 -2
- package/dist/email.js.map +1 -1
- package/dist/experimental/forever.d.ts +26 -71
- package/dist/experimental/forever.js +2 -3
- package/dist/experimental/forever.js.map +1 -1
- package/dist/experimental/memory/session/index.js +3 -12
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/workspace.d.ts +273 -0
- package/dist/experimental/workspace.js +1265 -0
- package/dist/experimental/workspace.js.map +1 -0
- package/dist/index-BS_jL8MI.d.ts +492 -0
- package/dist/index-WBy5hmm3.d.ts +2840 -0
- package/dist/index.d.ts +49 -1320
- package/dist/index.js +281 -138
- package/dist/index.js.map +1 -1
- package/dist/internal_context-DgcmHqS1.d.ts +37 -0
- package/dist/internal_context.d.ts +5 -32
- package/dist/internal_context.js +1 -2
- package/dist/internal_context.js.map +1 -1
- package/dist/mcp/client.d.ts +2 -575
- package/dist/mcp/client.js +1 -847
- package/dist/mcp/do-oauth-client-provider.d.ts +2 -61
- package/dist/mcp/do-oauth-client-provider.js +1 -2
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -95
- package/dist/mcp/index.js +60 -57
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.js +1 -2
- package/dist/mcp/x402.js.map +1 -1
- package/dist/observability/index.d.ts +2 -93
- package/dist/observability/index.js +4 -3
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +1 -2
- package/dist/react.js +1 -2
- package/dist/react.js.map +1 -1
- package/dist/retries-DXMQGhG3.d.ts +79 -0
- package/dist/retries.d.ts +7 -72
- package/dist/retries.js +1 -1
- package/dist/retries.js.map +1 -1
- package/dist/schedule.js +1 -2
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.js +1 -1
- package/dist/types-BB1plA51.d.ts +15 -0
- package/dist/types.d.ts +1 -14
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.js +1 -1
- package/dist/workflow-types-CZNXKj_D.d.ts +260 -0
- package/dist/workflow-types.d.ts +23 -235
- package/dist/workflow-types.js +1 -1
- package/dist/workflow-types.js.map +1 -1
- package/dist/workflows.d.ts +22 -23
- package/dist/workflows.js +5 -6
- package/dist/workflows.js.map +1 -1
- package/package.json +25 -13
- package/dist/agent-eZnMHidZ.d.ts +0 -273
- package/dist/client-connection-D3Wcd6Q6.js +0 -603
- package/dist/client-connection-D3Wcd6Q6.js.map +0 -1
- package/dist/client-storage-BPjfP_is.d.ts +0 -604
- package/dist/experimental/sub-agent.d.ts +0 -205
- package/dist/experimental/sub-agent.js +0 -191
- package/dist/experimental/sub-agent.js.map +0 -1
- package/dist/mcp/client.js.map +0 -1
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { Server } from "partyserver";
|
|
2
|
-
|
|
3
|
-
//#region src/experimental/sub-agent.d.ts
|
|
4
|
-
/** @internal */
|
|
5
|
-
interface FacetCapableCtx {
|
|
6
|
-
facets: {
|
|
7
|
-
get(name: string, getStartupOptions: () => {
|
|
8
|
-
id?: DurableObjectId | string;
|
|
9
|
-
class: DurableObjectClass;
|
|
10
|
-
} | Promise<{
|
|
11
|
-
id?: DurableObjectId | string;
|
|
12
|
-
class: DurableObjectClass;
|
|
13
|
-
}>): Fetcher;
|
|
14
|
-
abort(name: string, reason: unknown): void;
|
|
15
|
-
delete(name: string): void;
|
|
16
|
-
};
|
|
17
|
-
exports: Record<string, DurableObjectClass>;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Constructor type for a SubAgent subclass.
|
|
21
|
-
* Used by {@link SubAgent.subAgent} to reference the child class
|
|
22
|
-
* via `ctx.exports`.
|
|
23
|
-
*
|
|
24
|
-
* The class name (`cls.name`) must match the export name in the
|
|
25
|
-
* worker entry point — re-exports under a different name
|
|
26
|
-
* (e.g. `export { Foo as Bar }`) are not supported.
|
|
27
|
-
*/
|
|
28
|
-
type SubAgentClass<T extends SubAgent = SubAgent> = {
|
|
29
|
-
new (ctx: DurableObjectState, env: never): T;
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Wraps `T` in a `Promise` unless it already is one.
|
|
33
|
-
*/
|
|
34
|
-
type Promisify<T> = T extends Promise<unknown> ? T : Promise<T>;
|
|
35
|
-
/**
|
|
36
|
-
* Server / DurableObject internals excluded from the RPC stub.
|
|
37
|
-
* This is a blocklist — if `Server` or `SubAgent` gains new methods
|
|
38
|
-
* they must be added here to stay hidden from the stub type.
|
|
39
|
-
*/
|
|
40
|
-
type SubAgentInternals = "fetch" | "alarm" | "webSocketMessage" | "webSocketClose" | "webSocketError" | "sql" | "broadcast" | "getConnection" | "getConnections" | "getConnectionTags" | "setName" | "onStart" | "onConnect" | "onMessage" | "onClose" | "onError" | "onRequest" | "onException" | "onAlarm" | "subAgent" | "abortSubAgent" | "deleteSubAgent";
|
|
41
|
-
/**
|
|
42
|
-
* A typed RPC stub for a SubAgent. Exposes all public instance methods
|
|
43
|
-
* as callable RPC methods with Promise-wrapped return types.
|
|
44
|
-
*
|
|
45
|
-
* Methods inherited from `Server` / `DurableObject` internals are
|
|
46
|
-
* excluded — only user-defined methods on the SubAgent subclass are
|
|
47
|
-
* exposed.
|
|
48
|
-
*/
|
|
49
|
-
type SubAgentStub<T extends SubAgent> = { [K in keyof T as K extends SubAgentInternals ? never : T[K] extends ((...args: never[]) => unknown) ? K : never]: T[K] extends ((...args: infer A) => infer R) ? (...args: A) => Promisify<R> : never };
|
|
50
|
-
/**
|
|
51
|
-
* Base class for sub-agents — child Durable Objects that run as facets
|
|
52
|
-
* of a parent Agent (or another SubAgent) on the same machine, each
|
|
53
|
-
* with their own isolated SQLite storage.
|
|
54
|
-
*
|
|
55
|
-
* Extends partyserver's `Server`, so inherits:
|
|
56
|
-
* - `this.sql` tagged-template SQL helper
|
|
57
|
-
* - `this.name` identity
|
|
58
|
-
* - WebSocket hibernation + `onConnect`/`onMessage`/`onClose`
|
|
59
|
-
* - `broadcast()`, `getConnection()`, `getConnections()`
|
|
60
|
-
*
|
|
61
|
-
* SubAgents do **not** need wrangler.jsonc entries — they are
|
|
62
|
-
* referenced via `ctx.exports` and instantiated through the
|
|
63
|
-
* experimental facets API.
|
|
64
|
-
*
|
|
65
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```typescript
|
|
69
|
-
* import { SubAgent } from "agents/experimental/subagent";
|
|
70
|
-
*
|
|
71
|
-
* export class SearchAgent extends SubAgent {
|
|
72
|
-
* async search(query: string): Promise<Result[]> {
|
|
73
|
-
* const cached = this.sql`SELECT * FROM cache WHERE q = ${query}`;
|
|
74
|
-
* if (cached.length) return cached;
|
|
75
|
-
* // ... fetch, cache, return
|
|
76
|
-
* }
|
|
77
|
-
* }
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
declare class SubAgent<Env extends Cloudflare.Env = Cloudflare.Env> extends Server<Env> {
|
|
81
|
-
/**
|
|
82
|
-
* Get or create a named child sub-agent — a facet with its own
|
|
83
|
-
* isolated SQLite storage running on the same machine.
|
|
84
|
-
*
|
|
85
|
-
* The first call for a given name triggers the child's `onStart()`.
|
|
86
|
-
* Subsequent calls with the same name return the existing instance
|
|
87
|
-
* (the set-name fetch is a no-op if already initialized).
|
|
88
|
-
*
|
|
89
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
90
|
-
*
|
|
91
|
-
* @param cls The SubAgent subclass (must be exported from the worker)
|
|
92
|
-
* @param name Unique name for this child instance
|
|
93
|
-
* @returns A typed RPC stub for calling methods on the child
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* ```typescript
|
|
97
|
-
* const searcher = await this.subAgent(SearchAgent, "main-search");
|
|
98
|
-
* const results = await searcher.search("cloudflare agents");
|
|
99
|
-
* ```
|
|
100
|
-
*/
|
|
101
|
-
subAgent<T extends SubAgent>(cls: SubAgentClass<T>, name: string): Promise<SubAgentStub<T>>;
|
|
102
|
-
/**
|
|
103
|
-
* Forcefully abort a running child sub-agent. The child stops
|
|
104
|
-
* executing immediately and will be restarted on next
|
|
105
|
-
* {@link subAgent} call. Pending RPC calls receive the reason
|
|
106
|
-
* as an error. Transitively aborts the child's own children.
|
|
107
|
-
*
|
|
108
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
109
|
-
*
|
|
110
|
-
* @param name Name of the child to abort
|
|
111
|
-
* @param reason Error thrown to pending/future RPC callers
|
|
112
|
-
*/
|
|
113
|
-
abortSubAgent(name: string, reason?: unknown): void;
|
|
114
|
-
/**
|
|
115
|
-
* Delete a child sub-agent: abort it if running, then permanently
|
|
116
|
-
* wipe its storage. Transitively deletes the child's own children.
|
|
117
|
-
*
|
|
118
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
119
|
-
*
|
|
120
|
-
* @param name Name of the child to delete
|
|
121
|
-
*/
|
|
122
|
-
deleteSubAgent(name: string): void;
|
|
123
|
-
}
|
|
124
|
-
type Constructor<T = object> = new (...args: any[]) => T;
|
|
125
|
-
/**
|
|
126
|
-
* Mixin that adds sub-agent management methods to an Agent (or
|
|
127
|
-
* AIChatAgent, McpAgent, etc.) without shipping them in the base
|
|
128
|
-
* `Agent` class.
|
|
129
|
-
*
|
|
130
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* ```typescript
|
|
134
|
-
* import { Agent } from "agents";
|
|
135
|
-
* import { withSubAgents, SubAgent } from "agents/experimental/subagent";
|
|
136
|
-
*
|
|
137
|
-
* export class SearchAgent extends SubAgent {
|
|
138
|
-
* async search(query: string) { ... }
|
|
139
|
-
* }
|
|
140
|
-
*
|
|
141
|
-
* const SubAgentParent = withSubAgents(Agent);
|
|
142
|
-
*
|
|
143
|
-
* export class MyAgent extends SubAgentParent<Env> {
|
|
144
|
-
* async doStuff() {
|
|
145
|
-
* const searcher = await this.subAgent(SearchAgent, "main");
|
|
146
|
-
* await searcher.search("hello");
|
|
147
|
-
* }
|
|
148
|
-
* }
|
|
149
|
-
* ```
|
|
150
|
-
*/
|
|
151
|
-
declare function withSubAgents<TBase extends Constructor>(Base: TBase): {
|
|
152
|
-
new (...args: any[]): {
|
|
153
|
-
/**
|
|
154
|
-
* Get or create a named sub-agent — a child Durable Object with its
|
|
155
|
-
* own isolated SQLite storage, running alongside this Agent on the
|
|
156
|
-
* same machine. The child class must extend `SubAgent` and be exported
|
|
157
|
-
* from the worker entry point.
|
|
158
|
-
*
|
|
159
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
160
|
-
*
|
|
161
|
-
* @param cls The SubAgent subclass (must be exported from the worker)
|
|
162
|
-
* @param name Unique name for this child instance
|
|
163
|
-
* @returns A typed RPC stub for calling methods on the child
|
|
164
|
-
*/
|
|
165
|
-
subAgent<T extends SubAgent>(cls: SubAgentClass<T>, name: string): Promise<SubAgentStub<T>>;
|
|
166
|
-
/**
|
|
167
|
-
* Forcefully abort a running sub-agent. The child stops executing
|
|
168
|
-
* immediately and will be restarted on next {@link subAgent} call.
|
|
169
|
-
* Pending RPC calls receive the reason as an error.
|
|
170
|
-
* Transitively aborts the child's own children.
|
|
171
|
-
*
|
|
172
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
173
|
-
*
|
|
174
|
-
* @param name Name of the child to abort
|
|
175
|
-
* @param reason Error thrown to pending/future RPC callers
|
|
176
|
-
*/
|
|
177
|
-
abortSubAgent(name: string, reason?: unknown): void;
|
|
178
|
-
/**
|
|
179
|
-
* Delete a sub-agent: abort it if running, then permanently wipe its
|
|
180
|
-
* storage. Transitively deletes the child's own children.
|
|
181
|
-
*
|
|
182
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
183
|
-
*
|
|
184
|
-
* @param name Name of the child to delete
|
|
185
|
-
*/
|
|
186
|
-
deleteSubAgent(name: string): void;
|
|
187
|
-
};
|
|
188
|
-
} & TBase;
|
|
189
|
-
/**
|
|
190
|
-
* Synchronous validation that the SubAgent class exists in worker exports.
|
|
191
|
-
* Call this before `_getSubAgent` so the error is thrown synchronously
|
|
192
|
-
* in the caller’s scope (not as a rejected promise from an async function).
|
|
193
|
-
* This avoids unhandled-rejection noise in the workerd runtime.
|
|
194
|
-
* @internal
|
|
195
|
-
*/
|
|
196
|
-
declare function _validateSubAgentExport(ctx: DurableObjectState, cls: SubAgentClass): void;
|
|
197
|
-
/** @internal */
|
|
198
|
-
declare function _getSubAgent<T extends SubAgent>(ctx: DurableObjectState, cls: SubAgentClass<T>, name: string): Promise<SubAgentStub<T>>;
|
|
199
|
-
/** @internal */
|
|
200
|
-
declare function _abortSubAgent(ctx: DurableObjectState, name: string, reason?: unknown): void;
|
|
201
|
-
/** @internal */
|
|
202
|
-
declare function _deleteSubAgent(ctx: DurableObjectState, name: string): void;
|
|
203
|
-
//#endregion
|
|
204
|
-
export { FacetCapableCtx, SubAgent, SubAgentClass, SubAgentStub, _abortSubAgent, _deleteSubAgent, _getSubAgent, _validateSubAgentExport, withSubAgents };
|
|
205
|
-
//# sourceMappingURL=sub-agent.d.ts.map
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { Server } from "partyserver";
|
|
2
|
-
|
|
3
|
-
//#region src/experimental/sub-agent.ts
|
|
4
|
-
/**
|
|
5
|
-
* Base class for sub-agents — child Durable Objects that run as facets
|
|
6
|
-
* of a parent Agent (or another SubAgent) on the same machine, each
|
|
7
|
-
* with their own isolated SQLite storage.
|
|
8
|
-
*
|
|
9
|
-
* Extends partyserver's `Server`, so inherits:
|
|
10
|
-
* - `this.sql` tagged-template SQL helper
|
|
11
|
-
* - `this.name` identity
|
|
12
|
-
* - WebSocket hibernation + `onConnect`/`onMessage`/`onClose`
|
|
13
|
-
* - `broadcast()`, `getConnection()`, `getConnections()`
|
|
14
|
-
*
|
|
15
|
-
* SubAgents do **not** need wrangler.jsonc entries — they are
|
|
16
|
-
* referenced via `ctx.exports` and instantiated through the
|
|
17
|
-
* experimental facets API.
|
|
18
|
-
*
|
|
19
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* import { SubAgent } from "agents/experimental/subagent";
|
|
24
|
-
*
|
|
25
|
-
* export class SearchAgent extends SubAgent {
|
|
26
|
-
* async search(query: string): Promise<Result[]> {
|
|
27
|
-
* const cached = this.sql`SELECT * FROM cache WHERE q = ${query}`;
|
|
28
|
-
* if (cached.length) return cached;
|
|
29
|
-
* // ... fetch, cache, return
|
|
30
|
-
* }
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
var SubAgent = class extends Server {
|
|
35
|
-
/**
|
|
36
|
-
* Get or create a named child sub-agent — a facet with its own
|
|
37
|
-
* isolated SQLite storage running on the same machine.
|
|
38
|
-
*
|
|
39
|
-
* The first call for a given name triggers the child's `onStart()`.
|
|
40
|
-
* Subsequent calls with the same name return the existing instance
|
|
41
|
-
* (the set-name fetch is a no-op if already initialized).
|
|
42
|
-
*
|
|
43
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
44
|
-
*
|
|
45
|
-
* @param cls The SubAgent subclass (must be exported from the worker)
|
|
46
|
-
* @param name Unique name for this child instance
|
|
47
|
-
* @returns A typed RPC stub for calling methods on the child
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* ```typescript
|
|
51
|
-
* const searcher = await this.subAgent(SearchAgent, "main-search");
|
|
52
|
-
* const results = await searcher.search("cloudflare agents");
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
async subAgent(cls, name) {
|
|
56
|
-
_validateSubAgentExport(this.ctx, cls);
|
|
57
|
-
return _getSubAgent(this.ctx, cls, name);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Forcefully abort a running child sub-agent. The child stops
|
|
61
|
-
* executing immediately and will be restarted on next
|
|
62
|
-
* {@link subAgent} call. Pending RPC calls receive the reason
|
|
63
|
-
* as an error. Transitively aborts the child's own children.
|
|
64
|
-
*
|
|
65
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
66
|
-
*
|
|
67
|
-
* @param name Name of the child to abort
|
|
68
|
-
* @param reason Error thrown to pending/future RPC callers
|
|
69
|
-
*/
|
|
70
|
-
abortSubAgent(name, reason) {
|
|
71
|
-
_abortSubAgent(this.ctx, name, reason);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Delete a child sub-agent: abort it if running, then permanently
|
|
75
|
-
* wipe its storage. Transitively deletes the child's own children.
|
|
76
|
-
*
|
|
77
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
78
|
-
*
|
|
79
|
-
* @param name Name of the child to delete
|
|
80
|
-
*/
|
|
81
|
-
deleteSubAgent(name) {
|
|
82
|
-
_deleteSubAgent(this.ctx, name);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* Mixin that adds sub-agent management methods to an Agent (or
|
|
87
|
-
* AIChatAgent, McpAgent, etc.) without shipping them in the base
|
|
88
|
-
* `Agent` class.
|
|
89
|
-
*
|
|
90
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```typescript
|
|
94
|
-
* import { Agent } from "agents";
|
|
95
|
-
* import { withSubAgents, SubAgent } from "agents/experimental/subagent";
|
|
96
|
-
*
|
|
97
|
-
* export class SearchAgent extends SubAgent {
|
|
98
|
-
* async search(query: string) { ... }
|
|
99
|
-
* }
|
|
100
|
-
*
|
|
101
|
-
* const SubAgentParent = withSubAgents(Agent);
|
|
102
|
-
*
|
|
103
|
-
* export class MyAgent extends SubAgentParent<Env> {
|
|
104
|
-
* async doStuff() {
|
|
105
|
-
* const searcher = await this.subAgent(SearchAgent, "main");
|
|
106
|
-
* await searcher.search("hello");
|
|
107
|
-
* }
|
|
108
|
-
* }
|
|
109
|
-
* ```
|
|
110
|
-
*/
|
|
111
|
-
function withSubAgents(Base) {
|
|
112
|
-
class WithSubAgents extends Base {
|
|
113
|
-
/**
|
|
114
|
-
* Get or create a named sub-agent — a child Durable Object with its
|
|
115
|
-
* own isolated SQLite storage, running alongside this Agent on the
|
|
116
|
-
* same machine. The child class must extend `SubAgent` and be exported
|
|
117
|
-
* from the worker entry point.
|
|
118
|
-
*
|
|
119
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
120
|
-
*
|
|
121
|
-
* @param cls The SubAgent subclass (must be exported from the worker)
|
|
122
|
-
* @param name Unique name for this child instance
|
|
123
|
-
* @returns A typed RPC stub for calling methods on the child
|
|
124
|
-
*/
|
|
125
|
-
async subAgent(cls, name) {
|
|
126
|
-
const { ctx } = this;
|
|
127
|
-
_validateSubAgentExport(ctx, cls);
|
|
128
|
-
return _getSubAgent(ctx, cls, name);
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Forcefully abort a running sub-agent. The child stops executing
|
|
132
|
-
* immediately and will be restarted on next {@link subAgent} call.
|
|
133
|
-
* Pending RPC calls receive the reason as an error.
|
|
134
|
-
* Transitively aborts the child's own children.
|
|
135
|
-
*
|
|
136
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
137
|
-
*
|
|
138
|
-
* @param name Name of the child to abort
|
|
139
|
-
* @param reason Error thrown to pending/future RPC callers
|
|
140
|
-
*/
|
|
141
|
-
abortSubAgent(name, reason) {
|
|
142
|
-
const { ctx } = this;
|
|
143
|
-
_abortSubAgent(ctx, name, reason);
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Delete a sub-agent: abort it if running, then permanently wipe its
|
|
147
|
-
* storage. Transitively deletes the child's own children.
|
|
148
|
-
*
|
|
149
|
-
* @experimental Requires the `"experimental"` compatibility flag.
|
|
150
|
-
*
|
|
151
|
-
* @param name Name of the child to delete
|
|
152
|
-
*/
|
|
153
|
-
deleteSubAgent(name) {
|
|
154
|
-
const { ctx } = this;
|
|
155
|
-
_deleteSubAgent(ctx, name);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return WithSubAgents;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Synchronous validation that the SubAgent class exists in worker exports.
|
|
162
|
-
* Call this before `_getSubAgent` so the error is thrown synchronously
|
|
163
|
-
* in the caller’s scope (not as a rejected promise from an async function).
|
|
164
|
-
* This avoids unhandled-rejection noise in the workerd runtime.
|
|
165
|
-
* @internal
|
|
166
|
-
*/
|
|
167
|
-
function _validateSubAgentExport(ctx, cls) {
|
|
168
|
-
const { exports } = ctx;
|
|
169
|
-
if (!exports[cls.name]) throw new Error(`SubAgent class "${cls.name}" not found in worker exports. Make sure the class is exported from your worker entry point and that the export name matches the class name.`);
|
|
170
|
-
}
|
|
171
|
-
/** @internal */
|
|
172
|
-
async function _getSubAgent(ctx, cls, name) {
|
|
173
|
-
const { facets, exports } = ctx;
|
|
174
|
-
const stub = facets.get(name, () => ({ class: exports[cls.name] }));
|
|
175
|
-
const req = new Request("http://dummy-example.cloudflare.com/cdn-cgi/partyserver/set-name/");
|
|
176
|
-
req.headers.set("x-partykit-room", name);
|
|
177
|
-
await stub.fetch(req).then((res) => res.text());
|
|
178
|
-
return stub;
|
|
179
|
-
}
|
|
180
|
-
/** @internal */
|
|
181
|
-
function _abortSubAgent(ctx, name, reason) {
|
|
182
|
-
ctx.facets.abort(name, reason);
|
|
183
|
-
}
|
|
184
|
-
/** @internal */
|
|
185
|
-
function _deleteSubAgent(ctx, name) {
|
|
186
|
-
ctx.facets.delete(name);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
//#endregion
|
|
190
|
-
export { SubAgent, _abortSubAgent, _deleteSubAgent, _getSubAgent, _validateSubAgentExport, withSubAgents };
|
|
191
|
-
//# sourceMappingURL=sub-agent.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sub-agent.js","names":[],"sources":["../../src/experimental/sub-agent.ts"],"sourcesContent":["import { Server } from \"partyserver\";\n\n// ── Internal facet access types ─────────────────────────────────────\n// These mirror the experimental workerd `ctx.facets` API without\n// depending on the \"experimental\" compat flag at the type level.\n\n/** @internal */\nexport interface FacetCapableCtx {\n facets: {\n get(\n name: string,\n getStartupOptions: () =>\n | { id?: DurableObjectId | string; class: DurableObjectClass }\n | Promise<{\n id?: DurableObjectId | string;\n class: DurableObjectClass;\n }>\n ): Fetcher;\n abort(name: string, reason: unknown): void;\n delete(name: string): void;\n };\n exports: Record<string, DurableObjectClass>;\n}\n\n// ── Public types ────────────────────────────────────────────────────\n\n/**\n * Constructor type for a SubAgent subclass.\n * Used by {@link SubAgent.subAgent} to reference the child class\n * via `ctx.exports`.\n *\n * The class name (`cls.name`) must match the export name in the\n * worker entry point — re-exports under a different name\n * (e.g. `export { Foo as Bar }`) are not supported.\n */\nexport type SubAgentClass<T extends SubAgent = SubAgent> = {\n new (ctx: DurableObjectState, env: never): T;\n};\n\n/**\n * Wraps `T` in a `Promise` unless it already is one.\n */\ntype Promisify<T> = T extends Promise<unknown> ? T : Promise<T>;\n\n/**\n * Server / DurableObject internals excluded from the RPC stub.\n * This is a blocklist — if `Server` or `SubAgent` gains new methods\n * they must be added here to stay hidden from the stub type.\n */\ntype SubAgentInternals =\n | \"fetch\"\n | \"alarm\"\n | \"webSocketMessage\"\n | \"webSocketClose\"\n | \"webSocketError\"\n | \"sql\"\n | \"broadcast\"\n | \"getConnection\"\n | \"getConnections\"\n | \"getConnectionTags\"\n | \"setName\"\n | \"onStart\"\n | \"onConnect\"\n | \"onMessage\"\n | \"onClose\"\n | \"onError\"\n | \"onRequest\"\n | \"onException\"\n | \"onAlarm\"\n | \"subAgent\"\n | \"abortSubAgent\"\n | \"deleteSubAgent\";\n\n/**\n * A typed RPC stub for a SubAgent. Exposes all public instance methods\n * as callable RPC methods with Promise-wrapped return types.\n *\n * Methods inherited from `Server` / `DurableObject` internals are\n * excluded — only user-defined methods on the SubAgent subclass are\n * exposed.\n */\nexport type SubAgentStub<T extends SubAgent> = {\n [K in keyof T as K extends SubAgentInternals\n ? never\n : T[K] extends (...args: never[]) => unknown\n ? K\n : never]: T[K] extends (...args: infer A) => infer R\n ? (...args: A) => Promisify<R>\n : never;\n};\n\n// ── SubAgent class ──────────────────────────────────────────────────\n\n/**\n * Base class for sub-agents — child Durable Objects that run as facets\n * of a parent Agent (or another SubAgent) on the same machine, each\n * with their own isolated SQLite storage.\n *\n * Extends partyserver's `Server`, so inherits:\n * - `this.sql` tagged-template SQL helper\n * - `this.name` identity\n * - WebSocket hibernation + `onConnect`/`onMessage`/`onClose`\n * - `broadcast()`, `getConnection()`, `getConnections()`\n *\n * SubAgents do **not** need wrangler.jsonc entries — they are\n * referenced via `ctx.exports` and instantiated through the\n * experimental facets API.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @example\n * ```typescript\n * import { SubAgent } from \"agents/experimental/subagent\";\n *\n * export class SearchAgent extends SubAgent {\n * async search(query: string): Promise<Result[]> {\n * const cached = this.sql`SELECT * FROM cache WHERE q = ${query}`;\n * if (cached.length) return cached;\n * // ... fetch, cache, return\n * }\n * }\n * ```\n */\nexport class SubAgent<\n Env extends Cloudflare.Env = Cloudflare.Env\n> extends Server<Env> {\n /**\n * Get or create a named child sub-agent — a facet with its own\n * isolated SQLite storage running on the same machine.\n *\n * The first call for a given name triggers the child's `onStart()`.\n * Subsequent calls with the same name return the existing instance\n * (the set-name fetch is a no-op if already initialized).\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param cls The SubAgent subclass (must be exported from the worker)\n * @param name Unique name for this child instance\n * @returns A typed RPC stub for calling methods on the child\n *\n * @example\n * ```typescript\n * const searcher = await this.subAgent(SearchAgent, \"main-search\");\n * const results = await searcher.search(\"cloudflare agents\");\n * ```\n */\n async subAgent<T extends SubAgent>(\n cls: SubAgentClass<T>,\n name: string\n ): Promise<SubAgentStub<T>> {\n _validateSubAgentExport(this.ctx, cls);\n return _getSubAgent(this.ctx, cls, name);\n }\n\n /**\n * Forcefully abort a running child sub-agent. The child stops\n * executing immediately and will be restarted on next\n * {@link subAgent} call. Pending RPC calls receive the reason\n * as an error. Transitively aborts the child's own children.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to abort\n * @param reason Error thrown to pending/future RPC callers\n */\n abortSubAgent(name: string, reason?: unknown): void {\n _abortSubAgent(this.ctx, name, reason);\n }\n\n /**\n * Delete a child sub-agent: abort it if running, then permanently\n * wipe its storage. Transitively deletes the child's own children.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to delete\n */\n deleteSubAgent(name: string): void {\n _deleteSubAgent(this.ctx, name);\n }\n}\n\n// ── withSubAgents mixin ─────────────────────────────────────────────\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- mixin constructor constraint\ntype Constructor<T = object> = new (...args: any[]) => T;\n\n/**\n * Mixin that adds sub-agent management methods to an Agent (or\n * AIChatAgent, McpAgent, etc.) without shipping them in the base\n * `Agent` class.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @example\n * ```typescript\n * import { Agent } from \"agents\";\n * import { withSubAgents, SubAgent } from \"agents/experimental/subagent\";\n *\n * export class SearchAgent extends SubAgent {\n * async search(query: string) { ... }\n * }\n *\n * const SubAgentParent = withSubAgents(Agent);\n *\n * export class MyAgent extends SubAgentParent<Env> {\n * async doStuff() {\n * const searcher = await this.subAgent(SearchAgent, \"main\");\n * await searcher.search(\"hello\");\n * }\n * }\n * ```\n */\nexport function withSubAgents<TBase extends Constructor>(Base: TBase) {\n class WithSubAgents extends Base {\n /**\n * Get or create a named sub-agent — a child Durable Object with its\n * own isolated SQLite storage, running alongside this Agent on the\n * same machine. The child class must extend `SubAgent` and be exported\n * from the worker entry point.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param cls The SubAgent subclass (must be exported from the worker)\n * @param name Unique name for this child instance\n * @returns A typed RPC stub for calling methods on the child\n */\n async subAgent<T extends SubAgent>(\n cls: SubAgentClass<T>,\n name: string\n ): Promise<SubAgentStub<T>> {\n const { ctx } = this as unknown as { ctx: DurableObjectState };\n _validateSubAgentExport(ctx, cls);\n return _getSubAgent(ctx, cls, name);\n }\n\n /**\n * Forcefully abort a running sub-agent. The child stops executing\n * immediately and will be restarted on next {@link subAgent} call.\n * Pending RPC calls receive the reason as an error.\n * Transitively aborts the child's own children.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to abort\n * @param reason Error thrown to pending/future RPC callers\n */\n abortSubAgent(name: string, reason?: unknown): void {\n const { ctx } = this as unknown as { ctx: DurableObjectState };\n _abortSubAgent(ctx, name, reason);\n }\n\n /**\n * Delete a sub-agent: abort it if running, then permanently wipe its\n * storage. Transitively deletes the child's own children.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to delete\n */\n deleteSubAgent(name: string): void {\n const { ctx } = this as unknown as { ctx: DurableObjectState };\n _deleteSubAgent(ctx, name);\n }\n }\n return WithSubAgents;\n}\n\n// ── Shared helpers (used by both SubAgent and withSubAgents mixin) ───\n\n/**\n * Synchronous validation that the SubAgent class exists in worker exports.\n * Call this before `_getSubAgent` so the error is thrown synchronously\n * in the caller’s scope (not as a rejected promise from an async function).\n * This avoids unhandled-rejection noise in the workerd runtime.\n * @internal\n */\nexport function _validateSubAgentExport(\n ctx: DurableObjectState,\n cls: SubAgentClass\n): void {\n const { exports } = ctx as unknown as FacetCapableCtx;\n if (!exports[cls.name]) {\n throw new Error(\n `SubAgent class \"${cls.name}\" not found in worker exports. ` +\n `Make sure the class is exported from your worker entry point ` +\n `and that the export name matches the class name.`\n );\n }\n}\n\n/** @internal */\nexport async function _getSubAgent<T extends SubAgent>(\n ctx: DurableObjectState,\n cls: SubAgentClass<T>,\n name: string\n): Promise<SubAgentStub<T>> {\n const { facets, exports } = ctx as unknown as FacetCapableCtx;\n const stub = facets.get(name, () => ({\n class: exports[cls.name] as DurableObjectClass\n }));\n\n // Trigger Server initialization (setName → onStart) via fetch,\n // same pattern as getAgentByName / getServerByName.\n const req = new Request(\n \"http://dummy-example.cloudflare.com/cdn-cgi/partyserver/set-name/\"\n );\n req.headers.set(\"x-partykit-room\", name);\n await stub.fetch(req).then((res) => res.text());\n\n return stub as unknown as SubAgentStub<T>;\n}\n\n/** @internal */\nexport function _abortSubAgent(\n ctx: DurableObjectState,\n name: string,\n reason?: unknown\n): void {\n (ctx as unknown as FacetCapableCtx).facets.abort(name, reason);\n}\n\n/** @internal */\nexport function _deleteSubAgent(ctx: DurableObjectState, name: string): void {\n (ctx as unknown as FacetCapableCtx).facets.delete(name);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2HA,IAAa,WAAb,cAEU,OAAY;;;;;;;;;;;;;;;;;;;;;CAqBpB,MAAM,SACJ,KACA,MAC0B;AAC1B,0BAAwB,KAAK,KAAK,IAAI;AACtC,SAAO,aAAa,KAAK,KAAK,KAAK,KAAK;;;;;;;;;;;;;CAc1C,cAAc,MAAc,QAAwB;AAClD,iBAAe,KAAK,KAAK,MAAM,OAAO;;;;;;;;;;CAWxC,eAAe,MAAoB;AACjC,kBAAgB,KAAK,KAAK,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCnC,SAAgB,cAAyC,MAAa;CACpE,MAAM,sBAAsB,KAAK;;;;;;;;;;;;;EAa/B,MAAM,SACJ,KACA,MAC0B;GAC1B,MAAM,EAAE,QAAQ;AAChB,2BAAwB,KAAK,IAAI;AACjC,UAAO,aAAa,KAAK,KAAK,KAAK;;;;;;;;;;;;;EAcrC,cAAc,MAAc,QAAwB;GAClD,MAAM,EAAE,QAAQ;AAChB,kBAAe,KAAK,MAAM,OAAO;;;;;;;;;;EAWnC,eAAe,MAAoB;GACjC,MAAM,EAAE,QAAQ;AAChB,mBAAgB,KAAK,KAAK;;;AAG9B,QAAO;;;;;;;;;AAYT,SAAgB,wBACd,KACA,KACM;CACN,MAAM,EAAE,YAAY;AACpB,KAAI,CAAC,QAAQ,IAAI,MACf,OAAM,IAAI,MACR,mBAAmB,IAAI,KAAK,8IAG7B;;;AAKL,eAAsB,aACpB,KACA,KACA,MAC0B;CAC1B,MAAM,EAAE,QAAQ,YAAY;CAC5B,MAAM,OAAO,OAAO,IAAI,aAAa,EACnC,OAAO,QAAQ,IAAI,OACpB,EAAE;CAIH,MAAM,MAAM,IAAI,QACd,oEACD;AACD,KAAI,QAAQ,IAAI,mBAAmB,KAAK;AACxC,OAAM,KAAK,MAAM,IAAI,CAAC,MAAM,QAAQ,IAAI,MAAM,CAAC;AAE/C,QAAO;;;AAIT,SAAgB,eACd,KACA,MACA,QACM;AACN,CAAC,IAAmC,OAAO,MAAM,MAAM,OAAO;;;AAIhE,SAAgB,gBAAgB,KAAyB,MAAoB;AAC3E,CAAC,IAAmC,OAAO,OAAO,KAAK"}
|
package/dist/mcp/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../../src/mcp/client.ts"],"sourcesContent":["import type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport type {\n CallToolRequest,\n CallToolResultSchema,\n CompatibilityCallToolResultSchema,\n GetPromptRequest,\n Prompt,\n ReadResourceRequest,\n Resource,\n ResourceTemplate,\n Tool\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { CfWorkerJsonSchemaValidator } from \"@modelcontextprotocol/sdk/validation/cfworker-provider.js\";\nimport { type RetryOptions, tryN } from \"../retries\";\nimport type { ToolSet } from \"ai\";\nimport type { JSONSchema7 } from \"json-schema\";\nimport { nanoid } from \"nanoid\";\nimport { Emitter, type Event, DisposableStore } from \"../core/events\";\nimport type { MCPObservabilityEvent } from \"../observability/mcp\";\nimport {\n MCPClientConnection,\n MCPConnectionState,\n type MCPTransportOptions\n} from \"./client-connection\";\nimport { toErrorMessage } from \"./errors\";\nimport { RPC_DO_PREFIX } from \"./rpc\";\nimport type { TransportType } from \"./types\";\nimport type { MCPServerRow } from \"./client-storage\";\nimport type { AgentMcpOAuthProvider } from \"./do-oauth-client-provider\";\nimport { DurableObjectOAuthClientProvider } from \"./do-oauth-client-provider\";\n\nconst defaultClientOptions: ConstructorParameters<typeof Client>[1] = {\n jsonSchemaValidator: new CfWorkerJsonSchemaValidator()\n};\n\n/**\n * Blocked hostname patterns for SSRF protection.\n * Prevents MCP client from connecting to internal/private network addresses.\n */\nconst BLOCKED_HOSTNAMES = new Set([\n \"localhost\",\n \"0.0.0.0\",\n \"[::1]\",\n \"[::]\",\n \"metadata.google.internal\"\n]);\n\n/**\n * Check whether a hostname looks like a private/internal IP address.\n * Blocks RFC 1918, link-local, loopback, and cloud metadata endpoints.\n */\nfunction isBlockedUrl(url: string): boolean {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return true; // Malformed URLs are blocked\n }\n\n const hostname = parsed.hostname;\n\n if (BLOCKED_HOSTNAMES.has(hostname)) return true;\n\n // IPv4 checks\n const ipv4Parts = hostname.split(\".\");\n if (ipv4Parts.length === 4 && ipv4Parts.every((p) => /^\\d{1,3}$/.test(p))) {\n const [a, b] = ipv4Parts.map(Number);\n // 10.0.0.0/8\n if (a === 10) return true;\n // 172.16.0.0/12\n if (a === 172 && b >= 16 && b <= 31) return true;\n // 192.168.0.0/16\n if (a === 192 && b === 168) return true;\n // 127.0.0.0/8 (loopback)\n if (a === 127) return true;\n // 169.254.0.0/16 (link-local / cloud metadata)\n if (a === 169 && b === 254) return true;\n // 0.0.0.0/8\n if (a === 0) return true;\n }\n\n // IPv6 private range checks\n // URL parser keeps brackets: hostname for [fc00::1] is \"[fc00::1]\"\n if (hostname.startsWith(\"[\") && hostname.endsWith(\"]\")) {\n const addr = hostname.slice(1, -1).toLowerCase();\n // fc00::/7 — unique local addresses (fc00:: through fdff::)\n if (addr.startsWith(\"fc\") || addr.startsWith(\"fd\")) return true;\n // fe80::/10 — link-local addresses\n if (addr.startsWith(\"fe80\")) return true;\n }\n\n return false;\n}\n\n/**\n * Options that can be stored in the server_options column\n * This is what gets JSON.stringify'd and stored in the database\n */\nexport type MCPServerOptions = {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n /** Retry options for connection and reconnection attempts */\n retry?: RetryOptions;\n};\n\n/**\n * Result of an OAuth callback request\n */\nexport type MCPOAuthCallbackResult =\n | { serverId: string; authSuccess: true; authError?: undefined }\n | { serverId?: string; authSuccess: false; authError: string };\n\n/**\n * Options for registering an MCP server\n */\nexport type RegisterServerOptions = {\n url: string;\n name: string;\n callbackUrl?: string;\n client?: ConstructorParameters<typeof Client>[1];\n transport?: MCPTransportOptions;\n authUrl?: string;\n clientId?: string;\n /** Retry options for connection and reconnection attempts */\n retry?: RetryOptions;\n};\n\n/**\n * Result of attempting to connect to an MCP server.\n * Discriminated union ensures error is present only on failure.\n */\nexport type MCPConnectionResult =\n | {\n state: typeof MCPConnectionState.FAILED;\n error: string;\n }\n | {\n state: typeof MCPConnectionState.AUTHENTICATING;\n authUrl: string;\n clientId?: string;\n }\n | {\n state: typeof MCPConnectionState.CONNECTED;\n };\n\n/**\n * Result of discovering server capabilities.\n * success indicates whether discovery completed successfully.\n * state is the current connection state at time of return.\n * error is present when success is false.\n */\nexport type MCPDiscoverResult = {\n success: boolean;\n state: MCPConnectionState;\n error?: string;\n};\n\nexport type MCPClientOAuthCallbackConfig = {\n successRedirect?: string;\n errorRedirect?: string;\n customHandler?: (result: MCPClientOAuthResult) => Response;\n};\n\nexport type MCPClientOAuthResult =\n | { serverId: string; authSuccess: true; authError?: undefined }\n | {\n serverId?: string;\n authSuccess: false;\n /** May contain untrusted content from external OAuth providers. Escape appropriately for your output context. */\n authError: string;\n };\n\nexport type MCPClientManagerOptions = {\n storage: DurableObjectStorage;\n createAuthProvider?: (callbackUrl: string) => AgentMcpOAuthProvider;\n};\n\n/**\n * Utility class that aggregates multiple MCP clients into one\n */\nexport class MCPClientManager {\n public mcpConnections: Record<string, MCPClientConnection> = {};\n private _didWarnAboutUnstableGetAITools = false;\n private _oauthCallbackConfig?: MCPClientOAuthCallbackConfig;\n private _connectionDisposables = new Map<string, DisposableStore>();\n private _storage: DurableObjectStorage;\n private _createAuthProviderFn?: (\n callbackUrl: string\n ) => AgentMcpOAuthProvider;\n private _isRestored = false;\n private _pendingConnections = new Map<string, Promise<void>>();\n\n /** @internal Protected for testing purposes. */\n protected readonly _onObservabilityEvent =\n new Emitter<MCPObservabilityEvent>();\n public readonly onObservabilityEvent: Event<MCPObservabilityEvent> =\n this._onObservabilityEvent.event;\n\n private readonly _onServerStateChanged = new Emitter<void>();\n /**\n * Event that fires whenever any MCP server state changes (registered, connected, removed, etc.)\n * This is useful for broadcasting server state to clients.\n */\n public readonly onServerStateChanged: Event<void> =\n this._onServerStateChanged.event;\n\n /**\n * @param _name Name of the MCP client\n * @param _version Version of the MCP Client\n * @param options Storage adapter for persisting MCP server state\n */\n constructor(\n private _name: string,\n private _version: string,\n options: MCPClientManagerOptions\n ) {\n if (!options.storage) {\n throw new Error(\n \"MCPClientManager requires a valid DurableObjectStorage instance\"\n );\n }\n this._storage = options.storage;\n this._createAuthProviderFn = options.createAuthProvider;\n }\n\n // SQL helper - runs a query and returns results as array\n private sql<T extends Record<string, SqlStorageValue>>(\n query: string,\n ...bindings: SqlStorageValue[]\n ): T[] {\n return [...this._storage.sql.exec<T>(query, ...bindings)];\n }\n\n // Storage operations\n private saveServerToStorage(server: MCPServerRow): void {\n this.sql(\n `INSERT OR REPLACE INTO cf_agents_mcp_servers (\n id, name, server_url, client_id, auth_url, callback_url, server_options\n ) VALUES (?, ?, ?, ?, ?, ?, ?)`,\n server.id,\n server.name,\n server.server_url,\n server.client_id ?? null,\n server.auth_url ?? null,\n server.callback_url,\n server.server_options ?? null\n );\n }\n\n private removeServerFromStorage(serverId: string): void {\n this.sql(\"DELETE FROM cf_agents_mcp_servers WHERE id = ?\", serverId);\n }\n\n private getServersFromStorage(): MCPServerRow[] {\n return this.sql<MCPServerRow>(\n \"SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers\"\n );\n }\n\n /**\n * Get the retry options for a server from stored server_options\n */\n private getServerRetryOptions(serverId: string): RetryOptions | undefined {\n const rows = this.sql<MCPServerRow>(\n \"SELECT server_options FROM cf_agents_mcp_servers WHERE id = ?\",\n serverId\n );\n if (!rows.length || !rows[0].server_options) return undefined;\n const parsed: MCPServerOptions = JSON.parse(rows[0].server_options);\n return parsed.retry;\n }\n\n private clearServerAuthUrl(serverId: string): void {\n this.sql(\n \"UPDATE cf_agents_mcp_servers SET auth_url = NULL WHERE id = ?\",\n serverId\n );\n }\n\n private failConnection(\n serverId: string,\n error: string\n ): MCPOAuthCallbackResult {\n this.clearServerAuthUrl(serverId);\n if (this.mcpConnections[serverId]) {\n this.mcpConnections[serverId].connectionState = MCPConnectionState.FAILED;\n this.mcpConnections[serverId].connectionError = error;\n }\n this._onServerStateChanged.fire();\n return { serverId, authSuccess: false, authError: error };\n }\n\n jsonSchema: typeof import(\"ai\").jsonSchema | undefined;\n\n /**\n * Create an auth provider for a server\n * @internal\n */\n private createAuthProvider(\n serverId: string,\n callbackUrl: string,\n clientName: string,\n clientId?: string\n ): AgentMcpOAuthProvider {\n if (!this._storage) {\n throw new Error(\n \"Cannot create auth provider: storage is not initialized\"\n );\n }\n const authProvider = new DurableObjectOAuthClientProvider(\n this._storage,\n clientName,\n callbackUrl\n );\n authProvider.serverId = serverId;\n if (clientId) {\n authProvider.clientId = clientId;\n }\n return authProvider;\n }\n\n /**\n * Get saved RPC servers from storage (servers with rpc:// URLs).\n * These are restored separately by the Agent class since they need env bindings.\n */\n getRpcServersFromStorage(): MCPServerRow[] {\n return this.getServersFromStorage().filter((s) =>\n s.server_url.startsWith(RPC_DO_PREFIX)\n );\n }\n\n /**\n * Save an RPC server to storage for hibernation recovery.\n * The bindingName is stored in server_options so the Agent can look up\n * the namespace from env during restore.\n */\n saveRpcServerToStorage(\n id: string,\n name: string,\n normalizedName: string,\n bindingName: string,\n props?: Record<string, unknown>\n ): void {\n this.saveServerToStorage({\n id,\n name,\n server_url: `${RPC_DO_PREFIX}${normalizedName}`,\n client_id: null,\n auth_url: null,\n callback_url: \"\",\n server_options: JSON.stringify({ bindingName, props })\n });\n }\n\n /**\n * Restore MCP server connections from storage\n * This method is called on Agent initialization to restore previously connected servers.\n * RPC servers (rpc:// URLs) are skipped here -- they are restored by the Agent class\n * which has access to env bindings.\n *\n * @param clientName Name to use for OAuth client (typically the agent instance name)\n */\n async restoreConnectionsFromStorage(clientName: string): Promise<void> {\n if (this._isRestored) {\n return;\n }\n\n const servers = this.getServersFromStorage();\n\n if (!servers || servers.length === 0) {\n this._isRestored = true;\n return;\n }\n\n for (const server of servers) {\n if (server.server_url.startsWith(RPC_DO_PREFIX)) {\n continue;\n }\n\n const existingConn = this.mcpConnections[server.id];\n\n // Skip if connection already exists and is in a good state\n if (existingConn) {\n if (existingConn.connectionState === MCPConnectionState.READY) {\n console.warn(\n `[MCPClientManager] Server ${server.id} already has a ready connection. Skipping recreation.`\n );\n continue;\n }\n\n // Don't interrupt in-flight OAuth or connections\n if (\n existingConn.connectionState === MCPConnectionState.AUTHENTICATING ||\n existingConn.connectionState === MCPConnectionState.CONNECTING ||\n existingConn.connectionState === MCPConnectionState.DISCOVERING\n ) {\n // Let the existing flow complete\n continue;\n }\n\n // If failed, clean up the old connection before recreating\n if (existingConn.connectionState === MCPConnectionState.FAILED) {\n try {\n await existingConn.client.close();\n } catch (error) {\n console.warn(\n `[MCPClientManager] Error closing failed connection ${server.id}:`,\n error\n );\n }\n delete this.mcpConnections[server.id];\n this._connectionDisposables.get(server.id)?.dispose();\n this._connectionDisposables.delete(server.id);\n }\n }\n\n const parsedOptions: MCPServerOptions | null = server.server_options\n ? JSON.parse(server.server_options)\n : null;\n\n let authProvider: AgentMcpOAuthProvider | undefined;\n if (server.callback_url) {\n authProvider = this._createAuthProviderFn\n ? this._createAuthProviderFn(server.callback_url)\n : this.createAuthProvider(\n server.id,\n server.callback_url,\n clientName,\n server.client_id ?? undefined\n );\n authProvider.serverId = server.id;\n if (server.client_id) {\n authProvider.clientId = server.client_id;\n }\n }\n\n // Create the in-memory connection object (no need to save to storage - we just read from it!)\n const conn = this.createConnection(server.id, server.server_url, {\n client: parsedOptions?.client ?? {},\n transport: {\n ...(parsedOptions?.transport ?? {}),\n type: parsedOptions?.transport?.type ?? (\"auto\" as TransportType),\n authProvider\n }\n });\n\n // If auth_url exists, OAuth flow is in progress - set state and wait for callback\n if (server.auth_url) {\n conn.connectionState = MCPConnectionState.AUTHENTICATING;\n continue;\n }\n\n // Start connection in background (don't await) to avoid blocking the DO\n this._trackConnection(\n server.id,\n this._restoreServer(server.id, parsedOptions?.retry)\n );\n }\n\n this._isRestored = true;\n }\n\n /**\n * Track a pending connection promise for a server.\n * The promise is removed from the map when it settles.\n */\n private _trackConnection(serverId: string, promise: Promise<void>): void {\n const tracked = promise.finally(() => {\n // Only delete if it's still the same promise (not replaced by a newer one)\n if (this._pendingConnections.get(serverId) === tracked) {\n this._pendingConnections.delete(serverId);\n }\n });\n this._pendingConnections.set(serverId, tracked);\n }\n\n /**\n * Wait for all in-flight connection and discovery operations to settle.\n * This is useful when you need MCP tools to be available before proceeding,\n * e.g. before calling getAITools() after the agent wakes from hibernation.\n *\n * Returns once every pending connection has either connected and discovered,\n * failed, or timed out. Never rejects.\n *\n * @param options.timeout - Maximum time in milliseconds to wait.\n * `0` returns immediately without waiting.\n * `undefined` (default) waits indefinitely.\n */\n async waitForConnections(options?: { timeout?: number }): Promise<void> {\n if (this._pendingConnections.size === 0) {\n return;\n }\n if (options?.timeout != null && options.timeout <= 0) {\n return;\n }\n const settled = Promise.allSettled(this._pendingConnections.values());\n if (options?.timeout != null && options.timeout > 0) {\n let timerId: ReturnType<typeof setTimeout>;\n const timer = new Promise<void>((resolve) => {\n timerId = setTimeout(resolve, options.timeout);\n });\n await Promise.race([settled, timer]);\n clearTimeout(timerId!);\n } else {\n await settled;\n }\n }\n\n /**\n * Internal method to restore a single server connection and discovery\n */\n private async _restoreServer(\n serverId: string,\n retry?: RetryOptions\n ): Promise<void> {\n // Always try to connect - the connection logic will determine if OAuth is needed\n // If stored OAuth tokens are valid, connection will succeed automatically\n // If tokens are missing/invalid, connection will fail with Unauthorized\n // and state will be set to \"authenticating\"\n const maxAttempts = retry?.maxAttempts ?? 3;\n const baseDelayMs = retry?.baseDelayMs ?? 500;\n const maxDelayMs = retry?.maxDelayMs ?? 5000;\n\n const connectResult = await tryN(\n maxAttempts,\n async () => this.connectToServer(serverId),\n { baseDelayMs, maxDelayMs }\n ).catch((error) => {\n console.error(\n `Error connecting to ${serverId} after ${maxAttempts} attempts:`,\n error\n );\n return null;\n });\n\n if (connectResult?.state === MCPConnectionState.CONNECTED) {\n const discoverResult = await this.discoverIfConnected(serverId);\n if (discoverResult && !discoverResult.success) {\n console.error(`Error discovering ${serverId}:`, discoverResult.error);\n }\n }\n }\n\n /**\n * Connect to and register an MCP server\n *\n * @deprecated This method is maintained for backward compatibility.\n * For new code, use registerServer() and connectToServer() separately.\n *\n * @param url Server URL\n * @param options Connection options\n * @returns Object with server ID, auth URL (if OAuth), and client ID (if OAuth)\n */\n async connect(\n url: string,\n options: {\n // Allows you to reconnect to a server (in the case of an auth reconnect)\n reconnect?: {\n // server id\n id: string;\n oauthClientId?: string;\n oauthCode?: string;\n };\n // we're overriding authProvider here because we want to be able to access the auth URL\n transport?: MCPTransportOptions;\n client?: ConstructorParameters<typeof Client>[1];\n } = {}\n ): Promise<{\n id: string;\n authUrl?: string;\n clientId?: string;\n }> {\n /* Late initialization of jsonSchemaFn */\n /**\n * We need to delay loading ai sdk, because putting it in module scope is\n * causing issues with startup time.\n * The only place it's used is in getAITools, which only matters after\n * .connect() is called on at least one server.\n * So it's safe to delay loading it until .connect() is called.\n */\n await this.ensureJsonSchema();\n\n const id = options.reconnect?.id ?? nanoid(8);\n\n if (options.transport?.authProvider) {\n options.transport.authProvider.serverId = id;\n // reconnect with auth\n if (options.reconnect?.oauthClientId) {\n options.transport.authProvider.clientId =\n options.reconnect?.oauthClientId;\n }\n }\n\n if (isBlockedUrl(url)) {\n throw new Error(\n `Blocked URL: ${url} — MCP client connections to private/internal addresses are not allowed`\n );\n }\n\n // During OAuth reconnect, reuse existing connection to preserve state\n if (!options.reconnect?.oauthCode || !this.mcpConnections[id]) {\n const normalizedTransport = {\n ...options.transport,\n type: options.transport?.type ?? (\"auto\" as TransportType)\n };\n\n this.mcpConnections[id] = new MCPClientConnection(\n new URL(url),\n {\n name: this._name,\n version: this._version\n },\n {\n client: options.client ?? {},\n transport: normalizedTransport\n }\n );\n\n // Pipe connection-level observability events to the manager-level emitter\n // and track the subscription for cleanup.\n const store = new DisposableStore();\n // If we somehow already had disposables for this id, clear them first\n const existing = this._connectionDisposables.get(id);\n if (existing) existing.dispose();\n this._connectionDisposables.set(id, store);\n store.add(\n this.mcpConnections[id].onObservabilityEvent((event) => {\n this._onObservabilityEvent.fire(event);\n })\n );\n }\n\n // Initialize connection first. this will try connect\n await this.mcpConnections[id].init();\n\n // Handle OAuth completion if we have a reconnect code\n if (options.reconnect?.oauthCode) {\n try {\n await this.mcpConnections[id].completeAuthorization(\n options.reconnect.oauthCode\n );\n\n // Reinitialize connection\n await this.mcpConnections[id].init();\n } catch (error) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: url,\n transport: options.transport?.type ?? \"auto\",\n state: this.mcpConnections[id].connectionState,\n error: toErrorMessage(error)\n },\n timestamp: Date.now()\n });\n // Re-throw to signal failure to the caller\n throw error;\n }\n }\n\n // If connection is in authenticating state, return auth URL for OAuth flow\n const authUrl = options.transport?.authProvider?.authUrl;\n if (\n this.mcpConnections[id].connectionState ===\n MCPConnectionState.AUTHENTICATING &&\n authUrl &&\n options.transport?.authProvider?.redirectUrl\n ) {\n return {\n authUrl,\n clientId: options.transport?.authProvider?.clientId,\n id\n };\n }\n\n // If connection is connected, discover capabilities\n const discoverResult = await this.discoverIfConnected(id);\n if (discoverResult && !discoverResult.success) {\n throw new Error(\n `Failed to discover server capabilities: ${discoverResult.error}`\n );\n }\n\n return {\n id\n };\n }\n\n /**\n * Create an in-memory connection object and set up observability\n * Does NOT save to storage - use registerServer() for that\n * @returns The connection object (existing or newly created)\n */\n private createConnection(\n id: string,\n url: string,\n options: {\n client?: ConstructorParameters<typeof Client>[1];\n transport: MCPTransportOptions;\n }\n ): MCPClientConnection {\n // Return existing connection if already exists\n if (this.mcpConnections[id]) {\n return this.mcpConnections[id];\n }\n\n const normalizedTransport = {\n ...options.transport,\n type: options.transport?.type ?? (\"auto\" as TransportType)\n };\n\n this.mcpConnections[id] = new MCPClientConnection(\n new URL(url),\n {\n name: this._name,\n version: this._version\n },\n {\n client: { ...defaultClientOptions, ...options.client },\n transport: normalizedTransport\n }\n );\n\n // Pipe connection-level observability events to the manager-level emitter\n const store = new DisposableStore();\n const existing = this._connectionDisposables.get(id);\n if (existing) existing.dispose();\n this._connectionDisposables.set(id, store);\n store.add(\n this.mcpConnections[id].onObservabilityEvent((event) => {\n this._onObservabilityEvent.fire(event);\n })\n );\n\n return this.mcpConnections[id];\n }\n\n /**\n * Register an MCP server connection without connecting\n * Creates the connection object, sets up observability, and saves to storage\n *\n * @param id Server ID\n * @param options Registration options including URL, name, callback URL, and connection config\n * @returns Server ID\n */\n async registerServer(\n id: string,\n options: RegisterServerOptions\n ): Promise<string> {\n if (isBlockedUrl(options.url)) {\n throw new Error(\n `Blocked URL: ${options.url} — MCP client connections to private/internal addresses are not allowed`\n );\n }\n\n // Create the in-memory connection\n this.createConnection(id, options.url, {\n client: options.client,\n transport: {\n ...options.transport,\n type: options.transport?.type ?? (\"auto\" as TransportType)\n }\n });\n\n // Save to storage (exclude authProvider since it's recreated during restore)\n const { authProvider: _, ...transportWithoutAuth } =\n options.transport ?? {};\n this.saveServerToStorage({\n id,\n name: options.name,\n server_url: options.url,\n callback_url: options.callbackUrl ?? \"\",\n client_id: options.clientId ?? null,\n auth_url: options.authUrl ?? null,\n server_options: JSON.stringify({\n client: options.client,\n transport: transportWithoutAuth,\n retry: options.retry\n })\n });\n\n this._onServerStateChanged.fire();\n\n return id;\n }\n\n /**\n * Connect to an already registered MCP server and initialize the connection.\n *\n * For OAuth servers, returns `{ state: \"authenticating\", authUrl, clientId? }`.\n * The user must complete the OAuth flow via the authUrl, which triggers a\n * callback handled by `handleCallbackRequest()`.\n *\n * For non-OAuth servers, establishes the transport connection and returns\n * `{ state: \"connected\" }`. Call `discoverIfConnected()` afterwards to\n * discover capabilities and transition to \"ready\" state.\n *\n * @param id Server ID (must be registered first via registerServer())\n * @returns Connection result with current state and OAuth info (if applicable)\n */\n async connectToServer(id: string): Promise<MCPConnectionResult> {\n const conn = this.mcpConnections[id];\n if (!conn) {\n throw new Error(\n `Server ${id} is not registered. Call registerServer() first.`\n );\n }\n\n const error = await conn.init();\n this._onServerStateChanged.fire();\n\n switch (conn.connectionState) {\n case MCPConnectionState.FAILED:\n return {\n state: conn.connectionState,\n error: error ?? \"Unknown connection error\"\n };\n\n case MCPConnectionState.AUTHENTICATING: {\n const authUrl = conn.options.transport.authProvider?.authUrl;\n const redirectUrl = conn.options.transport.authProvider?.redirectUrl;\n\n if (!authUrl || !redirectUrl) {\n return {\n state: MCPConnectionState.FAILED,\n error: `OAuth configuration incomplete: missing ${!authUrl ? \"authUrl\" : \"redirectUrl\"}`\n };\n }\n\n const clientId = conn.options.transport.authProvider?.clientId;\n\n // Update storage with auth URL and client ID\n const servers = this.getServersFromStorage();\n const serverRow = servers.find((s) => s.id === id);\n if (serverRow) {\n this.saveServerToStorage({\n ...serverRow,\n auth_url: authUrl,\n client_id: clientId ?? null\n });\n // Broadcast again so clients receive the auth_url\n this._onServerStateChanged.fire();\n }\n\n this._onObservabilityEvent.fire({\n type: \"mcp:client:authorize\",\n payload: { serverId: id, authUrl, clientId },\n timestamp: Date.now()\n });\n\n return {\n state: conn.connectionState,\n authUrl,\n clientId\n };\n }\n\n case MCPConnectionState.CONNECTED:\n return { state: conn.connectionState };\n\n default:\n return {\n state: MCPConnectionState.FAILED,\n error: `Unexpected connection state after init: ${conn.connectionState}`\n };\n }\n }\n\n private extractServerIdFromState(state: string | null): string | null {\n if (!state) return null;\n const parts = state.split(\".\");\n return parts.length === 2 ? parts[1] : null;\n }\n\n isCallbackRequest(req: Request): boolean {\n if (req.method !== \"GET\") {\n return false;\n }\n\n const url = new URL(req.url);\n const state = url.searchParams.get(\"state\");\n const serverId = this.extractServerIdFromState(state);\n if (!serverId) {\n return false;\n }\n\n // Match by server ID AND verify the request origin + pathname matches the registered callback URL.\n // This prevents unrelated GET requests with a `state` param from being intercepted.\n const servers = this.getServersFromStorage();\n return servers.some((server) => {\n if (server.id !== serverId) return false;\n try {\n const storedUrl = new URL(server.callback_url);\n return (\n storedUrl.origin === url.origin && storedUrl.pathname === url.pathname\n );\n } catch {\n return false;\n }\n });\n }\n\n private validateCallbackRequest(\n req: Request\n ):\n | { valid: true; serverId: string; code: string; state: string }\n | { valid: false; serverId?: string; error: string } {\n const url = new URL(req.url);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n const errorDescription = url.searchParams.get(\"error_description\");\n\n // Early validation - return errors because we can't identify the connection\n if (!state) {\n return {\n valid: false,\n error: \"Unauthorized: no state provided\"\n };\n }\n\n const serverId = this.extractServerIdFromState(state);\n if (!serverId) {\n return {\n valid: false,\n error:\n \"No serverId found in state parameter. Expected format: {nonce}.{serverId}\"\n };\n }\n\n if (error) {\n return {\n serverId: serverId,\n valid: false,\n error: errorDescription || error\n };\n }\n\n if (!code) {\n return {\n serverId: serverId,\n valid: false,\n error: \"Unauthorized: no code provided\"\n };\n }\n\n const servers = this.getServersFromStorage();\n const serverExists = servers.some((server) => server.id === serverId);\n if (!serverExists) {\n return {\n serverId: serverId,\n valid: false,\n error: `No server found with id \"${serverId}\". Was the request matched with \\`isCallbackRequest()\\`?`\n };\n }\n\n if (this.mcpConnections[serverId] === undefined) {\n return {\n serverId: serverId,\n valid: false,\n error: `No connection found for serverId \"${serverId}\".`\n };\n }\n\n return {\n valid: true,\n serverId,\n code: code,\n state: state\n };\n }\n\n async handleCallbackRequest(req: Request): Promise<MCPOAuthCallbackResult> {\n const validation = this.validateCallbackRequest(req);\n\n if (!validation.valid) {\n if (validation.serverId && this.mcpConnections[validation.serverId]) {\n return this.failConnection(validation.serverId, validation.error);\n }\n\n return {\n serverId: validation.serverId,\n authSuccess: false,\n authError: validation.error\n };\n }\n\n const { serverId, code, state } = validation;\n const conn = this.mcpConnections[serverId]; // We have a valid connection - all errors from here should fail the connection\n\n try {\n if (!conn.options.transport.authProvider) {\n throw new Error(\n \"Trying to finalize authentication for a server connection without an authProvider\"\n );\n }\n\n const authProvider = conn.options.transport.authProvider;\n authProvider.serverId = serverId;\n\n // Two-phase state validation: check first (non-destructive), consume later\n // This prevents DoS attacks where attacker consumes valid state before legitimate callback\n const stateValidation = await authProvider.checkState(state);\n if (!stateValidation.valid) {\n throw new Error(stateValidation.error || \"Invalid state\");\n }\n\n // Already authenticated - just return success\n if (\n conn.connectionState === MCPConnectionState.READY ||\n conn.connectionState === MCPConnectionState.CONNECTED\n ) {\n this.clearServerAuthUrl(serverId);\n return { serverId, authSuccess: true };\n }\n\n if (conn.connectionState !== MCPConnectionState.AUTHENTICATING) {\n throw new Error(\n `Failed to authenticate: the client is in \"${conn.connectionState}\" state, expected \"authenticating\"`\n );\n }\n\n await authProvider.consumeState(state);\n await conn.completeAuthorization(code);\n await authProvider.deleteCodeVerifier();\n this.clearServerAuthUrl(serverId);\n conn.connectionError = null;\n this._onServerStateChanged.fire();\n\n return { serverId, authSuccess: true };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return this.failConnection(serverId, message);\n }\n }\n\n /**\n * Discover server capabilities if connection is in CONNECTED or READY state.\n * Transitions to DISCOVERING then READY (or CONNECTED on error).\n * Can be called to refresh server capabilities (e.g., from a UI refresh button).\n *\n * If called while a previous discovery is in-flight for the same server,\n * the previous discovery will be aborted.\n *\n * @param serverId The server ID to discover\n * @param options Optional configuration\n * @param options.timeoutMs Timeout in milliseconds (default: 30000)\n * @returns Result with current state and optional error, or undefined if connection not found\n */\n async discoverIfConnected(\n serverId: string,\n options: { timeoutMs?: number } = {}\n ): Promise<MCPDiscoverResult | undefined> {\n const conn = this.mcpConnections[serverId];\n if (!conn) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:discover\",\n payload: {},\n timestamp: Date.now()\n });\n return undefined;\n }\n\n // Delegate to connection's discover method which handles cancellation and timeout\n const result = await conn.discover(options);\n this._onServerStateChanged.fire();\n\n return {\n ...result,\n state: conn.connectionState\n };\n }\n\n /**\n * Establish connection in the background after OAuth completion.\n * This method connects to the server and discovers its capabilities.\n * The connection is automatically tracked so that `waitForConnections()`\n * will include it.\n * @param serverId The server ID to establish connection for\n */\n async establishConnection(serverId: string): Promise<void> {\n const promise = this._doEstablishConnection(serverId);\n this._trackConnection(serverId, promise);\n return promise;\n }\n\n private async _doEstablishConnection(serverId: string): Promise<void> {\n const conn = this.mcpConnections[serverId];\n if (!conn) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:preconnect\",\n payload: { serverId },\n timestamp: Date.now()\n });\n return;\n }\n\n // Skip if already discovering or ready - prevents duplicate work\n if (\n conn.connectionState === MCPConnectionState.DISCOVERING ||\n conn.connectionState === MCPConnectionState.READY\n ) {\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: conn.url.toString(),\n transport: conn.options.transport.type || \"unknown\",\n state: conn.connectionState\n },\n timestamp: Date.now()\n });\n return;\n }\n\n const retry = this.getServerRetryOptions(serverId);\n const maxAttempts = retry?.maxAttempts ?? 3;\n const baseDelayMs = retry?.baseDelayMs ?? 500;\n const maxDelayMs = retry?.maxDelayMs ?? 5000;\n\n const connectResult = await tryN(\n maxAttempts,\n async () => this.connectToServer(serverId),\n { baseDelayMs, maxDelayMs }\n );\n this._onServerStateChanged.fire();\n\n if (connectResult.state === MCPConnectionState.CONNECTED) {\n await this.discoverIfConnected(serverId);\n }\n\n this._onObservabilityEvent.fire({\n type: \"mcp:client:connect\",\n payload: {\n url: conn.url.toString(),\n transport: conn.options.transport.type || \"unknown\",\n state: conn.connectionState\n },\n timestamp: Date.now()\n });\n }\n\n /**\n * Configure OAuth callback handling\n * @param config OAuth callback configuration\n */\n configureOAuthCallback(config: MCPClientOAuthCallbackConfig): void {\n this._oauthCallbackConfig = config;\n }\n\n /**\n * Get the current OAuth callback configuration\n * @returns The current OAuth callback configuration\n */\n getOAuthCallbackConfig(): MCPClientOAuthCallbackConfig | undefined {\n return this._oauthCallbackConfig;\n }\n\n /**\n * @returns namespaced list of tools\n */\n listTools(): NamespacedData[\"tools\"] {\n return getNamespacedData(this.mcpConnections, \"tools\");\n }\n\n /**\n * Lazy-loads the jsonSchema function from the AI SDK.\n *\n * This defers importing the \"ai\" package until it's actually needed, which helps reduce\n * initial bundle size and startup time. The jsonSchema function is required for converting\n * MCP tools into AI SDK tool definitions via getAITools().\n *\n * @internal This method is for internal use only. It's automatically called before operations\n * that need jsonSchema (like getAITools() or OAuth flows). External consumers should not need\n * to call this directly.\n */\n async ensureJsonSchema() {\n if (!this.jsonSchema) {\n const { jsonSchema } = await import(\"ai\");\n this.jsonSchema = jsonSchema;\n }\n }\n\n /**\n * @returns a set of tools that you can use with the AI SDK\n */\n getAITools(): ToolSet {\n if (!this.jsonSchema) {\n throw new Error(\"jsonSchema not initialized.\");\n }\n\n // Warn if tools are being read from non-ready connections\n for (const [id, conn] of Object.entries(this.mcpConnections)) {\n if (\n conn.connectionState !== MCPConnectionState.READY &&\n conn.connectionState !== MCPConnectionState.AUTHENTICATING\n ) {\n console.warn(\n `[getAITools] WARNING: Reading tools from connection ${id} in state \"${conn.connectionState}\". Tools may not be loaded yet.`\n );\n }\n }\n\n const entries: [string, ToolSet[string]][] = [];\n for (const tool of getNamespacedData(this.mcpConnections, \"tools\")) {\n try {\n const toolKey = `tool_${tool.serverId.replace(/-/g, \"\")}_${tool.name}`;\n entries.push([\n toolKey,\n {\n description: tool.description,\n execute: async (args) => {\n const result = await this.callTool({\n arguments: args,\n name: tool.name,\n serverId: tool.serverId\n });\n if (result.isError) {\n const content = result.content as\n | Array<{ type: string; text?: string }>\n | undefined;\n const textContent = content?.[0];\n const message =\n textContent?.type === \"text\" && textContent.text\n ? textContent.text\n : \"Tool call failed\";\n throw new Error(message);\n }\n return result;\n },\n inputSchema: tool.inputSchema\n ? this.jsonSchema!(tool.inputSchema as JSONSchema7)\n : this.jsonSchema!({ type: \"object\" } as JSONSchema7),\n outputSchema: tool.outputSchema\n ? this.jsonSchema!(tool.outputSchema as JSONSchema7)\n : undefined\n }\n ]);\n } catch (e) {\n console.warn(\n `[getAITools] Skipping tool \"${tool.name}\" from \"${tool.serverId}\": ${e}`\n );\n }\n }\n return Object.fromEntries(entries);\n }\n\n /**\n * @deprecated this has been renamed to getAITools(), and unstable_getAITools will be removed in the next major version\n * @returns a set of tools that you can use with the AI SDK\n */\n unstable_getAITools(): ToolSet {\n if (!this._didWarnAboutUnstableGetAITools) {\n this._didWarnAboutUnstableGetAITools = true;\n console.warn(\n \"unstable_getAITools is deprecated, use getAITools instead. unstable_getAITools will be removed in the next major version.\"\n );\n }\n return this.getAITools();\n }\n\n /**\n * Closes all active in-memory connections to MCP servers.\n *\n * Note: This only closes the transport connections - it does NOT remove\n * servers from storage. Servers will still be listed and their callback\n * URLs will still match incoming OAuth requests.\n *\n * Use removeServer() instead if you want to fully clean up a server\n * (closes connection AND removes from storage).\n */\n async closeAllConnections() {\n const ids = Object.keys(this.mcpConnections);\n\n // Clear all pending connection tracking\n this._pendingConnections.clear();\n\n // Cancel all in-flight discoveries\n for (const id of ids) {\n this.mcpConnections[id].cancelDiscovery();\n }\n\n await Promise.all(\n ids.map(async (id) => {\n await this.mcpConnections[id].client.close();\n })\n );\n // Dispose all per-connection subscriptions\n for (const id of ids) {\n const store = this._connectionDisposables.get(id);\n if (store) store.dispose();\n this._connectionDisposables.delete(id);\n delete this.mcpConnections[id];\n }\n }\n\n /**\n * Closes a connection to an MCP server\n * @param id The id of the connection to close\n */\n async closeConnection(id: string) {\n if (!this.mcpConnections[id]) {\n throw new Error(`Connection with id \"${id}\" does not exist.`);\n }\n\n // Cancel any in-flight discovery\n this.mcpConnections[id].cancelDiscovery();\n\n // Remove from pending so waitForConnections() doesn't block on a closed server\n this._pendingConnections.delete(id);\n\n await this.mcpConnections[id].client.close();\n delete this.mcpConnections[id];\n\n const store = this._connectionDisposables.get(id);\n if (store) store.dispose();\n this._connectionDisposables.delete(id);\n }\n\n /**\n * Remove an MCP server - closes connection if active and removes from storage.\n */\n async removeServer(serverId: string): Promise<void> {\n if (this.mcpConnections[serverId]) {\n try {\n await this.closeConnection(serverId);\n } catch (_e) {\n // Ignore errors when closing\n }\n }\n this.removeServerFromStorage(serverId);\n this._onServerStateChanged.fire();\n }\n\n /**\n * List all MCP servers from storage\n */\n listServers(): MCPServerRow[] {\n return this.getServersFromStorage();\n }\n\n /**\n * Dispose the manager and all resources.\n */\n async dispose(): Promise<void> {\n try {\n await this.closeAllConnections();\n } finally {\n // Dispose manager-level emitters\n this._onServerStateChanged.dispose();\n this._onObservabilityEvent.dispose();\n }\n }\n\n /**\n * @returns namespaced list of prompts\n */\n listPrompts(): NamespacedData[\"prompts\"] {\n return getNamespacedData(this.mcpConnections, \"prompts\");\n }\n\n /**\n * @returns namespaced list of tools\n */\n listResources(): NamespacedData[\"resources\"] {\n return getNamespacedData(this.mcpConnections, \"resources\");\n }\n\n /**\n * @returns namespaced list of resource templates\n */\n listResourceTemplates(): NamespacedData[\"resourceTemplates\"] {\n return getNamespacedData(this.mcpConnections, \"resourceTemplates\");\n }\n\n /**\n * Namespaced version of callTool\n */\n async callTool(\n params: CallToolRequest[\"params\"] & { serverId: string },\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ) {\n const { serverId, ...mcpParams } = params;\n const unqualifiedName = mcpParams.name.replace(`${serverId}.`, \"\");\n return this.mcpConnections[serverId].client.callTool(\n {\n ...mcpParams,\n name: unqualifiedName\n },\n resultSchema,\n options\n );\n }\n\n /**\n * Namespaced version of readResource\n */\n readResource(\n params: ReadResourceRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.readResource(\n params,\n options\n );\n }\n\n /**\n * Namespaced version of getPrompt\n */\n getPrompt(\n params: GetPromptRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.getPrompt(\n params,\n options\n );\n }\n}\n\ntype NamespacedData = {\n tools: (Tool & { serverId: string })[];\n prompts: (Prompt & { serverId: string })[];\n resources: (Resource & { serverId: string })[];\n resourceTemplates: (ResourceTemplate & { serverId: string })[];\n};\n\nexport function getNamespacedData<T extends keyof NamespacedData>(\n mcpClients: Record<string, MCPClientConnection>,\n type: T\n): NamespacedData[T] {\n const sets = Object.entries(mcpClients).map(([name, conn]) => {\n return { data: conn[type], name };\n });\n\n const namespacedData = sets.flatMap(({ name: serverId, data }) => {\n return data.map((item) => {\n return {\n ...item,\n // we add a serverId so we can easily pull it out and send the tool call to the right server\n serverId\n };\n });\n });\n\n return namespacedData as NamespacedData[T]; // Type assertion needed due to TS limitations with conditional return types\n}\n"],"mappings":"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"}
|