xiaozhi-client 1.6.3 → 1.6.4-beta.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.
Files changed (40) hide show
  1. package/dist/MCPService-B1FvMc8R.d.ts +243 -0
  2. package/dist/WebServer.d.ts +33 -22
  3. package/dist/WebServer.js +65 -30
  4. package/dist/WebServer.js.map +1 -1
  5. package/dist/WebServerStandalone.js +65 -30
  6. package/dist/WebServerStandalone.js.map +1 -1
  7. package/dist/adapters/ConfigAdapter.d.ts +30 -0
  8. package/dist/adapters/ConfigAdapter.js +3 -0
  9. package/dist/adapters/ConfigAdapter.js.map +1 -0
  10. package/dist/cli.js +67 -32
  11. package/dist/cli.js.map +1 -1
  12. package/dist/configManager.d.ts +5 -0
  13. package/dist/configManager.js +2 -2
  14. package/dist/configManager.js.map +1 -1
  15. package/dist/mcpCommands.js +2 -2
  16. package/dist/mcpCommands.js.map +1 -1
  17. package/dist/mcpServerProxy.js +2 -2
  18. package/dist/mcpServerProxy.js.map +1 -1
  19. package/dist/services/MCPServer.d.ts +2 -235
  20. package/dist/services/MCPServer.js +4 -4
  21. package/dist/services/MCPServer.js.map +1 -1
  22. package/package.json +22 -30
  23. package/web/dist/assets/form-utils-BAESeaiO.js +22 -0
  24. package/web/dist/assets/form-utils-BAESeaiO.js.map +1 -0
  25. package/web/dist/assets/index-CCieCKu1.js +31 -0
  26. package/web/dist/assets/index-CCieCKu1.js.map +1 -0
  27. package/web/dist/assets/index-eZDZS6qd.css +1 -0
  28. package/web/dist/assets/radix-ui-DW48STyt.js +2 -0
  29. package/web/dist/assets/radix-ui-DW48STyt.js.map +1 -0
  30. package/web/dist/assets/react-vendor-Bm2cC0fo.js +184 -0
  31. package/web/dist/assets/react-vendor-Bm2cC0fo.js.map +1 -0
  32. package/web/dist/assets/utils-DE0xezXx.js +2 -0
  33. package/web/dist/assets/utils-DE0xezXx.js.map +1 -0
  34. package/web/dist/assets/vendor-C4NtkA-O.js +10 -0
  35. package/web/dist/assets/vendor-C4NtkA-O.js.map +1 -0
  36. package/web/dist/index.html +7 -2
  37. package/web/README.md +0 -169
  38. package/web/dist/assets/index-Jy5aLSeZ.js +0 -241
  39. package/web/dist/assets/index-Jy5aLSeZ.js.map +0 -1
  40. package/web/dist/assets/index-o2NfdFal.css +0 -1
@@ -1,239 +1,6 @@
1
- import { Tool } from '@modelcontextprotocol/sdk/types.js';
1
+ import { M as MCPServiceConfig, a as MCPService } from '../MCPService-B1FvMc8R.js';
2
2
  import { EventEmitter } from 'node:events';
3
-
4
- declare enum MCPTransportType {
5
- STDIO = "stdio",
6
- SSE = "sse",
7
- STREAMABLE_HTTP = "streamable-http",
8
- MODELSCOPE_SSE = "modelscope-sse"
9
- }
10
- declare enum ConnectionState {
11
- DISCONNECTED = "disconnected",
12
- CONNECTING = "connecting",
13
- CONNECTED = "connected",
14
- RECONNECTING = "reconnecting",
15
- FAILED = "failed"
16
- }
17
- interface ReconnectOptions {
18
- enabled: boolean;
19
- maxAttempts: number;
20
- initialInterval: number;
21
- maxInterval: number;
22
- backoffStrategy: "linear" | "exponential" | "fixed";
23
- backoffMultiplier: number;
24
- timeout: number;
25
- jitter: boolean;
26
- }
27
- interface PingOptions {
28
- enabled: boolean;
29
- interval: number;
30
- timeout: number;
31
- maxFailures: number;
32
- startDelay: number;
33
- }
34
- interface ModelScopeSSEOptions {
35
- eventSourceInit?: {
36
- fetch?: (url: string | URL | Request, init?: RequestInit) => Promise<Response>;
37
- };
38
- requestInit?: RequestInit;
39
- }
40
- interface MCPServiceConfig {
41
- name: string;
42
- type: MCPTransportType;
43
- command?: string;
44
- args?: string[];
45
- url?: string;
46
- apiKey?: string;
47
- headers?: Record<string, string>;
48
- modelScopeAuth?: boolean;
49
- customSSEOptions?: ModelScopeSSEOptions;
50
- reconnect?: Partial<ReconnectOptions>;
51
- ping?: Partial<PingOptions>;
52
- timeout?: number;
53
- retryAttempts?: number;
54
- }
55
- interface MCPServiceStatus {
56
- name: string;
57
- connected: boolean;
58
- initialized: boolean;
59
- transportType: MCPTransportType;
60
- toolCount: number;
61
- lastError?: string;
62
- reconnectAttempts: number;
63
- connectionState: ConnectionState;
64
- pingEnabled: boolean;
65
- lastPingTime?: Date;
66
- pingFailureCount: number;
67
- isPinging: boolean;
68
- }
69
- interface MCPServiceOptions {
70
- reconnect?: Partial<ReconnectOptions>;
71
- }
72
- interface ToolCallResult$1 {
73
- content: Array<{
74
- type: string;
75
- text: string;
76
- }>;
77
- isError?: boolean;
78
- }
79
- /**
80
- * MCP 服务类
81
- * 负责管理单个 MCP 服务的连接、工具管理和调用
82
- */
83
- declare class MCPService {
84
- private config;
85
- private client;
86
- private transport;
87
- private tools;
88
- private connectionState;
89
- private reconnectOptions;
90
- private reconnectState;
91
- private logger;
92
- private connectionTimeout;
93
- private initialized;
94
- private pingOptions;
95
- private pingTimer;
96
- private pingFailureCount;
97
- private lastPingTime;
98
- private isPinging;
99
- constructor(config: MCPServiceConfig, options?: MCPServiceOptions);
100
- /**
101
- * 带标签的日志方法
102
- */
103
- private logWithTag;
104
- /**
105
- * 验证配置
106
- */
107
- private validateConfig;
108
- /**
109
- * 连接到 MCP 服务
110
- */
111
- connect(): Promise<void>;
112
- /**
113
- * 尝试建立连接
114
- */
115
- private attemptConnection;
116
- /**
117
- * 处理连接成功
118
- */
119
- private handleConnectionSuccess;
120
- /**
121
- * 处理连接错误
122
- */
123
- private handleConnectionError;
124
- /**
125
- * 检查是否应该重连
126
- */
127
- private shouldReconnect;
128
- /**
129
- * 安排重连
130
- */
131
- private scheduleReconnect;
132
- /**
133
- * 计算下次重连间隔
134
- */
135
- private calculateNextInterval;
136
- /**
137
- * 清理连接资源
138
- */
139
- private cleanupConnection;
140
- /**
141
- * 停止重连
142
- */
143
- private stopReconnect;
144
- /**
145
- * 刷新工具列表
146
- */
147
- private refreshTools;
148
- /**
149
- * 断开连接
150
- */
151
- disconnect(): Promise<void>;
152
- /**
153
- * 手动重连
154
- */
155
- reconnect(): Promise<void>;
156
- /**
157
- * 获取工具列表
158
- */
159
- getTools(): Tool[];
160
- /**
161
- * 调用工具
162
- */
163
- callTool(name: string, arguments_: any): Promise<ToolCallResult$1>;
164
- /**
165
- * 获取服务配置
166
- */
167
- getConfig(): MCPServiceConfig;
168
- /**
169
- * 获取服务状态
170
- */
171
- getStatus(): MCPServiceStatus;
172
- /**
173
- * 检查是否已连接
174
- */
175
- isConnected(): boolean;
176
- /**
177
- * 启用自动重连
178
- */
179
- enableReconnect(): void;
180
- /**
181
- * 禁用自动重连
182
- */
183
- disableReconnect(): void;
184
- /**
185
- * 更新重连配置
186
- */
187
- updateReconnectOptions(options: Partial<ReconnectOptions>): void;
188
- /**
189
- * 获取重连配置
190
- */
191
- getReconnectOptions(): ReconnectOptions;
192
- /**
193
- * 重置重连状态
194
- */
195
- resetReconnectState(): void;
196
- /**
197
- * 启动ping监控
198
- */
199
- private startPingMonitoring;
200
- /**
201
- * 停止ping监控
202
- */
203
- private stopPingMonitoring;
204
- /**
205
- * 执行ping检查
206
- */
207
- private performPing;
208
- /**
209
- * 处理ping成功
210
- */
211
- private handlePingSuccess;
212
- /**
213
- * 处理ping失败
214
- */
215
- private handlePingFailure;
216
- /**
217
- * 重置ping状态
218
- */
219
- private resetPingState;
220
- /**
221
- * 启用ping监控
222
- */
223
- enablePing(): void;
224
- /**
225
- * 禁用ping监控
226
- */
227
- disablePing(): void;
228
- /**
229
- * 更新ping配置
230
- */
231
- updatePingOptions(options: Partial<PingOptions>): void;
232
- /**
233
- * 获取ping配置
234
- */
235
- getPingOptions(): PingOptions;
236
- }
3
+ import '@modelcontextprotocol/sdk/types.js';
237
4
 
238
5
  /**
239
6
  * MCP 服务管理器
@@ -1,8 +1,8 @@
1
- var q=Object.defineProperty;var s=(o,e)=>q(o,"name",{value:e,configurable:!0});import{EventEmitter as Te}from"events";import*as d from"fs";import*as u from"path";import T from"chalk";import b from"pino";function Y(o){let e=o.getFullYear(),t=String(o.getMonth()+1).padStart(2,"0"),n=String(o.getDate()).padStart(2,"0"),i=String(o.getHours()).padStart(2,"0"),r=String(o.getMinutes()).padStart(2,"0"),a=String(o.getSeconds()).padStart(2,"0");return`${e}-${t}-${n} ${i}:${r}:${a}`}s(Y,"formatDateTime");var y=class{static{s(this,"Logger")}logFilePath=null;pinoInstance;isDaemonMode;maxLogFileSize=10*1024*1024;maxLogFiles=5;constructor(){this.isDaemonMode=process.env.XIAOZHI_DAEMON==="true",this.pinoInstance=this.createPinoInstance()}createPinoInstance(){let e=[];if(!this.isDaemonMode){let t=this.createOptimizedConsoleStream();e.push({level:"debug",stream:t})}return this.logFilePath&&e.push({level:"debug",stream:b.destination({dest:this.logFilePath,sync:!1,append:!0,mkdir:!0})}),e.length===0&&e.push({level:"debug",stream:b.destination({dest:"/dev/null"})}),b({level:"debug",timestamp:b.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:s((t,n)=>({level:n}),"level")},base:null,serializers:{err:b.stdSerializers?.err||(t=>t)}},b.multistream(e,{dedupe:!0}))}createOptimizedConsoleStream(){let e=new Map([[20,{name:"DEBUG",color:T.gray}],[30,{name:"INFO",color:T.blue}],[40,{name:"WARN",color:T.yellow}],[50,{name:"ERROR",color:T.red}],[60,{name:"FATAL",color:T.red}]]);return{write:s(t=>{try{let n=JSON.parse(t),i=this.formatConsoleMessageOptimized(n,e);this.safeWrite(`${i}
2
- `)}catch{this.safeWrite(t)}},"write")}}safeWrite(e){try{process.stderr&&typeof process.stderr.write=="function"?process.stderr.write(e):console&&typeof console.error=="function"&&console.error(e.trim())}catch{}}formatConsoleMessageOptimized(e,t){let n=Y(new Date),i=t.get(e.level)||{name:"UNKNOWN",color:s(c=>c,"color")},r=i.color(`[${i.name}]`),a=e.msg;if(e.args&&Array.isArray(e.args)){let c=e.args.map(g=>typeof g=="object"?JSON.stringify(g):String(g)).join(" ");a=`${a} ${c}`}return`[${n}] ${r} ${a}`}initLogFile(e){this.logFilePath=u.join(e,"xiaozhi.log"),this.rotateLogFileIfNeeded(),d.existsSync(this.logFilePath)||d.writeFileSync(this.logFilePath,""),this.pinoInstance=this.createPinoInstance()}enableFileLogging(e){e&&this.logFilePath&&(this.pinoInstance=this.createPinoInstance())}info(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}success(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}warn(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.warn(e):this.pinoInstance.warn({args:t},e):this.pinoInstance.warn(e,t[0]||"")}error(e,...t){if(typeof e=="string")if(t.length===0)this.pinoInstance.error(e);else{let n=t.map(i=>i instanceof Error?{message:i.message,stack:i.stack,name:i.name,cause:i.cause}:i);this.pinoInstance.error({args:n},e)}else{let n=this.enhanceErrorObject(e);this.pinoInstance.error(n,t[0]||"")}}debug(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.debug(e):this.pinoInstance.debug({args:t},e):this.pinoInstance.debug(e,t[0]||"")}log(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}enhanceErrorObject(e){let t={...e};for(let[n,i]of Object.entries(t))i instanceof Error&&(t[n]={message:i.message,stack:i.stack,name:i.name,cause:i.cause});return t}rotateLogFileIfNeeded(){if(!(!this.logFilePath||!d.existsSync(this.logFilePath)))try{d.statSync(this.logFilePath).size>this.maxLogFileSize&&this.rotateLogFile()}catch{}}rotateLogFile(){if(this.logFilePath)try{let e=u.dirname(this.logFilePath),t=u.basename(this.logFilePath,".log");for(let i=this.maxLogFiles-1;i>=1;i--){let r=u.join(e,`${t}.${i}.log`),a=u.join(e,`${t}.${i+1}.log`);d.existsSync(r)&&(i===this.maxLogFiles-1?d.unlinkSync(r):d.renameSync(r,a))}let n=u.join(e,`${t}.1.log`);d.renameSync(this.logFilePath,n)}catch{}}cleanupOldLogs(){if(this.logFilePath)try{let e=u.dirname(this.logFilePath),t=u.basename(this.logFilePath,".log");for(let n=this.maxLogFiles+1;n<=this.maxLogFiles+10;n++){let i=u.join(e,`${t}.${n}.log`);d.existsSync(i)&&d.unlinkSync(i)}}catch{}}setLogFileOptions(e,t){this.maxLogFileSize=e,this.maxLogFiles=t}withTag(e){return this}close(){}},l=new y;import m from"ws";var h=class extends Error{constructor(t,n,i){super(n);this.code=t;this.data=i;this.name="ToolCallError"}static{s(this,"ToolCallError")}},w=class{static{s(this,"ProxyMCPServer")}endpointUrl;ws=null;logger;isConnected=!1;serverInitialized=!1;tools=new Map;connectionState="disconnected";reconnectOptions;reconnectState={attempts:0,nextInterval:0,timer:null,lastError:null,isManualDisconnect:!1};connectionTimeout=null;performanceMetrics={totalCalls:0,successfulCalls:0,failedCalls:0,averageResponseTime:0,minResponseTime:Number.MAX_VALUE,maxResponseTime:0,successRate:0,lastUpdated:new Date};callRecords=[];maxCallRecords=100;retryConfig={maxAttempts:3,initialDelay:1e3,maxDelay:1e4,backoffMultiplier:2,retryableErrors:[-32001,-32002]};toolCallConfig={timeout:3e4,retryAttempts:3,retryDelay:1e3};constructor(e,t){this.endpointUrl=e,this.logger=l,this.reconnectOptions={enabled:!0,maxAttempts:10,initialInterval:3e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t?.reconnect},this.reconnectState.nextInterval=this.reconnectOptions.initialInterval}setServiceManager(e){this.serviceManager=e,this.logger.info("\u5DF2\u8BBE\u7F6E MCPServiceManager"),this.syncToolsFromServiceManager()}syncToolsFromServiceManager(){let e=this.serviceManager;if(!e){this.logger.debug("MCPServiceManager \u672A\u8BBE\u7F6E\uFF0C\u8DF3\u8FC7\u5DE5\u5177\u540C\u6B65");return}try{let t=e.getAllTools(),n=new Map;for(let i of t)n.set(i.name,{name:i.name,description:i.description,inputSchema:i.inputSchema});this.tools=n,this.logger.info(`\u5DF2\u4ECE MCPServiceManager \u540C\u6B65 ${this.tools.size} \u4E2A\u5DE5\u5177`)}catch(t){this.logger.error(`\u540C\u6B65\u5DE5\u5177\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}addTool(e,t){return this.validateTool(e,t),this.tools.set(e,t),this.logger.debug(`\u5DE5\u5177 '${e}' \u5DF2\u6DFB\u52A0`),this}addTools(e){for(let[t,n]of Object.entries(e))this.addTool(t,n);return this}removeTool(e){return this.tools.delete(e)?this.logger.debug(`\u5DE5\u5177 '${e}' \u5DF2\u79FB\u9664`):this.logger.warn(`\u5C1D\u8BD5\u79FB\u9664\u4E0D\u5B58\u5728\u7684\u5DE5\u5177: '${e}'`),this}getTools(){try{this.syncToolsFromServiceManager()}catch{}return Array.from(this.tools.values())}hasTool(e){return this.tools.has(e)}validateTool(e,t){if(!e||typeof e!="string"||e.trim()==="")throw new Error("\u5DE5\u5177\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(this.tools.has(e))throw new Error(`\u5DE5\u5177 '${e}' \u5DF2\u5B58\u5728`);if(!t||typeof t!="object")throw new Error("\u5DE5\u5177\u5FC5\u987B\u662F\u6709\u6548\u7684\u5BF9\u8C61");if(!t.name||typeof t.name!="string")throw new Error("\u5DE5\u5177\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 'name' \u5B57\u6BB5");if(!t.description||typeof t.description!="string")throw new Error("\u5DE5\u5177\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 'description' \u5B57\u6BB5");if(!t.inputSchema||typeof t.inputSchema!="object")throw new Error("\u5DE5\u5177\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 'inputSchema' \u5B57\u6BB5");if(!t.inputSchema.type||!t.inputSchema.properties)throw new Error("\u5DE5\u5177\u7684 inputSchema \u5FC5\u987B\u5305\u542B 'type' \u548C 'properties' \u5B57\u6BB5")}async connect(){if(this.tools.size===0)throw new Error("\u672A\u914D\u7F6E\u4EFB\u4F55\u5DE5\u5177\u3002\u8BF7\u5728\u8FDE\u63A5\u524D\u81F3\u5C11\u6DFB\u52A0\u4E00\u4E2A\u5DE5\u5177\u3002");if(this.connectionState==="connecting")throw new Error("\u8FDE\u63A5\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210");return this.cleanupConnection(),this.reconnectState.isManualDisconnect=!1,this.attemptConnection()}async attemptConnection(){return this.connectionState="connecting",this.logger.info(`\u6B63\u5728\u8FDE\u63A5 MCP \u63A5\u5165\u70B9: ${this.endpointUrl} (\u5C1D\u8BD5 ${this.reconnectState.attempts+1}/${this.reconnectOptions.maxAttempts})`),new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let n=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(n),t(n)},this.reconnectOptions.timeout),this.ws=new m(this.endpointUrl),this.ws.on("open",()=>{this.handleConnectionSuccess(),e()}),this.ws.on("message",n=>{try{let i=JSON.parse(n.toString());this.handleMessage(i)}catch(i){this.logger.error("MCP \u6D88\u606F\u89E3\u6790\u9519\u8BEF:",i)}}),this.ws.on("close",(n,i)=>{this.handleConnectionClose(n,i.toString())}),this.ws.on("error",n=>{this.handleConnectionError(n),t(n)})})}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=!0,this.connectionState="connected",this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info("MCP WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB")}handleConnectionError(e){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.reconnectState.lastError=e,this.logger.error("MCP WebSocket \u9519\u8BEF:",e.message),this.cleanupConnection()}handleConnectionClose(e,t){if(this.isConnected=!1,this.serverInitialized=!1,this.logger.info(`MCP \u8FDE\u63A5\u5DF2\u5173\u95ED (\u4EE3\u7801: ${e}, \u539F\u56E0: ${t})`),this.reconnectState.isManualDisconnect){this.connectionState="disconnected";return}this.shouldReconnect()?this.scheduleReconnect():(this.connectionState="failed",this.logger.warn(`\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`))}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.connectionState="reconnecting",this.reconnectState.attempts++,this.calculateNextInterval(),this.logger.info(`\u5C06\u5728 ${this.reconnectState.nextInterval}ms \u540E\u8FDB\u884C\u7B2C ${this.reconnectState.attempts} \u6B21\u91CD\u8FDE`),this.reconnectState.timer&&clearTimeout(this.reconnectState.timer),this.reconnectState.timer=setTimeout(async()=>{try{await this.attemptConnection()}catch{}},this.reconnectState.nextInterval)}calculateNextInterval(){let e;switch(this.reconnectOptions.backoffStrategy){case"fixed":e=this.reconnectOptions.initialInterval;break;case"linear":e=this.reconnectOptions.initialInterval+this.reconnectState.attempts*this.reconnectOptions.backoffMultiplier*1e3;break;case"exponential":e=this.reconnectOptions.initialInterval*this.reconnectOptions.backoffMultiplier**(this.reconnectState.attempts-1);break;default:e=this.reconnectOptions.initialInterval}if(e=Math.min(e,this.reconnectOptions.maxInterval),this.reconnectOptions.jitter){let t=e*.1,n=(Math.random()-.5)*2*t;e+=n}this.reconnectState.nextInterval=Math.max(e,1e3)}cleanupConnection(){if(this.ws){this.ws.removeAllListeners();try{this.ws.readyState===m.OPEN?this.ws.close(1e3,"Cleaning up connection"):this.ws.readyState===m.CONNECTING&&this.ws.terminate()}catch(e){this.logger.debug("WebSocket \u5173\u95ED\u65F6\u51FA\u73B0\u9519\u8BEF\uFF08\u5DF2\u5FFD\u7565\uFF09:",e)}this.ws=null}this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=!1,this.serverInitialized=!1}stopReconnect(){this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null)}handleMessage(e){this.logger.debug("\u6536\u5230 MCP \u6D88\u606F:",JSON.stringify(e,null,2)),e.method&&this.handleServerRequest(e)}handleServerRequest(e){switch(e.method){case"initialize":case"notifications/initialized":this.sendResponse(e.id,{protocolVersion:"2024-11-05",capabilities:{tools:{listChanged:!0},logging:{}},serverInfo:{name:"xiaozhi-mcp-server",version:"1.0.0"}}),this.serverInitialized=!0,this.logger.info("MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210");break;case"tools/list":{let t=this.getTools();this.sendResponse(e.id,{tools:t}),this.logger.info(`MCP \u5DE5\u5177\u5217\u8868\u5DF2\u53D1\u9001 (${t.length}\u4E2A\u5DE5\u5177)`);break}case"tools/call":{this.handleToolCall(e).catch(t=>{this.logger.error("\u5904\u7406\u5DE5\u5177\u8C03\u7528\u65F6\u53D1\u751F\u672A\u6355\u83B7\u9519\u8BEF:",t)});break}case"ping":this.sendResponse(e.id,{}),this.logger.debug("\u56DE\u5E94 MCP ping \u6D88\u606F");break;default:this.logger.warn(`\u672A\u77E5\u7684 MCP \u8BF7\u6C42: ${e.method}`)}}sendResponse(e,t){if(this.logger.debug(`\u5C1D\u8BD5\u53D1\u9001\u54CD\u5E94: id=${e}, isConnected=${this.isConnected}, wsReadyState=${this.ws?.readyState}`),this.isConnected&&this.ws?.readyState===m.OPEN){let n={jsonrpc:"2.0",id:e,result:t};try{this.ws.send(JSON.stringify(n)),this.logger.info(`\u54CD\u5E94\u5DF2\u53D1\u9001: id=${e}`,{responseSize:JSON.stringify(n).length})}catch(i){this.logger.error(`\u53D1\u9001\u54CD\u5E94\u5931\u8D25: id=${e}`,i)}}else this.logger.error(`\u65E0\u6CD5\u53D1\u9001\u54CD\u5E94: id=${e}, \u8FDE\u63A5\u72B6\u6001\u68C0\u67E5\u5931\u8D25`,{isConnected:this.isConnected,wsReadyState:this.ws?.readyState,wsReadyStateText:this.ws?.readyState===m.OPEN?"OPEN":this.ws?.readyState===m.CONNECTING?"CONNECTING":this.ws?.readyState===m.CLOSING?"CLOSING":this.ws?.readyState===m.CLOSED?"CLOSED":"UNKNOWN"}),(!this.isConnected||this.ws?.readyState!==m.OPEN)&&(this.logger.warn(`\u5C1D\u8BD5\u91CD\u65B0\u8FDE\u63A5\u4EE5\u53D1\u9001\u54CD\u5E94: id=${e}`),this.scheduleReconnect())}getStatus(){return{connected:this.isConnected,initialized:this.serverInitialized,url:this.endpointUrl,availableTools:this.tools.size,connectionState:this.connectionState,reconnectAttempts:this.reconnectState.attempts,lastError:this.reconnectState.lastError?.message||null}}disconnect(){this.logger.info("\u4E3B\u52A8\u65AD\u5F00 MCP \u8FDE\u63A5"),this.reconnectState.isManualDisconnect=!0,this.stopReconnect(),this.cleanupConnection(),this.connectionState="disconnected"}async reconnect(){this.logger.info("\u624B\u52A8\u91CD\u8FDE MCP \u63A5\u5165\u70B9"),this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.isManualDisconnect=!1,this.cleanupConnection(),await this.connect()}enableReconnect(){this.reconnectOptions.enabled=!0,this.logger.info("\u81EA\u52A8\u91CD\u8FDE\u5DF2\u542F\u7528")}disableReconnect(){this.reconnectOptions.enabled=!1,this.stopReconnect(),this.logger.info("\u81EA\u52A8\u91CD\u8FDE\u5DF2\u7981\u7528")}updateReconnectOptions(e){this.reconnectOptions={...this.reconnectOptions,...e},this.logger.info("\u91CD\u8FDE\u914D\u7F6E\u5DF2\u66F4\u65B0",e)}getReconnectOptions(){return{...this.reconnectOptions}}resetReconnectState(){this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info("\u91CD\u8FDE\u72B6\u6001\u5DF2\u91CD\u7F6E")}async handleToolCall(e){if(e.id===void 0||e.id===null)throw new h(-32602,"\u8BF7\u6C42 ID \u4E0D\u80FD\u4E3A\u7A7A");let t=e.id,n=null;try{let i=this.validateToolCallParams(e.params);n=this.recordCallStart(i.name,t),this.logger.info(`\u5F00\u59CB\u5904\u7406\u5DE5\u5177\u8C03\u7528: ${i.name}`,{requestId:t,toolName:i.name,hasArguments:!!i.arguments});let r=this.serviceManager;if(!r)throw new h(-32001,"MCPServiceManager \u672A\u8BBE\u7F6E");let a=await this.executeToolWithRetry(r,i.name,i.arguments||{});this.sendResponse(t,{content:a.content||[{type:"text",text:JSON.stringify(a)}],isError:a.isError||!1}),n&&this.recordCallEnd(n,!0),this.logger.info(`\u5DE5\u5177\u8C03\u7528\u6210\u529F: ${i.name}`,{requestId:t,duration:n?.duration?`${n.duration}ms`:"unknown"})}catch(i){if(n){let r=i instanceof h?i.code:-32e3,a=i instanceof Error?i.message:"\u672A\u77E5\u9519\u8BEF";this.recordCallEnd(n,!1,r,a)}this.handleToolCallError(i,t,n?.duration||0)}}validateToolCallParams(e){if(!e||typeof e!="object")throw new h(-32602,"\u8BF7\u6C42\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61");if(!e.name||typeof e.name!="string")throw new h(-32602,"\u5DE5\u5177\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(e.arguments!==void 0&&(typeof e.arguments!="object"||Array.isArray(e.arguments)))throw new h(-32602,"\u5DE5\u5177\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61");return{name:e.name,arguments:e.arguments}}async executeToolWithRetry(e,t,n){let i=null;for(let r=1;r<=this.retryConfig.maxAttempts;r++)try{return await this.executeToolWithTimeout(e,t,n,this.toolCallConfig.timeout)}catch(a){if(a instanceof h?i=a:i=new h(-32e3,a instanceof Error?a.message:"\u672A\u77E5\u9519\u8BEF"),this.retryConfig.retryableErrors.includes(i.code)&&r<this.retryConfig.maxAttempts){let c=Math.min(this.retryConfig.initialDelay*this.retryConfig.backoffMultiplier**(r-1),this.retryConfig.maxDelay);this.logger.warn(`\u5DE5\u5177\u8C03\u7528\u5931\u8D25\uFF0C\u5C06\u5728 ${c}ms \u540E\u91CD\u8BD5 (${r}/${this.retryConfig.maxAttempts})`,{toolName:t,error:i.message,attempt:r,delay:c}),await new Promise(g=>setTimeout(g,c));continue}break}throw i}async executeToolWithTimeout(e,t,n,i=3e4){return new Promise((r,a)=>{let c=setTimeout(()=>{a(new h(-32002,`\u5DE5\u5177\u8C03\u7528\u8D85\u65F6 (${i}ms): ${t}`))},i);e.callTool(t,n).then(g=>{clearTimeout(c),r(g)}).catch(g=>{clearTimeout(c),g.message?.includes("\u672A\u627E\u5230\u5DE5\u5177")?a(new h(-32601,`\u5DE5\u5177\u4E0D\u5B58\u5728: ${t}`)):g.message?.includes("\u670D\u52A1")&&g.message?.includes("\u4E0D\u53EF\u7528")?a(new h(-32001,g.message)):g.message?.includes("\u6682\u65F6\u4E0D\u53EF\u7528")?a(new h(-32001,g.message)):g.message?.includes("\u6301\u7EED\u4E0D\u53EF\u7528")?a(new h(-32001,g.message)):a(new h(-32e3,`\u5DE5\u5177\u6267\u884C\u5931\u8D25: ${g.message}`))})})}handleToolCallError(e,t,n){let i;e instanceof h?i={code:e.code,message:e.message,data:e.data}:i={code:-32e3,message:e?.message||"\u672A\u77E5\u9519\u8BEF",data:{originalError:e?.toString()||"null"}},this.sendErrorResponse(t,i),this.logger.error("\u5DE5\u5177\u8C03\u7528\u5931\u8D25",{requestId:t,duration:`${n}ms`,error:i})}sendErrorResponse(e,t){if(this.isConnected&&this.ws?.readyState===m.OPEN){let n={jsonrpc:"2.0",id:e,error:t};this.ws.send(JSON.stringify(n)),this.logger.debug("\u5DF2\u53D1\u9001\u9519\u8BEF\u54CD\u5E94:",n)}}recordCallStart(e,t){let n={id:String(t),toolName:e,startTime:new Date,success:!1};return this.callRecords.push(n),this.callRecords.length>this.maxCallRecords&&this.callRecords.shift(),n}recordCallEnd(e,t,n,i){e.endTime=new Date,e.duration=e.endTime.getTime()-e.startTime.getTime(),e.success=t,e.errorCode=n,e.errorMessage=i,this.updatePerformanceMetrics(e)}updatePerformanceMetrics(e){if(this.performanceMetrics.totalCalls++,e.success?this.performanceMetrics.successfulCalls++:this.performanceMetrics.failedCalls++,e.duration!==void 0){e.duration<this.performanceMetrics.minResponseTime&&(this.performanceMetrics.minResponseTime=e.duration),e.duration>this.performanceMetrics.maxResponseTime&&(this.performanceMetrics.maxResponseTime=e.duration);let t=this.callRecords.filter(i=>i.duration!==void 0).reduce((i,r)=>i+(r.duration||0),0),n=this.callRecords.filter(i=>i.duration!==void 0).length;this.performanceMetrics.averageResponseTime=n>0?t/n:0}this.performanceMetrics.successRate=this.performanceMetrics.totalCalls>0?this.performanceMetrics.successfulCalls/this.performanceMetrics.totalCalls*100:0,this.performanceMetrics.lastUpdated=new Date}getPerformanceMetrics(){return{...this.performanceMetrics}}getCallRecords(e){let t=[...this.callRecords].reverse();return e?t.slice(0,e):t}resetPerformanceMetrics(){this.performanceMetrics={totalCalls:0,successfulCalls:0,failedCalls:0,averageResponseTime:0,minResponseTime:Number.MAX_VALUE,maxResponseTime:0,successRate:0,lastUpdated:new Date},this.callRecords=[]}updateToolCallConfig(e){this.toolCallConfig={...this.toolCallConfig,...e},this.logger.info("\u5DE5\u5177\u8C03\u7528\u914D\u7F6E\u5DF2\u66F4\u65B0",this.toolCallConfig)}updateRetryConfig(e){this.retryConfig={...this.retryConfig,...e},this.logger.info("\u91CD\u8BD5\u914D\u7F6E\u5DF2\u66F4\u65B0",this.retryConfig)}getConfiguration(){return{toolCall:{...this.toolCallConfig},retry:{...this.retryConfig}}}getEnhancedStatus(){return{connected:this.isConnected,initialized:this.serverInitialized,url:this.endpointUrl,availableTools:this.tools.size,connectionState:this.connectionState,reconnectAttempts:this.reconnectState.attempts,lastError:this.reconnectState.lastError?.message||null,performance:this.getPerformanceMetrics(),configuration:this.getConfiguration()}}};import{copyFileSync as ee,existsSync as R,readFileSync as te,writeFileSync as ne}from"fs";import{dirname as ie,resolve as S}from"path";import{fileURLToPath as oe}from"url";import*as I from"comment-json";import re from"dayjs";import k from"json5";import*as K from"json5-writer";function Z(o){if(!o||typeof o!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u6709\u6548\u7684\u5BF9\u8C61");if("command"in o&&typeof o.command=="string")return"stdio";if("type"in o&&o.type==="sse")return"sse";if("type"in o&&o.type==="streamable-http"||"url"in o&&typeof o.url=="string")return"streamable-http";throw new Error("\u65E0\u6CD5\u8BC6\u522B\u7684 MCP \u670D\u52A1\u914D\u7F6E\u7C7B\u578B\u3002\u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5\uFF08stdio\uFF09\u3001type: 'sse' \u5B57\u6BB5\uFF08sse\uFF09\u6216 url \u5B57\u6BB5\uFF08streamable-http\uFF09")}s(Z,"getMcpServerCommunicationType");function D(o,e){if(!e||typeof e!="object")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61`};try{switch(Z(e)){case"stdio":if(!e.command||typeof e.command!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 command \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(!Array.isArray(e.args))return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4`};if(e.env&&typeof e.env!="object")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61`};break;case"sse":if(e.type!=="sse")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 type \u5B57\u6BB5\u5FC5\u987B\u662F "sse"`};if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};break;case"streamable-http":if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(e.type&&e.type!=="streamable-http")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 type \u5B57\u6BB5\u5982\u679C\u5B58\u5728\uFF0C\u5FC5\u987B\u662F "streamable-http"`};break;default:return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u7C7B\u578B\u65E0\u6CD5\u8BC6\u522B`}}return{valid:!0}}catch(t){return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u65E0\u6548: ${t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}`}}}s(D,"validateMcpServerConfig");var B=ie(oe(import.meta.url)),L={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},j=class o{static{s(this,"ConfigManager")}static instance;defaultConfigPath;config=null;currentConfigPath=null;json5Writer=null;constructor(){let e=[S(B,"templates","default","xiaozhi.config.json"),S(B,"..","templates","default","xiaozhi.config.json"),S(process.cwd(),"templates","default","xiaozhi.config.json")];this.defaultConfigPath=e.find(t=>R(t))||e[0]}getConfigFilePath(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let n of t){let i=S(e,n);if(R(i))return i}return S(e,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return o.instance||(o.instance=new o),o.instance}configExists(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let n of t){let i=S(e,n);if(R(i))return!0}return!1}initConfig(e="json"){if(!R(this.defaultConfigPath))throw new Error(`\u9ED8\u8BA4\u914D\u7F6E\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${this.defaultConfigPath}`);if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let t=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),n=`xiaozhi.config.${e}`,i=S(t,n);ee(this.defaultConfigPath,i),this.config=null,this.json5Writer=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let e=this.getConfigFilePath();this.currentConfigPath=e;let t=this.getConfigFileFormat(e),i=te(e,"utf8").replace(/^\uFEFF/,""),r;switch(t){case"json5":r=k.parse(i),this.json5Writer=K.load(i);break;case"jsonc":r=I.parse(i);break;default:r=JSON.parse(i);break}return this.validateConfig(r),r}catch(e){throw e instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${e.message}`):e}}validateConfig(e){if(!e||typeof e!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let t=e;if(t.mcpEndpoint===void 0||t.mcpEndpoint===null)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(typeof t.mcpEndpoint!="string")if(Array.isArray(t.mcpEndpoint)){if(t.mcpEndpoint.length===0)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let n of t.mcpEndpoint)if(typeof n!="string"||n.trim()==="")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");if(!t.mcpServers||typeof t.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[n,i]of Object.entries(t.mcpServers)){if(!i||typeof i!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${n} \u65E0\u6548`);let r=D(n,i);if(!r.valid)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A${r.error}`)}}getConfig(){return this.config=this.loadConfig(),JSON.parse(JSON.stringify(this.config))}getMutableConfig(){return this.config||(this.config=this.loadConfig()),this.config}getMcpEndpoint(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?e.mcpEndpoint[0]||"":e.mcpEndpoint}getMcpEndpoints(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?[...e.mcpEndpoint]:e.mcpEndpoint?[e.mcpEndpoint]:[]}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(e){return this.getMcpServerConfig()[e]?.tools||{}}isToolEnabled(e,t){return this.getServerToolsConfig(e)[t]?.enable!==!1}updateMcpEndpoint(e){if(Array.isArray(e)){if(e.length===0)throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let n of e)if(!n||typeof n!="string")throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig();t.mcpEndpoint=e,this.saveConfig(t)}addMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),n=this.getMcpEndpoints();if(n.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let i=[...n,e];t.mcpEndpoint=i,this.saveConfig(t)}removeMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),n=this.getMcpEndpoints();if(n.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);if(n.length===1)throw new Error("\u4E0D\u80FD\u5220\u9664\u6700\u540E\u4E00\u4E2A MCP \u7AEF\u70B9");let r=n.filter(a=>a!==e);t.mcpEndpoint=r,this.saveConfig(t)}updateMcpServer(e,t){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let n=D(e,t);if(!n.valid)throw new Error(n.error||"\u670D\u52A1\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");let i=this.getMutableConfig();i.mcpServers[e]=t,this.saveConfig(i)}removeMcpServer(e){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getConfig();if(!t.mcpServers[e])throw new Error(`\u670D\u52A1 ${e} \u4E0D\u5B58\u5728`);let n={...t.mcpServers};delete n[e];let i={...t,mcpServers:n};this.saveConfig(i)}updateServerToolsConfig(e,t){let n=this.getMutableConfig();n.mcpServerConfig||(n.mcpServerConfig={}),Object.keys(t).length===0?delete n.mcpServerConfig[e]:n.mcpServerConfig[e]={tools:t},this.saveConfig(n)}removeServerToolsConfig(e){let n={...this.getConfig()};n.mcpServerConfig&&(delete n.mcpServerConfig[e],this.saveConfig(n))}setToolEnabled(e,t,n,i){let r=this.getMutableConfig();r.mcpServerConfig||(r.mcpServerConfig={}),r.mcpServerConfig[e]||(r.mcpServerConfig[e]={tools:{}}),r.mcpServerConfig[e].tools[t]={...r.mcpServerConfig[e].tools[t],enable:n,...i&&{description:i}},this.saveConfig(r)}saveConfig(e){try{this.validateConfig(e);let t;this.currentConfigPath?t=this.currentConfigPath:(t=this.getConfigFilePath(),this.currentConfigPath=t);let n=this.getConfigFileFormat(t),i;switch(n){case"json5":try{this.json5Writer?(this.json5Writer.write(e),i=this.json5Writer.toSource()):(console.warn("\u6CA1\u6709 json5Writer \u5B9E\u4F8B\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F"),i=k.stringify(e,null,2))}catch(r){console.warn("\u4F7F\u7528 json5-writer \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F:",r),i=k.stringify(e,null,2)}break;case"jsonc":try{i=I.stringify(e,null,2)}catch(r){console.warn("\u4F7F\u7528 comment-json \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON \u683C\u5F0F:",r),i=JSON.stringify(e,null,2)}break;default:i=JSON.stringify(e,null,2);break}ne(t,i,"utf8"),this.config=e,this.notifyConfigUpdate(e)}catch(t){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}reloadConfig(){this.config=null,this.currentConfigPath=null,this.json5Writer=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let t=this.getConfig().connection||{};return{heartbeatInterval:t.heartbeatInterval??L.heartbeatInterval,heartbeatTimeout:t.heartbeatTimeout??L.heartbeatTimeout,reconnectInterval:t.reconnectInterval??L.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(e){let t=this.getMutableConfig();t.connection||(t.connection={}),Object.assign(t.connection,e),this.saveConfig(t)}async updateToolUsageStats(e,t,n){try{let i=this.getMutableConfig();i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[e]||(i.mcpServerConfig[e]={tools:{}}),i.mcpServerConfig[e].tools[t]||(i.mcpServerConfig[e].tools[t]={enable:!0});let r=i.mcpServerConfig[e].tools[t],a=r.usageCount||0,c=r.lastUsedTime;r.usageCount=a+1,(!c||new Date(n)>new Date(c))&&(r.lastUsedTime=re(n).format("YYYY-MM-DD HH:mm:ss")),this.saveConfig(i),l.debug(`\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5DF2\u66F4\u65B0: ${e}/${t}, \u4F7F\u7528\u6B21\u6570: ${r.usageCount}`)}catch(i){l.error(`\u66F4\u65B0\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5931\u8D25 (${e}/${t}): ${i instanceof Error?i.message:String(i)}`)}}setHeartbeatInterval(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:e})}setHeartbeatTimeout(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:e})}setReconnectInterval(e){if(e<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:e})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(e){let t=this.getMutableConfig();t.modelscope||(t.modelscope={}),Object.assign(t.modelscope,e),this.saveConfig(t)}setModelScopeApiKey(e){if(!e||typeof e!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:e})}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}notifyConfigUpdate(e){try{let t=global.__webServer;t&&typeof t.broadcastConfigUpdate=="function"&&(t.broadcastConfigUpdate(e),console.log("\u5DF2\u901A\u8FC7 WebSocket \u5E7F\u64AD\u914D\u7F6E\u66F4\u65B0"))}catch(t){console.warn("\u901A\u77E5 Web \u754C\u9762\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",t instanceof Error?t.message:String(t))}}updateWebUIConfig(e){let t=this.getMutableConfig();t.webUI||(t.webUI={}),Object.assign(t.webUI,e),this.saveConfig(t)}setWebUIPort(e){if(!Number.isInteger(e)||e<=0||e>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:e})}},v=j.getInstance();import{randomUUID as se}from"crypto";import H from"express";var P=class{static{s(this,"TransportAdapter")}logger;messageHandler;connectionId;config;state="disconnected";constructor(e,t){this.messageHandler=e,this.config=t,this.connectionId=this.generateConnectionId(),this.logger=l}async handleIncomingMessage(e){try{this.logger.debug(`\u5904\u7406\u63A5\u6536\u5230\u7684\u6D88\u606F: ${e.method}`,e);let t=await this.messageHandler.handleMessage(e);this.logger.debug("\u53D1\u9001\u54CD\u5E94\u6D88\u606F:",t),await this.sendMessage(t)}catch(t){this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t);let n=this.createErrorResponse(t,e.id);await this.sendMessage(n)}}createErrorResponse(e,t){let n=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?n=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(n=-32602),{jsonrpc:"2.0",error:{code:n,message:e.message,data:{stack:e.stack}},id:t||null}}generateConnectionId(){let e=Date.now(),t=Math.random().toString(36).substr(2,9);return`${this.config.name}_${e}_${t}`}getConnectionId(){return this.connectionId}getState(){return this.state}setState(e){let t=this.state;this.state=e,t!==e&&(this.logger.info(`\u8FDE\u63A5\u72B6\u6001\u53D8\u66F4: ${t} -> ${e}`),this.onStateChange(t,e))}onStateChange(e,t){}getConfig(){return{...this.config}}getMessageHandler(){return this.messageHandler}parseMessage(e){try{let t=JSON.parse(e.trim());return!t.jsonrpc||t.jsonrpc!=="2.0"?(this.logger.warn("\u6536\u5230\u975E JSON-RPC 2.0 \u683C\u5F0F\u7684\u6D88\u606F",t),null):t.method?t:(this.logger.warn("\u6536\u5230\u6CA1\u6709 method \u5B57\u6BB5\u7684\u6D88\u606F",t),null)}catch(t){return this.logger.error("\u89E3\u6790 JSON \u6D88\u606F\u5931\u8D25",{data:e,error:t}),null}}serializeMessage(e){try{return JSON.stringify(e)}catch(t){this.logger.error("\u5E8F\u5217\u5316\u6D88\u606F\u5931\u8D25",{message:e,error:t});let n=t instanceof Error?t.message:String(t);throw new Error(`\u6D88\u606F\u5E8F\u5217\u5316\u5931\u8D25: ${n}`)}}validateMessage(e){return!(!e||typeof e!="object"||e.jsonrpc!=="2.0"||e.method&&typeof e.method!="string"||!e.method&&!e.result&&!e.error)}createTimeoutPromise(e,t){return Promise.race([e,new Promise((n,i)=>{setTimeout(()=>{i(new Error(`\u64CD\u4F5C\u8D85\u65F6: ${t}ms`))},t)})])}};var O=class extends P{static{s(this,"HTTPAdapter")}app;server=null;clients=new Map;port;host;enableSSE;enableRPC;corsOrigin;maxClients;constructor(e,t={name:"http"}){super(e,t),this.port=t.port||3e3,this.host=t.host||"0.0.0.0",this.enableSSE=t.enableSSE!==!1,this.enableRPC=t.enableRPC!==!1,this.corsOrigin=t.corsOrigin||"*",this.maxClients=t.maxClients!==void 0?t.maxClients:100,this.app=H(),this.setupMiddleware()}async initialize(){this.logger.info("\u521D\u59CB\u5316 HTTP \u9002\u914D\u5668");try{this.setupRoutes(),this.setState("connecting"),this.logger.info("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),e}}async start(){if(this.server){this.logger.warn("HTTP \u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");return}return this.logger.info(`\u542F\u52A8 HTTP \u670D\u52A1\u5668\u5728 ${this.host}:${this.port}`),new Promise((e,t)=>{this.server=this.app.listen(this.port,this.host,()=>{this.setState("connected"),this.logger.info("HTTP \u9002\u914D\u5668\u542F\u52A8\u6210\u529F"),this.logger.info(`- RPC \u7AEF\u70B9: http://${this.host}:${this.port}/rpc`),this.enableSSE&&(this.logger.info(`- SSE \u7AEF\u70B9: http://${this.host}:${this.port}/sse`),this.logger.info(`- \u6D88\u606F\u7AEF\u70B9: http://${this.host}:${this.port}/messages`)),e()}),this.server?.on("error",n=>{this.logger.error("HTTP \u670D\u52A1\u5668\u9519\u8BEF",n),this.setState("error"),t(n)})})}async stop(){if(this.server)return this.logger.info("\u505C\u6B62 HTTP \u670D\u52A1\u5668"),new Promise(e=>{for(let t of this.clients.values())t.response.end();this.clients.clear(),this.server.close(()=>{this.server=null,this.setState("disconnected"),this.logger.info("HTTP \u670D\u52A1\u5668\u5DF2\u505C\u6B62"),e()})})}async sendMessage(e){this.clients.size>0&&this.broadcastToClients(e)}setupMiddleware(){this.app.use(H.json({limit:"10mb"})),this.app.use(H.urlencoded({extended:!0})),this.app.use((e,t,n)=>{t.header("Access-Control-Allow-Origin",this.corsOrigin),t.header("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.header("Access-Control-Allow-Headers","Content-Type, Accept"),t.header("Cache-Control","no-cache"),n()}),this.app.use((e,t,n)=>{this.logger.debug(`${e.method} ${e.path}`,{query:e.query,headers:e.headers}),n()})}setupRoutes(){this.enableSSE&&(this.app.get("/sse",this.handleSSE.bind(this)),this.app.post("/messages",this.handleMessages.bind(this))),this.enableRPC&&this.app.post("/rpc",this.handleRPC.bind(this)),this.app.get("/status",this.handleStatus.bind(this)),this.app.get("/health",this.handleHealth.bind(this))}handleSSE(e,t){if(this.clients.size>=this.maxClients){t.status(503).json({error:"\u670D\u52A1\u5668\u7E41\u5FD9\uFF0C\u5BA2\u6237\u7AEF\u8FDE\u63A5\u6570\u5DF2\u8FBE\u4E0A\u9650",maxClients:this.maxClients});return}let n=Date.now().toString(),i=se();t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache, no-transform"),t.setHeader("Connection","keep-alive"),t.setHeader("X-Accel-Buffering","no");let r={id:n,sessionId:i,response:t,connectedAt:new Date};this.clients.set(i,r),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u8FDE\u63A5: ${n} (\u4F1A\u8BDD: ${i})`),t.write(`event: endpoint
1
+ var q=Object.defineProperty;var a=(o,e)=>q(o,"name",{value:e,configurable:!0});import{EventEmitter as Te}from"events";import*as d from"fs";import*as u from"path";import T from"chalk";import M from"pino";function Y(o){let e=o.getFullYear(),t=String(o.getMonth()+1).padStart(2,"0"),n=String(o.getDate()).padStart(2,"0"),i=String(o.getHours()).padStart(2,"0"),r=String(o.getMinutes()).padStart(2,"0"),s=String(o.getSeconds()).padStart(2,"0");return`${e}-${t}-${n} ${i}:${r}:${s}`}a(Y,"formatDateTime");var y=class{static{a(this,"Logger")}logFilePath=null;pinoInstance;isDaemonMode;maxLogFileSize=10*1024*1024;maxLogFiles=5;constructor(){this.isDaemonMode=process.env.XIAOZHI_DAEMON==="true",this.pinoInstance=this.createPinoInstance()}createPinoInstance(){let e=[];if(!this.isDaemonMode){let t=this.createOptimizedConsoleStream();e.push({level:"debug",stream:t})}return this.logFilePath&&e.push({level:"debug",stream:M.destination({dest:this.logFilePath,sync:!1,append:!0,mkdir:!0})}),e.length===0&&e.push({level:"debug",stream:M.destination({dest:"/dev/null"})}),M({level:"debug",timestamp:M.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:a((t,n)=>({level:n}),"level")},base:null,serializers:{err:M.stdSerializers?.err||(t=>t)}},M.multistream(e,{dedupe:!0}))}createOptimizedConsoleStream(){let e=new Map([[20,{name:"DEBUG",color:T.gray}],[30,{name:"INFO",color:T.blue}],[40,{name:"WARN",color:T.yellow}],[50,{name:"ERROR",color:T.red}],[60,{name:"FATAL",color:T.red}]]);return{write:a(t=>{try{let n=JSON.parse(t),i=this.formatConsoleMessageOptimized(n,e);this.safeWrite(`${i}
2
+ `)}catch{this.safeWrite(t)}},"write")}}safeWrite(e){try{process.stderr&&typeof process.stderr.write=="function"?process.stderr.write(e):console&&typeof console.error=="function"&&console.error(e.trim())}catch{}}formatConsoleMessageOptimized(e,t){let n=Y(new Date),i=t.get(e.level)||{name:"UNKNOWN",color:a(l=>l,"color")},r=i.color(`[${i.name}]`),s=e.msg;if(e.args&&Array.isArray(e.args)){let l=e.args.map(g=>typeof g=="object"?JSON.stringify(g):String(g)).join(" ");s=`${s} ${l}`}return`[${n}] ${r} ${s}`}initLogFile(e){this.logFilePath=u.join(e,"xiaozhi.log"),this.rotateLogFileIfNeeded(),d.existsSync(this.logFilePath)||d.writeFileSync(this.logFilePath,""),this.pinoInstance=this.createPinoInstance()}enableFileLogging(e){e&&this.logFilePath&&(this.pinoInstance=this.createPinoInstance())}info(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}success(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}warn(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.warn(e):this.pinoInstance.warn({args:t},e):this.pinoInstance.warn(e,t[0]||"")}error(e,...t){if(typeof e=="string")if(t.length===0)this.pinoInstance.error(e);else{let n=t.map(i=>i instanceof Error?{message:i.message,stack:i.stack,name:i.name,cause:i.cause}:i);this.pinoInstance.error({args:n},e)}else{let n=this.enhanceErrorObject(e);this.pinoInstance.error(n,t[0]||"")}}debug(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.debug(e):this.pinoInstance.debug({args:t},e):this.pinoInstance.debug(e,t[0]||"")}log(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}enhanceErrorObject(e){let t={...e};for(let[n,i]of Object.entries(t))i instanceof Error&&(t[n]={message:i.message,stack:i.stack,name:i.name,cause:i.cause});return t}rotateLogFileIfNeeded(){if(!(!this.logFilePath||!d.existsSync(this.logFilePath)))try{d.statSync(this.logFilePath).size>this.maxLogFileSize&&this.rotateLogFile()}catch{}}rotateLogFile(){if(this.logFilePath)try{let e=u.dirname(this.logFilePath),t=u.basename(this.logFilePath,".log");for(let i=this.maxLogFiles-1;i>=1;i--){let r=u.join(e,`${t}.${i}.log`),s=u.join(e,`${t}.${i+1}.log`);d.existsSync(r)&&(i===this.maxLogFiles-1?d.unlinkSync(r):d.renameSync(r,s))}let n=u.join(e,`${t}.1.log`);d.renameSync(this.logFilePath,n)}catch{}}cleanupOldLogs(){if(this.logFilePath)try{let e=u.dirname(this.logFilePath),t=u.basename(this.logFilePath,".log");for(let n=this.maxLogFiles+1;n<=this.maxLogFiles+10;n++){let i=u.join(e,`${t}.${n}.log`);d.existsSync(i)&&d.unlinkSync(i)}}catch{}}setLogFileOptions(e,t){this.maxLogFileSize=e,this.maxLogFiles=t}withTag(e){return this}close(){}},c=new y;import m from"ws";var h=class extends Error{constructor(t,n,i){super(n);this.code=t;this.data=i;this.name="ToolCallError"}static{a(this,"ToolCallError")}},w=class{static{a(this,"ProxyMCPServer")}endpointUrl;ws=null;logger;isConnected=!1;serverInitialized=!1;tools=new Map;connectionState="disconnected";reconnectOptions;reconnectState={attempts:0,nextInterval:0,timer:null,lastError:null,isManualDisconnect:!1};connectionTimeout=null;performanceMetrics={totalCalls:0,successfulCalls:0,failedCalls:0,averageResponseTime:0,minResponseTime:Number.MAX_VALUE,maxResponseTime:0,successRate:0,lastUpdated:new Date};callRecords=[];maxCallRecords=100;retryConfig={maxAttempts:3,initialDelay:1e3,maxDelay:1e4,backoffMultiplier:2,retryableErrors:[-32001,-32002]};toolCallConfig={timeout:3e4,retryAttempts:3,retryDelay:1e3};constructor(e,t){this.endpointUrl=e,this.logger=c,this.reconnectOptions={enabled:!0,maxAttempts:10,initialInterval:3e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t?.reconnect},this.reconnectState.nextInterval=this.reconnectOptions.initialInterval}setServiceManager(e){this.serviceManager=e,this.logger.info("\u5DF2\u8BBE\u7F6E MCPServiceManager"),this.syncToolsFromServiceManager()}syncToolsFromServiceManager(){let e=this.serviceManager;if(!e){this.logger.debug("MCPServiceManager \u672A\u8BBE\u7F6E\uFF0C\u8DF3\u8FC7\u5DE5\u5177\u540C\u6B65");return}try{let t=e.getAllTools(),n=new Map;for(let i of t)n.set(i.name,{name:i.name,description:i.description,inputSchema:i.inputSchema});this.tools=n,this.logger.info(`\u5DF2\u4ECE MCPServiceManager \u540C\u6B65 ${this.tools.size} \u4E2A\u5DE5\u5177`)}catch(t){this.logger.error(`\u540C\u6B65\u5DE5\u5177\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}addTool(e,t){return this.validateTool(e,t),this.tools.set(e,t),this.logger.debug(`\u5DE5\u5177 '${e}' \u5DF2\u6DFB\u52A0`),this}addTools(e){for(let[t,n]of Object.entries(e))this.addTool(t,n);return this}removeTool(e){return this.tools.delete(e)?this.logger.debug(`\u5DE5\u5177 '${e}' \u5DF2\u79FB\u9664`):this.logger.warn(`\u5C1D\u8BD5\u79FB\u9664\u4E0D\u5B58\u5728\u7684\u5DE5\u5177: '${e}'`),this}getTools(){try{this.syncToolsFromServiceManager()}catch{}return Array.from(this.tools.values())}hasTool(e){return this.tools.has(e)}validateTool(e,t){if(!e||typeof e!="string"||e.trim()==="")throw new Error("\u5DE5\u5177\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(this.tools.has(e))throw new Error(`\u5DE5\u5177 '${e}' \u5DF2\u5B58\u5728`);if(!t||typeof t!="object")throw new Error("\u5DE5\u5177\u5FC5\u987B\u662F\u6709\u6548\u7684\u5BF9\u8C61");if(!t.name||typeof t.name!="string")throw new Error("\u5DE5\u5177\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 'name' \u5B57\u6BB5");if(!t.description||typeof t.description!="string")throw new Error("\u5DE5\u5177\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 'description' \u5B57\u6BB5");if(!t.inputSchema||typeof t.inputSchema!="object")throw new Error("\u5DE5\u5177\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 'inputSchema' \u5B57\u6BB5");if(!t.inputSchema.type||!t.inputSchema.properties)throw new Error("\u5DE5\u5177\u7684 inputSchema \u5FC5\u987B\u5305\u542B 'type' \u548C 'properties' \u5B57\u6BB5")}async connect(){if(this.tools.size===0)throw new Error("\u672A\u914D\u7F6E\u4EFB\u4F55\u5DE5\u5177\u3002\u8BF7\u5728\u8FDE\u63A5\u524D\u81F3\u5C11\u6DFB\u52A0\u4E00\u4E2A\u5DE5\u5177\u3002");if(this.connectionState==="connecting")throw new Error("\u8FDE\u63A5\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210");return this.cleanupConnection(),this.reconnectState.isManualDisconnect=!1,this.attemptConnection()}async attemptConnection(){return this.connectionState="connecting",this.logger.info(`\u6B63\u5728\u8FDE\u63A5 MCP \u63A5\u5165\u70B9: ${this.endpointUrl} (\u5C1D\u8BD5 ${this.reconnectState.attempts+1}/${this.reconnectOptions.maxAttempts})`),new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let n=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(n),t(n)},this.reconnectOptions.timeout),this.ws=new m(this.endpointUrl),this.ws.on("open",()=>{this.handleConnectionSuccess(),e()}),this.ws.on("message",n=>{try{let i=JSON.parse(n.toString());this.handleMessage(i)}catch(i){this.logger.error("MCP \u6D88\u606F\u89E3\u6790\u9519\u8BEF:",i)}}),this.ws.on("close",(n,i)=>{this.handleConnectionClose(n,i.toString())}),this.ws.on("error",n=>{this.handleConnectionError(n),t(n)})})}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=!0,this.connectionState="connected",this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info("MCP WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB")}handleConnectionError(e){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.reconnectState.lastError=e,this.logger.error("MCP WebSocket \u9519\u8BEF:",e.message),this.cleanupConnection()}handleConnectionClose(e,t){if(this.isConnected=!1,this.serverInitialized=!1,this.logger.info(`MCP \u8FDE\u63A5\u5DF2\u5173\u95ED (\u4EE3\u7801: ${e}, \u539F\u56E0: ${t})`),this.reconnectState.isManualDisconnect){this.connectionState="disconnected";return}this.shouldReconnect()?this.scheduleReconnect():(this.connectionState="failed",this.logger.warn(`\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`))}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.connectionState="reconnecting",this.reconnectState.attempts++,this.calculateNextInterval(),this.logger.info(`\u5C06\u5728 ${this.reconnectState.nextInterval}ms \u540E\u8FDB\u884C\u7B2C ${this.reconnectState.attempts} \u6B21\u91CD\u8FDE`),this.reconnectState.timer&&clearTimeout(this.reconnectState.timer),this.reconnectState.timer=setTimeout(async()=>{try{await this.attemptConnection()}catch{}},this.reconnectState.nextInterval)}calculateNextInterval(){let e;switch(this.reconnectOptions.backoffStrategy){case"fixed":e=this.reconnectOptions.initialInterval;break;case"linear":e=this.reconnectOptions.initialInterval+this.reconnectState.attempts*this.reconnectOptions.backoffMultiplier*1e3;break;case"exponential":e=this.reconnectOptions.initialInterval*this.reconnectOptions.backoffMultiplier**(this.reconnectState.attempts-1);break;default:e=this.reconnectOptions.initialInterval}if(e=Math.min(e,this.reconnectOptions.maxInterval),this.reconnectOptions.jitter){let t=e*.1,n=(Math.random()-.5)*2*t;e+=n}this.reconnectState.nextInterval=Math.max(e,1e3)}cleanupConnection(){if(this.ws){this.ws.removeAllListeners();try{this.ws.readyState===m.OPEN?this.ws.close(1e3,"Cleaning up connection"):this.ws.readyState===m.CONNECTING&&this.ws.terminate()}catch(e){this.logger.debug("WebSocket \u5173\u95ED\u65F6\u51FA\u73B0\u9519\u8BEF\uFF08\u5DF2\u5FFD\u7565\uFF09:",e)}this.ws=null}this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=!1,this.serverInitialized=!1}stopReconnect(){this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null)}handleMessage(e){this.logger.debug("\u6536\u5230 MCP \u6D88\u606F:",JSON.stringify(e,null,2)),e.method&&this.handleServerRequest(e)}handleServerRequest(e){switch(e.method){case"initialize":case"notifications/initialized":this.sendResponse(e.id,{protocolVersion:"2024-11-05",capabilities:{tools:{listChanged:!0},logging:{}},serverInfo:{name:"xiaozhi-mcp-server",version:"1.0.0"}}),this.serverInitialized=!0,this.logger.info("MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210");break;case"tools/list":{let t=this.getTools();this.sendResponse(e.id,{tools:t}),this.logger.info(`MCP \u5DE5\u5177\u5217\u8868\u5DF2\u53D1\u9001 (${t.length}\u4E2A\u5DE5\u5177)`);break}case"tools/call":{this.handleToolCall(e).catch(t=>{this.logger.error("\u5904\u7406\u5DE5\u5177\u8C03\u7528\u65F6\u53D1\u751F\u672A\u6355\u83B7\u9519\u8BEF:",t)});break}case"ping":this.sendResponse(e.id,{}),this.logger.debug("\u56DE\u5E94 MCP ping \u6D88\u606F");break;default:this.logger.warn(`\u672A\u77E5\u7684 MCP \u8BF7\u6C42: ${e.method}`)}}sendResponse(e,t){if(this.logger.debug(`\u5C1D\u8BD5\u53D1\u9001\u54CD\u5E94: id=${e}, isConnected=${this.isConnected}, wsReadyState=${this.ws?.readyState}`),this.isConnected&&this.ws?.readyState===m.OPEN){let n={jsonrpc:"2.0",id:e,result:t};try{this.ws.send(JSON.stringify(n)),this.logger.info(`\u54CD\u5E94\u5DF2\u53D1\u9001: id=${e}`,{responseSize:JSON.stringify(n).length})}catch(i){this.logger.error(`\u53D1\u9001\u54CD\u5E94\u5931\u8D25: id=${e}`,i)}}else this.logger.error(`\u65E0\u6CD5\u53D1\u9001\u54CD\u5E94: id=${e}, \u8FDE\u63A5\u72B6\u6001\u68C0\u67E5\u5931\u8D25`,{isConnected:this.isConnected,wsReadyState:this.ws?.readyState,wsReadyStateText:this.ws?.readyState===m.OPEN?"OPEN":this.ws?.readyState===m.CONNECTING?"CONNECTING":this.ws?.readyState===m.CLOSING?"CLOSING":this.ws?.readyState===m.CLOSED?"CLOSED":"UNKNOWN"}),(!this.isConnected||this.ws?.readyState!==m.OPEN)&&(this.logger.warn(`\u5C1D\u8BD5\u91CD\u65B0\u8FDE\u63A5\u4EE5\u53D1\u9001\u54CD\u5E94: id=${e}`),this.scheduleReconnect())}getStatus(){return{connected:this.isConnected,initialized:this.serverInitialized,url:this.endpointUrl,availableTools:this.tools.size,connectionState:this.connectionState,reconnectAttempts:this.reconnectState.attempts,lastError:this.reconnectState.lastError?.message||null}}disconnect(){this.logger.info("\u4E3B\u52A8\u65AD\u5F00 MCP \u8FDE\u63A5"),this.reconnectState.isManualDisconnect=!0,this.stopReconnect(),this.cleanupConnection(),this.connectionState="disconnected"}async reconnect(){this.logger.info("\u624B\u52A8\u91CD\u8FDE MCP \u63A5\u5165\u70B9"),this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.isManualDisconnect=!1,this.cleanupConnection(),await this.connect()}enableReconnect(){this.reconnectOptions.enabled=!0,this.logger.info("\u81EA\u52A8\u91CD\u8FDE\u5DF2\u542F\u7528")}disableReconnect(){this.reconnectOptions.enabled=!1,this.stopReconnect(),this.logger.info("\u81EA\u52A8\u91CD\u8FDE\u5DF2\u7981\u7528")}updateReconnectOptions(e){this.reconnectOptions={...this.reconnectOptions,...e},this.logger.info("\u91CD\u8FDE\u914D\u7F6E\u5DF2\u66F4\u65B0",e)}getReconnectOptions(){return{...this.reconnectOptions}}resetReconnectState(){this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info("\u91CD\u8FDE\u72B6\u6001\u5DF2\u91CD\u7F6E")}async handleToolCall(e){if(e.id===void 0||e.id===null)throw new h(-32602,"\u8BF7\u6C42 ID \u4E0D\u80FD\u4E3A\u7A7A");let t=e.id,n=null;try{let i=this.validateToolCallParams(e.params);n=this.recordCallStart(i.name,t),this.logger.info(`\u5F00\u59CB\u5904\u7406\u5DE5\u5177\u8C03\u7528: ${i.name}`,{requestId:t,toolName:i.name,hasArguments:!!i.arguments});let r=this.serviceManager;if(!r)throw new h(-32001,"MCPServiceManager \u672A\u8BBE\u7F6E");let s=await this.executeToolWithRetry(r,i.name,i.arguments||{});this.sendResponse(t,{content:s.content||[{type:"text",text:JSON.stringify(s)}],isError:s.isError||!1}),n&&this.recordCallEnd(n,!0),this.logger.info(`\u5DE5\u5177\u8C03\u7528\u6210\u529F: ${i.name}`,{requestId:t,duration:n?.duration?`${n.duration}ms`:"unknown"})}catch(i){if(n){let r=i instanceof h?i.code:-32e3,s=i instanceof Error?i.message:"\u672A\u77E5\u9519\u8BEF";this.recordCallEnd(n,!1,r,s)}this.handleToolCallError(i,t,n?.duration||0)}}validateToolCallParams(e){if(!e||typeof e!="object")throw new h(-32602,"\u8BF7\u6C42\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61");if(!e.name||typeof e.name!="string")throw new h(-32602,"\u5DE5\u5177\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(e.arguments!==void 0&&(typeof e.arguments!="object"||Array.isArray(e.arguments)))throw new h(-32602,"\u5DE5\u5177\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61");return{name:e.name,arguments:e.arguments}}async executeToolWithRetry(e,t,n){let i=null;for(let r=1;r<=this.retryConfig.maxAttempts;r++)try{return await this.executeToolWithTimeout(e,t,n,this.toolCallConfig.timeout)}catch(s){if(s instanceof h?i=s:i=new h(-32e3,s instanceof Error?s.message:"\u672A\u77E5\u9519\u8BEF"),this.retryConfig.retryableErrors.includes(i.code)&&r<this.retryConfig.maxAttempts){let l=Math.min(this.retryConfig.initialDelay*this.retryConfig.backoffMultiplier**(r-1),this.retryConfig.maxDelay);this.logger.warn(`\u5DE5\u5177\u8C03\u7528\u5931\u8D25\uFF0C\u5C06\u5728 ${l}ms \u540E\u91CD\u8BD5 (${r}/${this.retryConfig.maxAttempts})`,{toolName:t,error:i.message,attempt:r,delay:l}),await new Promise(g=>setTimeout(g,l));continue}break}throw i}async executeToolWithTimeout(e,t,n,i=3e4){return new Promise((r,s)=>{let l=setTimeout(()=>{s(new h(-32002,`\u5DE5\u5177\u8C03\u7528\u8D85\u65F6 (${i}ms): ${t}`))},i);e.callTool(t,n).then(g=>{clearTimeout(l),r(g)}).catch(g=>{clearTimeout(l),g.message?.includes("\u672A\u627E\u5230\u5DE5\u5177")?s(new h(-32601,`\u5DE5\u5177\u4E0D\u5B58\u5728: ${t}`)):g.message?.includes("\u670D\u52A1")&&g.message?.includes("\u4E0D\u53EF\u7528")?s(new h(-32001,g.message)):g.message?.includes("\u6682\u65F6\u4E0D\u53EF\u7528")?s(new h(-32001,g.message)):g.message?.includes("\u6301\u7EED\u4E0D\u53EF\u7528")?s(new h(-32001,g.message)):s(new h(-32e3,`\u5DE5\u5177\u6267\u884C\u5931\u8D25: ${g.message}`))})})}handleToolCallError(e,t,n){let i;e instanceof h?i={code:e.code,message:e.message,data:e.data}:i={code:-32e3,message:e?.message||"\u672A\u77E5\u9519\u8BEF",data:{originalError:e?.toString()||"null"}},this.sendErrorResponse(t,i),this.logger.error("\u5DE5\u5177\u8C03\u7528\u5931\u8D25",{requestId:t,duration:`${n}ms`,error:i})}sendErrorResponse(e,t){if(this.isConnected&&this.ws?.readyState===m.OPEN){let n={jsonrpc:"2.0",id:e,error:t};this.ws.send(JSON.stringify(n)),this.logger.debug("\u5DF2\u53D1\u9001\u9519\u8BEF\u54CD\u5E94:",n)}}recordCallStart(e,t){let n={id:String(t),toolName:e,startTime:new Date,success:!1};return this.callRecords.push(n),this.callRecords.length>this.maxCallRecords&&this.callRecords.shift(),n}recordCallEnd(e,t,n,i){e.endTime=new Date,e.duration=e.endTime.getTime()-e.startTime.getTime(),e.success=t,e.errorCode=n,e.errorMessage=i,this.updatePerformanceMetrics(e)}updatePerformanceMetrics(e){if(this.performanceMetrics.totalCalls++,e.success?this.performanceMetrics.successfulCalls++:this.performanceMetrics.failedCalls++,e.duration!==void 0){e.duration<this.performanceMetrics.minResponseTime&&(this.performanceMetrics.minResponseTime=e.duration),e.duration>this.performanceMetrics.maxResponseTime&&(this.performanceMetrics.maxResponseTime=e.duration);let t=this.callRecords.filter(i=>i.duration!==void 0).reduce((i,r)=>i+(r.duration||0),0),n=this.callRecords.filter(i=>i.duration!==void 0).length;this.performanceMetrics.averageResponseTime=n>0?t/n:0}this.performanceMetrics.successRate=this.performanceMetrics.totalCalls>0?this.performanceMetrics.successfulCalls/this.performanceMetrics.totalCalls*100:0,this.performanceMetrics.lastUpdated=new Date}getPerformanceMetrics(){return{...this.performanceMetrics}}getCallRecords(e){let t=[...this.callRecords].reverse();return e?t.slice(0,e):t}resetPerformanceMetrics(){this.performanceMetrics={totalCalls:0,successfulCalls:0,failedCalls:0,averageResponseTime:0,minResponseTime:Number.MAX_VALUE,maxResponseTime:0,successRate:0,lastUpdated:new Date},this.callRecords=[]}updateToolCallConfig(e){this.toolCallConfig={...this.toolCallConfig,...e},this.logger.info("\u5DE5\u5177\u8C03\u7528\u914D\u7F6E\u5DF2\u66F4\u65B0",this.toolCallConfig)}updateRetryConfig(e){this.retryConfig={...this.retryConfig,...e},this.logger.info("\u91CD\u8BD5\u914D\u7F6E\u5DF2\u66F4\u65B0",this.retryConfig)}getConfiguration(){return{toolCall:{...this.toolCallConfig},retry:{...this.retryConfig}}}getEnhancedStatus(){return{connected:this.isConnected,initialized:this.serverInitialized,url:this.endpointUrl,availableTools:this.tools.size,connectionState:this.connectionState,reconnectAttempts:this.reconnectState.attempts,lastError:this.reconnectState.lastError?.message||null,performance:this.getPerformanceMetrics(),configuration:this.getConfiguration()}}};import{copyFileSync as ee,existsSync as R,readFileSync as te,writeFileSync as ne}from"fs";import{dirname as ie,resolve as S}from"path";import{fileURLToPath as oe}from"url";import*as I from"comment-json";import re from"dayjs";import k from"json5";import*as K from"json5-writer";function Z(o){if(!o||typeof o!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u6709\u6548\u7684\u5BF9\u8C61");if("command"in o&&typeof o.command=="string")return"stdio";if("type"in o&&o.type==="sse")return"sse";if("type"in o&&o.type==="streamable-http"||"url"in o&&typeof o.url=="string")return"streamable-http";throw new Error("\u65E0\u6CD5\u8BC6\u522B\u7684 MCP \u670D\u52A1\u914D\u7F6E\u7C7B\u578B\u3002\u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5\uFF08stdio\uFF09\u3001type: 'sse' \u5B57\u6BB5\uFF08sse\uFF09\u6216 url \u5B57\u6BB5\uFF08streamable-http\uFF09")}a(Z,"getMcpServerCommunicationType");function D(o,e){if(!e||typeof e!="object")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61`};try{switch(Z(e)){case"stdio":if(!e.command||typeof e.command!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 command \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(!Array.isArray(e.args))return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4`};if(e.env&&typeof e.env!="object")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61`};break;case"sse":if(e.type!=="sse")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 type \u5B57\u6BB5\u5FC5\u987B\u662F "sse"`};if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};break;case"streamable-http":if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(e.type&&e.type!=="streamable-http")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 type \u5B57\u6BB5\u5982\u679C\u5B58\u5728\uFF0C\u5FC5\u987B\u662F "streamable-http"`};break;default:return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u7C7B\u578B\u65E0\u6CD5\u8BC6\u522B`}}return{valid:!0}}catch(t){return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u65E0\u6548: ${t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}`}}}a(D,"validateMcpServerConfig");var B=ie(oe(import.meta.url)),L={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},j=class o{static{a(this,"ConfigManager")}static instance;defaultConfigPath;config=null;currentConfigPath=null;json5Writer=null;constructor(){let e=[S(B,"templates","default","xiaozhi.config.json"),S(B,"..","templates","default","xiaozhi.config.json"),S(process.cwd(),"templates","default","xiaozhi.config.json")];this.defaultConfigPath=e.find(t=>R(t))||e[0]}getConfigFilePath(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let n of t){let i=S(e,n);if(R(i))return i}return S(e,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return o.instance||(o.instance=new o),o.instance}configExists(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let n of t){let i=S(e,n);if(R(i))return!0}return!1}initConfig(e="json"){if(!R(this.defaultConfigPath))throw new Error(`\u9ED8\u8BA4\u914D\u7F6E\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${this.defaultConfigPath}`);if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let t=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),n=`xiaozhi.config.${e}`,i=S(t,n);ee(this.defaultConfigPath,i),this.config=null,this.json5Writer=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let e=this.getConfigFilePath();this.currentConfigPath=e;let t=this.getConfigFileFormat(e),i=te(e,"utf8").replace(/^\uFEFF/,""),r;switch(t){case"json5":r=k.parse(i),this.json5Writer=K.load(i);break;case"jsonc":r=I.parse(i);break;default:r=JSON.parse(i);break}return this.validateConfig(r),r}catch(e){throw e instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${e.message}`):e}}validateConfig(e){if(!e||typeof e!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let t=e;if(t.mcpEndpoint===void 0||t.mcpEndpoint===null)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(typeof t.mcpEndpoint!="string")if(Array.isArray(t.mcpEndpoint)){if(t.mcpEndpoint.length===0)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let n of t.mcpEndpoint)if(typeof n!="string"||n.trim()==="")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");if(!t.mcpServers||typeof t.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[n,i]of Object.entries(t.mcpServers)){if(!i||typeof i!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${n} \u65E0\u6548`);let r=D(n,i);if(!r.valid)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A${r.error}`)}}getConfig(){return this.config=this.loadConfig(),JSON.parse(JSON.stringify(this.config))}getMutableConfig(){return this.config||(this.config=this.loadConfig()),this.config}getMcpEndpoint(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?e.mcpEndpoint[0]||"":e.mcpEndpoint}getMcpEndpoints(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?[...e.mcpEndpoint]:e.mcpEndpoint?[e.mcpEndpoint]:[]}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(e){return this.getMcpServerConfig()[e]?.tools||{}}isToolEnabled(e,t){return this.getServerToolsConfig(e)[t]?.enable!==!1}updateMcpEndpoint(e){if(Array.isArray(e)){if(e.length===0)throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let n of e)if(!n||typeof n!="string")throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig();t.mcpEndpoint=e,this.saveConfig(t)}addMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),n=this.getMcpEndpoints();if(n.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let i=[...n,e];t.mcpEndpoint=i,this.saveConfig(t)}removeMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),n=this.getMcpEndpoints();if(n.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);if(n.length===1)throw new Error("\u4E0D\u80FD\u5220\u9664\u6700\u540E\u4E00\u4E2A MCP \u7AEF\u70B9");let r=n.filter(s=>s!==e);t.mcpEndpoint=r,this.saveConfig(t)}updateMcpServer(e,t){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let n=D(e,t);if(!n.valid)throw new Error(n.error||"\u670D\u52A1\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");let i=this.getMutableConfig();i.mcpServers[e]=t,this.saveConfig(i)}removeMcpServer(e){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getConfig();if(!t.mcpServers[e])throw new Error(`\u670D\u52A1 ${e} \u4E0D\u5B58\u5728`);let n={...t.mcpServers};delete n[e];let i={...t,mcpServers:n};this.saveConfig(i)}updateServerToolsConfig(e,t){let n=this.getMutableConfig();n.mcpServerConfig||(n.mcpServerConfig={}),Object.keys(t).length===0?delete n.mcpServerConfig[e]:n.mcpServerConfig[e]={tools:t},this.saveConfig(n)}removeServerToolsConfig(e){let n={...this.getConfig()};n.mcpServerConfig&&(delete n.mcpServerConfig[e],this.saveConfig(n))}cleanupInvalidServerToolsConfig(){let e=this.getMutableConfig();if(!e.mcpServerConfig)return;let t=Object.keys(e.mcpServers),i=Object.keys(e.mcpServerConfig).filter(r=>!t.includes(r));if(i.length>0){for(let r of i)delete e.mcpServerConfig[r];this.saveConfig(e),c.info(`\u5DF2\u6E05\u7406 ${i.length} \u4E2A\u65E0\u6548\u7684\u670D\u52A1\u5DE5\u5177\u914D\u7F6E: ${i.join(", ")}`)}}setToolEnabled(e,t,n,i){let r=this.getMutableConfig();r.mcpServerConfig||(r.mcpServerConfig={}),r.mcpServerConfig[e]||(r.mcpServerConfig[e]={tools:{}}),r.mcpServerConfig[e].tools[t]={...r.mcpServerConfig[e].tools[t],enable:n,...i&&{description:i}},this.saveConfig(r)}saveConfig(e){try{this.validateConfig(e);let t;this.currentConfigPath?t=this.currentConfigPath:(t=this.getConfigFilePath(),this.currentConfigPath=t);let n=this.getConfigFileFormat(t),i;switch(n){case"json5":try{this.json5Writer?(this.json5Writer.write(e),i=this.json5Writer.toSource()):(console.warn("\u6CA1\u6709 json5Writer \u5B9E\u4F8B\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F"),i=k.stringify(e,null,2))}catch(r){console.warn("\u4F7F\u7528 json5-writer \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F:",r),i=k.stringify(e,null,2)}break;case"jsonc":try{i=I.stringify(e,null,2)}catch(r){console.warn("\u4F7F\u7528 comment-json \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON \u683C\u5F0F:",r),i=JSON.stringify(e,null,2)}break;default:i=JSON.stringify(e,null,2);break}ne(t,i,"utf8"),this.config=e,this.notifyConfigUpdate(e)}catch(t){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}reloadConfig(){this.config=null,this.currentConfigPath=null,this.json5Writer=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let t=this.getConfig().connection||{};return{heartbeatInterval:t.heartbeatInterval??L.heartbeatInterval,heartbeatTimeout:t.heartbeatTimeout??L.heartbeatTimeout,reconnectInterval:t.reconnectInterval??L.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(e){let t=this.getMutableConfig();t.connection||(t.connection={}),Object.assign(t.connection,e),this.saveConfig(t)}async updateToolUsageStats(e,t,n){try{let i=this.getMutableConfig();i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[e]||(i.mcpServerConfig[e]={tools:{}}),i.mcpServerConfig[e].tools[t]||(i.mcpServerConfig[e].tools[t]={enable:!0});let r=i.mcpServerConfig[e].tools[t],s=r.usageCount||0,l=r.lastUsedTime;r.usageCount=s+1,(!l||new Date(n)>new Date(l))&&(r.lastUsedTime=re(n).format("YYYY-MM-DD HH:mm:ss")),this.saveConfig(i),c.debug(`\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5DF2\u66F4\u65B0: ${e}/${t}, \u4F7F\u7528\u6B21\u6570: ${r.usageCount}`)}catch(i){c.error(`\u66F4\u65B0\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5931\u8D25 (${e}/${t}): ${i instanceof Error?i.message:String(i)}`)}}setHeartbeatInterval(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:e})}setHeartbeatTimeout(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:e})}setReconnectInterval(e){if(e<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:e})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(e){let t=this.getMutableConfig();t.modelscope||(t.modelscope={}),Object.assign(t.modelscope,e),this.saveConfig(t)}setModelScopeApiKey(e){if(!e||typeof e!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:e})}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}notifyConfigUpdate(e){try{let t=global.__webServer;t&&typeof t.broadcastConfigUpdate=="function"&&(t.broadcastConfigUpdate(e),console.log("\u5DF2\u901A\u8FC7 WebSocket \u5E7F\u64AD\u914D\u7F6E\u66F4\u65B0"))}catch(t){console.warn("\u901A\u77E5 Web \u754C\u9762\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",t instanceof Error?t.message:String(t))}}updateWebUIConfig(e){let t=this.getMutableConfig();t.webUI||(t.webUI={}),Object.assign(t.webUI,e),this.saveConfig(t)}setWebUIPort(e){if(!Number.isInteger(e)||e<=0||e>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:e})}},v=j.getInstance();import{randomUUID as se}from"crypto";import H from"express";var P=class{static{a(this,"TransportAdapter")}logger;messageHandler;connectionId;config;state="disconnected";constructor(e,t){this.messageHandler=e,this.config=t,this.connectionId=this.generateConnectionId(),this.logger=c}async handleIncomingMessage(e){try{this.logger.debug(`\u5904\u7406\u63A5\u6536\u5230\u7684\u6D88\u606F: ${e.method}`,e);let t=await this.messageHandler.handleMessage(e);this.logger.debug("\u53D1\u9001\u54CD\u5E94\u6D88\u606F:",t),await this.sendMessage(t)}catch(t){this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t);let n=this.createErrorResponse(t,e.id);await this.sendMessage(n)}}createErrorResponse(e,t){let n=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?n=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(n=-32602),{jsonrpc:"2.0",error:{code:n,message:e.message,data:{stack:e.stack}},id:t||null}}generateConnectionId(){let e=Date.now(),t=Math.random().toString(36).substr(2,9);return`${this.config.name}_${e}_${t}`}getConnectionId(){return this.connectionId}getState(){return this.state}setState(e){let t=this.state;this.state=e,t!==e&&(this.logger.info(`\u8FDE\u63A5\u72B6\u6001\u53D8\u66F4: ${t} -> ${e}`),this.onStateChange(t,e))}onStateChange(e,t){}getConfig(){return{...this.config}}getMessageHandler(){return this.messageHandler}parseMessage(e){try{let t=JSON.parse(e.trim());return!t.jsonrpc||t.jsonrpc!=="2.0"?(this.logger.warn("\u6536\u5230\u975E JSON-RPC 2.0 \u683C\u5F0F\u7684\u6D88\u606F",t),null):t.method?t:(this.logger.warn("\u6536\u5230\u6CA1\u6709 method \u5B57\u6BB5\u7684\u6D88\u606F",t),null)}catch(t){return this.logger.error("\u89E3\u6790 JSON \u6D88\u606F\u5931\u8D25",{data:e,error:t}),null}}serializeMessage(e){try{return JSON.stringify(e)}catch(t){this.logger.error("\u5E8F\u5217\u5316\u6D88\u606F\u5931\u8D25",{message:e,error:t});let n=t instanceof Error?t.message:String(t);throw new Error(`\u6D88\u606F\u5E8F\u5217\u5316\u5931\u8D25: ${n}`)}}validateMessage(e){return!(!e||typeof e!="object"||e.jsonrpc!=="2.0"||e.method&&typeof e.method!="string"||!e.method&&!e.result&&!e.error)}createTimeoutPromise(e,t){return Promise.race([e,new Promise((n,i)=>{setTimeout(()=>{i(new Error(`\u64CD\u4F5C\u8D85\u65F6: ${t}ms`))},t)})])}};var O=class extends P{static{a(this,"HTTPAdapter")}app;server=null;clients=new Map;port;host;enableSSE;enableRPC;corsOrigin;maxClients;constructor(e,t={name:"http"}){super(e,t),this.port=t.port||3e3,this.host=t.host||"0.0.0.0",this.enableSSE=t.enableSSE!==!1,this.enableRPC=t.enableRPC!==!1,this.corsOrigin=t.corsOrigin||"*",this.maxClients=t.maxClients!==void 0?t.maxClients:100,this.app=H(),this.setupMiddleware()}async initialize(){this.logger.info("\u521D\u59CB\u5316 HTTP \u9002\u914D\u5668");try{this.setupRoutes(),this.setState("connecting"),this.logger.info("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),e}}async start(){if(this.server){this.logger.warn("HTTP \u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");return}return this.logger.info(`\u542F\u52A8 HTTP \u670D\u52A1\u5668\u5728 ${this.host}:${this.port}`),new Promise((e,t)=>{this.server=this.app.listen(this.port,this.host,()=>{this.setState("connected"),this.logger.info("HTTP \u9002\u914D\u5668\u542F\u52A8\u6210\u529F"),this.logger.info(`- RPC \u7AEF\u70B9: http://${this.host}:${this.port}/rpc`),this.enableSSE&&(this.logger.info(`- SSE \u7AEF\u70B9: http://${this.host}:${this.port}/sse`),this.logger.info(`- \u6D88\u606F\u7AEF\u70B9: http://${this.host}:${this.port}/messages`)),e()}),this.server?.on("error",n=>{this.logger.error("HTTP \u670D\u52A1\u5668\u9519\u8BEF",n),this.setState("error"),t(n)})})}async stop(){if(this.server)return this.logger.info("\u505C\u6B62 HTTP \u670D\u52A1\u5668"),new Promise(e=>{for(let t of this.clients.values())t.response.end();this.clients.clear(),this.server.close(()=>{this.server=null,this.setState("disconnected"),this.logger.info("HTTP \u670D\u52A1\u5668\u5DF2\u505C\u6B62"),e()})})}async sendMessage(e){this.clients.size>0&&this.broadcastToClients(e)}setupMiddleware(){this.app.use(H.json({limit:"10mb"})),this.app.use(H.urlencoded({extended:!0})),this.app.use((e,t,n)=>{t.header("Access-Control-Allow-Origin",this.corsOrigin),t.header("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.header("Access-Control-Allow-Headers","Content-Type, Accept"),t.header("Cache-Control","no-cache"),n()}),this.app.use((e,t,n)=>{this.logger.debug(`${e.method} ${e.path}`,{query:e.query,headers:e.headers}),n()})}setupRoutes(){this.enableSSE&&(this.app.get("/sse",this.handleSSE.bind(this)),this.app.post("/messages",this.handleMessages.bind(this))),this.enableRPC&&this.app.post("/rpc",this.handleRPC.bind(this)),this.app.get("/status",this.handleStatus.bind(this)),this.app.get("/health",this.handleHealth.bind(this))}handleSSE(e,t){if(this.clients.size>=this.maxClients){t.status(503).json({error:"\u670D\u52A1\u5668\u7E41\u5FD9\uFF0C\u5BA2\u6237\u7AEF\u8FDE\u63A5\u6570\u5DF2\u8FBE\u4E0A\u9650",maxClients:this.maxClients});return}let n=Date.now().toString(),i=se();t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache, no-transform"),t.setHeader("Connection","keep-alive"),t.setHeader("X-Accel-Buffering","no");let r={id:n,sessionId:i,response:t,connectedAt:new Date};this.clients.set(i,r),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u8FDE\u63A5: ${n} (\u4F1A\u8BDD: ${i})`),t.write(`event: endpoint
3
3
  data: /messages?sessionId=${i}
4
4
 
5
- `),e.on("close",()=>{this.clients.delete(i),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u65AD\u5F00\u8FDE\u63A5: ${n} (\u4F1A\u8BDD: ${i})`)}),e.on("error",a=>{this.logger.error(`SSE \u5BA2\u6237\u7AEF\u8FDE\u63A5\u9519\u8BEF: ${n}`,a),this.clients.delete(i)})}async handleMessages(e,t){try{let n=e.query.sessionId,i=e.body;if(this.logger.debug(`\u6536\u5230 SSE \u6D88\u606F (\u4F1A\u8BDD: ${n}):`,i),!n||!this.clients.has(n)){t.status(400).json({jsonrpc:"2.0",error:{code:-32600,message:"\u65E0\u6548\u6216\u7F3A\u5C11 sessionId"},id:i.id});return}let r=await this.messageHandler.handleMessage(i);this.logger.debug("SSE \u6D88\u606F\u5904\u7406\u54CD\u5E94:",r);let a=this.clients.get(n);a&&this.sendToClient(a,r),t.status(202).send()}catch(n){this.logger.error("\u5904\u7406 SSE \u6D88\u606F\u65F6\u51FA\u9519",n),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:n.message}})}}async handleRPC(e,t){try{let n=e.body;this.logger.debug("\u6536\u5230 RPC \u6D88\u606F:",n);let i=await this.messageHandler.handleMessage(n);t.json(i)}catch(n){this.logger.error("\u5904\u7406 RPC \u6D88\u606F\u65F6\u51FA\u9519",n),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:n.message},id:e.body?.id||null})}}handleStatus(e,t){t.json({status:"ok",mode:"mcp-server",serviceManager:"running",clients:this.clients.size,tools:0,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,uptime:process.uptime()})}handleHealth(e,t){t.json({status:"ok",mode:"mcp-server",timestamp:new Date().toISOString()})}sendToClient(e,t){try{let n=this.serializeMessage(t);e.response.write(`data: ${n}
5
+ `),e.on("close",()=>{this.clients.delete(i),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u65AD\u5F00\u8FDE\u63A5: ${n} (\u4F1A\u8BDD: ${i})`)}),e.on("error",s=>{this.logger.error(`SSE \u5BA2\u6237\u7AEF\u8FDE\u63A5\u9519\u8BEF: ${n}`,s),this.clients.delete(i)})}async handleMessages(e,t){try{let n=e.query.sessionId,i=e.body;if(this.logger.debug(`\u6536\u5230 SSE \u6D88\u606F (\u4F1A\u8BDD: ${n}):`,i),!n||!this.clients.has(n)){t.status(400).json({jsonrpc:"2.0",error:{code:-32600,message:"\u65E0\u6548\u6216\u7F3A\u5C11 sessionId"},id:i.id});return}let r=await this.messageHandler.handleMessage(i);this.logger.debug("SSE \u6D88\u606F\u5904\u7406\u54CD\u5E94:",r);let s=this.clients.get(n);s&&this.sendToClient(s,r),t.status(202).send()}catch(n){this.logger.error("\u5904\u7406 SSE \u6D88\u606F\u65F6\u51FA\u9519",n),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:n.message}})}}async handleRPC(e,t){try{let n=e.body;this.logger.debug("\u6536\u5230 RPC \u6D88\u606F:",n);let i=await this.messageHandler.handleMessage(n);t.json(i)}catch(n){this.logger.error("\u5904\u7406 RPC \u6D88\u606F\u65F6\u51FA\u9519",n),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:n.message},id:e.body?.id||null})}}handleStatus(e,t){t.json({status:"ok",mode:"mcp-server",serviceManager:"running",clients:this.clients.size,tools:0,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,uptime:process.uptime()})}handleHealth(e,t){t.json({status:"ok",mode:"mcp-server",timestamp:new Date().toISOString()})}sendToClient(e,t){try{let n=this.serializeMessage(t);e.response.write(`data: ${n}
6
6
 
7
- `),this.logger.debug(`\u6D88\u606F\u5DF2\u53D1\u9001\u5230\u5BA2\u6237\u7AEF ${e.id}`,{sessionId:e.sessionId,messageId:t.id})}catch(n){this.logger.error(`\u5411\u5BA2\u6237\u7AEF ${e.id} \u53D1\u9001\u6D88\u606F\u5931\u8D25`,n),this.clients.delete(e.sessionId)}}broadcastToClients(e){for(let t of this.clients.values())this.sendToClient(t,e)}getStatus(){return{isRunning:this.server!==null,port:this.port,host:this.host,clientCount:this.clients.size,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,connectionId:this.connectionId,state:this.state}}getClients(){return Array.from(this.clients.values()).map(e=>({id:e.id,sessionId:e.sessionId,connectedAt:e.connectedAt}))}};import it,{WebSocketServer as ot}from"ws";import{EventEmitter as G}from"events";import{Client as Pe}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as J}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as ae}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as ce}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{EventSource as le}from"eventsource";typeof global<"u"&&!global.EventSource&&(global.EventSource=le);function ge(){return l}s(ge,"getLogger");function he(o){switch(ge().info(`[TransportFactory] \u521B\u5EFA ${o.type} transport for ${o.name}`),o.type){case"stdio":return pe(o);case"sse":return de(o);case"modelscope-sse":return fe(o);case"streamable-http":return ue(o);default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${o.type}`)}}s(he,"createTransport");function pe(o){if(!o.command)throw new Error("stdio transport \u9700\u8981 command \u914D\u7F6E");return new ae({command:o.command,args:o.args||[]})}s(pe,"createStdioTransport");function de(o){if(!o.url)throw new Error("SSE transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(o.url),t=me(o);return new J(e,t)}s(de,"createSSETransport");function fe(o){if(!o.url)throw new Error("ModelScope SSE transport \u9700\u8981 URL \u914D\u7F6E");if(!o.apiKey)throw new Error("ModelScope SSE transport \u9700\u8981 apiKey \u914D\u7F6E");let e=new URL(o.url),t=Ce(o);return new J(e,t)}s(fe,"createModelScopeSSETransport");function ue(o){if(!o.url)throw new Error("StreamableHTTP transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(o.url),t=Se(o);return new ce(e,t)}s(ue,"createStreamableHTTPTransport");function me(o){let e={};return o.apiKey?e.headers={Authorization:`Bearer ${o.apiKey}`,...o.headers}:o.headers&&(e.headers=o.headers),e}s(me,"createSSEOptions");function Ce(o){let e=o.apiKey;return o.customSSEOptions?o.customSSEOptions:{eventSourceInit:{fetch:s(async(t,n)=>{let i={...n?.headers,Authorization:`Bearer ${e}`};return fetch(t,{...n,headers:i})},"fetch")},requestInit:{headers:{Authorization:`Bearer ${e}`,...o.headers}}}}s(Ce,"createModelScopeSSEOptions");function Se(o){let e={};return o.apiKey?e.headers={Authorization:`Bearer ${o.apiKey}`,...o.headers}:o.headers&&(e.headers=o.headers),e}s(Se,"createStreamableHTTPOptions");function ve(o){if(!o.name||typeof o.name!="string")throw new Error("\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 name \u5B57\u6BB5");if(!o.type)throw new Error("\u914D\u7F6E\u5FC5\u987B\u5305\u542B type \u5B57\u6BB5");switch(o.type){case"stdio":if(!o.command)throw new Error("stdio \u7C7B\u578B\u9700\u8981 command \u5B57\u6BB5");break;case"sse":case"streamable-http":if(!o.url)throw new Error(`${o.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;case"modelscope-sse":if(!o.url)throw new Error("modelscope-sse \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5");if(!o.apiKey)throw new Error("modelscope-sse \u7C7B\u578B\u9700\u8981 apiKey \u5B57\u6BB5\u3002\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E modelscope.apiKey \u6216\u786E\u4FDD\u670D\u52A1\u914D\u7F6E\u5305\u542B apiKey");break;default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${o.type}`)}}s(ve,"validateConfig");function Me(){return["stdio","sse","modelscope-sse","streamable-http"]}s(Me,"getSupportedTypes");var F={create:he,validateConfig:ve,getSupportedTypes:Me};var x=class{static{s(this,"MCPService")}config;client=null;transport=null;tools=new Map;connectionState="disconnected";reconnectOptions;reconnectState;logger;connectionTimeout=null;initialized=!1;pingOptions;pingTimer=null;pingFailureCount=0;lastPingTime=null;isPinging=!1;constructor(e,t){this.config=e,this.logger=l,this.validateConfig(),this.reconnectOptions={enabled:!0,maxAttempts:10,initialInterval:3e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t?.reconnect,...e.reconnect},this.pingOptions={enabled:!0,interval:3e4,timeout:5e3,maxFailures:3,startDelay:5e3,...e.ping},this.reconnectState={attempts:0,nextInterval:this.reconnectOptions.initialInterval,timer:null,lastError:null,isManualDisconnect:!1}}logWithTag(e,t,...n){let i=`[MCP-${this.config.name}] ${t}`;this.logger[e](i,...n)}validateConfig(){F.validateConfig(this.config)}async connect(){if(this.connectionState==="connecting")throw new Error("\u8FDE\u63A5\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210");return this.cleanupConnection(),this.reconnectState.isManualDisconnect=!1,this.attemptConnection()}async attemptConnection(){return this.connectionState="connecting",this.logWithTag("info",`\u6B63\u5728\u8FDE\u63A5 MCP \u670D\u52A1: ${this.config.name} (\u5C1D\u8BD5 ${this.reconnectState.attempts+1}/${this.reconnectOptions.maxAttempts})`),new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let n=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(n),t(n)},this.reconnectOptions.timeout);try{this.client=new Pe({name:`xiaozhi-${this.config.name}-client`,version:"1.0.0"},{capabilities:{tools:{}}}),this.transport=F.create(this.config),this.client.connect(this.transport).then(async()=>{this.handleConnectionSuccess(),await this.refreshTools(),e()}).catch(n=>{this.handleConnectionError(n),t(n)})}catch(n){this.handleConnectionError(n),t(n)}})}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.connectionState="connected",this.initialized=!0,this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.resetPingState(),this.logWithTag("info",`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u5DF2\u5EFA\u7ACB`),this.startPingMonitoring()}handleConnectionError(e){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.reconnectState.lastError=e,this.logger.error(`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u9519\u8BEF:`,e.message),this.cleanupConnection(),this.shouldReconnect()?this.scheduleReconnect():(this.connectionState="failed",this.logger.warn(`${this.config.name} \u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`))}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.connectionState="reconnecting",this.reconnectState.attempts++,this.calculateNextInterval(),this.logger.info(`${this.config.name} \u5C06\u5728 ${this.reconnectState.nextInterval}ms \u540E\u8FDB\u884C\u7B2C ${this.reconnectState.attempts} \u6B21\u91CD\u8FDE`),this.reconnectState.timer&&clearTimeout(this.reconnectState.timer),this.reconnectState.timer=setTimeout(async()=>{try{await this.attemptConnection()}catch{}},this.reconnectState.nextInterval)}calculateNextInterval(){let e;switch(this.reconnectOptions.backoffStrategy){case"fixed":e=this.reconnectOptions.initialInterval;break;case"linear":e=this.reconnectOptions.initialInterval+this.reconnectState.attempts*this.reconnectOptions.backoffMultiplier*1e3;break;case"exponential":e=this.reconnectOptions.initialInterval*this.reconnectOptions.backoffMultiplier**(this.reconnectState.attempts-1);break;default:e=this.reconnectOptions.initialInterval}if(e=Math.min(e,this.reconnectOptions.maxInterval),this.reconnectOptions.jitter){let t=e*.1,n=(Math.random()-.5)*2*t;e+=n}this.reconnectState.nextInterval=Math.max(e,1e3)}cleanupConnection(){if(this.stopPingMonitoring(),this.client){try{this.client.close().catch(()=>{})}catch{}this.client=null}this.transport=null,this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.initialized=!1}stopReconnect(){this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null)}async refreshTools(){if(!this.client)throw new Error("\u5BA2\u6237\u7AEF\u672A\u521D\u59CB\u5316");try{let t=(await this.client.listTools()).tools||[];this.tools.clear();for(let n of t)this.tools.set(n.name,n);this.logger.info(`${this.config.name} \u670D\u52A1\u52A0\u8F7D\u4E86 ${t.length} \u4E2A\u5DE5\u5177: ${t.map(n=>n.name).join(", ")}`)}catch(e){throw this.logger.error(`${this.config.name} \u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25:`,e instanceof Error?e.message:String(e)),e}}async disconnect(){this.logger.info(`\u4E3B\u52A8\u65AD\u5F00 MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5`),this.reconnectState.isManualDisconnect=!0,this.stopPingMonitoring(),this.stopReconnect(),this.cleanupConnection(),this.connectionState="disconnected"}async reconnect(){this.logger.info(`\u624B\u52A8\u91CD\u8FDE MCP \u670D\u52A1 ${this.config.name}`),this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.isManualDisconnect=!1,this.cleanupConnection(),await this.connect()}getTools(){return Array.from(this.tools.values())}async callTool(e,t){if(!this.client)throw new Error(`\u670D\u52A1 ${this.config.name} \u672A\u8FDE\u63A5`);if(!this.tools.has(e))throw new Error(`\u5DE5\u5177 ${e} \u5728\u670D\u52A1 ${this.config.name} \u4E2D\u4E0D\u5B58\u5728`);this.logger.info(`\u8C03\u7528 ${this.config.name} \u670D\u52A1\u7684\u5DE5\u5177 ${e}\uFF0C\u53C2\u6570:`,JSON.stringify(t));try{let n=await this.client.callTool({name:e,arguments:t||{}});return this.logger.info(`\u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,`${JSON.stringify(n).substring(0,500)}...`),n}catch(n){throw this.logger.error(`\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,n instanceof Error?n.message:String(n)),n}}getConfig(){return this.config}getStatus(){return{name:this.config.name,connected:this.connectionState==="connected",initialized:this.initialized,transportType:this.config.type,toolCount:this.tools.size,lastError:this.reconnectState.lastError?.message,reconnectAttempts:this.reconnectState.attempts,connectionState:this.connectionState,pingEnabled:this.pingOptions.enabled,lastPingTime:this.lastPingTime||void 0,pingFailureCount:this.pingFailureCount,isPinging:this.isPinging}}isConnected(){return this.connectionState==="connected"&&this.initialized}enableReconnect(){this.reconnectOptions.enabled=!0,this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u542F\u7528`)}disableReconnect(){this.reconnectOptions.enabled=!1,this.stopReconnect(),this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u7981\u7528`)}updateReconnectOptions(e){this.reconnectOptions={...this.reconnectOptions,...e},this.logger.info(`${this.config.name} \u91CD\u8FDE\u914D\u7F6E\u5DF2\u66F4\u65B0`,e)}getReconnectOptions(){return{...this.reconnectOptions}}resetReconnectState(){this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info(`${this.config.name} \u91CD\u8FDE\u72B6\u6001\u5DF2\u91CD\u7F6E`)}startPingMonitoring(){!this.pingOptions.enabled||this.pingTimer||!this.isConnected()||(this.logger.info(`${this.config.name} \u542F\u52A8ping\u76D1\u63A7\uFF0C\u95F4\u9694: ${this.pingOptions.interval}ms`),setTimeout(()=>{this.isConnected()&&!this.pingTimer&&(this.pingTimer=setInterval(()=>{this.performPing()},this.pingOptions.interval))},this.pingOptions.startDelay))}stopPingMonitoring(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null,this.logger.debug(`${this.config.name} \u505C\u6B62ping\u76D1\u63A7`))}async performPing(){if(!this.client||this.isPinging||!this.isConnected())return;this.isPinging=!0;let e=performance.now();try{this.logger.debug(`${this.config.name} \u53D1\u9001ping\u8BF7\u6C42\uFF08\u901A\u8FC7listTools\u68C0\u6D4B\u8FDE\u63A5\uFF09`);let t=this.client.listTools(),n=new Promise((r,a)=>{setTimeout(()=>{a(new Error(`Ping\u8D85\u65F6 (${this.pingOptions.timeout}ms)`))},this.pingOptions.timeout)});await Promise.race([t,n]);let i=performance.now()-e;this.handlePingSuccess(i)}catch(t){let n=performance.now()-e;this.handlePingFailure(t,n)}finally{this.isPinging=!1}}handlePingSuccess(e){this.pingFailureCount=0,this.lastPingTime=new Date,this.logger.debug(`${this.config.name} ping\u6210\u529F\uFF0C\u5EF6\u8FDF: ${e.toFixed(2)}ms`)}handlePingFailure(e,t){if(this.pingFailureCount++,this.logger.warn(`${this.config.name} ping\u5931\u8D25 (${this.pingFailureCount}/${this.pingOptions.maxFailures})\uFF0C\u5EF6\u8FDF: ${t.toFixed(2)}ms\uFF0C\u9519\u8BEF: ${e.message}`),this.pingFailureCount>=this.pingOptions.maxFailures){this.logger.error(`${this.config.name} \u8FDE\u7EEDping\u5931\u8D25\u8FBE\u5230\u9608\u503C\uFF0C\u89E6\u53D1\u91CD\u8FDE\u673A\u5236`),this.stopPingMonitoring();let n=new Error(`Ping\u68C0\u6D4B\u5931\u8D25\uFF0C\u8FDE\u7EED\u5931\u8D25${this.pingFailureCount}\u6B21\uFF0C\u8FDE\u63A5\u53EF\u80FD\u5DF2\u65AD\u5F00`);this.handleConnectionError(n)}}resetPingState(){this.pingFailureCount=0,this.lastPingTime=null,this.isPinging=!1}enablePing(){this.pingOptions.enabled=!0,this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u542F\u7528`),this.isConnected()&&this.startPingMonitoring()}disablePing(){this.pingOptions.enabled=!1,this.stopPingMonitoring(),this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u7981\u7528`)}updatePingOptions(e){let t=this.pingOptions.enabled;this.pingOptions={...this.pingOptions,...e},this.logger.info(`${this.config.name} ping\u914D\u7F6E\u5DF2\u66F4\u65B0`,e),t!==this.pingOptions.enabled&&(this.pingOptions.enabled&&this.isConnected()?this.startPingMonitoring():this.pingOptions.enabled||this.stopPingMonitoring())}getPingOptions(){return{...this.pingOptions}}};var $=class{static{s(this,"MCPServiceManager")}services=new Map;configs={};logger;tools=new Map;constructor(e){this.logger=l,this.configs=e||{}}async startAllServices(){this.logger.info("[MCPManager] \u6B63\u5728\u542F\u52A8\u6240\u6709 MCP \u670D\u52A1...");let e=Object.entries(this.configs);if(e.length===0){this.logger.warn("[MCPManager] \u6CA1\u6709\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1\uFF0C\u8BF7\u4F7F\u7528 addServiceConfig() \u6DFB\u52A0\u670D\u52A1\u914D\u7F6E");return}for(let[t]of e)await this.startService(t);this.logger.info("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u542F\u52A8\u5B8C\u6210")}async startService(e){this.logger.info(`[MCPManager] \u542F\u52A8 MCP \u670D\u52A1: ${e}`);let t=this.configs[e];if(!t)throw new Error(`\u672A\u627E\u5230\u670D\u52A1\u914D\u7F6E: ${e}`);try{this.services.has(e)&&await this.stopService(e);let n=new x(t);await n.connect(),this.services.set(e,n),await this.refreshToolsCache();let i=n.getTools();this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u542F\u52A8\u6210\u529F\uFF0C\u52A0\u8F7D\u4E86 ${i.length} \u4E2A\u5DE5\u5177:`,i.map(r=>r.name).join(", "))}catch(n){throw this.logger.error(`[MCPManager] \u542F\u52A8 ${e} \u670D\u52A1\u5931\u8D25:`,n.message),n}}async stopService(e){this.logger.info(`[MCPManager] \u505C\u6B62 MCP \u670D\u52A1: ${e}`);let t=this.services.get(e);if(!t){this.logger.warn(`[MCPManager] \u670D\u52A1 ${e} \u4E0D\u5B58\u5728\u6216\u672A\u542F\u52A8`);return}try{await t.disconnect(),this.services.delete(e),await this.refreshToolsCache(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(n){throw this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,n.message),n}}async refreshToolsCache(){this.tools.clear();for(let[e,t]of this.services)if(t.isConnected()){let n=t.getTools();for(let i of n){let r=`${e}__${i.name}`;this.tools.set(r,{serviceName:e,originalName:i.name,tool:i})}}await this.syncToolsConfigToFile()}getAllTools(){let e=[];for(let[t,n]of this.tools)e.push({name:t,description:n.tool.description||"",inputSchema:n.tool.inputSchema,serviceName:n.serviceName,originalName:n.originalName});return e}async callTool(e,t){this.logger.info(`[MCPManager] \u8C03\u7528\u5DE5\u5177: ${e}\uFF0C\u53C2\u6570:`,t);let n=this.tools.get(e);if(!n)throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);let i=this.services.get(n.serviceName);if(!i)throw new Error(`\u670D\u52A1 ${n.serviceName} \u4E0D\u53EF\u7528`);if(!i.isConnected())throw new Error(`\u670D\u52A1 ${n.serviceName} \u672A\u8FDE\u63A5`);try{let r=await i.callTool(n.originalName,t||{});return this.logger.info(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,r),r}catch(r){throw this.logger.error(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,r.message),r}}async stopAllServices(){this.logger.info("[MCPManager] \u6B63\u5728\u505C\u6B62\u6240\u6709 MCP \u670D\u52A1...");for(let[e,t]of this.services)try{await t.disconnect(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(n){this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,n.message)}this.services.clear(),this.tools.clear(),this.logger.info("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u5DF2\u505C\u6B62")}getStatus(){let e={services:{},totalTools:this.tools.size,availableTools:Array.from(this.tools.keys())};for(let[t,n]of this.services){let i=n.getStatus();e.services[t]={connected:i.connected,clientName:`xiaozhi-${t}-client`}}return e}getService(e){return this.services.get(e)}getAllServices(){return new Map(this.services)}enhanceServiceConfig(e){let t={...e};try{if(e.type==="modelscope-sse"){let n=v.getModelScopeApiKey();if(n)t.apiKey=n,this.logger.info(`[MCPManager] \u4E3A ${e.name} \u670D\u52A1\u6DFB\u52A0 ModelScope API Key`);else throw this.logger.warn(`[MCPManager] ${e.name} \u670D\u52A1\u9700\u8981 ModelScope API Key\uFF0C\u4F46\u672A\u5728\u914D\u7F6E\u4E2D\u627E\u5230`),new Error(`ModelScope SSE \u670D\u52A1 ${e.name} \u9700\u8981 API Key\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E modelscope.apiKey`)}return t}catch(n){throw this.logger.error(`[MCPManager] \u914D\u7F6E\u589E\u5F3A\u5931\u8D25: ${e.name}`,n),n}}addServiceConfig(e,t){let n,i;if(typeof e=="string"&&t)i=e,n=t;else if(typeof e=="object")i=e.name,n=e;else throw new Error("Invalid arguments for addServiceConfig");let r=this.enhanceServiceConfig(n);this.configs[i]=r,this.logger.info(`[MCPManager] \u5DF2\u6DFB\u52A0\u670D\u52A1\u914D\u7F6E: ${i}`)}updateServiceConfig(e,t){let n=this.enhanceServiceConfig(t);this.configs[e]=n,this.logger.info(`[MCPManager] \u5DF2\u66F4\u65B0\u5E76\u589E\u5F3A\u670D\u52A1\u914D\u7F6E: ${e}`)}removeServiceConfig(e){delete this.configs[e],this.logger.info(`[MCPManager] \u5DF2\u79FB\u9664\u670D\u52A1\u914D\u7F6E: ${e}`)}async syncToolsConfigToFile(){try{this.logger.debug("[MCPManager] \u5F00\u59CB\u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6");let e=v.getMcpServerConfig();for(let[t,n]of this.services){if(!n.isConnected())continue;let i=n.getTools();if(i.length===0)continue;let r=e[t]?.tools||{},a={};for(let f of i){let M=r[f.name];M?a[f.name]={...M,description:f.description||M.description||""}:a[f.name]={description:f.description||"",enable:!0}}let c=i.map(f=>f.name),C=Object.keys(r).filter(f=>!c.includes(f));if(C.length>0&&this.logger.info(`[MCPManager] \u68C0\u6D4B\u5230\u670D\u52A1 ${t} \u79FB\u9664\u4E86 ${C.length} \u4E2A\u5DE5\u5177: ${C.join(", ")}`),this.hasToolsConfigChanged(r,a)){v.updateServerToolsConfig(t,a);let f=Object.keys(a).filter(E=>!r[E]),M=Object.keys(a).filter(E=>{let _=r[E],X=a[E];return _&&_.description!==X.description});this.logger.info(`[MCPManager] \u5DF2\u540C\u6B65\u670D\u52A1 ${t} \u7684\u5DE5\u5177\u914D\u7F6E:`),f.length>0&&this.logger.info(` - \u65B0\u589E\u5DE5\u5177: ${f.join(", ")}`),M.length>0&&this.logger.info(` - \u66F4\u65B0\u5DE5\u5177: ${M.join(", ")}`),C.length>0&&this.logger.info(` - \u79FB\u9664\u5DE5\u5177: ${C.join(", ")}`)}}this.logger.debug("[MCPManager] \u5DE5\u5177\u914D\u7F6E\u540C\u6B65\u5B8C\u6210")}catch(e){this.logger.error("[MCPManager] \u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:",e)}}hasToolsConfigChanged(e,t){let n=Object.keys(e),i=Object.keys(t);if(n.length!==i.length)return!0;let r=i.filter(c=>!n.includes(c)),a=n.filter(c=>!i.includes(c));if(r.length>0||a.length>0)return!0;for(let c of n){let g=e[c],C=t[c];if(g.description!==C.description)return!0}return!1}};var N=class{static{s(this,"MCPMessageHandler")}logger;serviceManager;constructor(e){this.serviceManager=e,this.logger=l}async handleMessage(e){this.logger.debug(`\u5904\u7406 MCP \u6D88\u606F: ${e.method}`,e);try{switch(e.method){case"initialize":return await this.handleInitialize(e.params,e.id);case"tools/list":return await this.handleToolsList(e.id);case"tools/call":return await this.handleToolCall(e.params,e.id);case"ping":return await this.handlePing(e.id);default:throw new Error(`\u672A\u77E5\u7684\u65B9\u6CD5: ${e.method}`)}}catch(t){return this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t),this.createErrorResponse(t,e.id)}}async handleInitialize(e,t){return this.logger.info("\u5904\u7406 initialize \u8BF7\u6C42",e),{jsonrpc:"2.0",result:{serverInfo:{name:"xiaozhi-mcp-server",version:"1.0.0"},capabilities:{tools:{},logging:{}},protocolVersion:"2024-11-05"},id:t||null}}async handleToolsList(e){this.logger.info("\u5904\u7406 tools/list \u8BF7\u6C42");try{let n=this.serviceManager.getAllTools().map(i=>({name:i.name,description:i.description,inputSchema:i.inputSchema}));return this.logger.info(`\u8FD4\u56DE ${n.length} \u4E2A\u5DE5\u5177`),{jsonrpc:"2.0",result:{tools:n},id:e||null}}catch(t){throw this.logger.error("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25",t),t}}async handleToolCall(e,t){this.logger.info(`\u5904\u7406 tools/call \u8BF7\u6C42: ${e.name}`,e);try{if(!e.name)throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let n=await this.serviceManager.callTool(e.name,e.arguments||{});return this.logger.info(`\u5DE5\u5177 ${e.name} \u8C03\u7528\u6210\u529F`),{jsonrpc:"2.0",result:{content:n.content,isError:n.isError||!1},id:t||null}}catch(n){throw this.logger.error(`\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),n}}async handlePing(e){return this.logger.debug("\u5904\u7406 ping \u8BF7\u6C42"),{jsonrpc:"2.0",result:{status:"ok",timestamp:new Date().toISOString()},id:e||null}}createErrorResponse(e,t){let n=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?n=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(n=-32602),{jsonrpc:"2.0",error:{code:n,message:e.message,data:{stack:e.stack}},id:t||null}}getServiceManager(){return this.serviceManager}};var U=class{static{s(this,"ToolRegistry")}serviceManager;logger;constructor(e){this.serviceManager=e,this.logger=l}async initialize(){this.logger.info("\u521D\u59CB\u5316\u5DE5\u5177\u6CE8\u518C\u8868")}getAllTools(){return this.serviceManager.getAllTools().map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,serviceName:e.serviceName,originalName:e.originalName}))}findTool(e){return this.getAllTools().find(n=>n.name===e)||null}hasTool(e){return this.findTool(e)!==null}},W=class extends G{static{s(this,"ConnectionManager")}connections=new Map;logger;constructor(){super(),this.logger=l}async initialize(){this.logger.info("\u521D\u59CB\u5316\u8FDE\u63A5\u7BA1\u7406\u5668")}registerConnection(e,t,n){let i={id:e,transportName:t,state:n,connectedAt:new Date,lastActivity:new Date};this.connections.set(e,i),this.emit("connectionRegistered",i),this.logger.debug(`\u8FDE\u63A5\u5DF2\u6CE8\u518C: ${e} (${t})`)}updateConnectionState(e,t){let n=this.connections.get(e);n&&(n.state=t,n.lastActivity=new Date,this.emit("connectionStateChanged",n),this.logger.debug(`\u8FDE\u63A5\u72B6\u6001\u66F4\u65B0: ${e} -> ${t}`))}removeConnection(e){let t=this.connections.get(e);t&&(this.connections.delete(e),this.emit("connectionRemoved",t),this.logger.debug(`\u8FDE\u63A5\u5DF2\u79FB\u9664: ${e}`))}getAllConnections(){return Array.from(this.connections.values())}getActiveConnectionCount(){return Array.from(this.connections.values()).filter(e=>e.state==="connected").length}async closeAllConnections(){this.logger.info("\u5173\u95ED\u6240\u6709\u8FDE\u63A5"),this.connections.clear(),this.emit("allConnectionsClosed")}},A=class extends G{static{s(this,"UnifiedMCPServer")}serviceManager;messageHandler;transportAdapters=new Map;toolRegistry;connectionManager;isRunning=!1;logger;config;constructor(e={}){super(),this.config={name:"UnifiedMCPServer",enableLogging:!0,logLevel:"info",maxConnections:100,connectionTimeout:3e4,...e},this.logger=l,this.serviceManager=new $,this.messageHandler=new N(this.serviceManager),this.toolRegistry=new U(this.serviceManager),this.connectionManager=new W,this.setupEventListeners()}setupEventListeners(){this.connectionManager.on("connectionRegistered",e=>{this.emit("connectionRegistered",e)}),this.connectionManager.on("connectionStateChanged",e=>{this.emit("connectionStateChanged",e)}),this.connectionManager.on("connectionRemoved",e=>{this.emit("connectionRemoved",e)})}async initialize(){this.logger.info("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{await this.serviceManager.startAllServices(),await this.toolRegistry.initialize(),await this.connectionManager.initialize(),this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210"),this.emit("initialized")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5931\u8D25",e),e}}async registerTransport(e,t){if(this.transportAdapters.has(e))throw new Error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5DF2\u5B58\u5728`);this.logger.info(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668: ${e}`);try{await t.initialize(),this.transportAdapters.set(e,t),this.connectionManager.registerConnection(t.getConnectionId(),e,t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u6CE8\u518C\u6210\u529F`),this.emit("transportRegistered",{name:e,adapter:t})}catch(n){throw this.logger.error(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5931\u8D25`,n),n}}async start(){if(this.isRunning)throw new Error("\u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");this.logger.info("\u542F\u52A8\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.start(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u6210\u529F`)}catch(n){throw this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u5931\u8D25`,n),n}this.isRunning=!0,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u6210\u529F"),this.emit("started")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25",e),e}}async stop(){if(this.isRunning){this.logger.info("\u505C\u6B62\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.stop(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u6210\u529F`)}catch(n){this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u5931\u8D25`,n)}await this.connectionManager.closeAllConnections(),await this.serviceManager.stopAllServices(),this.isRunning=!1,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u6210\u529F"),this.emit("stopped")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u5931\u8D25",e),e}}}getServiceManager(){return this.serviceManager}getToolRegistry(){return this.toolRegistry}getConnectionManager(){return this.connectionManager}getMessageHandler(){return this.messageHandler}getStatus(){return{isRunning:this.isRunning,transportCount:this.transportAdapters.size,activeConnections:this.connectionManager.getActiveConnectionCount(),toolCount:this.toolRegistry.getAllTools().length,config:this.config}}getTransportAdapters(){return new Map(this.transportAdapters)}isServerRunning(){return this.isRunning}};async function V(o={name:"http"}){l.info("\u521B\u5EFA HTTP \u6A21\u5F0F\u670D\u52A1\u5668");let e=new A;await e.initialize();let t=e.getMessageHandler(),n=new O(t,o);return await e.registerTransport("http",n),l.info("HTTP \u6A21\u5F0F\u670D\u52A1\u5668\u521B\u5EFA\u6210\u529F"),e}s(V,"createHTTPServer");var p=new y,Q=class extends Te{static{s(this,"MCPServer")}unifiedServer=null;proxyMCPServer=null;port;isStarted=!1;constructor(e=3e3){super(),this.port=e}async initializeUnifiedServer(){if(!this.unifiedServer){p.info("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{let e={name:"http",port:this.port,host:"0.0.0.0",enableSSE:!0,enableRPC:!0};this.unifiedServer=await V(e),this.unifiedServer.on("started",()=>this.emit("started")),this.unifiedServer.on("stopped",()=>this.emit("stopped")),this.unifiedServer.on("connectionRegistered",t=>{this.emit("connectionRegistered",t)}),p.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw p.error("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u5931\u8D25",e),e}}}async initializeMCPClient(){try{let e=null;try{v.configExists()&&(e=v.getMcpEndpoints().find(n=>n&&!n.includes("<\u8BF7\u586B\u5199"))||null)}catch(t){p.warn("\u4ECE\u914D\u7F6E\u4E2D\u8BFB\u53D6\u5C0F\u667A\u63A5\u5165\u70B9\u5931\u8D25:",t)}e?(this.proxyMCPServer=new w(e),this.unifiedServer&&this.proxyMCPServer.setServiceManager(this.unifiedServer.getServiceManager()),await this.proxyMCPServer.connect(),p.info("\u5C0F\u667A\u63A5\u5165\u70B9\u8FDE\u63A5\u6210\u529F")):p.info("\u672A\u914D\u7F6E\u6709\u6548\u7684\u5C0F\u667A\u63A5\u5165\u70B9\uFF0C\u8DF3\u8FC7\u8FDE\u63A5")}catch(e){p.error("\u521D\u59CB\u5316\u5C0F\u667A\u63A5\u5165\u70B9\u8FDE\u63A5\u5931\u8D25:",e)}}async start(){if(this.isStarted){p.warn("\u670D\u52A1\u5668\u5DF2\u542F\u52A8");return}try{p.info("\u542F\u52A8 MCP \u670D\u52A1\u5668"),await this.initializeUnifiedServer(),this.unifiedServer&&await this.unifiedServer.start(),this.initializeMCPClient().catch(e=>{p.error("\u521D\u59CB\u5316\u5C0F\u667A\u63A5\u5165\u70B9\u8FDE\u63A5\u5931\u8D25:",e)}),this.isStarted=!0,this.emit("started"),p.info("MCP \u670D\u52A1\u5668\u542F\u52A8\u6210\u529F")}catch(e){throw p.error("\u542F\u52A8 MCP \u670D\u52A1\u5668\u5931\u8D25:",e),e}}async stop(){if(!this.isStarted){p.warn("\u670D\u52A1\u5668\u672A\u542F\u52A8");return}try{p.info("\u505C\u6B62 MCP \u670D\u52A1\u5668"),this.unifiedServer&&await this.unifiedServer.stop(),this.proxyMCPServer&&(this.proxyMCPServer.disconnect(),this.proxyMCPServer=null),this.isStarted=!1,this.emit("stopped"),p.info("MCP \u670D\u52A1\u5668\u5DF2\u505C\u6B62")}catch(e){throw p.error("\u505C\u6B62 MCP \u670D\u52A1\u5668\u5931\u8D25:",e),e}}getServiceManager(){return this.unifiedServer?.getServiceManager()||null}getMessageHandler(){return this.unifiedServer?.getMessageHandler()||null}getStatus(){return this.unifiedServer?{...this.unifiedServer.getStatus(),port:this.port,mode:"mcp-server",proxyConnected:this.proxyMCPServer!==null}:{isRunning:!1,port:this.port,mode:"mcp-server"}}isRunning(){return this.isStarted&&(this.unifiedServer?.isServerRunning()||!1)}};export{Q as MCPServer};
7
+ `),this.logger.debug(`\u6D88\u606F\u5DF2\u53D1\u9001\u5230\u5BA2\u6237\u7AEF ${e.id}`,{sessionId:e.sessionId,messageId:t.id})}catch(n){this.logger.error(`\u5411\u5BA2\u6237\u7AEF ${e.id} \u53D1\u9001\u6D88\u606F\u5931\u8D25`,n),this.clients.delete(e.sessionId)}}broadcastToClients(e){for(let t of this.clients.values())this.sendToClient(t,e)}getStatus(){return{isRunning:this.server!==null,port:this.port,host:this.host,clientCount:this.clients.size,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,connectionId:this.connectionId,state:this.state}}getClients(){return Array.from(this.clients.values()).map(e=>({id:e.id,sessionId:e.sessionId,connectedAt:e.connectedAt}))}};import it,{WebSocketServer as ot}from"ws";import{EventEmitter as G}from"events";import{Client as Pe}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as J}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as ae}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as ce}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{EventSource as le}from"eventsource";typeof global<"u"&&!global.EventSource&&(global.EventSource=le);function ge(){return c}a(ge,"getLogger");function he(o){switch(ge().info(`[TransportFactory] \u521B\u5EFA ${o.type} transport for ${o.name}`),o.type){case"stdio":return pe(o);case"sse":return de(o);case"modelscope-sse":return fe(o);case"streamable-http":return ue(o);default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${o.type}`)}}a(he,"createTransport");function pe(o){if(!o.command)throw new Error("stdio transport \u9700\u8981 command \u914D\u7F6E");return new ae({command:o.command,args:o.args||[]})}a(pe,"createStdioTransport");function de(o){if(!o.url)throw new Error("SSE transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(o.url),t=me(o);return new J(e,t)}a(de,"createSSETransport");function fe(o){if(!o.url)throw new Error("ModelScope SSE transport \u9700\u8981 URL \u914D\u7F6E");if(!o.apiKey)throw new Error("ModelScope SSE transport \u9700\u8981 apiKey \u914D\u7F6E");let e=new URL(o.url),t=Ce(o);return new J(e,t)}a(fe,"createModelScopeSSETransport");function ue(o){if(!o.url)throw new Error("StreamableHTTP transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(o.url),t=Se(o);return new ce(e,t)}a(ue,"createStreamableHTTPTransport");function me(o){let e={};return o.apiKey?e.headers={Authorization:`Bearer ${o.apiKey}`,...o.headers}:o.headers&&(e.headers=o.headers),e}a(me,"createSSEOptions");function Ce(o){let e=o.apiKey;return o.customSSEOptions?o.customSSEOptions:{eventSourceInit:{fetch:a(async(t,n)=>{let i={...n?.headers,Authorization:`Bearer ${e}`};return fetch(t,{...n,headers:i})},"fetch")},requestInit:{headers:{Authorization:`Bearer ${e}`,...o.headers}}}}a(Ce,"createModelScopeSSEOptions");function Se(o){let e={};return o.apiKey?e.headers={Authorization:`Bearer ${o.apiKey}`,...o.headers}:o.headers&&(e.headers=o.headers),e}a(Se,"createStreamableHTTPOptions");function ve(o){if(!o.name||typeof o.name!="string")throw new Error("\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 name \u5B57\u6BB5");if(!o.type)throw new Error("\u914D\u7F6E\u5FC5\u987B\u5305\u542B type \u5B57\u6BB5");switch(o.type){case"stdio":if(!o.command)throw new Error("stdio \u7C7B\u578B\u9700\u8981 command \u5B57\u6BB5");break;case"sse":case"streamable-http":if(!o.url)throw new Error(`${o.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;case"modelscope-sse":if(!o.url)throw new Error("modelscope-sse \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5");if(!o.apiKey)throw new Error("modelscope-sse \u7C7B\u578B\u9700\u8981 apiKey \u5B57\u6BB5\u3002\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E modelscope.apiKey \u6216\u786E\u4FDD\u670D\u52A1\u914D\u7F6E\u5305\u542B apiKey");break;default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${o.type}`)}}a(ve,"validateConfig");function be(){return["stdio","sse","modelscope-sse","streamable-http"]}a(be,"getSupportedTypes");var F={create:he,validateConfig:ve,getSupportedTypes:be};var x=class{static{a(this,"MCPService")}config;client=null;transport=null;tools=new Map;connectionState="disconnected";reconnectOptions;reconnectState;logger;connectionTimeout=null;initialized=!1;pingOptions;pingTimer=null;pingFailureCount=0;lastPingTime=null;isPinging=!1;constructor(e,t){this.config=e,this.logger=c,this.validateConfig(),this.reconnectOptions={enabled:!0,maxAttempts:10,initialInterval:3e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t?.reconnect,...e.reconnect},this.pingOptions={enabled:!0,interval:3e4,timeout:5e3,maxFailures:3,startDelay:5e3,...e.ping},this.reconnectState={attempts:0,nextInterval:this.reconnectOptions.initialInterval,timer:null,lastError:null,isManualDisconnect:!1}}logWithTag(e,t,...n){let i=`[MCP-${this.config.name}] ${t}`;this.logger[e](i,...n)}validateConfig(){F.validateConfig(this.config)}async connect(){if(this.connectionState==="connecting")throw new Error("\u8FDE\u63A5\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210");return this.cleanupConnection(),this.reconnectState.isManualDisconnect=!1,this.attemptConnection()}async attemptConnection(){return this.connectionState="connecting",this.logWithTag("info",`\u6B63\u5728\u8FDE\u63A5 MCP \u670D\u52A1: ${this.config.name} (\u5C1D\u8BD5 ${this.reconnectState.attempts+1}/${this.reconnectOptions.maxAttempts})`),new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let n=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(n),t(n)},this.reconnectOptions.timeout);try{this.client=new Pe({name:`xiaozhi-${this.config.name}-client`,version:"1.0.0"},{capabilities:{tools:{}}}),this.transport=F.create(this.config),this.client.connect(this.transport).then(async()=>{this.handleConnectionSuccess(),await this.refreshTools(),e()}).catch(n=>{this.handleConnectionError(n),t(n)})}catch(n){this.handleConnectionError(n),t(n)}})}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.connectionState="connected",this.initialized=!0,this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.resetPingState(),this.logWithTag("info",`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u5DF2\u5EFA\u7ACB`),this.startPingMonitoring()}handleConnectionError(e){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.reconnectState.lastError=e,this.logger.error(`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u9519\u8BEF:`,e.message),this.cleanupConnection(),this.shouldReconnect()?this.scheduleReconnect():(this.connectionState="failed",this.logger.warn(`${this.config.name} \u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`))}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.connectionState="reconnecting",this.reconnectState.attempts++,this.calculateNextInterval(),this.logger.info(`${this.config.name} \u5C06\u5728 ${this.reconnectState.nextInterval}ms \u540E\u8FDB\u884C\u7B2C ${this.reconnectState.attempts} \u6B21\u91CD\u8FDE`),this.reconnectState.timer&&clearTimeout(this.reconnectState.timer),this.reconnectState.timer=setTimeout(async()=>{try{await this.attemptConnection()}catch{}},this.reconnectState.nextInterval)}calculateNextInterval(){let e;switch(this.reconnectOptions.backoffStrategy){case"fixed":e=this.reconnectOptions.initialInterval;break;case"linear":e=this.reconnectOptions.initialInterval+this.reconnectState.attempts*this.reconnectOptions.backoffMultiplier*1e3;break;case"exponential":e=this.reconnectOptions.initialInterval*this.reconnectOptions.backoffMultiplier**(this.reconnectState.attempts-1);break;default:e=this.reconnectOptions.initialInterval}if(e=Math.min(e,this.reconnectOptions.maxInterval),this.reconnectOptions.jitter){let t=e*.1,n=(Math.random()-.5)*2*t;e+=n}this.reconnectState.nextInterval=Math.max(e,1e3)}cleanupConnection(){if(this.stopPingMonitoring(),this.client){try{this.client.close().catch(()=>{})}catch{}this.client=null}this.transport=null,this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.initialized=!1}stopReconnect(){this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null)}async refreshTools(){if(!this.client)throw new Error("\u5BA2\u6237\u7AEF\u672A\u521D\u59CB\u5316");try{let t=(await this.client.listTools()).tools||[];this.tools.clear();for(let n of t)this.tools.set(n.name,n);this.logger.info(`${this.config.name} \u670D\u52A1\u52A0\u8F7D\u4E86 ${t.length} \u4E2A\u5DE5\u5177: ${t.map(n=>n.name).join(", ")}`)}catch(e){throw this.logger.error(`${this.config.name} \u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25:`,e instanceof Error?e.message:String(e)),e}}async disconnect(){this.logger.info(`\u4E3B\u52A8\u65AD\u5F00 MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5`),this.reconnectState.isManualDisconnect=!0,this.stopPingMonitoring(),this.stopReconnect(),this.cleanupConnection(),this.connectionState="disconnected"}async reconnect(){this.logger.info(`\u624B\u52A8\u91CD\u8FDE MCP \u670D\u52A1 ${this.config.name}`),this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.isManualDisconnect=!1,this.cleanupConnection(),await this.connect()}getTools(){return Array.from(this.tools.values())}async callTool(e,t){if(!this.client)throw new Error(`\u670D\u52A1 ${this.config.name} \u672A\u8FDE\u63A5`);if(!this.tools.has(e))throw new Error(`\u5DE5\u5177 ${e} \u5728\u670D\u52A1 ${this.config.name} \u4E2D\u4E0D\u5B58\u5728`);this.logger.info(`\u8C03\u7528 ${this.config.name} \u670D\u52A1\u7684\u5DE5\u5177 ${e}\uFF0C\u53C2\u6570:`,JSON.stringify(t));for(let n=0;n<2;n++)try{let i=await this.client.callTool({name:e,arguments:t||{}});return this.logger.info(`\u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,`${JSON.stringify(i).substring(0,500)}...`),i}catch(i){let r=i instanceof Error?i.message:String(i);if(this.isSessionExpiredError(r)&&n===0){this.logger.warn(`\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25\uFF0C\u68C0\u6D4B\u5230\u4F1A\u8BDD\u8FC7\u671F\uFF0C\u5C1D\u8BD5\u91CD\u8FDE...`);try{await this.reconnect(),this.logger.info(`\u670D\u52A1 ${this.config.name} \u91CD\u8FDE\u6210\u529F\uFF0C\u91CD\u8BD5\u5DE5\u5177\u8C03\u7528`);continue}catch(s){throw this.logger.error(`\u670D\u52A1 ${this.config.name} \u91CD\u8FDE\u5931\u8D25:`,s instanceof Error?s.message:String(s)),this.logger.error(`\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,r),i}}throw this.logger.error(`\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,r),i}throw new Error(`\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25\uFF1A\u8D85\u51FA\u6700\u5927\u91CD\u8BD5\u6B21\u6570`)}isSessionExpiredError(e){return e.includes("HTTP 401")&&e.includes("SessionExpired")||e.includes("session")&&e.includes("expired")}getConfig(){return this.config}getStatus(){return{name:this.config.name,connected:this.connectionState==="connected",initialized:this.initialized,transportType:this.config.type,toolCount:this.tools.size,lastError:this.reconnectState.lastError?.message,reconnectAttempts:this.reconnectState.attempts,connectionState:this.connectionState,pingEnabled:this.pingOptions.enabled,lastPingTime:this.lastPingTime||void 0,pingFailureCount:this.pingFailureCount,isPinging:this.isPinging}}isConnected(){return this.connectionState==="connected"&&this.initialized}enableReconnect(){this.reconnectOptions.enabled=!0,this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u542F\u7528`)}disableReconnect(){this.reconnectOptions.enabled=!1,this.stopReconnect(),this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u7981\u7528`)}updateReconnectOptions(e){this.reconnectOptions={...this.reconnectOptions,...e},this.logger.info(`${this.config.name} \u91CD\u8FDE\u914D\u7F6E\u5DF2\u66F4\u65B0`,e)}getReconnectOptions(){return{...this.reconnectOptions}}resetReconnectState(){this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info(`${this.config.name} \u91CD\u8FDE\u72B6\u6001\u5DF2\u91CD\u7F6E`)}startPingMonitoring(){!this.pingOptions.enabled||this.pingTimer||!this.isConnected()||(this.logger.info(`${this.config.name} \u542F\u52A8ping\u76D1\u63A7\uFF0C\u95F4\u9694: ${this.pingOptions.interval}ms`),setTimeout(()=>{this.isConnected()&&!this.pingTimer&&(this.pingTimer=setInterval(()=>{this.performPing()},this.pingOptions.interval))},this.pingOptions.startDelay))}stopPingMonitoring(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null,this.logger.debug(`${this.config.name} \u505C\u6B62ping\u76D1\u63A7`))}async performPing(){if(!this.client||this.isPinging||!this.isConnected())return;this.isPinging=!0;let e=performance.now();try{this.logger.debug(`${this.config.name} \u53D1\u9001ping\u8BF7\u6C42\uFF08\u901A\u8FC7listTools\u68C0\u6D4B\u8FDE\u63A5\uFF09`);let t=this.client.listTools(),n=new Promise((r,s)=>{setTimeout(()=>{s(new Error(`Ping\u8D85\u65F6 (${this.pingOptions.timeout}ms)`))},this.pingOptions.timeout)});await Promise.race([t,n]);let i=performance.now()-e;this.handlePingSuccess(i)}catch(t){let n=performance.now()-e;this.handlePingFailure(t,n)}finally{this.isPinging=!1}}handlePingSuccess(e){this.pingFailureCount=0,this.lastPingTime=new Date,this.logger.debug(`${this.config.name} ping\u6210\u529F\uFF0C\u5EF6\u8FDF: ${e.toFixed(2)}ms`)}handlePingFailure(e,t){if(this.pingFailureCount++,this.logger.warn(`${this.config.name} ping\u5931\u8D25 (${this.pingFailureCount}/${this.pingOptions.maxFailures})\uFF0C\u5EF6\u8FDF: ${t.toFixed(2)}ms\uFF0C\u9519\u8BEF: ${e.message}`),this.pingFailureCount>=this.pingOptions.maxFailures){this.logger.error(`${this.config.name} \u8FDE\u7EEDping\u5931\u8D25\u8FBE\u5230\u9608\u503C\uFF0C\u89E6\u53D1\u91CD\u8FDE\u673A\u5236`),this.stopPingMonitoring();let n=new Error(`Ping\u68C0\u6D4B\u5931\u8D25\uFF0C\u8FDE\u7EED\u5931\u8D25${this.pingFailureCount}\u6B21\uFF0C\u8FDE\u63A5\u53EF\u80FD\u5DF2\u65AD\u5F00`);this.handleConnectionError(n)}}resetPingState(){this.pingFailureCount=0,this.lastPingTime=null,this.isPinging=!1}enablePing(){this.pingOptions.enabled=!0,this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u542F\u7528`),this.isConnected()&&this.startPingMonitoring()}disablePing(){this.pingOptions.enabled=!1,this.stopPingMonitoring(),this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u7981\u7528`)}updatePingOptions(e){let t=this.pingOptions.enabled;this.pingOptions={...this.pingOptions,...e},this.logger.info(`${this.config.name} ping\u914D\u7F6E\u5DF2\u66F4\u65B0`,e),t!==this.pingOptions.enabled&&(this.pingOptions.enabled&&this.isConnected()?this.startPingMonitoring():this.pingOptions.enabled||this.stopPingMonitoring())}getPingOptions(){return{...this.pingOptions}}};var $=class{static{a(this,"MCPServiceManager")}services=new Map;configs={};logger;tools=new Map;constructor(e){this.logger=c,this.configs=e||{}}async startAllServices(){this.logger.info("[MCPManager] \u6B63\u5728\u542F\u52A8\u6240\u6709 MCP \u670D\u52A1...");let e=Object.entries(this.configs);if(e.length===0){this.logger.warn("[MCPManager] \u6CA1\u6709\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1\uFF0C\u8BF7\u4F7F\u7528 addServiceConfig() \u6DFB\u52A0\u670D\u52A1\u914D\u7F6E");return}for(let[t]of e)await this.startService(t);this.logger.info("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u542F\u52A8\u5B8C\u6210")}async startService(e){this.logger.info(`[MCPManager] \u542F\u52A8 MCP \u670D\u52A1: ${e}`);let t=this.configs[e];if(!t)throw new Error(`\u672A\u627E\u5230\u670D\u52A1\u914D\u7F6E: ${e}`);try{this.services.has(e)&&await this.stopService(e);let n=new x(t);await n.connect(),this.services.set(e,n),await this.refreshToolsCache();let i=n.getTools();this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u542F\u52A8\u6210\u529F\uFF0C\u52A0\u8F7D\u4E86 ${i.length} \u4E2A\u5DE5\u5177:`,i.map(r=>r.name).join(", "))}catch(n){throw this.logger.error(`[MCPManager] \u542F\u52A8 ${e} \u670D\u52A1\u5931\u8D25:`,n.message),n}}async stopService(e){this.logger.info(`[MCPManager] \u505C\u6B62 MCP \u670D\u52A1: ${e}`);let t=this.services.get(e);if(!t){this.logger.warn(`[MCPManager] \u670D\u52A1 ${e} \u4E0D\u5B58\u5728\u6216\u672A\u542F\u52A8`);return}try{await t.disconnect(),this.services.delete(e),await this.refreshToolsCache(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(n){throw this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,n.message),n}}async refreshToolsCache(){this.tools.clear();for(let[e,t]of this.services)if(t.isConnected()){let n=t.getTools();for(let i of n){let r=`${e}__${i.name}`;this.tools.set(r,{serviceName:e,originalName:i.name,tool:i})}}await this.syncToolsConfigToFile()}getAllTools(){let e=[];for(let[t,n]of this.tools)e.push({name:t,description:n.tool.description||"",inputSchema:n.tool.inputSchema,serviceName:n.serviceName,originalName:n.originalName});return e}async callTool(e,t){this.logger.info(`[MCPManager] \u8C03\u7528\u5DE5\u5177: ${e}\uFF0C\u53C2\u6570:`,t);let n=this.tools.get(e);if(!n)throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);let i=this.services.get(n.serviceName);if(!i)throw new Error(`\u670D\u52A1 ${n.serviceName} \u4E0D\u53EF\u7528`);if(!i.isConnected())throw new Error(`\u670D\u52A1 ${n.serviceName} \u672A\u8FDE\u63A5`);try{let r=await i.callTool(n.originalName,t||{});return this.logger.info(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,r),r}catch(r){throw this.logger.error(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,r.message),r}}async stopAllServices(){this.logger.info("[MCPManager] \u6B63\u5728\u505C\u6B62\u6240\u6709 MCP \u670D\u52A1...");for(let[e,t]of this.services)try{await t.disconnect(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(n){this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,n.message)}this.services.clear(),this.tools.clear(),this.logger.info("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u5DF2\u505C\u6B62")}getStatus(){let e={services:{},totalTools:this.tools.size,availableTools:Array.from(this.tools.keys())};for(let[t,n]of this.services){let i=n.getStatus();e.services[t]={connected:i.connected,clientName:`xiaozhi-${t}-client`}}return e}getService(e){return this.services.get(e)}getAllServices(){return new Map(this.services)}enhanceServiceConfig(e){let t={...e};try{if(e.type==="modelscope-sse"){let n=v.getModelScopeApiKey();if(n)t.apiKey=n,this.logger.info(`[MCPManager] \u4E3A ${e.name} \u670D\u52A1\u6DFB\u52A0 ModelScope API Key`);else throw this.logger.warn(`[MCPManager] ${e.name} \u670D\u52A1\u9700\u8981 ModelScope API Key\uFF0C\u4F46\u672A\u5728\u914D\u7F6E\u4E2D\u627E\u5230`),new Error(`ModelScope SSE \u670D\u52A1 ${e.name} \u9700\u8981 API Key\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E modelscope.apiKey`)}return t}catch(n){throw this.logger.error(`[MCPManager] \u914D\u7F6E\u589E\u5F3A\u5931\u8D25: ${e.name}`,n),n}}addServiceConfig(e,t){let n,i;if(typeof e=="string"&&t)i=e,n=t;else if(typeof e=="object")i=e.name,n=e;else throw new Error("Invalid arguments for addServiceConfig");let r=this.enhanceServiceConfig(n);this.configs[i]=r,this.logger.info(`[MCPManager] \u5DF2\u6DFB\u52A0\u670D\u52A1\u914D\u7F6E: ${i}`)}updateServiceConfig(e,t){let n=this.enhanceServiceConfig(t);this.configs[e]=n,this.logger.info(`[MCPManager] \u5DF2\u66F4\u65B0\u5E76\u589E\u5F3A\u670D\u52A1\u914D\u7F6E: ${e}`)}removeServiceConfig(e){delete this.configs[e],this.logger.info(`[MCPManager] \u5DF2\u79FB\u9664\u670D\u52A1\u914D\u7F6E: ${e}`)}async syncToolsConfigToFile(){try{this.logger.debug("[MCPManager] \u5F00\u59CB\u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6");let e=v.getMcpServerConfig();for(let[t,n]of this.services){if(!n.isConnected())continue;let i=n.getTools();if(i.length===0)continue;let r=e[t]?.tools||{},s={};for(let f of i){let b=r[f.name];b?s[f.name]={...b,description:f.description||b.description||""}:s[f.name]={description:f.description||"",enable:!0}}let l=i.map(f=>f.name),C=Object.keys(r).filter(f=>!l.includes(f));if(C.length>0&&this.logger.info(`[MCPManager] \u68C0\u6D4B\u5230\u670D\u52A1 ${t} \u79FB\u9664\u4E86 ${C.length} \u4E2A\u5DE5\u5177: ${C.join(", ")}`),this.hasToolsConfigChanged(r,s)){v.updateServerToolsConfig(t,s);let f=Object.keys(s).filter(E=>!r[E]),b=Object.keys(s).filter(E=>{let _=r[E],X=s[E];return _&&_.description!==X.description});this.logger.info(`[MCPManager] \u5DF2\u540C\u6B65\u670D\u52A1 ${t} \u7684\u5DE5\u5177\u914D\u7F6E:`),f.length>0&&this.logger.info(` - \u65B0\u589E\u5DE5\u5177: ${f.join(", ")}`),b.length>0&&this.logger.info(` - \u66F4\u65B0\u5DE5\u5177: ${b.join(", ")}`),C.length>0&&this.logger.info(` - \u79FB\u9664\u5DE5\u5177: ${C.join(", ")}`)}}this.logger.debug("[MCPManager] \u5DE5\u5177\u914D\u7F6E\u540C\u6B65\u5B8C\u6210")}catch(e){this.logger.error("[MCPManager] \u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:",e)}}hasToolsConfigChanged(e,t){let n=Object.keys(e),i=Object.keys(t);if(n.length!==i.length)return!0;let r=i.filter(l=>!n.includes(l)),s=n.filter(l=>!i.includes(l));if(r.length>0||s.length>0)return!0;for(let l of n){let g=e[l],C=t[l];if(g.description!==C.description)return!0}return!1}};var N=class{static{a(this,"MCPMessageHandler")}logger;serviceManager;constructor(e){this.serviceManager=e,this.logger=c}async handleMessage(e){this.logger.debug(`\u5904\u7406 MCP \u6D88\u606F: ${e.method}`,e);try{switch(e.method){case"initialize":return await this.handleInitialize(e.params,e.id);case"tools/list":return await this.handleToolsList(e.id);case"tools/call":return await this.handleToolCall(e.params,e.id);case"ping":return await this.handlePing(e.id);default:throw new Error(`\u672A\u77E5\u7684\u65B9\u6CD5: ${e.method}`)}}catch(t){return this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t),this.createErrorResponse(t,e.id)}}async handleInitialize(e,t){return this.logger.info("\u5904\u7406 initialize \u8BF7\u6C42",e),{jsonrpc:"2.0",result:{serverInfo:{name:"xiaozhi-mcp-server",version:"1.0.0"},capabilities:{tools:{},logging:{}},protocolVersion:"2024-11-05"},id:t||null}}async handleToolsList(e){this.logger.info("\u5904\u7406 tools/list \u8BF7\u6C42");try{let n=this.serviceManager.getAllTools().map(i=>({name:i.name,description:i.description,inputSchema:i.inputSchema}));return this.logger.info(`\u8FD4\u56DE ${n.length} \u4E2A\u5DE5\u5177`),{jsonrpc:"2.0",result:{tools:n},id:e||null}}catch(t){throw this.logger.error("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25",t),t}}async handleToolCall(e,t){this.logger.info(`\u5904\u7406 tools/call \u8BF7\u6C42: ${e.name}`,e);try{if(!e.name)throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let n=await this.serviceManager.callTool(e.name,e.arguments||{});return this.logger.info(`\u5DE5\u5177 ${e.name} \u8C03\u7528\u6210\u529F`),{jsonrpc:"2.0",result:{content:n.content,isError:n.isError||!1},id:t||null}}catch(n){throw this.logger.error(`\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),n}}async handlePing(e){return this.logger.debug("\u5904\u7406 ping \u8BF7\u6C42"),{jsonrpc:"2.0",result:{status:"ok",timestamp:new Date().toISOString()},id:e||null}}createErrorResponse(e,t){let n=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?n=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(n=-32602),{jsonrpc:"2.0",error:{code:n,message:e.message,data:{stack:e.stack}},id:t||null}}getServiceManager(){return this.serviceManager}};var U=class{static{a(this,"ToolRegistry")}serviceManager;logger;constructor(e){this.serviceManager=e,this.logger=c}async initialize(){this.logger.info("\u521D\u59CB\u5316\u5DE5\u5177\u6CE8\u518C\u8868")}getAllTools(){return this.serviceManager.getAllTools().map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,serviceName:e.serviceName,originalName:e.originalName}))}findTool(e){return this.getAllTools().find(n=>n.name===e)||null}hasTool(e){return this.findTool(e)!==null}},W=class extends G{static{a(this,"ConnectionManager")}connections=new Map;logger;constructor(){super(),this.logger=c}async initialize(){this.logger.info("\u521D\u59CB\u5316\u8FDE\u63A5\u7BA1\u7406\u5668")}registerConnection(e,t,n){let i={id:e,transportName:t,state:n,connectedAt:new Date,lastActivity:new Date};this.connections.set(e,i),this.emit("connectionRegistered",i),this.logger.debug(`\u8FDE\u63A5\u5DF2\u6CE8\u518C: ${e} (${t})`)}updateConnectionState(e,t){let n=this.connections.get(e);n&&(n.state=t,n.lastActivity=new Date,this.emit("connectionStateChanged",n),this.logger.debug(`\u8FDE\u63A5\u72B6\u6001\u66F4\u65B0: ${e} -> ${t}`))}removeConnection(e){let t=this.connections.get(e);t&&(this.connections.delete(e),this.emit("connectionRemoved",t),this.logger.debug(`\u8FDE\u63A5\u5DF2\u79FB\u9664: ${e}`))}getAllConnections(){return Array.from(this.connections.values())}getActiveConnectionCount(){return Array.from(this.connections.values()).filter(e=>e.state==="connected").length}async closeAllConnections(){this.logger.info("\u5173\u95ED\u6240\u6709\u8FDE\u63A5"),this.connections.clear(),this.emit("allConnectionsClosed")}},A=class extends G{static{a(this,"UnifiedMCPServer")}serviceManager;messageHandler;transportAdapters=new Map;toolRegistry;connectionManager;isRunning=!1;logger;config;constructor(e={}){super(),this.config={name:"UnifiedMCPServer",enableLogging:!0,logLevel:"info",maxConnections:100,connectionTimeout:3e4,...e},this.logger=c,this.serviceManager=new $,this.messageHandler=new N(this.serviceManager),this.toolRegistry=new U(this.serviceManager),this.connectionManager=new W,this.setupEventListeners()}setupEventListeners(){this.connectionManager.on("connectionRegistered",e=>{this.emit("connectionRegistered",e)}),this.connectionManager.on("connectionStateChanged",e=>{this.emit("connectionStateChanged",e)}),this.connectionManager.on("connectionRemoved",e=>{this.emit("connectionRemoved",e)})}async initialize(){this.logger.info("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{await this.serviceManager.startAllServices(),await this.toolRegistry.initialize(),await this.connectionManager.initialize(),this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210"),this.emit("initialized")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5931\u8D25",e),e}}async registerTransport(e,t){if(this.transportAdapters.has(e))throw new Error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5DF2\u5B58\u5728`);this.logger.info(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668: ${e}`);try{await t.initialize(),this.transportAdapters.set(e,t),this.connectionManager.registerConnection(t.getConnectionId(),e,t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u6CE8\u518C\u6210\u529F`),this.emit("transportRegistered",{name:e,adapter:t})}catch(n){throw this.logger.error(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5931\u8D25`,n),n}}async start(){if(this.isRunning)throw new Error("\u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");this.logger.info("\u542F\u52A8\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.start(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u6210\u529F`)}catch(n){throw this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u5931\u8D25`,n),n}this.isRunning=!0,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u6210\u529F"),this.emit("started")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25",e),e}}async stop(){if(this.isRunning){this.logger.info("\u505C\u6B62\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.stop(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u6210\u529F`)}catch(n){this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u5931\u8D25`,n)}await this.connectionManager.closeAllConnections(),await this.serviceManager.stopAllServices(),this.isRunning=!1,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u6210\u529F"),this.emit("stopped")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u5931\u8D25",e),e}}}getServiceManager(){return this.serviceManager}getToolRegistry(){return this.toolRegistry}getConnectionManager(){return this.connectionManager}getMessageHandler(){return this.messageHandler}getStatus(){return{isRunning:this.isRunning,transportCount:this.transportAdapters.size,activeConnections:this.connectionManager.getActiveConnectionCount(),toolCount:this.toolRegistry.getAllTools().length,config:this.config}}getTransportAdapters(){return new Map(this.transportAdapters)}isServerRunning(){return this.isRunning}};async function V(o={name:"http"}){c.info("\u521B\u5EFA HTTP \u6A21\u5F0F\u670D\u52A1\u5668");let e=new A;await e.initialize();let t=e.getMessageHandler(),n=new O(t,o);return await e.registerTransport("http",n),c.info("HTTP \u6A21\u5F0F\u670D\u52A1\u5668\u521B\u5EFA\u6210\u529F"),e}a(V,"createHTTPServer");var p=new y,Q=class extends Te{static{a(this,"MCPServer")}unifiedServer=null;proxyMCPServer=null;port;isStarted=!1;constructor(e=3e3){super(),this.port=e}async initializeUnifiedServer(){if(!this.unifiedServer){p.info("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{let e={name:"http",port:this.port,host:"0.0.0.0",enableSSE:!0,enableRPC:!0};this.unifiedServer=await V(e),this.unifiedServer.on("started",()=>this.emit("started")),this.unifiedServer.on("stopped",()=>this.emit("stopped")),this.unifiedServer.on("connectionRegistered",t=>{this.emit("connectionRegistered",t)}),p.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw p.error("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u5931\u8D25",e),e}}}async initializeMCPClient(){try{let e=null;try{v.configExists()&&(e=v.getMcpEndpoints().find(n=>n&&!n.includes("<\u8BF7\u586B\u5199"))||null)}catch(t){p.warn("\u4ECE\u914D\u7F6E\u4E2D\u8BFB\u53D6\u5C0F\u667A\u63A5\u5165\u70B9\u5931\u8D25:",t)}e?(this.proxyMCPServer=new w(e),this.unifiedServer&&this.proxyMCPServer.setServiceManager(this.unifiedServer.getServiceManager()),await this.proxyMCPServer.connect(),p.info("\u5C0F\u667A\u63A5\u5165\u70B9\u8FDE\u63A5\u6210\u529F")):p.info("\u672A\u914D\u7F6E\u6709\u6548\u7684\u5C0F\u667A\u63A5\u5165\u70B9\uFF0C\u8DF3\u8FC7\u8FDE\u63A5")}catch(e){p.error("\u521D\u59CB\u5316\u5C0F\u667A\u63A5\u5165\u70B9\u8FDE\u63A5\u5931\u8D25:",e)}}async start(){if(this.isStarted){p.warn("\u670D\u52A1\u5668\u5DF2\u542F\u52A8");return}try{p.info("\u542F\u52A8 MCP \u670D\u52A1\u5668"),await this.initializeUnifiedServer(),this.unifiedServer&&await this.unifiedServer.start(),this.initializeMCPClient().catch(e=>{p.error("\u521D\u59CB\u5316\u5C0F\u667A\u63A5\u5165\u70B9\u8FDE\u63A5\u5931\u8D25:",e)}),this.isStarted=!0,this.emit("started"),p.info("MCP \u670D\u52A1\u5668\u542F\u52A8\u6210\u529F")}catch(e){throw p.error("\u542F\u52A8 MCP \u670D\u52A1\u5668\u5931\u8D25:",e),e}}async stop(){if(!this.isStarted){p.warn("\u670D\u52A1\u5668\u672A\u542F\u52A8");return}try{p.info("\u505C\u6B62 MCP \u670D\u52A1\u5668"),this.unifiedServer&&await this.unifiedServer.stop(),this.proxyMCPServer&&(this.proxyMCPServer.disconnect(),this.proxyMCPServer=null),this.isStarted=!1,this.emit("stopped"),p.info("MCP \u670D\u52A1\u5668\u5DF2\u505C\u6B62")}catch(e){throw p.error("\u505C\u6B62 MCP \u670D\u52A1\u5668\u5931\u8D25:",e),e}}getServiceManager(){return this.unifiedServer?.getServiceManager()||null}getMessageHandler(){return this.unifiedServer?.getMessageHandler()||null}getStatus(){return this.unifiedServer?{...this.unifiedServer.getStatus(),port:this.port,mode:"mcp-server",proxyConnected:this.proxyMCPServer!==null}:{isRunning:!1,port:this.port,mode:"mcp-server"}}isRunning(){return this.isStarted&&(this.unifiedServer?.isServerRunning()||!1)}};export{Q as MCPServer};
8
8
  //# sourceMappingURL=MCPServer.js.map