diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 8425c96..3bb77d6 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -498,9 +498,9 @@ export class ClineProvider implements vscode.WebviewViewProvider { } break } - case "retryMcpServer": { + case "restartMcpServer": { try { - await this.mcpHub?.retryConnection(message.text!) + await this.mcpHub?.restartConnection(message.text!) } catch (error) { console.error(`Failed to retry connection for ${message.text}:`, error) } diff --git a/src/services/mcp/McpHub.ts b/src/services/mcp/McpHub.ts index 088dd84..0ac14b9 100644 --- a/src/services/mcp/McpHub.ts +++ b/src/services/mcp/McpHub.ts @@ -23,6 +23,7 @@ import { } from "../../shared/mcp" import { fileExistsAtPath } from "../../utils/fs" import { arePathsEqual } from "../../utils/path" +import delay from "delay" export type McpConnection = { server: McpServer @@ -121,7 +122,7 @@ export class McpHub { } private async connectToServer(name: string, config: StdioServerParameters): Promise { - // Remove existing connection if it exists + // Remove existing connection if it exists (should never happen, the connection should be deleted beforehand) this.connections = this.connections.filter((conn) => conn.server.name !== name) try { @@ -176,7 +177,6 @@ export class McpHub { transport, } this.connections.push(connection) - await this.notifyWebviewOfServerChanges() return } @@ -219,8 +219,6 @@ export class McpHub { connection.server.tools = await this.fetchToolsList(name) connection.server.resources = await this.fetchResourcesList(name) connection.server.resourceTemplates = await this.fetchResourceTemplatesList(name) - - await this.notifyWebviewOfServerChanges() } catch (error) { // Update status with error const connection = this.connections.find((conn) => conn.server.name === name) @@ -228,7 +226,6 @@ export class McpHub { connection.server.status = "disconnected" connection.server.error = error instanceof Error ? error.message : String(error) } - await this.notifyWebviewOfServerChanges() throw error } } @@ -281,7 +278,6 @@ export class McpHub { console.error(`Failed to close transport for ${name}:`, error) } this.connections = this.connections.filter((conn) => conn.server.name !== name) - await this.notifyWebviewOfServerChanges() } } @@ -321,10 +317,11 @@ export class McpHub { } // If server exists with same config, do nothing } + await this.notifyWebviewOfServerChanges() this.isConnecting = false } - async retryConnection(serverName: string): Promise { + async restartConnection(serverName: string): Promise { this.isConnecting = true const provider = this.providerRef.deref() if (!provider) { @@ -335,6 +332,10 @@ export class McpHub { const connection = this.connections.find((conn) => conn.server.name === serverName) const config = connection?.server.config if (config) { + connection.server.status = "connecting" + await this.notifyWebviewOfServerChanges() + await delay(500) // artificial delay to show user that server is restarting + await this.deleteConnection(serverName) // Try to connect again using existing config await this.connectToServer(serverName, JSON.parse(config)) } @@ -344,9 +345,20 @@ export class McpHub { } private async notifyWebviewOfServerChanges(): Promise { + // servers should always be sorted in the order they are defined in the settings file + const settingsPath = await this.getMcpSettingsFilePath() + const content = await fs.readFile(settingsPath, "utf-8") + const config = JSON.parse(content) + const serverOrder = Object.keys(config.mcpServers || {}) await this.providerRef.deref()?.postMessageToWebview({ type: "mcpServers", - mcpServers: this.connections.map((connection) => connection.server), + mcpServers: [...this.connections] + .sort((a, b) => { + const indexA = serverOrder.indexOf(a.server.name) + const indexB = serverOrder.indexOf(b.server.name) + return indexA - indexB + }) + .map((connection) => connection.server), }) } diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index cfd7de0..859fd71 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -24,7 +24,7 @@ export interface WebviewMessage { | "cancelTask" | "refreshOpenRouterModels" | "openMcpSettings" - | "retryMcpServer" + | "restartMcpServer" text?: string askResponse?: ClineAskResponse apiConfiguration?: ApiConfiguration diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index b10210f..ee16804 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -820,12 +820,12 @@ export const ChatRowContent = ({ }} /> {useMcpServer.arguments && ( -
+
Arguments diff --git a/webview-ui/src/components/mcp/McpResourceRow.tsx b/webview-ui/src/components/mcp/McpResourceRow.tsx index 815b329..6d44b9c 100644 --- a/webview-ui/src/components/mcp/McpResourceRow.tsx +++ b/webview-ui/src/components/mcp/McpResourceRow.tsx @@ -12,7 +12,7 @@ const McpResourceRow = ({ item }: McpResourceRowProps) => {
{
diff --git a/webview-ui/src/components/mcp/McpView.tsx b/webview-ui/src/components/mcp/McpView.tsx index 8be4c5c..fab84e3 100644 --- a/webview-ui/src/components/mcp/McpView.tsx +++ b/webview-ui/src/components/mcp/McpView.tsx @@ -150,9 +150,9 @@ const ServerRow = ({ server }: { server: McpServer }) => { } } - const handleRetry = () => { + const handleRestart = () => { vscode.postMessage({ - type: "retryMcpServer", + type: "restartMcpServer", text: server.name, }) } @@ -196,9 +196,11 @@ const ServerRow = ({ server }: { server: McpServer }) => { borderRadius: "0 0 4px 4px", }}>
{server.error}
- - - Retry Connection + + {server.status === "connecting" ? "Retrying..." : "Retry Connection"}
) : ( @@ -206,7 +208,7 @@ const ServerRow = ({ server }: { server: McpServer }) => {
@@ -217,7 +219,7 @@ const ServerRow = ({ server }: { server: McpServer }) => { {server.tools && server.tools.length > 0 ? (
+ style={{ display: "flex", flexDirection: "column", gap: "8px", width: "100%" }}> {server.tools.map((tool) => ( ))} @@ -233,7 +235,7 @@ const ServerRow = ({ server }: { server: McpServer }) => { {(server.resources && server.resources.length > 0) || (server.resourceTemplates && server.resourceTemplates.length > 0) ? (
+ style={{ display: "flex", flexDirection: "column", gap: "8px", width: "100%" }}> {[...(server.resourceTemplates || []), ...(server.resources || [])].map( (item) => ( { )} + + + {server.status === "connecting" ? "Restarting..." : "Restart Server"} +
) )}