diff --git a/src/extension/host-binary/host-binary b/src/extension/host-binary/host-binary new file mode 100755 index 00000000..ec52dda0 Binary files /dev/null and b/src/extension/host-binary/host-binary differ diff --git a/src/extension/host-binary/pkg/clients/config.yml b/src/extension/host-binary/pkg/clients/config.yml index 6f9213ee..7061daa4 100644 --- a/src/extension/host-binary/pkg/clients/config.yml +++ b/src/extension/host-binary/pkg/clients/config.yml @@ -38,6 +38,20 @@ system: list: '.mcpServers | to_entries | map(.value + {"name": .key})' set: .mcpServers[$NAME] = $JSON del: del(.mcpServers[$NAME]) + vscode: + displayName: VS Code + installCheckPaths: + - /Applications/Visual Studio Code.app + - $ProgramFiles/Microsoft VS Code/ + - $USERPROFILE/AppData/Local/Programs/Microsoft VS Code/ + paths: + linux: $HOME/.config/Code/User/settings.json + darwin: $HOME/Library/Application Support/Code/User/settings.json + windows: $APPDATA/Code/User/settings.json + yq: + list: '.mcp.servers | to_entries | map(.value + {"name": .key})' + set: .mcp.servers[$NAME] = $JSON+{"type":"stdio"} + del: del(.mcp.servers[$NAME]) project: cursor: displayname: Cursor diff --git a/src/extension/ui/src/MCPClients.ts b/src/extension/ui/src/MCPClients.ts index 01525957..bd8980f8 100644 --- a/src/extension/ui/src/MCPClients.ts +++ b/src/extension/ui/src/MCPClients.ts @@ -3,6 +3,7 @@ import ClaudeDesktop from "./mcp-clients/ClaudeDesktop"; import ContinueDotDev from "./mcp-clients/ContinueDotDev"; import Cursor from "./mcp-clients/Cursor"; import Gordon from "./mcp-clients/Gordon"; +import VSCode from "./mcp-clients/VSCode"; import { MCPClient } from "./types/mcp"; export type MCPClientState = { @@ -28,6 +29,9 @@ export const getMCPClientStates = async (ddClient: v1.DockerDesktopClient) => { if (fromCLI["cursor"]) { mcpClientStates[Cursor.name] = toState(Cursor, fromCLI["cursor"]); } + if (fromCLI["vscode"]) { + mcpClientStates[VSCode.name] = toState(VSCode, fromCLI["vscode"]); + } if (fromCLI["continue"]) { mcpClientStates[ContinueDotDev.name] = toState(ContinueDotDev, fromCLI["continue"]); } diff --git a/src/extension/ui/src/assets/vscode.svg b/src/extension/ui/src/assets/vscode.svg new file mode 100644 index 00000000..c453e633 --- /dev/null +++ b/src/extension/ui/src/assets/vscode.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/extension/ui/src/components/tabs/YourClients.tsx b/src/extension/ui/src/components/tabs/YourClients.tsx index cb50f606..b9eff9dc 100644 --- a/src/extension/ui/src/components/tabs/YourClients.tsx +++ b/src/extension/ui/src/components/tabs/YourClients.tsx @@ -15,7 +15,7 @@ import { ListItem, ListItemText, Stack, - Typography + Typography, } from '@mui/material'; import { useEffect, useState } from 'react'; @@ -23,6 +23,7 @@ import ClaudeIcon from '../../assets/claude-ai-icon.svg'; import ContinueIcon from '../../assets/continue.svg'; import CursorIcon from '../../assets/cursor.svg'; import GordonIcon from '../../assets/gordon-icon.png'; +import VSCodeIcon from '../../assets/vscode.svg'; import { CATALOG_LAYOUT_SX, DOCKER_MCP_COMMAND } from '../../Constants'; // Initialize the Docker Desktop client @@ -37,6 +38,7 @@ const iconMap = { Gordon: GordonIcon, Cursor: CursorIcon, 'Continue.dev': ContinueIcon, + 'VS Code': VSCodeIcon, }; const MCPClientSettings = ({ appProps }: MCPClientSettingsProps) => { @@ -70,7 +72,7 @@ const MCPClientSettings = ({ appProps }: MCPClientSettingsProps) => { appProps={appProps} /> ); - } + }, )} @@ -210,10 +212,10 @@ function ClientSetting({ )) || ( - - Disconnect - - )} + + Disconnect + + )} )} @@ -246,10 +248,10 @@ function ClientSetting({ )) || ( - - Connect - - )} + + Connect + + )} )} @@ -281,10 +283,10 @@ function ClientSetting({ )) || ( - - Connect - - )} + + Connect + + )} )} @@ -342,7 +344,7 @@ function ClientSetting({ primary={
} /> - ) + ), )} diff --git a/src/extension/ui/src/mcp-clients/VSCode.ts b/src/extension/ui/src/mcp-clients/VSCode.ts new file mode 100644 index 00000000..57840ebf --- /dev/null +++ b/src/extension/ui/src/mcp-clients/VSCode.ts @@ -0,0 +1,41 @@ +import { v1 } from "@docker/extension-api-client-types"; +import { DOCKER_MCP_COMMAND } from "../Constants"; +import { MCPClient } from "./MCPTypes"; + +class VSCodeClient implements MCPClient { + name = "VS Code"; + url = "https://code.visualstudio.com/download"; + manualConfigSteps = [ + "Open Command Palette (Ctrl/Cmd + Shift + P) and run MCP: Add Server", + "Select Command (stdio) as the server type", + "Set server name: MCP_DOCKER", + "Paste the command: " + + '
' +
+        DOCKER_MCP_COMMAND +
+        "
", + "Choose Workspace Settings or User Settings based on your preference", + "Open the Chat view (Ctrl/Cmd + Shift + I) and select Agent mode", + "Click the Tools button to verify MCP_DOCKER tools are available" + ]; + expectedConfigPath = { + darwin: ".vscode/mcp.json or $HOME/Library/Application Support/Code/User/settings.json", + linux: ".vscode/mcp.json or $HOME/.config/Code/User/settings.json", + win32: ".vscode\\mcp.json or %APPDATA%\\Code\\User\\settings.json", + }; + connect = async (client: v1.DockerDesktopClient) => { + try { + await client.extension.host?.cli.exec("host-binary", ["client", "connect", "--global", "vscode"]); + } catch (e) { + client.desktopUI.toast.error("Unable to connect VS Code"); + } + }; + disconnect = async (client: v1.DockerDesktopClient) => { + try { + await client.extension.host?.cli.exec("host-binary", ["client", "disconnect", "--global", "vscode"]); + } catch (e) { + client.desktopUI.toast.error("Unable to disconnect VS Code"); + } + }; +} + +export default new VSCodeClient();