Skip to content

Commit 37d5665

Browse files
committed
Use the host-binary CLI to connect/disconnect claude
Signed-off-by: David Gageot <[email protected]>
1 parent ab38660 commit 37d5665

File tree

2 files changed

+9
-94
lines changed

2 files changed

+9
-94
lines changed

src/extension/ui/src/MCPClients.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ export const getMCPClientStates = async (ddClient: v1.DockerDesktopClient) => {
1818
mcpClientStates[mcpClient.name] = { exists: false, configured: false, path, client: mcpClient };
1919
} else if (content === undefined) {
2020
mcpClientStates[mcpClient.name] = { exists: true, configured: false, path, client: mcpClient };
21-
}
22-
else {
21+
} else {
2322
mcpClientStates[mcpClient.name] = { exists: true, configured: mcpClient.validateConfig(content), path: path, client: mcpClient };
2423
}
2524
}

src/extension/ui/src/mcp-clients/ClaudeDesktop.ts

Lines changed: 8 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { v1 } from "@docker/extension-api-client-types";
22
import { BUSYBOX } from "../Constants";
3-
import { getUser, writeToMount } from "../utils/Files";
3+
import { getUser } from "../utils/Files";
44
import { MCPClient, SAMPLE_MCP_CONFIG } from "./MCPTypes";
55

66
class ClaudeDesktopClient implements MCPClient {
@@ -12,9 +12,9 @@ class ClaudeDesktopClient implements MCPClient {
1212
"Click on the <strong>Developer</strong> tab",
1313
"Click on the <strong>Edit Config</strong> button",
1414
"Add MCP_DOCKER to <code>mcpServers</code> section:" +
15-
'<pre style="font-family: monospace; overflow: auto; width: 80%; background-color: grey.200; padding: 1; border-radius: 1; font-size: 12px;">' +
16-
JSON.stringify(SAMPLE_MCP_CONFIG, null, 2) +
17-
"</pre>",
15+
'<pre style="font-family: monospace; overflow: auto; width: 80%; background-color: grey.200; padding: 1; border-radius: 1; font-size: 12px;">' +
16+
JSON.stringify(SAMPLE_MCP_CONFIG, null, 2) +
17+
"</pre>",
1818
];
1919
expectedConfigPath = {
2020
darwin:
@@ -56,101 +56,17 @@ class ClaudeDesktopClient implements MCPClient {
5656
}
5757
};
5858
connect = async (client: v1.DockerDesktopClient) => {
59-
const platform = client.host.platform;
60-
let path = "";
61-
switch (platform) {
62-
case "darwin":
63-
path = "/Users/$USER/Library/Application Support/Claude/";
64-
break;
65-
case "linux":
66-
path = "/home/$USER/.config/claude/";
67-
break;
68-
case "win32":
69-
path = "%APPDATA%\\Claude\\";
70-
break;
71-
default:
72-
throw new Error("Unsupported platform: " + platform);
73-
}
74-
const user = await getUser(client);
75-
path = path.replace("$USER", user);
76-
77-
let payload: Record<string, any> = {};
7859
try {
79-
const result = await client.docker.cli.exec("run", [
80-
"--rm",
81-
"--mount",
82-
`type=bind,source="${path}",target=/claude_desktop_config`,
83-
BUSYBOX,
84-
"/bin/cat",
85-
"/claude_desktop_config/claude_desktop_config.json",
86-
]);
87-
if (result.stdout) {
88-
payload = JSON.parse(result.stdout);
89-
}
60+
await client.extension.host?.cli.exec("host-binary", ["client", "connect", "--global", "claude-desktop"]);
9061
} catch (e) {
91-
// No config or malformed config found, overwrite it
92-
}
93-
94-
if (!payload.mcpServers) {
95-
payload.mcpServers = {};
96-
}
97-
payload.mcpServers.MCP_DOCKER = SAMPLE_MCP_CONFIG.mcpServers.MCP_DOCKER;
98-
99-
try {
100-
await writeToMount(
101-
client,
102-
`type=bind,source="${path}",target=/claude_desktop_config`,
103-
"/claude_desktop_config/claude_desktop_config.json",
104-
JSON.stringify(payload, null, 2)
105-
);
106-
} catch (e) {
107-
client.desktopUI.toast.error((e as any).stderr);
62+
client.desktopUI.toast.error("Unable to connect Claude Desktop");
10863
}
10964
};
11065
disconnect = async (client: v1.DockerDesktopClient) => {
111-
const platform = client.host.platform;
112-
let path = "";
113-
switch (platform) {
114-
case "darwin":
115-
path = "/Users/$USER/Library/Application Support/Claude/";
116-
break;
117-
case "linux":
118-
path = "/home/$USER/.config/claude/";
119-
break;
120-
case "win32":
121-
path = "%APPDATA%\\Claude\\";
122-
break;
123-
default:
124-
throw new Error("Unsupported platform: " + platform);
125-
}
126-
const user = await getUser(client);
127-
path = path.replace("$USER", user);
12866
try {
129-
// This method is only called after the config has been validated, so we can safely assume it's a valid config.
130-
const previousConfig = JSON.parse(
131-
(
132-
await client.docker.cli.exec("run", [
133-
"--rm",
134-
"--mount",
135-
`type=bind,source="${path}",target=/claude_desktop_config`,
136-
"-w",
137-
"/claude_desktop_config",
138-
BUSYBOX,
139-
"/bin/cat",
140-
"/claude_desktop_config/claude_desktop_config.json",
141-
])
142-
).stdout || "{}"
143-
);
144-
const newConfig = { ...previousConfig };
145-
delete newConfig.mcpServers.MCP_DOCKER;
146-
await writeToMount(
147-
client,
148-
`type=bind,source="${path}",target=/claude_desktop_config`,
149-
"/claude_desktop_config/claude_desktop_config.json",
150-
JSON.stringify(newConfig, null, 2)
151-
);
67+
await client.extension.host?.cli.exec("host-binary", ["client", "disconnect", "--global", "claude-desktop"]);
15268
} catch (e) {
153-
client.desktopUI.toast.error((e as any).stderr);
69+
client.desktopUI.toast.error("Unable to disconnect Claude Desktop");
15470
}
15571
};
15672
validateConfig = (content: string) => {

0 commit comments

Comments
 (0)