@cuylabs/agent-core 0.11.0 → 0.13.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/{chunk-GFTW23FV.js → chunk-BGG2HVIR.js} +4 -2
- package/dist/{chunk-TOTDGK3P.js → chunk-CSR75JVC.js} +4 -5
- package/dist/{chunk-ICZ66572.js → chunk-CZ5XOVDV.js} +40 -9
- package/dist/{chunk-2O4MCSQS.js → chunk-FYC33XFI.js} +31 -10
- package/dist/{chunk-WBPOZ7CL.js → chunk-HNEI7JVE.js} +114 -38
- package/dist/{chunk-SPILYYDF.js → chunk-I7EJGKUP.js} +79 -7
- package/dist/{chunk-SSFBF3US.js → chunk-JPBFAQNS.js} +7 -12
- package/dist/{chunk-5FMSGQVX.js → chunk-JZRLCTSD.js} +8 -2
- package/dist/{chunk-V4RFNEET.js → chunk-MLTJHUVG.js} +34 -16
- package/dist/{chunk-QAL3OMI3.js → chunk-MO3N6M32.js} +4 -1
- package/dist/{chunk-CMYN2RCB.js → chunk-NWQUZWLT.js} +13 -7
- package/dist/{chunk-MXAP4UG6.js → chunk-QJV5XPPS.js} +238 -86
- package/dist/{chunk-T4UIX5D7.js → chunk-S6AKEPAX.js} +9 -3
- package/dist/{chunk-N3VX7FEE.js → chunk-STDJYXYK.js} +1 -4
- package/dist/{chunk-6HZBHFOL.js → chunk-TPZ37IWI.js} +10 -1
- package/dist/{chunk-NDZWXCBZ.js → chunk-TZ4VA4VX.js} +33 -11
- package/dist/chunk-US7S4FYW.js +610 -0
- package/dist/{chunk-RN6WZEUF.js → chunk-WI5JFEAI.js} +71 -36
- package/dist/{chunk-5NVVNXPQ.js → chunk-ZKEC7MFQ.js} +5 -30
- package/dist/dispatch/index.d.ts +5 -3
- package/dist/dispatch/index.js +3 -3
- package/dist/execution/index.d.ts +6 -4
- package/dist/execution/index.js +7 -7
- package/dist/index.d.ts +8 -5
- package/dist/index.js +119 -116
- package/dist/inference/errors/index.js +1 -1
- package/dist/inference/index.d.ts +6 -4
- package/dist/inference/index.js +6 -6
- package/dist/{instance-DzPiv6EK.d.ts → instance-N5VhcNT2.d.ts} +45 -7
- package/dist/logger/index.js +1 -1
- package/dist/mcp/index.d.ts +116 -3
- package/dist/mcp/index.js +6 -2
- package/dist/middleware/index.d.ts +5 -3
- package/dist/middleware/index.js +3 -3
- package/dist/{model-messages-CJfwfzGe.d.ts → model-messages-DnsiSiZj.d.ts} +1 -1
- package/dist/models/index.js +2 -2
- package/dist/models/reasoning/index.js +2 -2
- package/dist/plugin/index.d.ts +4 -2
- package/dist/plugin/index.js +1 -1
- package/dist/profiles/index.d.ts +4 -2
- package/dist/profiles/index.js +1 -1
- package/dist/prompt/index.d.ts +5 -3
- package/dist/prompt/index.js +2 -2
- package/dist/safety/index.d.ts +5 -3
- package/dist/safety/index.js +1 -1
- package/dist/skill/index.d.ts +5 -3
- package/dist/skill/index.js +2 -2
- package/dist/storage/index.d.ts +5 -3
- package/dist/storage/index.js +1 -1
- package/dist/subagents/index.d.ts +4 -2
- package/dist/subagents/index.js +4 -4
- package/dist/team/index.d.ts +5 -3
- package/dist/team/index.js +1 -1
- package/dist/tool/index.d.ts +5 -3
- package/dist/tool/index.js +2 -2
- package/dist/{types-Bj_J8u_W.d.ts → types-DMjoFKKv.d.ts} +55 -7
- package/package.json +1 -6
- package/dist/chunk-ROTGCYDW.js +0 -221
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
import {
|
|
2
|
+
silentLogger
|
|
3
|
+
} from "./chunk-S6AKEPAX.js";
|
|
4
|
+
|
|
5
|
+
// src/mcp/manager.ts
|
|
6
|
+
import {
|
|
7
|
+
dynamicTool,
|
|
8
|
+
jsonSchema
|
|
9
|
+
} from "ai";
|
|
10
|
+
|
|
11
|
+
// src/mcp/modules.ts
|
|
12
|
+
var mcpClientModule;
|
|
13
|
+
var stdioModule;
|
|
14
|
+
var streamableHttpModule;
|
|
15
|
+
var sseModule;
|
|
16
|
+
async function getMcpClientModule() {
|
|
17
|
+
if (!mcpClientModule) {
|
|
18
|
+
try {
|
|
19
|
+
mcpClientModule = await import("@modelcontextprotocol/sdk/client/index.js");
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error(
|
|
22
|
+
"MCP support requires @modelcontextprotocol/sdk. Install it with: npm install @modelcontextprotocol/sdk"
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return mcpClientModule;
|
|
27
|
+
}
|
|
28
|
+
async function getStdioClientModule() {
|
|
29
|
+
if (!stdioModule) {
|
|
30
|
+
try {
|
|
31
|
+
stdioModule = await import("@modelcontextprotocol/sdk/client/stdio.js");
|
|
32
|
+
} catch {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"Stdio MCP transport requires @modelcontextprotocol/sdk. Install it with: npm install @modelcontextprotocol/sdk"
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return stdioModule;
|
|
39
|
+
}
|
|
40
|
+
async function getStreamableHttpClientModule() {
|
|
41
|
+
if (!streamableHttpModule) {
|
|
42
|
+
try {
|
|
43
|
+
streamableHttpModule = await import("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
44
|
+
} catch {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"HTTP MCP transport requires @modelcontextprotocol/sdk. Install it with: npm install @modelcontextprotocol/sdk"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return streamableHttpModule;
|
|
51
|
+
}
|
|
52
|
+
async function getSseClientModule() {
|
|
53
|
+
if (!sseModule) {
|
|
54
|
+
try {
|
|
55
|
+
sseModule = await import("@modelcontextprotocol/sdk/client/sse.js");
|
|
56
|
+
} catch {
|
|
57
|
+
throw new Error(
|
|
58
|
+
"SSE MCP transport requires @modelcontextprotocol/sdk. Install it with: npm install @modelcontextprotocol/sdk"
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return sseModule;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/mcp/manager.ts
|
|
66
|
+
var CLIENT_VERSION = "1.0.0";
|
|
67
|
+
function mcpToModelOutput(options) {
|
|
68
|
+
const result = options.output;
|
|
69
|
+
if (!("content" in result) || !Array.isArray(result.content)) {
|
|
70
|
+
return {
|
|
71
|
+
type: "json",
|
|
72
|
+
value: result
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
type: "content",
|
|
77
|
+
value: result.content.map((part) => {
|
|
78
|
+
if (part.type === "text" && "text" in part) {
|
|
79
|
+
return { type: "text", text: part.text };
|
|
80
|
+
}
|
|
81
|
+
if (part.type === "image" && "data" in part && "mimeType" in part) {
|
|
82
|
+
return {
|
|
83
|
+
type: "file-data",
|
|
84
|
+
data: part.data,
|
|
85
|
+
mediaType: part.mimeType
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
type: "text",
|
|
90
|
+
text: JSON.stringify(part)
|
|
91
|
+
};
|
|
92
|
+
})
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function toolToAiSdkTool(options) {
|
|
96
|
+
const { client, tool } = options;
|
|
97
|
+
const inputSchema = {
|
|
98
|
+
...tool.inputSchema,
|
|
99
|
+
properties: tool.inputSchema.properties ?? {},
|
|
100
|
+
additionalProperties: false
|
|
101
|
+
};
|
|
102
|
+
return dynamicTool({
|
|
103
|
+
description: tool.description,
|
|
104
|
+
...tool.title ? { title: tool.title } : {},
|
|
105
|
+
inputSchema: jsonSchema(inputSchema),
|
|
106
|
+
execute: async (params) => {
|
|
107
|
+
return client.callTool({
|
|
108
|
+
name: tool.name,
|
|
109
|
+
arguments: params
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
toModelOutput: mcpToModelOutput
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
var DefaultMCPManager = class {
|
|
116
|
+
config;
|
|
117
|
+
connections = /* @__PURE__ */ new Map();
|
|
118
|
+
log;
|
|
119
|
+
toolCache;
|
|
120
|
+
resourceCache;
|
|
121
|
+
resourceTemplateCache;
|
|
122
|
+
promptCache;
|
|
123
|
+
constructor(config, logger) {
|
|
124
|
+
this.config = config;
|
|
125
|
+
this.log = logger?.child("mcp") ?? silentLogger;
|
|
126
|
+
}
|
|
127
|
+
async connect() {
|
|
128
|
+
if (this.connections.size > 0) {
|
|
129
|
+
await this.close();
|
|
130
|
+
}
|
|
131
|
+
const results = /* @__PURE__ */ new Map();
|
|
132
|
+
const connectPromises = Object.entries(this.config).map(
|
|
133
|
+
async ([name, serverConfig]) => {
|
|
134
|
+
if (serverConfig.enabled === false) {
|
|
135
|
+
const status = { status: "disabled" };
|
|
136
|
+
this.connections.set(name, {
|
|
137
|
+
client: void 0,
|
|
138
|
+
config: serverConfig,
|
|
139
|
+
status
|
|
140
|
+
});
|
|
141
|
+
results.set(name, status);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
results.set(name, { status: "connecting" });
|
|
145
|
+
try {
|
|
146
|
+
const { client, toolCount } = await this.createClient(
|
|
147
|
+
name,
|
|
148
|
+
serverConfig
|
|
149
|
+
);
|
|
150
|
+
const status = { status: "connected", toolCount };
|
|
151
|
+
this.connections.set(name, { client, config: serverConfig, status });
|
|
152
|
+
results.set(name, status);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
155
|
+
const status = {
|
|
156
|
+
status: "error",
|
|
157
|
+
error: errorMessage
|
|
158
|
+
};
|
|
159
|
+
results.set(name, status);
|
|
160
|
+
this.connections.set(name, {
|
|
161
|
+
client: void 0,
|
|
162
|
+
config: serverConfig,
|
|
163
|
+
status
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
await Promise.all(connectPromises);
|
|
169
|
+
this.invalidateCaches();
|
|
170
|
+
return results;
|
|
171
|
+
}
|
|
172
|
+
async getTools() {
|
|
173
|
+
await this.ensureInitialized();
|
|
174
|
+
if (this.toolCache) {
|
|
175
|
+
return this.toolCache;
|
|
176
|
+
}
|
|
177
|
+
const allTools = {};
|
|
178
|
+
await Promise.all(
|
|
179
|
+
Array.from(this.connections.entries()).map(
|
|
180
|
+
async ([serverName, connection]) => {
|
|
181
|
+
if (connection.status.status !== "connected" || !connection.client) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
const tools = await this.listAllTools(
|
|
186
|
+
connection.client,
|
|
187
|
+
connection.config
|
|
188
|
+
);
|
|
189
|
+
for (const tool of tools) {
|
|
190
|
+
allTools[`${serverName}__${tool.name}`] = toolToAiSdkTool({
|
|
191
|
+
serverName,
|
|
192
|
+
client: connection.client,
|
|
193
|
+
tool
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
this.log.warn(`Failed to get tools from ${serverName}`, {
|
|
198
|
+
error: error instanceof Error ? error.message : String(error)
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
);
|
|
204
|
+
this.toolCache = allTools;
|
|
205
|
+
return allTools;
|
|
206
|
+
}
|
|
207
|
+
async listResources() {
|
|
208
|
+
await this.ensureInitialized();
|
|
209
|
+
if (this.resourceCache) {
|
|
210
|
+
return this.resourceCache;
|
|
211
|
+
}
|
|
212
|
+
const resources = await this.collectAcrossServers({
|
|
213
|
+
fetch: (client, config) => this.listAllResources(client, config),
|
|
214
|
+
map: (server, resource) => ({ server, ...resource }),
|
|
215
|
+
logLabel: "resources"
|
|
216
|
+
});
|
|
217
|
+
this.resourceCache = resources;
|
|
218
|
+
return resources;
|
|
219
|
+
}
|
|
220
|
+
async listResourceTemplates() {
|
|
221
|
+
await this.ensureInitialized();
|
|
222
|
+
if (this.resourceTemplateCache) {
|
|
223
|
+
return this.resourceTemplateCache;
|
|
224
|
+
}
|
|
225
|
+
const templates = await this.collectAcrossServers({
|
|
226
|
+
fetch: (client, config) => this.listAllResourceTemplates(client, config),
|
|
227
|
+
map: (server, template) => ({ server, ...template }),
|
|
228
|
+
logLabel: "resource templates"
|
|
229
|
+
});
|
|
230
|
+
this.resourceTemplateCache = templates;
|
|
231
|
+
return templates;
|
|
232
|
+
}
|
|
233
|
+
async readResource(serverName, uri) {
|
|
234
|
+
const connection = await this.getConnectedConnection(serverName);
|
|
235
|
+
return connection.client.readResource(
|
|
236
|
+
{ uri },
|
|
237
|
+
this.requestOptions(connection.config)
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
async listPrompts() {
|
|
241
|
+
await this.ensureInitialized();
|
|
242
|
+
if (this.promptCache) {
|
|
243
|
+
return this.promptCache;
|
|
244
|
+
}
|
|
245
|
+
const prompts = await this.collectAcrossServers({
|
|
246
|
+
fetch: (client, config) => this.listAllPrompts(client, config),
|
|
247
|
+
map: (server, prompt) => ({ server, ...prompt }),
|
|
248
|
+
logLabel: "prompts"
|
|
249
|
+
});
|
|
250
|
+
this.promptCache = prompts;
|
|
251
|
+
return prompts;
|
|
252
|
+
}
|
|
253
|
+
async getPrompt(serverName, name, args) {
|
|
254
|
+
const connection = await this.getConnectedConnection(serverName);
|
|
255
|
+
return connection.client.getPrompt(
|
|
256
|
+
{ name, arguments: args },
|
|
257
|
+
this.requestOptions(connection.config)
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
getStatus(serverName) {
|
|
261
|
+
const connection = this.connections.get(serverName);
|
|
262
|
+
return connection?.status ?? { status: "disconnected" };
|
|
263
|
+
}
|
|
264
|
+
getAllStatus() {
|
|
265
|
+
const status = /* @__PURE__ */ new Map();
|
|
266
|
+
for (const [name, connection] of this.connections) {
|
|
267
|
+
status.set(name, connection.status);
|
|
268
|
+
}
|
|
269
|
+
return status;
|
|
270
|
+
}
|
|
271
|
+
async close() {
|
|
272
|
+
const closePromises = Array.from(this.connections.values()).map(
|
|
273
|
+
async (connection) => {
|
|
274
|
+
if (connection.client) {
|
|
275
|
+
try {
|
|
276
|
+
await connection.client.close();
|
|
277
|
+
} catch {
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
await Promise.all(closePromises);
|
|
283
|
+
this.connections.clear();
|
|
284
|
+
this.invalidateCaches();
|
|
285
|
+
}
|
|
286
|
+
isConnected() {
|
|
287
|
+
for (const connection of this.connections.values()) {
|
|
288
|
+
if (connection.status.status === "connected") {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
invalidateCaches() {
|
|
295
|
+
this.toolCache = void 0;
|
|
296
|
+
this.resourceCache = void 0;
|
|
297
|
+
this.resourceTemplateCache = void 0;
|
|
298
|
+
this.promptCache = void 0;
|
|
299
|
+
}
|
|
300
|
+
async ensureInitialized() {
|
|
301
|
+
if (this.connections.size === 0) {
|
|
302
|
+
await this.connect();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
requestOptions(config) {
|
|
306
|
+
return { timeout: config.timeout ?? 3e4 };
|
|
307
|
+
}
|
|
308
|
+
async collectAcrossServers(options) {
|
|
309
|
+
const collected = [];
|
|
310
|
+
await Promise.all(
|
|
311
|
+
Array.from(this.connections.entries()).map(
|
|
312
|
+
async ([serverName, connection]) => {
|
|
313
|
+
if (connection.status.status !== "connected" || !connection.client) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
const items = await options.fetch(
|
|
318
|
+
connection.client,
|
|
319
|
+
connection.config
|
|
320
|
+
);
|
|
321
|
+
for (const item of items) {
|
|
322
|
+
collected.push(options.map(serverName, item));
|
|
323
|
+
}
|
|
324
|
+
} catch (error) {
|
|
325
|
+
this.log.warn(
|
|
326
|
+
`Failed to get ${options.logLabel} from ${serverName}`,
|
|
327
|
+
{
|
|
328
|
+
error: error instanceof Error ? error.message : String(error)
|
|
329
|
+
}
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
return collected;
|
|
336
|
+
}
|
|
337
|
+
async getConnectedConnection(serverName) {
|
|
338
|
+
await this.ensureInitialized();
|
|
339
|
+
const connection = this.connections.get(serverName);
|
|
340
|
+
if (!connection) {
|
|
341
|
+
throw new Error(`MCP server "${serverName}" is not configured.`);
|
|
342
|
+
}
|
|
343
|
+
if (connection.status.status !== "connected" || !connection.client) {
|
|
344
|
+
const reason = connection.status.status === "error" ? connection.status.error : connection.status.status;
|
|
345
|
+
throw new Error(
|
|
346
|
+
`MCP server "${serverName}" is not connected${reason ? `: ${reason}` : "."}`
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
return { client: connection.client, config: connection.config };
|
|
350
|
+
}
|
|
351
|
+
async collectPaginated(options) {
|
|
352
|
+
const items = [];
|
|
353
|
+
let cursor;
|
|
354
|
+
do {
|
|
355
|
+
const page = await options.fetchPage(cursor);
|
|
356
|
+
const batch = page[options.itemsKey];
|
|
357
|
+
if (Array.isArray(batch)) {
|
|
358
|
+
items.push(...batch);
|
|
359
|
+
}
|
|
360
|
+
cursor = page.nextCursor;
|
|
361
|
+
} while (cursor);
|
|
362
|
+
return items;
|
|
363
|
+
}
|
|
364
|
+
listAllTools(client, config) {
|
|
365
|
+
return this.collectPaginated({
|
|
366
|
+
fetchPage: (cursor) => client.listTools(
|
|
367
|
+
cursor ? { cursor } : void 0,
|
|
368
|
+
this.requestOptions(config)
|
|
369
|
+
),
|
|
370
|
+
itemsKey: "tools"
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
listAllResources(client, config) {
|
|
374
|
+
return this.collectPaginated({
|
|
375
|
+
fetchPage: (cursor) => client.listResources(
|
|
376
|
+
cursor ? { cursor } : void 0,
|
|
377
|
+
this.requestOptions(config)
|
|
378
|
+
),
|
|
379
|
+
itemsKey: "resources"
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
listAllResourceTemplates(client, config) {
|
|
383
|
+
return this.collectPaginated({
|
|
384
|
+
fetchPage: (cursor) => client.listResourceTemplates(
|
|
385
|
+
cursor ? { cursor } : void 0,
|
|
386
|
+
this.requestOptions(config)
|
|
387
|
+
),
|
|
388
|
+
itemsKey: "resourceTemplates"
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
listAllPrompts(client, config) {
|
|
392
|
+
return this.collectPaginated({
|
|
393
|
+
fetchPage: (cursor) => client.listPrompts(
|
|
394
|
+
cursor ? { cursor } : void 0,
|
|
395
|
+
this.requestOptions(config)
|
|
396
|
+
),
|
|
397
|
+
itemsKey: "prompts"
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
async createClient(name, config) {
|
|
401
|
+
const { Client } = await getMcpClientModule();
|
|
402
|
+
const client = new Client(
|
|
403
|
+
{
|
|
404
|
+
name: config.name ?? name,
|
|
405
|
+
version: CLIENT_VERSION
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
...config.capabilities ? { capabilities: config.capabilities } : {},
|
|
409
|
+
listChanged: {
|
|
410
|
+
tools: {
|
|
411
|
+
autoRefresh: false,
|
|
412
|
+
onChanged: () => this.invalidateCaches()
|
|
413
|
+
},
|
|
414
|
+
prompts: {
|
|
415
|
+
autoRefresh: false,
|
|
416
|
+
onChanged: () => this.invalidateCaches()
|
|
417
|
+
},
|
|
418
|
+
resources: {
|
|
419
|
+
autoRefresh: false,
|
|
420
|
+
onChanged: () => this.invalidateCaches()
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
);
|
|
425
|
+
if (config.onUncaughtError) {
|
|
426
|
+
client.onerror = (error) => config.onUncaughtError?.(error);
|
|
427
|
+
}
|
|
428
|
+
const transport = await this.createTransport(config);
|
|
429
|
+
if (config.onUncaughtError) {
|
|
430
|
+
transport.onerror = (error) => config.onUncaughtError?.(error);
|
|
431
|
+
}
|
|
432
|
+
await client.connect(transport, this.requestOptions(config));
|
|
433
|
+
const tools = await this.listAllTools(client, config);
|
|
434
|
+
return { client, toolCount: tools.length };
|
|
435
|
+
}
|
|
436
|
+
async createTransport(config) {
|
|
437
|
+
if (config.transport === "stdio") {
|
|
438
|
+
const { StdioClientTransport } = await getStdioClientModule();
|
|
439
|
+
return new StdioClientTransport({
|
|
440
|
+
command: config.command,
|
|
441
|
+
args: config.args,
|
|
442
|
+
env: config.env,
|
|
443
|
+
cwd: config.cwd
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
const requestInit = {
|
|
447
|
+
...config.headers ? { headers: config.headers } : {},
|
|
448
|
+
...config.redirect ? { redirect: config.redirect } : {}
|
|
449
|
+
};
|
|
450
|
+
if (config.transport === "http") {
|
|
451
|
+
const { StreamableHTTPClientTransport } = await getStreamableHttpClientModule();
|
|
452
|
+
return new StreamableHTTPClientTransport(new URL(config.url), {
|
|
453
|
+
...config.authProvider ? { authProvider: config.authProvider } : {},
|
|
454
|
+
requestInit,
|
|
455
|
+
...config.fetch ? { fetch: config.fetch } : {}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
const { SSEClientTransport } = await getSseClientModule();
|
|
459
|
+
return new SSEClientTransport(new URL(config.url), {
|
|
460
|
+
...config.authProvider ? { authProvider: config.authProvider } : {},
|
|
461
|
+
requestInit,
|
|
462
|
+
...config.fetch ? { fetch: config.fetch } : {}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
// src/mcp/auth.ts
|
|
468
|
+
var ClientCredentialsProvider = class {
|
|
469
|
+
_tokens;
|
|
470
|
+
_expiresAt;
|
|
471
|
+
_options;
|
|
472
|
+
constructor(options) {
|
|
473
|
+
this._options = options;
|
|
474
|
+
}
|
|
475
|
+
// ── OAuthClientProvider: required ─────────────────────────────────────────
|
|
476
|
+
get redirectUrl() {
|
|
477
|
+
return void 0;
|
|
478
|
+
}
|
|
479
|
+
get clientMetadata() {
|
|
480
|
+
return {
|
|
481
|
+
redirect_uris: [],
|
|
482
|
+
grant_types: ["client_credentials"],
|
|
483
|
+
token_endpoint_auth_method: "client_secret_basic",
|
|
484
|
+
scope: this._options.scope
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
clientInformation() {
|
|
488
|
+
return {
|
|
489
|
+
client_id: this._options.clientId,
|
|
490
|
+
client_secret: this._options.clientSecret
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
saveClientInformation() {
|
|
494
|
+
}
|
|
495
|
+
async tokens() {
|
|
496
|
+
const bufferMs = (this._options.expiryBufferSeconds ?? 60) * 1e3;
|
|
497
|
+
const hasValid = this._tokens !== void 0 && (this._expiresAt === void 0 || Date.now() < this._expiresAt - bufferMs);
|
|
498
|
+
if (hasValid) {
|
|
499
|
+
return this._tokens;
|
|
500
|
+
}
|
|
501
|
+
return this._fetchTokens();
|
|
502
|
+
}
|
|
503
|
+
async saveTokens(tokens) {
|
|
504
|
+
this._tokens = tokens;
|
|
505
|
+
this._expiresAt = tokens.expires_in !== void 0 ? Date.now() + tokens.expires_in * 1e3 : void 0;
|
|
506
|
+
}
|
|
507
|
+
redirectToAuthorization(_authorizationUrl) {
|
|
508
|
+
throw new Error(
|
|
509
|
+
"ClientCredentialsProvider: redirectToAuthorization() was called unexpectedly. Verify that the tokenUrl, clientId, clientSecret, and scope are correct."
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
saveCodeVerifier() {
|
|
513
|
+
}
|
|
514
|
+
codeVerifier() {
|
|
515
|
+
throw new Error(
|
|
516
|
+
"ClientCredentialsProvider: codeVerifier() is not used for client_credentials."
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
prepareTokenRequest(scope) {
|
|
520
|
+
const params = new URLSearchParams({ grant_type: "client_credentials" });
|
|
521
|
+
const effectiveScope = scope ?? this._options.scope;
|
|
522
|
+
if (effectiveScope) params.set("scope", effectiveScope);
|
|
523
|
+
return params;
|
|
524
|
+
}
|
|
525
|
+
addClientAuthentication(headers) {
|
|
526
|
+
const encoded = `${encodeURIComponent(this._options.clientId)}:${encodeURIComponent(this._options.clientSecret)}`;
|
|
527
|
+
headers.set("Authorization", `Basic ${btoa(encoded)}`);
|
|
528
|
+
}
|
|
529
|
+
// ── OAuthClientProvider: optional ─────────────────────────────────────────
|
|
530
|
+
invalidateCredentials(scope) {
|
|
531
|
+
if (scope === "all" || scope === "tokens") {
|
|
532
|
+
this._tokens = void 0;
|
|
533
|
+
this._expiresAt = void 0;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
// ── Private ────────────────────────────────────────────────────────────────
|
|
537
|
+
async _fetchTokens() {
|
|
538
|
+
const { tokenUrl, scope } = this._options;
|
|
539
|
+
const params = this.prepareTokenRequest(scope);
|
|
540
|
+
const headers = new Headers({
|
|
541
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
542
|
+
});
|
|
543
|
+
this.addClientAuthentication(headers);
|
|
544
|
+
const response = await fetch(tokenUrl, {
|
|
545
|
+
method: "POST",
|
|
546
|
+
headers,
|
|
547
|
+
body: params.toString()
|
|
548
|
+
});
|
|
549
|
+
if (!response.ok) {
|
|
550
|
+
const body = await response.text().catch(() => "");
|
|
551
|
+
throw new Error(
|
|
552
|
+
`ClientCredentialsProvider: token fetch failed (HTTP ${response.status}): ${body}`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
const json = await response.json();
|
|
556
|
+
const tokens = {
|
|
557
|
+
access_token: String(json.access_token),
|
|
558
|
+
token_type: String(json.token_type ?? "bearer"),
|
|
559
|
+
expires_in: typeof json.expires_in === "number" ? json.expires_in : void 0,
|
|
560
|
+
scope: typeof json.scope === "string" ? json.scope : void 0,
|
|
561
|
+
refresh_token: typeof json.refresh_token === "string" ? json.refresh_token : void 0
|
|
562
|
+
};
|
|
563
|
+
await this.saveTokens(tokens);
|
|
564
|
+
return tokens;
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
// src/mcp/factories.ts
|
|
569
|
+
function createMCPManager(config) {
|
|
570
|
+
return new DefaultMCPManager(config);
|
|
571
|
+
}
|
|
572
|
+
function stdioServer(command, args, options) {
|
|
573
|
+
return {
|
|
574
|
+
transport: "stdio",
|
|
575
|
+
command,
|
|
576
|
+
args,
|
|
577
|
+
...options
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
function httpServer(url, options) {
|
|
581
|
+
return {
|
|
582
|
+
transport: "http",
|
|
583
|
+
url,
|
|
584
|
+
...options
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
function sseServer(url, options) {
|
|
588
|
+
return {
|
|
589
|
+
transport: "sse",
|
|
590
|
+
url,
|
|
591
|
+
...options
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
function serviceAccountServer(url, credentials, options) {
|
|
595
|
+
return {
|
|
596
|
+
transport: "http",
|
|
597
|
+
url,
|
|
598
|
+
authProvider: new ClientCredentialsProvider(credentials),
|
|
599
|
+
...options
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export {
|
|
604
|
+
ClientCredentialsProvider,
|
|
605
|
+
createMCPManager,
|
|
606
|
+
stdioServer,
|
|
607
|
+
httpServer,
|
|
608
|
+
sseServer,
|
|
609
|
+
serviceAccountServer
|
|
610
|
+
};
|