Skip to content

Commit 2f81a40

Browse files
authored
Merge pull request #107 from OpenAgentPlatform/tool
fix: error occurrence for tool when toggle diffrent tool
2 parents c53d2f4 + e54be54 commit 2f81a40

File tree

2 files changed

+43
-40
lines changed

2 files changed

+43
-40
lines changed

Diff for: services/mcpServer/index.ts

+31-40
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"
55
import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js";
66
import path from "path";
77
import { handleConnectToServer } from "../connectServer.js";
8-
import { SystemCommandManager } from "../syscmd/index.js";
98
import logger from "../utils/logger.js";
109
import { convertToOpenAITools, loadConfigAndServers } from "../utils/toolHandler.js";
11-
import { iServerConfig, iTool } from "../utils/types.js";
10+
import { iConfig, iServerConfig, iTool } from "../utils/types.js";
1211
import { IMCPServerManager } from "./interface.js";
1312

1413
export class MCPServerManager implements IMCPServerManager {
@@ -20,6 +19,7 @@ export class MCPServerManager implements IMCPServerManager {
2019
private toolInfos: iTool[] = [];
2120
// SSE/Websocket 開起來的Client
2221
private tempClients: Map<string, Client> = new Map();
22+
private prevConfig: Record<string, iServerConfig> = {};
2323
public configPath: string;
2424

2525
private constructor(configPath?: string) {
@@ -52,9 +52,11 @@ export class MCPServerManager implements IMCPServerManager {
5252
await this.connectAllServers();
5353
}
5454

55+
// 連接所有 MCP 伺服器,不檢查是否已經開啟,執行前請確保 mcpServers 都已關閉
5556
async connectAllServers(): Promise<{ serverName: string; error: unknown }[]> {
5657
const errorArray: { serverName: string; error: unknown }[] = [];
5758
const { config, servers } = await loadConfigAndServers(this.configPath);
59+
this.prevConfig = config.mcpServers;
5860
// only connect enabled servers
5961
const enabledServers = Object.keys(config.mcpServers).filter((serverName) => config.mcpServers[serverName].enabled);
6062
logger.info(`Connect to ${enabledServers.length} enabled servers...`);
@@ -147,6 +149,8 @@ export class MCPServerManager implements IMCPServerManager {
147149
});
148150
}
149151

152+
logger.info(`Add new server completed: ${serverName}`);
153+
150154
return {
151155
success: true,
152156
serverName,
@@ -171,16 +175,19 @@ export class MCPServerManager implements IMCPServerManager {
171175
async syncServersWithConfig(): Promise<{ serverName: string; error: unknown }[]> {
172176
logger.info("Syncing servers with configuration...");
173177
const errorArray: { serverName: string; error: unknown }[] = [];
178+
let newConfig: iConfig | undefined;
174179

175180
try {
176181
// Get configuration differences
177-
const { config: newConfig } = await loadConfigAndServers(this.configPath);
178-
const currentServers = new Set(this.servers.keys());
182+
const { config: newConfig_ } = await loadConfigAndServers(this.configPath);
183+
newConfig = newConfig_;
184+
const currentRunningServers = new Set(this.servers.keys());
179185
const configuredServers = new Set(Object.keys(newConfig.mcpServers || {}));
180186

181187
// Handle servers to be removed
182-
for (const serverName of currentServers) {
183-
if (!configuredServers.has(serverName)) {
188+
for (const serverName of currentRunningServers) {
189+
// 設定中沒有此 server 或 有此 server 但設定中 disabled
190+
if (!configuredServers.has(serverName) || !newConfig.mcpServers[serverName].enabled) {
184191
logger.info(`Removing server: ${serverName}`);
185192
await this.disconnectSingleServer(serverName);
186193
}
@@ -190,8 +197,13 @@ export class MCPServerManager implements IMCPServerManager {
190197
for (const serverName of configuredServers) {
191198
try {
192199
const serverConfig = newConfig.mcpServers[serverName];
200+
// 設定中 disabled 則不處理
201+
if (!serverConfig.enabled) continue;
202+
203+
if (!serverConfig.transport) serverConfig.transport = "command";
193204

194-
if (!currentServers.has(serverName)) {
205+
// 該 Server 還沒有執行
206+
if (!currentRunningServers.has(serverName)) {
195207
// New server
196208
logger.info(`Adding new server: ${serverName}`);
197209
const result = await this.connectSingleServer(serverName, serverConfig, {});
@@ -202,11 +214,11 @@ export class MCPServerManager implements IMCPServerManager {
202214
});
203215
}
204216
} else {
205-
// Existing server, check properties
217+
// 該 Server 已經執行,確認設定是否變更
206218
// check command, args(string[]), env(Record<string, string>)
207219
const isPropertiesChanged = this.checkPropertiesChanged(serverName, serverConfig);
208220
if (isPropertiesChanged) {
209-
logger.info(`Properties changed for server: ${serverName}`);
221+
logger.info(`Properties changed and Restart server: ${serverName}`);
210222
await this.disconnectSingleServer(serverName);
211223
const result = await this.connectSingleServer(serverName, serverConfig, {});
212224
if (!result.success) {
@@ -241,6 +253,10 @@ export class MCPServerManager implements IMCPServerManager {
241253
} catch (error) {
242254
logger.error("Error during server configuration sync:", error);
243255
throw error;
256+
} finally {
257+
if (newConfig) {
258+
this.prevConfig = newConfig.mcpServers;
259+
}
244260
}
245261
}
246262

@@ -279,7 +295,7 @@ export class MCPServerManager implements IMCPServerManager {
279295
// Remove from toolInfos
280296
this.toolInfos = this.toolInfos.filter((info) => info.name !== serverName);
281297

282-
logger.info(`Server ${serverName} disconnected`);
298+
logger.info(`Remove server completed: ${serverName}`);
283299
}
284300
} catch (error) {
285301
logger.error(`Error disconnecting server ${serverName}:`, error);
@@ -314,36 +330,11 @@ export class MCPServerManager implements IMCPServerManager {
314330
}
315331

316332
checkPropertiesChanged(serverName: string, config: iServerConfig) {
317-
const client = this.servers.get(serverName);
318-
if (!client) return true;
319-
const currentParams = (client?.transport as any)._serverParams as iServerConfig;
320-
321-
// check transport type changed
322-
if (currentParams.transport !== config.transport) return true;
323-
324-
// if command transport, check command, args and env
325-
if (config.transport === "command" && currentParams.transport === "command") {
326-
const currentCommand = currentParams.command || "";
327-
const newCommand = SystemCommandManager.getInstance().getValue(config.command || "") || config.command || "";
328-
const currentArgs = currentParams.args || [];
329-
const newArgs = config.args || [];
330-
331-
return (
332-
currentCommand !== newCommand ||
333-
currentArgs.join(",") !== newArgs.join(",") ||
334-
JSON.stringify(currentParams.env) !== JSON.stringify(config.env)
335-
);
336-
}
337-
338-
// if sse or websocket transport, check url
339-
if (
340-
(config.transport === "sse" || config.transport === "websocket") &&
341-
(currentParams.transport === "sse" || currentParams.transport === "websocket")
342-
) {
343-
return currentParams.url !== config.url;
344-
}
333+
const currentParams = this.prevConfig[serverName] as iServerConfig;
345334

346-
return false;
335+
if (!currentParams || !config) return true;
336+
if (JSON.stringify(currentParams) !== JSON.stringify(config)) return true;
337+
else return false;
347338
}
348339

349340
getAvailableTools(): ToolDefinition[] {
@@ -388,4 +379,4 @@ export class MCPServerManager implements IMCPServerManager {
388379
// logger.info("Reconnect all MCP servers completed");
389380
// return errorArray;
390381
// }
391-
}
382+
}

Diff for: src/views/Overlay/Tools.tsx

+12
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ const Tools = () => {
328328
newConfig.mcpServers[tool.name].enabled = !currentEnabled
329329

330330
const data = await updateMCPConfig(newConfig)
331+
if (data.errors && Array.isArray(data.errors) && data.errors.length) {
332+
data.errors
333+
.map((e: any) => e.serverName)
334+
.forEach((serverName: string) => {
335+
newConfig.mcpServers[serverName].enabled = false
336+
newConfig.mcpServers[serverName].disabled = true
337+
})
338+
339+
// reset enable
340+
await updateMCPConfig(newConfig)
341+
}
342+
331343
if (data.success) {
332344
setMcpConfig(newConfig)
333345
await fetchTools()

0 commit comments

Comments
 (0)