@xiaozhi-client/mcp-core 1.10.5 → 1.10.6-beta.1

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/index.js DELETED
@@ -1,922 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
- // src/types.ts
5
- var MCPTransportType = /* @__PURE__ */ ((MCPTransportType2) => {
6
- MCPTransportType2["STDIO"] = "stdio";
7
- MCPTransportType2["SSE"] = "sse";
8
- MCPTransportType2["HTTP"] = "http";
9
- return MCPTransportType2;
10
- })(MCPTransportType || {});
11
- var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
12
- ConnectionState2["DISCONNECTED"] = "disconnected";
13
- ConnectionState2["CONNECTING"] = "connecting";
14
- ConnectionState2["CONNECTED"] = "connected";
15
- ConnectionState2["RECONNECTING"] = "reconnecting";
16
- ConnectionState2["FAILED"] = "failed";
17
- ConnectionState2["ERROR"] = "error";
18
- return ConnectionState2;
19
- })(ConnectionState || {});
20
- function isValidToolJSONSchema(obj) {
21
- return typeof obj === "object" && obj !== null && "type" in obj && obj.type === "object";
22
- }
23
- __name(isValidToolJSONSchema, "isValidToolJSONSchema");
24
- function ensureToolJSONSchema(schema) {
25
- if (isValidToolJSONSchema(schema)) {
26
- return schema;
27
- }
28
- return {
29
- type: "object",
30
- properties: {},
31
- required: [],
32
- additionalProperties: true
33
- };
34
- }
35
- __name(ensureToolJSONSchema, "ensureToolJSONSchema");
36
- var ToolCallErrorCode = /* @__PURE__ */ ((ToolCallErrorCode2) => {
37
- ToolCallErrorCode2[ToolCallErrorCode2["INVALID_PARAMS"] = -32602] = "INVALID_PARAMS";
38
- ToolCallErrorCode2[ToolCallErrorCode2["TOOL_NOT_FOUND"] = -32601] = "TOOL_NOT_FOUND";
39
- ToolCallErrorCode2[ToolCallErrorCode2["SERVICE_UNAVAILABLE"] = -32001] = "SERVICE_UNAVAILABLE";
40
- ToolCallErrorCode2[ToolCallErrorCode2["TIMEOUT"] = -32002] = "TIMEOUT";
41
- ToolCallErrorCode2[ToolCallErrorCode2["TOOL_EXECUTION_ERROR"] = -32e3] = "TOOL_EXECUTION_ERROR";
42
- return ToolCallErrorCode2;
43
- })(ToolCallErrorCode || {});
44
- var ToolCallError = class extends Error {
45
- constructor(code, message, data) {
46
- super(message);
47
- this.code = code;
48
- this.data = data;
49
- this.name = "ToolCallError";
50
- }
51
- static {
52
- __name(this, "ToolCallError");
53
- }
54
- };
55
-
56
- // src/connection.ts
57
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
58
-
59
- // src/transport-factory.ts
60
- import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
61
- import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
62
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
63
- import { EventSource } from "eventsource";
64
- var globalThisAny = typeof globalThis !== "undefined" ? globalThis : global;
65
- if (typeof globalThisAny !== "undefined" && !globalThisAny.EventSource) {
66
- globalThisAny.EventSource = EventSource;
67
- }
68
- function createTransport(config) {
69
- switch (config.type) {
70
- case "stdio" /* STDIO */:
71
- return createStdioTransport(config);
72
- case "sse" /* SSE */:
73
- return createSSETransport(config);
74
- case "http" /* HTTP */:
75
- return createHTTPTransport(config);
76
- default:
77
- throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${config.type}`);
78
- }
79
- }
80
- __name(createTransport, "createTransport");
81
- function createStdioTransport(config) {
82
- if (!config.command) {
83
- throw new Error("stdio transport \u9700\u8981 command \u914D\u7F6E");
84
- }
85
- return new StdioClientTransport({
86
- command: config.command,
87
- args: config.args || [],
88
- env: config.env
89
- // 传递环境变量
90
- });
91
- }
92
- __name(createStdioTransport, "createStdioTransport");
93
- function createSSETransport(config) {
94
- if (!config.url) {
95
- throw new Error("SSE transport \u9700\u8981 URL \u914D\u7F6E");
96
- }
97
- const url = new URL(config.url);
98
- const options = createSSEOptions(config);
99
- return new SSEClientTransport(url, options);
100
- }
101
- __name(createSSETransport, "createSSETransport");
102
- function createHTTPTransport(config) {
103
- if (!config.url) {
104
- throw new Error("HTTP transport \u9700\u8981 URL \u914D\u7F6E");
105
- }
106
- const url = new URL(config.url);
107
- const options = createStreamableHTTPOptions(config);
108
- return new StreamableHTTPClientTransport(url, options);
109
- }
110
- __name(createHTTPTransport, "createHTTPTransport");
111
- function createSSEOptions(config) {
112
- const options = {};
113
- if (config.apiKey) {
114
- options.requestInit = {
115
- headers: {
116
- Authorization: `Bearer ${config.apiKey}`,
117
- ...config.headers
118
- }
119
- };
120
- } else if (config.headers) {
121
- options.requestInit = {
122
- headers: config.headers
123
- };
124
- }
125
- return options;
126
- }
127
- __name(createSSEOptions, "createSSEOptions");
128
- function createStreamableHTTPOptions(config) {
129
- const options = {};
130
- if (config.apiKey) {
131
- options.requestInit = {
132
- headers: {
133
- Authorization: `Bearer ${config.apiKey}`,
134
- ...config.headers
135
- }
136
- };
137
- } else if (config.headers) {
138
- options.requestInit = {
139
- headers: config.headers
140
- };
141
- }
142
- return options;
143
- }
144
- __name(createStreamableHTTPOptions, "createStreamableHTTPOptions");
145
- function validateConfig(config) {
146
- if (config.type && !Object.values(MCPTransportType).includes(config.type)) {
147
- throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${config.type}`);
148
- }
149
- if (!config.type) {
150
- throw new Error("\u4F20\u8F93\u7C7B\u578B\u672A\u8BBE\u7F6E\uFF0C\u8FD9\u5E94\u8BE5\u5728 inferTransportType \u4E2D\u5904\u7406");
151
- }
152
- switch (config.type) {
153
- case "stdio" /* STDIO */:
154
- if (!config.command) {
155
- throw new Error("stdio \u7C7B\u578B\u9700\u8981 command \u5B57\u6BB5");
156
- }
157
- break;
158
- case "sse" /* SSE */:
159
- if (config.url === void 0 || config.url === null) {
160
- throw new Error(`${config.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);
161
- }
162
- break;
163
- case "http" /* HTTP */:
164
- if (config.url === void 0 || config.url === null) {
165
- throw new Error(`${config.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);
166
- }
167
- break;
168
- default:
169
- throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${config.type}`);
170
- }
171
- }
172
- __name(validateConfig, "validateConfig");
173
- function getSupportedTypes() {
174
- return [
175
- "stdio" /* STDIO */,
176
- "sse" /* SSE */,
177
- "http" /* HTTP */
178
- ];
179
- }
180
- __name(getSupportedTypes, "getSupportedTypes");
181
- var TransportFactory = {
182
- create: createTransport,
183
- validateConfig,
184
- getSupportedTypes
185
- };
186
-
187
- // src/utils/type-normalizer.ts
188
- var TypeFieldNormalizer;
189
- ((TypeFieldNormalizer2) => {
190
- function normalizeTypeField2(config) {
191
- if (!config || typeof config !== "object") {
192
- return config;
193
- }
194
- const normalizedConfig = JSON.parse(JSON.stringify(config));
195
- if (!("type" in normalizedConfig)) {
196
- return normalizedConfig;
197
- }
198
- const originalType = normalizedConfig.type;
199
- if (originalType === "stdio" || originalType === "sse" || originalType === "http") {
200
- return normalizedConfig;
201
- }
202
- const normalizedType = normalizeTypeValue(originalType);
203
- if (normalizedType === "stdio" || normalizedType === "sse" || normalizedType === "http") {
204
- normalizedConfig.type = normalizedType;
205
- }
206
- return normalizedConfig;
207
- }
208
- TypeFieldNormalizer2.normalizeTypeField = normalizeTypeField2;
209
- __name(normalizeTypeField2, "normalizeTypeField");
210
- function normalizeTypeValue(type) {
211
- if (type === "http" || type === "streamable-http" || type === "streamable_http" || type === "streamableHttp") {
212
- return "http";
213
- }
214
- if (type === "sse" || type === "s_se" || type === "s-se") {
215
- return "sse";
216
- }
217
- if (type === "stdio") {
218
- return "stdio";
219
- }
220
- return convertToStandardFormat(type);
221
- }
222
- TypeFieldNormalizer2.normalizeTypeValue = normalizeTypeValue;
223
- __name(normalizeTypeValue, "normalizeTypeValue");
224
- function convertToStandardFormat(str) {
225
- const lowered = str.toLowerCase();
226
- if (lowered.includes("http") || lowered.includes("streamable")) {
227
- return "http";
228
- }
229
- if (lowered.includes("sse")) {
230
- return "sse";
231
- }
232
- if (lowered.includes("stdio")) {
233
- return "stdio";
234
- }
235
- return str;
236
- }
237
- __name(convertToStandardFormat, "convertToStandardFormat");
238
- })(TypeFieldNormalizer || (TypeFieldNormalizer = {}));
239
- function normalizeTypeField(config) {
240
- return TypeFieldNormalizer.normalizeTypeField(config);
241
- }
242
- __name(normalizeTypeField, "normalizeTypeField");
243
-
244
- // src/utils/validators.ts
245
- function inferTransportTypeFromUrl(url, options) {
246
- try {
247
- const parsedUrl = new URL(url);
248
- const pathname = parsedUrl.pathname;
249
- if (pathname.endsWith("/sse")) {
250
- return "sse" /* SSE */;
251
- }
252
- if (pathname.endsWith("/mcp")) {
253
- return "http" /* HTTP */;
254
- }
255
- if (options?.serviceName) {
256
- }
257
- return "http" /* HTTP */;
258
- } catch (error) {
259
- if (options?.serviceName) {
260
- }
261
- return "http" /* HTTP */;
262
- }
263
- }
264
- __name(inferTransportTypeFromUrl, "inferTransportTypeFromUrl");
265
- function inferTransportTypeFromConfig(config, serviceName) {
266
- if (config.type) {
267
- const normalizedConfig = TypeFieldNormalizer.normalizeTypeField(config);
268
- return normalizedConfig;
269
- }
270
- if (config.command) {
271
- return {
272
- ...config,
273
- type: "stdio" /* STDIO */
274
- };
275
- }
276
- if (config.url !== void 0 && config.url !== null) {
277
- const inferredType = inferTransportTypeFromUrl(config.url, {
278
- serviceName
279
- });
280
- return {
281
- ...config,
282
- type: inferredType
283
- };
284
- }
285
- throw new Error(
286
- `\u65E0\u6CD5\u4E3A\u670D\u52A1 ${serviceName || "\u672A\u77E5"} \u63A8\u65AD\u4F20\u8F93\u7C7B\u578B\u3002\u8BF7\u663E\u5F0F\u6307\u5B9A type \u5B57\u6BB5\uFF0C\u6216\u63D0\u4F9B command/url \u914D\u7F6E`
287
- );
288
- }
289
- __name(inferTransportTypeFromConfig, "inferTransportTypeFromConfig");
290
- function validateToolCallParams(params, options) {
291
- const opts = {
292
- validateName: true,
293
- validateArguments: true,
294
- allowEmptyArguments: true,
295
- ...options
296
- };
297
- if (!params || typeof params !== "object") {
298
- throw new ToolCallError(
299
- -32602 /* INVALID_PARAMS */,
300
- "\u8BF7\u6C42\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61"
301
- );
302
- }
303
- const paramsObj = params;
304
- if (opts.validateName) {
305
- if (!paramsObj.name || typeof paramsObj.name !== "string") {
306
- throw new ToolCallError(
307
- -32602 /* INVALID_PARAMS */,
308
- "\u5DE5\u5177\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32"
309
- );
310
- }
311
- }
312
- if (opts.validateArguments && paramsObj.arguments !== void 0 && paramsObj.arguments !== null) {
313
- if (typeof paramsObj.arguments !== "object" || Array.isArray(paramsObj.arguments)) {
314
- throw new ToolCallError(
315
- -32602 /* INVALID_PARAMS */,
316
- "\u5DE5\u5177\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61"
317
- );
318
- }
319
- }
320
- if (!opts.allowEmptyArguments && paramsObj.arguments !== void 0 && paramsObj.arguments !== null) {
321
- const argsObj = paramsObj.arguments;
322
- if (Object.keys(argsObj).length === 0) {
323
- throw new ToolCallError(
324
- -32602 /* INVALID_PARAMS */,
325
- "\u5DE5\u5177\u53C2\u6570\u4E0D\u80FD\u4E3A\u7A7A"
326
- );
327
- }
328
- }
329
- if (opts.customValidator) {
330
- const error = opts.customValidator(paramsObj);
331
- if (error) {
332
- throw new ToolCallError(-32602 /* INVALID_PARAMS */, error);
333
- }
334
- }
335
- return {
336
- name: paramsObj.name,
337
- arguments: paramsObj.arguments
338
- };
339
- }
340
- __name(validateToolCallParams, "validateToolCallParams");
341
-
342
- // src/connection.ts
343
- var MCPConnection = class {
344
- static {
345
- __name(this, "MCPConnection");
346
- }
347
- name;
348
- // 服务名称(独立字段)
349
- config;
350
- client = null;
351
- transport = null;
352
- tools = /* @__PURE__ */ new Map();
353
- connectionState = "disconnected" /* DISCONNECTED */;
354
- connectionTimeout = null;
355
- initialized = false;
356
- callbacks;
357
- // 心跳检测相关
358
- heartbeatTimer = null;
359
- heartbeatConfig;
360
- constructor(name, config, callbacks) {
361
- this.name = name;
362
- this.config = inferTransportTypeFromConfig(config, name);
363
- this.callbacks = callbacks;
364
- this.heartbeatConfig = {
365
- enabled: config.heartbeat?.enabled ?? true,
366
- // 默认启用
367
- interval: config.heartbeat?.interval ?? 30 * 1e3
368
- // 默认 30 秒
369
- };
370
- this.validateConfig();
371
- }
372
- /**
373
- * 验证配置
374
- */
375
- validateConfig() {
376
- if (!this.name || typeof this.name !== "string") {
377
- throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
378
- }
379
- const fullConfig = {
380
- name: this.name,
381
- ...this.config
382
- };
383
- TransportFactory.validateConfig(fullConfig);
384
- }
385
- /**
386
- * 连接到 MCP 服务
387
- */
388
- async connect() {
389
- if (this.connectionState === "connecting" /* CONNECTING */) {
390
- throw new Error("\u8FDE\u63A5\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210");
391
- }
392
- this.cleanupConnection();
393
- return this.attemptConnection();
394
- }
395
- /**
396
- * 尝试建立连接
397
- */
398
- async attemptConnection() {
399
- this.connectionState = "connecting" /* CONNECTING */;
400
- return new Promise((resolve, reject) => {
401
- const CONNECTION_TIMEOUT = 3e4;
402
- this.connectionTimeout = setTimeout(() => {
403
- const error = new Error(`\u8FDE\u63A5\u8D85\u65F6 (${CONNECTION_TIMEOUT}ms)`);
404
- this.handleConnectionError(error);
405
- reject(error);
406
- }, CONNECTION_TIMEOUT);
407
- try {
408
- this.client = new Client(
409
- {
410
- name: `xiaozhi-${this.name}-client`,
411
- version: "1.0.0"
412
- },
413
- {
414
- capabilities: {}
415
- }
416
- );
417
- const fullConfig = {
418
- name: this.name,
419
- ...this.config
420
- };
421
- this.transport = TransportFactory.create(fullConfig);
422
- this.client.connect(this.transport).then(async () => {
423
- this.handleConnectionSuccess();
424
- await this.refreshTools();
425
- this.callbacks?.onConnected?.({
426
- serviceName: this.name,
427
- tools: this.getTools(),
428
- connectionTime: /* @__PURE__ */ new Date()
429
- });
430
- resolve();
431
- }).catch((error) => {
432
- this.handleConnectionError(error);
433
- reject(error);
434
- });
435
- } catch (error) {
436
- this.handleConnectionError(error);
437
- reject(error);
438
- }
439
- });
440
- }
441
- /**
442
- * 处理连接成功
443
- */
444
- handleConnectionSuccess() {
445
- if (this.connectionTimeout) {
446
- clearTimeout(this.connectionTimeout);
447
- this.connectionTimeout = null;
448
- }
449
- this.connectionState = "connected" /* CONNECTED */;
450
- this.initialized = true;
451
- this.startHeartbeat();
452
- }
453
- /**
454
- * 处理连接错误
455
- */
456
- handleConnectionError(error) {
457
- this.connectionState = "disconnected" /* DISCONNECTED */;
458
- this.initialized = false;
459
- if (this.connectionTimeout) {
460
- clearTimeout(this.connectionTimeout);
461
- this.connectionTimeout = null;
462
- }
463
- this.cleanupConnection();
464
- this.callbacks?.onConnectionFailed?.({
465
- serviceName: this.name,
466
- error,
467
- attempt: 0
468
- });
469
- }
470
- /**
471
- * 清理连接资源
472
- */
473
- cleanupConnection() {
474
- this.stopHeartbeat();
475
- if (this.client) {
476
- try {
477
- this.client.close().catch(() => {
478
- });
479
- } catch (error) {
480
- }
481
- this.client = null;
482
- }
483
- this.transport = null;
484
- if (this.connectionTimeout) {
485
- clearTimeout(this.connectionTimeout);
486
- this.connectionTimeout = null;
487
- }
488
- this.initialized = false;
489
- }
490
- /**
491
- * 刷新工具列表
492
- */
493
- async refreshTools() {
494
- if (!this.client) {
495
- throw new Error("\u5BA2\u6237\u7AEF\u672A\u521D\u59CB\u5316");
496
- }
497
- try {
498
- const toolsResult = await this.client.listTools();
499
- const tools = toolsResult.tools || [];
500
- this.tools.clear();
501
- for (const tool of tools) {
502
- this.tools.set(tool.name, tool);
503
- }
504
- } catch (error) {
505
- throw error;
506
- }
507
- }
508
- /**
509
- * 断开连接
510
- */
511
- async disconnect() {
512
- this.cleanupConnection();
513
- this.connectionState = "disconnected" /* DISCONNECTED */;
514
- this.callbacks?.onDisconnected?.({
515
- serviceName: this.name,
516
- reason: "\u624B\u52A8\u65AD\u5F00",
517
- disconnectionTime: /* @__PURE__ */ new Date()
518
- });
519
- }
520
- /**
521
- * 获取工具列表
522
- */
523
- getTools() {
524
- return Array.from(this.tools.values());
525
- }
526
- /**
527
- * 检测是否为会话过期错误
528
- */
529
- isSessionExpiredError(error) {
530
- if (error instanceof Error) {
531
- const message = error.message.toLowerCase();
532
- return message.includes("session expired") || message.includes("\u4F1A\u8BDD\u8FC7\u671F") || message.includes("401") || message.includes("unauthorized");
533
- }
534
- return false;
535
- }
536
- /**
537
- * 自动重连
538
- */
539
- async reconnect() {
540
- this.connectionState = "reconnecting" /* RECONNECTING */;
541
- this.cleanupConnection();
542
- return this.attemptConnection();
543
- }
544
- /**
545
- * 启动心跳检测
546
- */
547
- async startHeartbeat() {
548
- if (this.config.type === "stdio") {
549
- return;
550
- }
551
- if (!this.heartbeatConfig?.enabled) {
552
- return;
553
- }
554
- const interval = this.heartbeatConfig?.interval ?? 30 * 1e3;
555
- this.heartbeatTimer = setInterval(() => {
556
- this.performHeartbeat().catch((error) => {
557
- });
558
- }, interval);
559
- }
560
- /**
561
- * 执行一次心跳检查
562
- */
563
- async performHeartbeat() {
564
- if (!this.client) {
565
- return;
566
- }
567
- try {
568
- await this.client.ping();
569
- } catch (error) {
570
- await this.reconnect();
571
- }
572
- }
573
- /**
574
- * 停止心跳检测
575
- */
576
- stopHeartbeat() {
577
- if (this.heartbeatTimer) {
578
- clearInterval(this.heartbeatTimer);
579
- this.heartbeatTimer = null;
580
- }
581
- }
582
- /**
583
- * 调用工具
584
- */
585
- async callTool(name, arguments_) {
586
- if (!this.client) {
587
- throw new Error(`\u670D\u52A1 ${this.name} \u672A\u8FDE\u63A5`);
588
- }
589
- if (!this.tools.has(name)) {
590
- throw new Error(`\u5DE5\u5177 ${name} \u5728\u670D\u52A1 ${this.name} \u4E2D\u4E0D\u5B58\u5728`);
591
- }
592
- try {
593
- const result = await this.client.callTool({
594
- name,
595
- arguments: arguments_ || {}
596
- });
597
- return result;
598
- } catch (error) {
599
- if (this.isSessionExpiredError(error)) {
600
- await this.reconnect();
601
- return await this.client.callTool({
602
- name,
603
- arguments: arguments_ || {}
604
- });
605
- }
606
- throw error;
607
- }
608
- }
609
- /**
610
- * 获取服务配置
611
- */
612
- getConfig() {
613
- return {
614
- name: this.name,
615
- ...this.config
616
- };
617
- }
618
- /**
619
- * 获取服务状态
620
- */
621
- getStatus() {
622
- return {
623
- name: this.name,
624
- connected: this.connectionState === "connected" /* CONNECTED */,
625
- initialized: this.initialized,
626
- transportType: this.config.type || "http" /* HTTP */,
627
- toolCount: this.tools.size,
628
- connectionState: this.connectionState
629
- };
630
- }
631
- /**
632
- * 检查是否已连接
633
- */
634
- isConnected() {
635
- return this.connectionState === "connected" /* CONNECTED */ && this.initialized;
636
- }
637
- };
638
-
639
- // src/manager.ts
640
- import { EventEmitter } from "events";
641
- var MCPManager = class extends EventEmitter {
642
- static {
643
- __name(this, "MCPManager");
644
- }
645
- connections = /* @__PURE__ */ new Map();
646
- configs = /* @__PURE__ */ new Map();
647
- constructor() {
648
- super();
649
- }
650
- /**
651
- * 添加 MCP 服务器配置
652
- * @param name 服务器名称
653
- * @param config 服务器配置
654
- *
655
- * @example
656
- * ```typescript
657
- * // 添加 stdio 服务
658
- * manager.addServer('calculator', {
659
- * type: 'stdio',
660
- * command: 'node',
661
- * args: ['calculator.js']
662
- * });
663
- *
664
- * // 添加 HTTP 服务
665
- * manager.addServer('web-search', {
666
- * type: 'http',
667
- * url: 'https://api.example.com/mcp',
668
- * headers: {
669
- * Authorization: 'Bearer your-api-key'
670
- * }
671
- * });
672
- * ```
673
- */
674
- addServer(name, config) {
675
- if (this.configs.has(name)) {
676
- throw new Error(`\u670D\u52A1 ${name} \u5DF2\u5B58\u5728`);
677
- }
678
- const normalizedConfig = { ...config };
679
- if (config.type) {
680
- const typeStr = String(config.type);
681
- if (typeStr === "http") {
682
- normalizedConfig.type = "http" /* HTTP */;
683
- } else if (typeStr === "sse") {
684
- normalizedConfig.type = "sse" /* SSE */;
685
- } else {
686
- normalizedConfig.type = config.type;
687
- }
688
- }
689
- this.configs.set(name, normalizedConfig);
690
- }
691
- /**
692
- * 移除服务器配置
693
- * @param name 服务器名称
694
- */
695
- removeServer(name) {
696
- return this.configs.delete(name);
697
- }
698
- /**
699
- * 连接所有已添加的 MCP 服务
700
- * 所有服务并行连接,单个服务失败不会影响其他服务
701
- *
702
- * @example
703
- * ```typescript
704
- * await manager.connect();
705
- * ```
706
- */
707
- async connect() {
708
- this.emit("connect");
709
- const promises = Array.from(this.configs.entries()).map(
710
- async ([name, config]) => {
711
- try {
712
- const connection = new MCPConnection(name, config, {
713
- onConnected: /* @__PURE__ */ __name((data) => {
714
- this.emit("connected", {
715
- serverName: data.serviceName,
716
- tools: data.tools
717
- });
718
- }, "onConnected"),
719
- onDisconnected: /* @__PURE__ */ __name((data) => {
720
- this.emit("disconnected", {
721
- serverName: data.serviceName,
722
- reason: data.reason
723
- });
724
- }, "onDisconnected"),
725
- onConnectionFailed: /* @__PURE__ */ __name((data) => {
726
- this.emit("error", {
727
- serverName: data.serviceName,
728
- error: data.error
729
- });
730
- }, "onConnectionFailed")
731
- });
732
- await connection.connect();
733
- this.connections.set(name, connection);
734
- } catch (error) {
735
- this.emit("error", { serverName: name, error });
736
- throw error;
737
- }
738
- }
739
- );
740
- await Promise.allSettled(promises);
741
- }
742
- /**
743
- * 断开所有 MCP 服务连接
744
- *
745
- * @example
746
- * ```typescript
747
- * await manager.disconnect();
748
- * ```
749
- */
750
- async disconnect() {
751
- const promises = Array.from(this.connections.values()).map(
752
- (conn) => conn.disconnect()
753
- );
754
- await Promise.allSettled(promises);
755
- this.connections.clear();
756
- this.emit("disconnect");
757
- }
758
- /**
759
- * 调用指定服务的工具
760
- * @param serverName 服务名称
761
- * @param toolName 工具名称
762
- * @param args 工具参数
763
- *
764
- * @example
765
- * ```typescript
766
- * const result = await manager.callTool('datetime', 'get_current_time', {
767
- * format: 'YYYY-MM-DD HH:mm:ss'
768
- * });
769
- * ```
770
- */
771
- async callTool(serverName, toolName, args) {
772
- const connection = this.connections.get(serverName);
773
- if (!connection) {
774
- throw new Error(`\u670D\u52A1 ${serverName} \u4E0D\u5B58\u5728`);
775
- }
776
- if (!connection.isConnected()) {
777
- throw new Error(`\u670D\u52A1 ${serverName} \u672A\u8FDE\u63A5`);
778
- }
779
- return connection.callTool(toolName, args);
780
- }
781
- /**
782
- * 列出所有可用的工具
783
- * @returns 工具列表,格式为 [{ name, serverName, description, inputSchema }]
784
- *
785
- * @example
786
- * ```typescript
787
- * const tools = manager.listTools();
788
- * console.log('可用工具:', tools.map(t => `${t.serverName}/${t.name}`));
789
- * ```
790
- */
791
- listTools() {
792
- const allTools = [];
793
- for (const [serverName, connection] of this.connections) {
794
- if (connection.isConnected()) {
795
- const tools = connection.getTools();
796
- for (const tool of tools) {
797
- allTools.push({
798
- name: tool.name,
799
- serverName,
800
- description: tool.description || "",
801
- inputSchema: tool.inputSchema
802
- });
803
- }
804
- }
805
- }
806
- return allTools;
807
- }
808
- /**
809
- * 获取服务状态
810
- * @param serverName 服务名称
811
- * @returns 服务状态,如果服务不存在则返回 null
812
- *
813
- * @example
814
- * ```typescript
815
- * const status = manager.getServerStatus('datetime');
816
- * if (status) {
817
- * console.log(`已连接: ${status.connected}, 工具数: ${status.toolCount}`);
818
- * }
819
- * ```
820
- */
821
- getServerStatus(serverName) {
822
- const connection = this.connections.get(serverName);
823
- if (!connection) {
824
- return null;
825
- }
826
- const status = connection.getStatus();
827
- return {
828
- connected: status.connected,
829
- toolCount: status.toolCount
830
- };
831
- }
832
- /**
833
- * 获取所有服务的状态
834
- * @returns 所有服务的状态映射
835
- *
836
- * @example
837
- * ```typescript
838
- * const statuses = manager.getAllServerStatus();
839
- * console.log(statuses);
840
- * // {
841
- * // datetime: { connected: true, toolCount: 3 },
842
- * // calculator: { connected: true, toolCount: 1 }
843
- * // }
844
- * ```
845
- */
846
- getAllServerStatus() {
847
- const statuses = {};
848
- for (const [serverName, connection] of this.connections) {
849
- const status = connection.getStatus();
850
- statuses[serverName] = {
851
- connected: status.connected,
852
- toolCount: status.toolCount
853
- };
854
- }
855
- return statuses;
856
- }
857
- /**
858
- * 检查服务是否已连接
859
- * @param serverName 服务名称
860
- *
861
- * @example
862
- * ```typescript
863
- * if (manager.isConnected('datetime')) {
864
- * console.log('datetime 服务已连接');
865
- * }
866
- * ```
867
- */
868
- isConnected(serverName) {
869
- const connection = this.connections.get(serverName);
870
- return connection ? connection.isConnected() : false;
871
- }
872
- /**
873
- * 获取已配置的服务列表
874
- * @returns 服务名称数组
875
- *
876
- * @example
877
- * ```typescript
878
- * const servers = manager.getServerNames();
879
- * console.log('已配置的服务:', servers);
880
- * ```
881
- */
882
- getServerNames() {
883
- return Array.from(this.configs.keys());
884
- }
885
- /**
886
- * 获取已连接的服务列表
887
- * @returns 已连接的服务名称数组
888
- *
889
- * @example
890
- * ```typescript
891
- * const connectedServers = manager.getConnectedServerNames();
892
- * console.log('已连接的服务:', connectedServers);
893
- * ```
894
- */
895
- getConnectedServerNames() {
896
- const connected = [];
897
- for (const [serverName, connection] of this.connections) {
898
- if (connection.isConnected()) {
899
- connected.push(serverName);
900
- }
901
- }
902
- return connected;
903
- }
904
- };
905
- export {
906
- ConnectionState,
907
- MCPConnection,
908
- MCPManager,
909
- MCPManager as MCPServiceManager,
910
- MCPTransportType,
911
- ToolCallError,
912
- ToolCallErrorCode,
913
- TransportFactory,
914
- TypeFieldNormalizer,
915
- ensureToolJSONSchema,
916
- inferTransportTypeFromConfig,
917
- inferTransportTypeFromUrl,
918
- isValidToolJSONSchema,
919
- normalizeTypeField,
920
- validateToolCallParams
921
- };
922
- //# sourceMappingURL=index.js.map