open-codex-computer-use-mcp 0.1.30 → 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,9 +46,16 @@ open-computer-use --version
46
46
  # Install into Claude Code for the current project
47
47
  open-computer-use install-claude-mcp
48
48
 
49
+ # Install into Gemini CLI for the current project or user config
50
+ open-computer-use install-gemini-mcp
51
+ open-computer-use install-gemini-mcp --scope user
52
+
49
53
  # Install into Codex as a plain MCP entry in ~/.codex/config.toml
50
54
  open-computer-use install-codex-mcp
51
55
 
56
+ # Install into opencode in ~/.config/opencode
57
+ open-computer-use install-opencode-mcp
58
+
52
59
  # Check permissions first; if Accessibility / Screen Recording is missing, open the permission onboarding window
53
60
  # If both are already granted, this just prints the status and exits
54
61
  open-computer-use doctor
@@ -67,7 +74,7 @@ open-computer-use install-codex-plugin
67
74
 
68
75
  ## Notes
69
76
 
70
- - Version: `0.1.30`
77
+ - Version: `0.1.33`
71
78
  - Platform: macOS 14+
72
79
  - Architectures: `arm64` and `x64` via a universal app bundle
73
80
  - The host terminal or app still needs macOS `Accessibility` and `Screen Recording` permissions
@@ -17,7 +17,9 @@ Commands:
17
17
  call <tool> Call one tool, or run a JSON array of tool calls.
18
18
  turn-ended Notify the running MCP process that the host turn ended.
19
19
  install-claude-mcp Install the MCP server into ~/.claude.json for this project.
20
+ install-gemini-mcp Install the MCP server into Gemini CLI config.
20
21
  install-codex-mcp Install the MCP server into ~/.codex/config.toml.
22
+ install-opencode-mcp Install the MCP server into ~/.config/opencode.
21
23
  install-codex-plugin Install this npm package into the local Codex plugin cache.
22
24
  help [command] Show general or command-specific help.
23
25
  version Print the CLI version.
@@ -43,7 +45,9 @@ done
43
45
  package_root="$(cd "$(dirname "${script_path}")/.." && pwd)"
44
46
  app_binary="${package_root}/dist/Open Computer Use.app/Contents/MacOS/OpenComputerUse"
45
47
  install_claude_mcp_script="${package_root}/scripts/install-claude-mcp.sh"
48
+ install_gemini_mcp_script="${package_root}/scripts/install-gemini-mcp.sh"
46
49
  install_mcp_script="${package_root}/scripts/install-codex-mcp.sh"
50
+ install_opencode_mcp_script="${package_root}/scripts/install-opencode-mcp.sh"
47
51
  install_script="${package_root}/scripts/install-codex-plugin.sh"
48
52
 
49
53
  if [[ "${1:-}" == "install-claude-mcp" || "${1:-}" == "install-clauce-mcp" ]]; then
@@ -51,11 +55,21 @@ if [[ "${1:-}" == "install-claude-mcp" || "${1:-}" == "install-clauce-mcp" ]]; t
51
55
  exec "${install_claude_mcp_script}" "$@"
52
56
  fi
53
57
 
58
+ if [[ "${1:-}" == "install-gemini-mcp" ]]; then
59
+ shift
60
+ exec "${install_gemini_mcp_script}" "$@"
61
+ fi
62
+
54
63
  if [[ "${1:-}" == "install-codex-mcp" ]]; then
55
64
  shift
56
65
  exec "${install_mcp_script}" "$@"
57
66
  fi
58
67
 
68
+ if [[ "${1:-}" == "install-opencode-mcp" ]]; then
69
+ shift
70
+ exec "${install_opencode_mcp_script}" "$@"
71
+ fi
72
+
59
73
  if [[ "${1:-}" == "install-codex-plugin" ]]; then
60
74
  shift
61
75
  exec "${install_script}" "$@"
@@ -91,6 +105,26 @@ EOF
91
105
  exit 0
92
106
  fi
93
107
 
108
+ if [[ "${1:-}" == "help" && "${2:-}" == "install-gemini-mcp" ]]; then
109
+ cat <<'EOF'
110
+ Usage:
111
+ open-computer-use install-gemini-mcp [--scope project|user]
112
+
113
+ Install the open-computer-use MCP server into Gemini CLI config.
114
+ EOF
115
+ exit 0
116
+ fi
117
+
118
+ if [[ "${1:-}" == "help" && "${2:-}" == "install-opencode-mcp" ]]; then
119
+ cat <<'EOF'
120
+ Usage:
121
+ open-computer-use install-opencode-mcp
122
+
123
+ Install the open-computer-use MCP server into ~/.config/opencode.
124
+ EOF
125
+ exit 0
126
+ fi
127
+
94
128
  if [[ "${1:-}" == "help" && ( "${2:-}" == "install-claude-mcp" || "${2:-}" == "install-clauce-mcp" ) ]]; then
95
129
  cat <<'EOF'
96
130
  Usage:
@@ -17,7 +17,9 @@ Commands:
17
17
  call <tool> Call one tool, or run a JSON array of tool calls.
18
18
  turn-ended Notify the running MCP process that the host turn ended.
19
19
  install-claude-mcp Install the MCP server into ~/.claude.json for this project.
20
+ install-gemini-mcp Install the MCP server into Gemini CLI config.
20
21
  install-codex-mcp Install the MCP server into ~/.codex/config.toml.
22
+ install-opencode-mcp Install the MCP server into ~/.config/opencode.
21
23
  install-codex-plugin Install this npm package into the local Codex plugin cache.
22
24
  help [command] Show general or command-specific help.
23
25
  version Print the CLI version.
@@ -43,7 +45,9 @@ done
43
45
  package_root="$(cd "$(dirname "${script_path}")/.." && pwd)"
44
46
  app_binary="${package_root}/dist/Open Computer Use.app/Contents/MacOS/OpenComputerUse"
45
47
  install_claude_mcp_script="${package_root}/scripts/install-claude-mcp.sh"
48
+ install_gemini_mcp_script="${package_root}/scripts/install-gemini-mcp.sh"
46
49
  install_mcp_script="${package_root}/scripts/install-codex-mcp.sh"
50
+ install_opencode_mcp_script="${package_root}/scripts/install-opencode-mcp.sh"
47
51
  install_script="${package_root}/scripts/install-codex-plugin.sh"
48
52
 
49
53
  if [[ "${1:-}" == "install-claude-mcp" || "${1:-}" == "install-clauce-mcp" ]]; then
@@ -51,11 +55,21 @@ if [[ "${1:-}" == "install-claude-mcp" || "${1:-}" == "install-clauce-mcp" ]]; t
51
55
  exec "${install_claude_mcp_script}" "$@"
52
56
  fi
53
57
 
58
+ if [[ "${1:-}" == "install-gemini-mcp" ]]; then
59
+ shift
60
+ exec "${install_gemini_mcp_script}" "$@"
61
+ fi
62
+
54
63
  if [[ "${1:-}" == "install-codex-mcp" ]]; then
55
64
  shift
56
65
  exec "${install_mcp_script}" "$@"
57
66
  fi
58
67
 
68
+ if [[ "${1:-}" == "install-opencode-mcp" ]]; then
69
+ shift
70
+ exec "${install_opencode_mcp_script}" "$@"
71
+ fi
72
+
59
73
  if [[ "${1:-}" == "install-codex-plugin" ]]; then
60
74
  shift
61
75
  exec "${install_script}" "$@"
@@ -91,6 +105,26 @@ EOF
91
105
  exit 0
92
106
  fi
93
107
 
108
+ if [[ "${1:-}" == "help" && "${2:-}" == "install-gemini-mcp" ]]; then
109
+ cat <<'EOF'
110
+ Usage:
111
+ open-computer-use install-gemini-mcp [--scope project|user]
112
+
113
+ Install the open-computer-use MCP server into Gemini CLI config.
114
+ EOF
115
+ exit 0
116
+ fi
117
+
118
+ if [[ "${1:-}" == "help" && "${2:-}" == "install-opencode-mcp" ]]; then
119
+ cat <<'EOF'
120
+ Usage:
121
+ open-computer-use install-opencode-mcp
122
+
123
+ Install the open-computer-use MCP server into ~/.config/opencode.
124
+ EOF
125
+ exit 0
126
+ fi
127
+
94
128
  if [[ "${1:-}" == "help" && ( "${2:-}" == "install-claude-mcp" || "${2:-}" == "install-clauce-mcp" ) ]]; then
95
129
  cat <<'EOF'
96
130
  Usage:
@@ -17,7 +17,9 @@ Commands:
17
17
  call <tool> Call one tool, or run a JSON array of tool calls.
18
18
  turn-ended Notify the running MCP process that the host turn ended.
19
19
  install-claude-mcp Install the MCP server into ~/.claude.json for this project.
20
+ install-gemini-mcp Install the MCP server into Gemini CLI config.
20
21
  install-codex-mcp Install the MCP server into ~/.codex/config.toml.
22
+ install-opencode-mcp Install the MCP server into ~/.config/opencode.
21
23
  install-codex-plugin Install this npm package into the local Codex plugin cache.
22
24
  help [command] Show general or command-specific help.
23
25
  version Print the CLI version.
@@ -43,7 +45,9 @@ done
43
45
  package_root="$(cd "$(dirname "${script_path}")/.." && pwd)"
44
46
  app_binary="${package_root}/dist/Open Computer Use.app/Contents/MacOS/OpenComputerUse"
45
47
  install_claude_mcp_script="${package_root}/scripts/install-claude-mcp.sh"
48
+ install_gemini_mcp_script="${package_root}/scripts/install-gemini-mcp.sh"
46
49
  install_mcp_script="${package_root}/scripts/install-codex-mcp.sh"
50
+ install_opencode_mcp_script="${package_root}/scripts/install-opencode-mcp.sh"
47
51
  install_script="${package_root}/scripts/install-codex-plugin.sh"
48
52
 
49
53
  if [[ "${1:-}" == "install-claude-mcp" || "${1:-}" == "install-clauce-mcp" ]]; then
@@ -51,11 +55,21 @@ if [[ "${1:-}" == "install-claude-mcp" || "${1:-}" == "install-clauce-mcp" ]]; t
51
55
  exec "${install_claude_mcp_script}" "$@"
52
56
  fi
53
57
 
58
+ if [[ "${1:-}" == "install-gemini-mcp" ]]; then
59
+ shift
60
+ exec "${install_gemini_mcp_script}" "$@"
61
+ fi
62
+
54
63
  if [[ "${1:-}" == "install-codex-mcp" ]]; then
55
64
  shift
56
65
  exec "${install_mcp_script}" "$@"
57
66
  fi
58
67
 
68
+ if [[ "${1:-}" == "install-opencode-mcp" ]]; then
69
+ shift
70
+ exec "${install_opencode_mcp_script}" "$@"
71
+ fi
72
+
59
73
  if [[ "${1:-}" == "install-codex-plugin" ]]; then
60
74
  shift
61
75
  exec "${install_script}" "$@"
@@ -91,6 +105,26 @@ EOF
91
105
  exit 0
92
106
  fi
93
107
 
108
+ if [[ "${1:-}" == "help" && "${2:-}" == "install-gemini-mcp" ]]; then
109
+ cat <<'EOF'
110
+ Usage:
111
+ open-computer-use install-gemini-mcp [--scope project|user]
112
+
113
+ Install the open-computer-use MCP server into Gemini CLI config.
114
+ EOF
115
+ exit 0
116
+ fi
117
+
118
+ if [[ "${1:-}" == "help" && "${2:-}" == "install-opencode-mcp" ]]; then
119
+ cat <<'EOF'
120
+ Usage:
121
+ open-computer-use install-opencode-mcp
122
+
123
+ Install the open-computer-use MCP server into ~/.config/opencode.
124
+ EOF
125
+ exit 0
126
+ fi
127
+
94
128
  if [[ "${1:-}" == "help" && ( "${2:-}" == "install-claude-mcp" || "${2:-}" == "install-clauce-mcp" ) ]]; then
95
129
  cat <<'EOF'
96
130
  Usage:
@@ -21,7 +21,7 @@
21
21
  <key>CFBundlePackageType</key>
22
22
  <string>APPL</string>
23
23
  <key>CFBundleShortVersionString</key>
24
- <string>0.1.30</string>
24
+ <string>0.1.33</string>
25
25
  <key>CFBundleVersion</key>
26
26
  <string>1</string>
27
27
  <key>LSMinimumSystemVersion</key>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-codex-computer-use-mcp",
3
- "version": "0.1.30",
3
+ "version": "0.1.33",
4
4
  "description": "Prebuilt macOS Computer Use MCP server. After install, run open-computer-use doctor.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/iFurySt/open-codex-computer-use",
@@ -46,8 +46,10 @@
46
46
  "plugins/open-computer-use/assets/",
47
47
  "plugins/open-computer-use/scripts/",
48
48
  "scripts/install-claude-mcp.sh",
49
+ "scripts/install-gemini-mcp.sh",
49
50
  "scripts/install-config-helper.mjs",
50
51
  "scripts/install-codex-mcp.sh",
52
+ "scripts/install-opencode-mcp.sh",
51
53
  "scripts/install-codex-plugin.sh",
52
54
  "scripts/postinstall.mjs",
53
55
  "README.md",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-computer-use",
3
- "version": "0.1.30",
3
+ "version": "0.1.33",
4
4
  "description": "Open-source macOS Computer Use MCP server packaged as a Codex plugin.",
5
5
  "author": {
6
6
  "name": "Leo",
@@ -12,6 +12,8 @@ function usage() {
12
12
  process.stdout.write(`Usage:
13
13
  node ./scripts/install-config-helper.mjs claude-mcp <config-path> <project-root> <server-name> <command-name>
14
14
  node ./scripts/install-config-helper.mjs codex-mcp <config-path> <server-name> <command-name>
15
+ node ./scripts/install-config-helper.mjs gemini-mcp <config-path> <server-name> <command-name>
16
+ node ./scripts/install-config-helper.mjs opencode-mcp <primary-config-path> <secondary-config-path> <server-name> <command-name>
15
17
  node ./scripts/install-config-helper.mjs codex-plugin-version <plugin-manifest-path>
16
18
  node ./scripts/install-config-helper.mjs codex-plugin-config <config-path> <repo-root> <marketplace-name> <plugin-name>
17
19
  node ./scripts/install-config-helper.mjs copy-into-dir <target-dir> <source-path> [<source-path> ...]
@@ -29,6 +31,53 @@ function ensureParentDir(filePath) {
29
31
  mkdirSync(path.dirname(filePath), { recursive: true });
30
32
  }
31
33
 
34
+ function readJSONObjectConfig(configPath, label) {
35
+ const raw = readTextIfExists(configPath);
36
+ if (raw.trim().length === 0) {
37
+ return {};
38
+ }
39
+
40
+ let data;
41
+ try {
42
+ data = JSON.parse(raw);
43
+ } catch (error) {
44
+ fail(`Existing ${label} is not valid JSON: ${error.message}`);
45
+ }
46
+
47
+ if (data === null || Array.isArray(data) || typeof data !== "object") {
48
+ fail(`Existing ${label} root is not a JSON object; refusing to modify it.`);
49
+ }
50
+
51
+ return data;
52
+ }
53
+
54
+ function ensureObjectField(parent, key, label) {
55
+ const value = parent[key] ?? {};
56
+ if (value === null || Array.isArray(value) || typeof value !== "object") {
57
+ fail(label);
58
+ }
59
+ parent[key] = value;
60
+ return value;
61
+ }
62
+
63
+ function getOptionalObjectField(parent, key, label) {
64
+ if (!(key in parent) || parent[key] === undefined) {
65
+ return undefined;
66
+ }
67
+
68
+ const value = parent[key];
69
+ if (value === null || Array.isArray(value) || typeof value !== "object") {
70
+ fail(label);
71
+ }
72
+
73
+ return value;
74
+ }
75
+
76
+ function writeJSONConfig(configPath, data) {
77
+ ensureParentDir(configPath);
78
+ writeFileSync(configPath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
79
+ }
80
+
32
81
  function normalizeNewlines(text) {
33
82
  return text.replace(/\r\n/g, "\n");
34
83
  }
@@ -168,41 +217,55 @@ function installClaudeMcp(configPath, projectRoot, serverName, commandName) {
168
217
  args: ["mcp"],
169
218
  };
170
219
  const legacyServerName = "open-codex-computer-use";
220
+ const data = readJSONObjectConfig(configPath, `Claude config ${configPath}`);
221
+ const projects = ensureObjectField(data, "projects", 'Existing Claude config has non-object "projects"; refusing to modify it.');
222
+ const projectEntry = ensureObjectField(
223
+ projects,
224
+ projectRoot,
225
+ `Existing Claude project entry for ${projectRoot} is not an object; refusing to modify it.`,
226
+ );
227
+ const mcpServers = ensureObjectField(
228
+ projectEntry,
229
+ "mcpServers",
230
+ `Existing Claude project MCP config for ${projectRoot} is not an object; refusing to modify it.`,
231
+ );
171
232
 
172
- const raw = readTextIfExists(configPath);
173
- let data;
233
+ const target = mcpServers[serverName];
234
+ const legacy = mcpServers[legacyServerName];
235
+ const targetMatches = JSON.stringify(target) === JSON.stringify(desiredEntry);
236
+ const legacyMatches = JSON.stringify(legacy) === JSON.stringify(desiredEntry);
174
237
 
175
- if (raw.trim().length === 0) {
176
- data = {};
177
- } else {
178
- try {
179
- data = JSON.parse(raw);
180
- } catch (error) {
181
- fail(`Existing Claude config is not valid JSON: ${error.message}`);
182
- }
238
+ if (targetMatches && !legacyMatches) {
239
+ process.stdout.write(`Claude MCP server "${serverName}" is already installed for ${projectRoot} in ${configPath}.\n`);
240
+ return;
183
241
  }
184
242
 
185
- if (data === null || Array.isArray(data) || typeof data !== "object") {
186
- fail("Existing Claude config root is not a JSON object; refusing to modify it.");
243
+ mcpServers[serverName] = desiredEntry;
244
+ if (legacyMatches) {
245
+ delete mcpServers[legacyServerName];
187
246
  }
188
247
 
189
- const projects = data.projects ?? {};
190
- if (projects === null || Array.isArray(projects) || typeof projects !== "object") {
191
- fail('Existing Claude config has non-object "projects"; refusing to modify it.');
192
- }
193
- data.projects = projects;
248
+ writeJSONConfig(configPath, data);
194
249
 
195
- const projectEntry = projects[projectRoot] ?? {};
196
- if (projectEntry === null || Array.isArray(projectEntry) || typeof projectEntry !== "object") {
197
- fail(`Existing Claude project entry for ${projectRoot} is not an object; refusing to modify it.`);
250
+ if (targetMatches && legacyMatches) {
251
+ process.stdout.write(`Claude MCP server "${serverName}" was already installed for ${projectRoot}; removed legacy alias "${legacyServerName}" from ${configPath}.\n`);
252
+ } else {
253
+ process.stdout.write(`Installed Claude MCP server "${serverName}" for ${projectRoot} into ${configPath}.\n`);
198
254
  }
199
- projects[projectRoot] = projectEntry;
255
+ }
200
256
 
201
- const mcpServers = projectEntry.mcpServers ?? {};
202
- if (mcpServers === null || Array.isArray(mcpServers) || typeof mcpServers !== "object") {
203
- fail(`Existing Claude project MCP config for ${projectRoot} is not an object; refusing to modify it.`);
204
- }
205
- projectEntry.mcpServers = mcpServers;
257
+ function installGeminiMcp(configPath, serverName, commandName) {
258
+ const desiredEntry = {
259
+ command: commandName,
260
+ args: ["mcp"],
261
+ };
262
+ const legacyServerName = "open-codex-computer-use";
263
+ const data = readJSONObjectConfig(configPath, `Gemini config ${configPath}`);
264
+ const mcpServers = ensureObjectField(
265
+ data,
266
+ "mcpServers",
267
+ `Existing Gemini config has non-object "mcpServers"; refusing to modify it.`,
268
+ );
206
269
 
207
270
  const target = mcpServers[serverName];
208
271
  const legacy = mcpServers[legacyServerName];
@@ -210,7 +273,7 @@ function installClaudeMcp(configPath, projectRoot, serverName, commandName) {
210
273
  const legacyMatches = JSON.stringify(legacy) === JSON.stringify(desiredEntry);
211
274
 
212
275
  if (targetMatches && !legacyMatches) {
213
- process.stdout.write(`Claude MCP server "${serverName}" is already installed for ${projectRoot} in ${configPath}.\n`);
276
+ process.stdout.write(`Gemini MCP server "${serverName}" is already installed in ${configPath}.\n`);
214
277
  return;
215
278
  }
216
279
 
@@ -219,16 +282,98 @@ function installClaudeMcp(configPath, projectRoot, serverName, commandName) {
219
282
  delete mcpServers[legacyServerName];
220
283
  }
221
284
 
222
- ensureParentDir(configPath);
223
- writeFileSync(configPath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
285
+ writeJSONConfig(configPath, data);
224
286
 
225
287
  if (targetMatches && legacyMatches) {
226
- process.stdout.write(`Claude MCP server "${serverName}" was already installed for ${projectRoot}; removed legacy alias "${legacyServerName}" from ${configPath}.\n`);
288
+ process.stdout.write(`Gemini MCP server "${serverName}" was already installed; removed legacy alias "${legacyServerName}" from ${configPath}.\n`);
227
289
  } else {
228
- process.stdout.write(`Installed Claude MCP server "${serverName}" for ${projectRoot} into ${configPath}.\n`);
290
+ process.stdout.write(`Installed Gemini MCP server "${serverName}" into ${configPath}.\n`);
229
291
  }
230
292
  }
231
293
 
294
+ function installOpencodeMcp(primaryConfigPath, secondaryConfigPath, serverName, commandName) {
295
+ const desiredEntry = {
296
+ type: "local",
297
+ command: [commandName, "mcp"],
298
+ };
299
+ const legacyServerName = "open-codex-computer-use";
300
+ const configEntries = [{ path: primaryConfigPath, role: "primary" }];
301
+ if (secondaryConfigPath && secondaryConfigPath !== primaryConfigPath) {
302
+ configEntries.push({ path: secondaryConfigPath, role: "secondary" });
303
+ }
304
+
305
+ const records = configEntries.map((entry) => ({
306
+ ...entry,
307
+ data: readJSONObjectConfig(entry.path, `opencode config ${entry.path}`),
308
+ dirty: false,
309
+ }));
310
+
311
+ const targetMatches = [];
312
+ const extraAliases = [];
313
+ for (const record of records) {
314
+ const mcp = getOptionalObjectField(
315
+ record.data,
316
+ "mcp",
317
+ `Existing opencode config has non-object "mcp" in ${record.path}; refusing to modify it.`,
318
+ );
319
+ if (!mcp) {
320
+ continue;
321
+ }
322
+
323
+ if (JSON.stringify(mcp[serverName]) === JSON.stringify(desiredEntry)) {
324
+ targetMatches.push(record.path);
325
+ }
326
+ if (serverName in mcp || legacyServerName in mcp) {
327
+ extraAliases.push(record.path);
328
+ }
329
+ }
330
+
331
+ if (targetMatches.length === 1 && extraAliases.length === 1 && targetMatches[0] === extraAliases[0]) {
332
+ process.stdout.write(`opencode MCP server "${serverName}" is already installed in ${targetMatches[0]}.\n`);
333
+ return;
334
+ }
335
+
336
+ for (const record of records) {
337
+ const mcp = ensureObjectField(
338
+ record.data,
339
+ "mcp",
340
+ `Existing opencode config has non-object "mcp" in ${record.path}; refusing to modify it.`,
341
+ );
342
+
343
+ if (record.role === "primary") {
344
+ if (JSON.stringify(mcp[serverName]) !== JSON.stringify(desiredEntry)) {
345
+ mcp[serverName] = desiredEntry;
346
+ record.dirty = true;
347
+ }
348
+ if (legacyServerName in mcp) {
349
+ delete mcp[legacyServerName];
350
+ record.dirty = true;
351
+ }
352
+ continue;
353
+ }
354
+
355
+ if (serverName in mcp) {
356
+ delete mcp[serverName];
357
+ record.dirty = true;
358
+ }
359
+ if (legacyServerName in mcp) {
360
+ delete mcp[legacyServerName];
361
+ record.dirty = true;
362
+ }
363
+ if (Object.keys(mcp).length === 0) {
364
+ delete record.data.mcp;
365
+ }
366
+ }
367
+
368
+ for (const record of records) {
369
+ if (record.dirty) {
370
+ writeJSONConfig(record.path, record.data);
371
+ }
372
+ }
373
+
374
+ process.stdout.write(`Installed opencode MCP server "${serverName}" into ${primaryConfigPath}.\n`);
375
+ }
376
+
232
377
  function installCodexMcp(configPath, serverName, commandName) {
233
378
  const desiredBody = `command = ${JSON.stringify(commandName)}\nargs = ["mcp"]`;
234
379
  const targetHeader = `mcp_servers."${serverName}"`;
@@ -347,6 +492,20 @@ function main(argv) {
347
492
  }
348
493
  installCodexMcp(...args);
349
494
  return;
495
+ case "gemini-mcp":
496
+ if (args.length !== 3) {
497
+ usage();
498
+ process.exit(1);
499
+ }
500
+ installGeminiMcp(...args);
501
+ return;
502
+ case "opencode-mcp":
503
+ if (args.length !== 4) {
504
+ usage();
505
+ process.exit(1);
506
+ }
507
+ installOpencodeMcp(...args);
508
+ return;
350
509
  case "codex-plugin-version":
351
510
  if (args.length !== 1) {
352
511
  usage();
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ config_helper="${script_dir}/install-config-helper.mjs"
7
+ server_name="open-computer-use"
8
+ command_name="open-computer-use"
9
+ scope="project"
10
+
11
+ usage() {
12
+ cat <<'EOF'
13
+ Usage: ./scripts/install-gemini-mcp.sh [--scope project|user]
14
+
15
+ Install the open-computer-use stdio MCP entry into Gemini CLI config.
16
+ Defaults to project scope, which writes ./.gemini/settings.json for the current project.
17
+ Set GEMINI_CONFIG_PATH to override the target file directly.
18
+ EOF
19
+ }
20
+
21
+ while [[ $# -gt 0 ]]; do
22
+ case "$1" in
23
+ --scope)
24
+ if [[ $# -lt 2 ]]; then
25
+ echo "--scope requires a value" >&2
26
+ usage >&2
27
+ exit 1
28
+ fi
29
+ scope="$2"
30
+ shift 2
31
+ ;;
32
+ -h|--help)
33
+ usage
34
+ exit 0
35
+ ;;
36
+ *)
37
+ echo "Unknown argument: $1" >&2
38
+ usage >&2
39
+ exit 1
40
+ ;;
41
+ esac
42
+ done
43
+
44
+ case "${scope}" in
45
+ project)
46
+ default_config_path="$(pwd -P)/.gemini/settings.json"
47
+ ;;
48
+ user)
49
+ default_config_path="${HOME}/.gemini/settings.json"
50
+ ;;
51
+ *)
52
+ echo "Unsupported Gemini scope: ${scope}" >&2
53
+ usage >&2
54
+ exit 1
55
+ ;;
56
+ esac
57
+
58
+ config_path="${GEMINI_CONFIG_PATH:-${default_config_path}}"
59
+
60
+ node "${config_helper}" gemini-mcp "${config_path}" "${server_name}" "${command_name}"
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ config_helper="${script_dir}/install-config-helper.mjs"
7
+ server_name="open-computer-use"
8
+ command_name="open-computer-use"
9
+ opencode_config_dir="${XDG_CONFIG_HOME:-${HOME}/.config}/opencode"
10
+
11
+ usage() {
12
+ cat <<'EOF'
13
+ Usage: ./scripts/install-opencode-mcp.sh
14
+
15
+ Install the open-computer-use stdio MCP entry into opencode config.
16
+ Set OPENCODE_CONFIG_PATH to override the primary config file directly.
17
+ EOF
18
+ }
19
+
20
+ while [[ $# -gt 0 ]]; do
21
+ case "$1" in
22
+ -h|--help)
23
+ usage
24
+ exit 0
25
+ ;;
26
+ *)
27
+ echo "Unknown argument: $1" >&2
28
+ usage >&2
29
+ exit 1
30
+ ;;
31
+ esac
32
+ done
33
+
34
+ if [[ -n "${OPENCODE_CONFIG_PATH:-}" ]]; then
35
+ primary_config_path="${OPENCODE_CONFIG_PATH}"
36
+ secondary_config_path=""
37
+ elif [[ -f "${opencode_config_dir}/opencode.json" ]]; then
38
+ primary_config_path="${opencode_config_dir}/opencode.json"
39
+ secondary_config_path="${opencode_config_dir}/config.json"
40
+ elif [[ -f "${opencode_config_dir}/config.json" ]]; then
41
+ primary_config_path="${opencode_config_dir}/config.json"
42
+ secondary_config_path="${opencode_config_dir}/opencode.json"
43
+ else
44
+ primary_config_path="${opencode_config_dir}/opencode.json"
45
+ secondary_config_path="${opencode_config_dir}/config.json"
46
+ fi
47
+
48
+ node "${config_helper}" opencode-mcp "${primary_config_path}" "${secondary_config_path}" "${server_name}" "${command_name}"
@@ -11,14 +11,14 @@ const mcpConfig = {
11
11
  };
12
12
  const lines = [
13
13
  "",
14
- "Installed open-codex-computer-use-mcp@0.1.30.",
14
+ "Installed open-codex-computer-use-mcp@0.1.33.",
15
15
  "Package: https://www.npmjs.com/package/open-codex-computer-use-mcp",
16
16
  "Commands: open-computer-use, open-computer-use-mcp, open-codex-computer-use-mcp",
17
17
  "",
18
18
  "Next:",
19
19
  "1. Run open-computer-use doctor",
20
20
  "2. In macOS System Settings, grant Accessibility and Screen Recording to your host terminal or MCP client",
21
- "3. Run open-computer-use install-claude-mcp for Claude Code, open-computer-use install-codex-mcp for Codex, or open-computer-use install-codex-plugin for the local plugin cache",
21
+ "3. Run open-computer-use install-claude-mcp, install-gemini-mcp, install-codex-mcp, or install-opencode-mcp for your host CLI, or install-codex-plugin for the local Codex plugin cache",
22
22
  "",
23
23
  "You can add this to any MCP-capable client:",
24
24
  JSON.stringify(mcpConfig, null, 2),