@voltajeba/selenium-mcp 0.0.0-stage → 1.0.26
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 +52 -2
- package/bin/selenium-mcp.js +136 -0
- package/package.json +32 -4
package/README.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @voltajeba/selenium-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server that lets AI coding assistants (Claude Code, Cursor, VS Code, Claude Desktop) drive a real Chrome, Edge, or Firefox through Selenium WebDriver — built for Java/Selenium/REST Assured test automation engineers.
|
|
4
|
+
|
|
5
|
+
This package bundles its own Java runtime, so **you don't need Java installed**. All you need is Node.js (for `npx`) and a browser.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
**Claude Code / Cursor / Claude Desktop** (`.mcp.json`, `mcp.json`, `claude_desktop_config.json`):
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"selenium-mcp": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "@voltajeba/selenium-mcp"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**VS Code** (`.vscode/mcp.json`):
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"servers": {
|
|
27
|
+
"selenium-mcp": {
|
|
28
|
+
"command": "npx",
|
|
29
|
+
"args": ["-y", "@voltajeba/selenium-mcp"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
On **native Windows**, Claude Code needs `npx` wrapped in `cmd /c`: `"command": "cmd", "args": ["/c", "npx", "-y", "@voltajeba/selenium-mcp"]`.
|
|
36
|
+
|
|
37
|
+
Or, in Claude Code, from a terminal: `claude mcp add selenium-mcp -- npx -y @voltajeba/selenium-mcp`
|
|
38
|
+
|
|
39
|
+
The first start downloads about 90 MB (the runtime for your OS, plus the server). If your client times out on that first start, restart the server once — or pre-download it with `npx -y @voltajeba/selenium-mcp --version` in a terminal.
|
|
40
|
+
|
|
41
|
+
Supported platforms: Windows x64, Linux x64 (glibc), macOS Intel, macOS Apple Silicon.
|
|
42
|
+
|
|
43
|
+
## Options
|
|
44
|
+
|
|
45
|
+
Any extra arguments are passed to the server, e.g. to load fewer tools:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
"args": ["-y", "@voltajeba/selenium-mcp", "--selenium.mcp.exclude-tool-groups=api,network,cookies"]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Logs go to `~/.selenium-mcp/mcp-server.log`.
|
|
52
|
+
|
|
53
|
+
Full tool reference and documentation: [selenium-mcp.xpathy.uk](https://selenium-mcp.xpathy.uk/) · Source: [GitHub](https://github.com/Volta-Jebaprashanth/selenium-mcp)
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Launches the selenium-mcp jar on the Java runtime bundled in the matching
|
|
3
|
+
// @voltajeba/selenium-mcp-<platform>-<arch> package. stdout carries the MCP protocol,
|
|
4
|
+
// so this script must never write to it - diagnostics go to stderr only.
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { spawn, spawnSync } = require('child_process');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const { version } = require('../package.json');
|
|
13
|
+
const SUPPORTED = ['win32-x64', 'linux-x64', 'darwin-x64', 'darwin-arm64'];
|
|
14
|
+
const target = `${process.platform}-${process.arch}`;
|
|
15
|
+
const platformPackage = `@voltajeba/selenium-mcp-${target}`;
|
|
16
|
+
|
|
17
|
+
function resolvePlatformPackage() {
|
|
18
|
+
try {
|
|
19
|
+
return path.dirname(require.resolve(`${platformPackage}/package.json`));
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// npm skips an optionalDependency it can't fetch (e.g. a run that raced a release
|
|
26
|
+
// still being processed by the registry), and npx then reuses that incomplete install
|
|
27
|
+
// from its cache on every later run. When we're running from the npx cache, install
|
|
28
|
+
// the missing platform package into it so the next start doesn't hit this again.
|
|
29
|
+
function repairNpxInstall() {
|
|
30
|
+
const npxInstallDir = path.resolve(__dirname, '..', '..', '..', '..');
|
|
31
|
+
const npmCli = process.env.npm_execpath;
|
|
32
|
+
if (path.basename(path.dirname(npxInstallDir)) !== '_npx' || !npmCli || !/npm-cli\.js$/.test(npmCli)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
process.stderr.write(`selenium-mcp: ${platformPackage} is missing from the npx cache - installing it...\n`);
|
|
36
|
+
const result = spawnSync(
|
|
37
|
+
process.execPath,
|
|
38
|
+
[npmCli, 'install', '--no-save', '--no-audit', '--no-fund', `${platformPackage}@${version}`],
|
|
39
|
+
// npm's own output goes to stderr (fd 2): stdout belongs to the MCP client.
|
|
40
|
+
{ cwd: npxInstallDir, stdio: ['ignore', 2, 2] }
|
|
41
|
+
);
|
|
42
|
+
return result.status === 0 ? resolvePlatformPackage() : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let packageDir = resolvePlatformPackage();
|
|
46
|
+
if (!packageDir && SUPPORTED.includes(target)) {
|
|
47
|
+
packageDir = repairNpxInstall();
|
|
48
|
+
}
|
|
49
|
+
if (!packageDir) {
|
|
50
|
+
const npxInstallDir = path.resolve(__dirname, '..', '..', '..', '..');
|
|
51
|
+
process.stderr.write(
|
|
52
|
+
SUPPORTED.includes(target)
|
|
53
|
+
? `selenium-mcp: ${platformPackage}@${version} is not installed, and installing it failed.\n` +
|
|
54
|
+
(path.basename(path.dirname(npxInstallDir)) === '_npx'
|
|
55
|
+
? `Delete ${npxInstallDir} and restart the server so npx reinstalls it.\n`
|
|
56
|
+
: `Reinstall @voltajeba/selenium-mcp without --omit=optional / --no-optional.\n`)
|
|
57
|
+
: `selenium-mcp: no bundled Java runtime for ${target}. Supported: ${SUPPORTED.join(', ')}.\n` +
|
|
58
|
+
'On other platforms, install Java 21+ and run the jar from ' +
|
|
59
|
+
'https://github.com/Volta-Jebaprashanth/selenium-mcp/releases/latest\n'
|
|
60
|
+
);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const isWindows = process.platform === 'win32';
|
|
65
|
+
const java = path.join(packageDir, 'runtime', 'bin', isWindows ? 'java.exe' : 'java');
|
|
66
|
+
const jar = path.join(packageDir, 'selenium-mcp.jar');
|
|
67
|
+
|
|
68
|
+
if (!isWindows) {
|
|
69
|
+
// Package managers don't always preserve the executable bit. jspawnhelper is what
|
|
70
|
+
// the JVM uses to start child processes such as chromedriver.
|
|
71
|
+
for (const file of [java, path.join(packageDir, 'runtime', 'lib', 'jspawnhelper')]) {
|
|
72
|
+
try {
|
|
73
|
+
fs.chmodSync(file, 0o755);
|
|
74
|
+
} catch {
|
|
75
|
+
// Already executable or not present; java will report a real problem itself.
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const args = process.argv.slice(2);
|
|
81
|
+
|
|
82
|
+
if (args[0] === '--version') {
|
|
83
|
+
// Terminal-only convenience (an MCP client never passes it): lets users pre-download
|
|
84
|
+
// the package with `npx -y @voltajeba/selenium-mcp --version` before the first real start.
|
|
85
|
+
process.stdout.write(`@voltajeba/selenium-mcp ${version} (${platformPackage})\n`);
|
|
86
|
+
process.exit(0);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!args.some((arg) => arg.startsWith('--logging.file.name'))) {
|
|
90
|
+
// The jar's default log path is relative to the working directory, which an MCP
|
|
91
|
+
// client may set to somewhere unexpected or read-only.
|
|
92
|
+
const logDir = path.join(os.homedir(), '.selenium-mcp');
|
|
93
|
+
try {
|
|
94
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
95
|
+
args.push(`--logging.file.name=${path.join(logDir, 'mcp-server.log')}`);
|
|
96
|
+
} catch {
|
|
97
|
+
// Fall back to the jar's default log location.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// The server closes its browsers when it shuts down cleanly: on a signal (SIGTERM etc. run the
|
|
102
|
+
// JVM's shutdown hooks) or at the end of stdin. On Windows neither survives a plain spawn: Node
|
|
103
|
+
// puts the child in a job object that is killed outright along with this launcher, and child.kill()
|
|
104
|
+
// is a hard TerminateProcess, so an MCP client killing the launcher would leave chromedriver and
|
|
105
|
+
// browser processes behind. There the server runs detached, outside the job, and reads stdin through
|
|
106
|
+
// this launcher, so it sees end-of-input - and shuts down cleanly - when the launcher goes away.
|
|
107
|
+
const child = isWindows
|
|
108
|
+
? spawn(java, ['-jar', jar, ...args], { stdio: ['pipe', 'inherit', 'inherit'], detached: true, windowsHide: true })
|
|
109
|
+
: spawn(java, ['-jar', jar, ...args], { stdio: 'inherit' });
|
|
110
|
+
|
|
111
|
+
if (isWindows) {
|
|
112
|
+
process.stdin.pipe(child.stdin);
|
|
113
|
+
child.stdin.on('error', () => {
|
|
114
|
+
// The server already exited; its exit handler below ends this process.
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
|
|
119
|
+
process.on(signal, () => {
|
|
120
|
+
if (!isWindows) {
|
|
121
|
+
child.kill(signal);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
child.stdin.end();
|
|
125
|
+
setTimeout(() => child.kill(), 10000).unref();
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
child.on('error', (err) => {
|
|
130
|
+
process.stderr.write(`selenium-mcp: failed to start ${java}: ${err.message}\n`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
child.on('exit', (code, signal) => {
|
|
135
|
+
process.exit(signal ? 128 + (os.constants.signals[signal] ?? 0) : code ?? 1);
|
|
136
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltajeba/selenium-mcp",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.26",
|
|
4
|
+
"description": "Selenium MCP server for Java/Selenium test automation engineers, with a Java runtime bundled - no JDK install needed.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"selenium",
|
|
9
|
+
"webdriver",
|
|
10
|
+
"test-automation"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://selenium-mcp.xpathy.uk/",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/Volta-Jebaprashanth/selenium-mcp.git"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"bin": {
|
|
19
|
+
"selenium-mcp": "bin/selenium-mcp.js"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"bin/"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"optionalDependencies": {
|
|
28
|
+
"@voltajeba/selenium-mcp-win32-x64": "1.0.26",
|
|
29
|
+
"@voltajeba/selenium-mcp-linux-x64": "1.0.26",
|
|
30
|
+
"@voltajeba/selenium-mcp-darwin-x64": "1.0.26",
|
|
31
|
+
"@voltajeba/selenium-mcp-darwin-arm64": "1.0.26"
|
|
32
|
+
},
|
|
33
|
+
"mcpName": "io.github.volta-jebaprashanth/selenium-mcp"
|
|
34
|
+
}
|