Skip to content

Commit a7a96fb

Browse files
committed
Add commands to reload and toggle MCP servers; update UI and localization
1 parent 03d96ab commit a7a96fb

File tree

8 files changed

+129
-2
lines changed

8 files changed

+129
-2
lines changed

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@
169169
"command": "roo.acceptInput",
170170
"title": "%command.acceptInput.title%",
171171
"category": "%configuration.title%"
172+
},
173+
{
174+
"command": "extension.reloadAllMcpServers",
175+
"title": "Reload All MCP Servers",
176+
"icon": "$(sync)"
177+
},
178+
{
179+
"command": "extension.toggleAllMcpServersDisabled",
180+
"title": "Toggle All MCP Servers Enabled/Disabled",
181+
"icon": "$(power)"
172182
}
173183
],
174184
"menus": {

src/activate/registerCommands.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,35 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
174174

175175
visibleProvider.postMessageToWebview({ type: "acceptInput" })
176176
},
177+
"extension.reloadAllMcpServers": async () => {
178+
const visibleProvider = getVisibleProviderOrLog(outputChannel)
179+
if (!visibleProvider) {
180+
return
181+
}
182+
try {
183+
await visibleProvider.getMcpHub()?.restartAllMcpServers()
184+
} catch (error) {
185+
outputChannel.appendLine(`Failed to reload all MCP servers: ${error}`)
186+
vscode.window.showErrorMessage(`Failed to reload all MCP servers: ${error}`)
187+
}
188+
},
189+
"extension.toggleAllMcpServersDisabled": async () => {
190+
const visibleProvider = getVisibleProviderOrLog(outputChannel)
191+
if (!visibleProvider) {
192+
return
193+
}
194+
try {
195+
const mcpHub = visibleProvider.getMcpHub()
196+
if (mcpHub) {
197+
const allServers = mcpHub.getAllServers()
198+
const anyEnabled = allServers.some((server) => !server.disabled)
199+
await mcpHub.toggleAllServersDisabled(anyEnabled)
200+
}
201+
} catch (error) {
202+
outputChannel.appendLine(`Failed to toggle all MCP servers: ${error}`)
203+
vscode.window.showErrorMessage(`Failed to toggle all MCP servers: ${error}`)
204+
}
205+
},
177206
}
178207
}
179208

src/core/webview/webviewMessageHandler.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,5 +1255,16 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
12551255
await provider.postStateToWebview()
12561256
break
12571257
}
1258+
case "executeVSCodeCommand": {
1259+
if (message.command) {
1260+
try {
1261+
await vscode.commands.executeCommand(message.command)
1262+
} catch (error) {
1263+
provider.log(`Failed to execute VS Code command ${message.command}: ${error}`)
1264+
vscode.window.showErrorMessage(`Failed to execute command: ${message.command}`)
1265+
}
1266+
}
1267+
break
1268+
}
12581269
}
12591270
}

src/services/mcp/McpHub.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,4 +1306,52 @@ export class McpHub {
13061306
}
13071307
this.disposables.forEach((d) => d.dispose())
13081308
}
1309+
1310+
/**
1311+
* Enables or disables all global MCP servers at once.
1312+
* When activated, the configuration is reloaded.
1313+
* @param disabled true = disable all, false = enable all
1314+
*/
1315+
public async toggleAllServersDisabled(disabled: boolean): Promise<void> {
1316+
// Collect all global server names
1317+
const allServers = this.getAllServers()
1318+
1319+
// Set the Disabled flag for all servers
1320+
for (const server of allServers) {
1321+
await this.updateServerConfig(server.name, { disabled }, server.source)
1322+
const conn = this.findConnection(server.name, server.source)
1323+
if (conn) {
1324+
conn.server.disabled = disabled
1325+
}
1326+
}
1327+
1328+
// If activated, reload configuration
1329+
if (!disabled) {
1330+
// Re-initialize all servers, both global and project
1331+
await this.initializeMcpServers("global")
1332+
await this.initializeMcpServers("project")
1333+
}
1334+
1335+
await this.notifyWebviewOfServerChanges()
1336+
}
1337+
1338+
/**
1339+
* Restarts all currently active MCP servers.
1340+
* This will trigger a popup for each server being restarted.
1341+
*/
1342+
public async restartAllMcpServers(): Promise<void> {
1343+
const allServers = this.getAllServers() // Get all servers, regardless of disabled state
1344+
const restartPromises = allServers.map(async (server) => {
1345+
// Only restart if not disabled
1346+
if (!server.disabled) {
1347+
try {
1348+
await this.restartConnection(server.name, server.source)
1349+
} catch (error) {
1350+
this.showErrorMessage(`Failed to restart MCP server ${server.name}`, error)
1351+
}
1352+
}
1353+
})
1354+
await Promise.all(restartPromises)
1355+
await this.notifyWebviewOfServerChanges()
1356+
}
13091357
}

src/shared/WebviewMessage.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ export interface WebviewMessage {
132132
| "toggleApiConfigPin"
133133
| "setHistoryPreviewCollapsed"
134134
| "condenseTaskContextRequest"
135+
| "executeVSCodeCommand"
135136
text?: string
136137
disabled?: boolean
137138
askResponse?: ClineAskResponse
@@ -161,6 +162,7 @@ export interface WebviewMessage {
161162
hasSystemPromptOverride?: boolean
162163
terminalOperation?: "continue" | "abort"
163164
historyPreviewCollapsed?: boolean
165+
command?: string
164166
}
165167

166168
export const checkoutDiffPayloadSchema = z.object({

webview-ui/src/components/mcp/McpView.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,29 @@ const McpView = ({ onDone }: McpViewProps) => {
105105
</div>
106106
</div>
107107

108+
<div style={{ display: "flex", flexDirection: "column", gap: "10px", marginBottom: "15px" }}>
109+
<Button
110+
onClick={() =>
111+
vscode.postMessage({
112+
type: "executeVSCodeCommand",
113+
command: "extension.reloadAllMcpServers",
114+
})
115+
}
116+
data-testid="reload-all-mcp-servers-button">
117+
{t("mcp:reloadAllServers")}
118+
</Button>
119+
<Button
120+
onClick={() =>
121+
vscode.postMessage({
122+
type: "executeVSCodeCommand",
123+
command: "extension.toggleAllMcpServersDisabled",
124+
})
125+
}
126+
data-testid="toggle-all-mcp-servers-button">
127+
{t("mcp:toggleAllServers")}
128+
</Button>
129+
</div>
130+
108131
{/* Server List */}
109132
{servers.length > 0 && (
110133
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>

webview-ui/src/i18n/locales/de/mcp.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,7 @@
5353
"serverStatus": {
5454
"retrying": "Wiederhole...",
5555
"retryConnection": "Verbindung wiederholen"
56-
}
56+
},
57+
"reloadAllServers": "Alle MCP-Server neu laden",
58+
"toggleAllServers": "Alle MCP-Server aktivieren/deaktivieren"
5759
}

webview-ui/src/i18n/locales/en/mcp.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,7 @@
5353
"serverStatus": {
5454
"retrying": "Retrying...",
5555
"retryConnection": "Retry Connection"
56-
}
56+
},
57+
"reloadAllServers": "Reload All MCP Servers",
58+
"toggleAllServers": "Toggle All MCP Servers Enabled/Disabled"
5759
}

0 commit comments

Comments
 (0)