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 +8 -1
- package/bin/open-codex-computer-use-mcp +34 -0
- package/bin/open-computer-use +34 -0
- package/bin/open-computer-use-mcp +34 -0
- package/dist/Open Computer Use.app/Contents/Info.plist +1 -1
- package/dist/Open Computer Use.app/Contents/MacOS/OpenComputerUse +0 -0
- package/package.json +3 -1
- package/plugins/open-computer-use/.codex-plugin/plugin.json +1 -1
- package/scripts/install-config-helper.mjs +190 -31
- package/scripts/install-gemini-mcp.sh +60 -0
- package/scripts/install-opencode-mcp.sh +48 -0
- package/scripts/postinstall.mjs +2 -2
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.
|
|
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:
|
package/bin/open-computer-use
CHANGED
|
@@ -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:
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-codex-computer-use-mcp",
|
|
3
|
-
"version": "0.1.
|
|
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",
|
|
@@ -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
|
|
173
|
-
|
|
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 (
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
186
|
-
|
|
243
|
+
mcpServers[serverName] = desiredEntry;
|
|
244
|
+
if (legacyMatches) {
|
|
245
|
+
delete mcpServers[legacyServerName];
|
|
187
246
|
}
|
|
188
247
|
|
|
189
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
255
|
+
}
|
|
200
256
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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(`
|
|
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
|
-
|
|
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(`
|
|
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
|
|
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}"
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -11,14 +11,14 @@ const mcpConfig = {
|
|
|
11
11
|
};
|
|
12
12
|
const lines = [
|
|
13
13
|
"",
|
|
14
|
-
"Installed open-codex-computer-use-mcp@0.1.
|
|
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
|
|
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),
|