seleniumboot-mcp 0.1.0__tar.gz
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.
- seleniumboot_mcp-0.1.0/PKG-INFO +229 -0
- seleniumboot_mcp-0.1.0/README.md +207 -0
- seleniumboot_mcp-0.1.0/pyproject.toml +37 -0
- seleniumboot_mcp-0.1.0/setup.cfg +4 -0
- seleniumboot_mcp-0.1.0/src/selenium_mcp/__init__.py +0 -0
- seleniumboot_mcp-0.1.0/src/selenium_mcp/server.py +78 -0
- seleniumboot_mcp-0.1.0/src/selenium_mcp/tools/__init__.py +0 -0
- seleniumboot_mcp-0.1.0/src/selenium_mcp/tools/assertion_tools.py +245 -0
- seleniumboot_mcp-0.1.0/src/selenium_mcp/tools/browser_tools.py +240 -0
- seleniumboot_mcp-0.1.0/src/selenium_mcp/tools/codegen_tools.py +391 -0
- seleniumboot_mcp-0.1.0/src/selenium_mcp/tools/element_tools.py +364 -0
- seleniumboot_mcp-0.1.0/src/seleniumboot_mcp.egg-info/PKG-INFO +229 -0
- seleniumboot_mcp-0.1.0/src/seleniumboot_mcp.egg-info/SOURCES.txt +19 -0
- seleniumboot_mcp-0.1.0/src/seleniumboot_mcp.egg-info/dependency_links.txt +1 -0
- seleniumboot_mcp-0.1.0/src/seleniumboot_mcp.egg-info/entry_points.txt +2 -0
- seleniumboot_mcp-0.1.0/src/seleniumboot_mcp.egg-info/requires.txt +2 -0
- seleniumboot_mcp-0.1.0/src/seleniumboot_mcp.egg-info/top_level.txt +2 -0
- seleniumboot_mcp-0.1.0/src/tools/assertion_tools.py +245 -0
- seleniumboot_mcp-0.1.0/src/tools/browser_tools.py +240 -0
- seleniumboot_mcp-0.1.0/src/tools/codegen_tools.py +391 -0
- seleniumboot_mcp-0.1.0/src/tools/element_tools.py +364 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: seleniumboot-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python MCP server for Selenium WebDriver โ browser automation and Java TestNG/JUnit5 codegen
|
|
5
|
+
Author-email: Panjatan <panjatan.tech@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/seleniumboot/selenium-mcp
|
|
8
|
+
Project-URL: Repository, https://github.com/seleniumboot/selenium-mcp
|
|
9
|
+
Project-URL: Issues, https://github.com/seleniumboot/selenium-mcp/issues
|
|
10
|
+
Keywords: selenium,mcp,test-automation,webdriver,testng,junit,model-context-protocol
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Testing
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: mcp>=1.0.0
|
|
21
|
+
Requires-Dist: selenium>=4.6.0
|
|
22
|
+
|
|
23
|
+
# Selenium MCP Server ๐ค๐
|
|
24
|
+
|
|
25
|
+
A Python-based **Model Context Protocol (MCP)** server for Selenium WebDriver automation.
|
|
26
|
+
Built for AI assistants like Claude Desktop โ with first-class support for generating
|
|
27
|
+
**Java TestNG** and **JUnit 5** test scripts.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
| Category | Tools |
|
|
34
|
+
|----------------|-------------------------------------------------------------------|
|
|
35
|
+
| **Browser** | start, navigate, screenshot, page source, title, URL, JS exec |
|
|
36
|
+
| **Elements** | click, type, find, hover, drag-drop, select, scroll, wait |
|
|
37
|
+
| **Assertions** | title, URL, text, visibility, attribute, page content, count |
|
|
38
|
+
| **Codegen** | Generate Python pytest ยท Java TestNG ยท Java JUnit 5 test scripts |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Clone
|
|
46
|
+
git clone https://github.com/yourname/selenium-mcp
|
|
47
|
+
cd selenium-mcp
|
|
48
|
+
|
|
49
|
+
# Install dependencies
|
|
50
|
+
pip install -r requirements.txt
|
|
51
|
+
|
|
52
|
+
# Or install as a package
|
|
53
|
+
pip install -e .
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**requirements.txt**
|
|
57
|
+
```
|
|
58
|
+
mcp>=1.0.0
|
|
59
|
+
selenium>=4.6.0
|
|
60
|
+
```
|
|
61
|
+
> Selenium 4.6+ ships with **Selenium Manager** โ no separate driver manager needed.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Configure Claude Desktop
|
|
66
|
+
|
|
67
|
+
Edit `claude_desktop_config.json`:
|
|
68
|
+
|
|
69
|
+
**macOS/Linux:** `~/.config/claude-desktop/config.json`
|
|
70
|
+
**Windows:** `%APPDATA%\claude-desktop\config.json`
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"selenium-mcp": {
|
|
76
|
+
"command": "python",
|
|
77
|
+
"args": ["/absolute/path/to/selenium-mcp/src/server.py"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Restart Claude Desktop.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Usage with Claude
|
|
88
|
+
|
|
89
|
+
### Browser automation
|
|
90
|
+
```
|
|
91
|
+
"Start Chrome browser, go to https://github.com, search for selenium, click the first result"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Assertion example
|
|
95
|
+
```
|
|
96
|
+
"Navigate to https://example.com and assert the page title contains 'Example Domain'"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Java codegen โ the killer feature
|
|
100
|
+
```
|
|
101
|
+
"Generate a Java TestNG test class for everything we just did"
|
|
102
|
+
```
|
|
103
|
+
Claude will produce a ready-to-run Java class with WebDriverWait, @BeforeMethod,
|
|
104
|
+
@Test, @AfterMethod โ drop it straight into your Maven/Gradle project.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Tool Reference
|
|
109
|
+
|
|
110
|
+
### Browser Tools
|
|
111
|
+
| Tool | Description |
|
|
112
|
+
|--------------------|------------------------------------------|
|
|
113
|
+
| `start_browser` | Start Chrome or Firefox |
|
|
114
|
+
| `navigate` | Go to URL |
|
|
115
|
+
| `take_screenshot` | Capture page as base64 PNG |
|
|
116
|
+
| `get_page_title` | Return page title |
|
|
117
|
+
| `get_current_url` | Return current URL |
|
|
118
|
+
| `get_page_source` | Return full HTML source |
|
|
119
|
+
| `execute_script` | Run JavaScript |
|
|
120
|
+
| `go_back/forward` | Browser history navigation |
|
|
121
|
+
| `refresh` | Reload current page |
|
|
122
|
+
| `switch_to_window` | Switch between tabs/windows |
|
|
123
|
+
| `close_browser` | Quit the browser |
|
|
124
|
+
|
|
125
|
+
### Element Tools
|
|
126
|
+
| Tool | Description |
|
|
127
|
+
|---------------------|-----------------------------------------|
|
|
128
|
+
| `find_element` | Find element, return tag/text/state |
|
|
129
|
+
| `find_elements` | Find all matching elements |
|
|
130
|
+
| `click` | Click with explicit wait |
|
|
131
|
+
| `type_text` | Clear + type into input |
|
|
132
|
+
| `get_text` | Get visible text |
|
|
133
|
+
| `get_attribute` | Get any attribute value |
|
|
134
|
+
| `select_option` | Select from `<select>` dropdown |
|
|
135
|
+
| `hover` | Mouse hover |
|
|
136
|
+
| `double_click` | Double click |
|
|
137
|
+
| `right_click` | Context menu click |
|
|
138
|
+
| `drag_and_drop` | Drag source โ target |
|
|
139
|
+
| `is_displayed` | Check visibility |
|
|
140
|
+
| `is_enabled` | Check enabled state |
|
|
141
|
+
| `wait_for_element` | Wait: visible/clickable/present/hidden |
|
|
142
|
+
| `scroll_to_element` | Scroll element into view |
|
|
143
|
+
| `clear_field` | Clear input field |
|
|
144
|
+
|
|
145
|
+
### Assertion Tools
|
|
146
|
+
| Tool | Description |
|
|
147
|
+
|----------------------------|-------------------------------------|
|
|
148
|
+
| `assert_title` | Page title equals/contains |
|
|
149
|
+
| `assert_url` | URL equals/contains |
|
|
150
|
+
| `assert_text` | Element text equals/contains |
|
|
151
|
+
| `assert_element_visible` | Element is visible |
|
|
152
|
+
| `assert_element_not_visible` | Element is hidden/absent |
|
|
153
|
+
| `assert_attribute` | Element attribute value |
|
|
154
|
+
| `assert_page_contains` | Body text contains string |
|
|
155
|
+
| `assert_element_count` | Count of matching elements |
|
|
156
|
+
|
|
157
|
+
### Codegen Tools
|
|
158
|
+
| Tool | Description |
|
|
159
|
+
|-------------------------|----------------------------------------------|
|
|
160
|
+
| `generate_python_test` | Generate pytest class from session |
|
|
161
|
+
| `generate_java_testng` | Generate Java TestNG class from session |
|
|
162
|
+
| `generate_java_junit5` | Generate Java JUnit 5 class from session |
|
|
163
|
+
| `get_session_log` | View recorded actions |
|
|
164
|
+
| `clear_session_log` | Reset the session recording |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Java Output Example
|
|
169
|
+
|
|
170
|
+
After a session: navigate โ fill login form โ click submit
|
|
171
|
+
|
|
172
|
+
```java
|
|
173
|
+
// Generated by selenium-mcp
|
|
174
|
+
package com.tests.selenium;
|
|
175
|
+
|
|
176
|
+
import org.testng.annotations.*;
|
|
177
|
+
import org.openqa.selenium.*;
|
|
178
|
+
import org.openqa.selenium.chrome.ChromeDriver;
|
|
179
|
+
import org.openqa.selenium.support.ui.*;
|
|
180
|
+
import java.time.Duration;
|
|
181
|
+
|
|
182
|
+
public class LoginTest {
|
|
183
|
+
|
|
184
|
+
private WebDriver driver;
|
|
185
|
+
private WebDriverWait wait;
|
|
186
|
+
|
|
187
|
+
@BeforeMethod
|
|
188
|
+
public void setUp() {
|
|
189
|
+
driver = new ChromeDriver();
|
|
190
|
+
driver.manage().window().maximize();
|
|
191
|
+
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@AfterMethod
|
|
195
|
+
public void tearDown() {
|
|
196
|
+
if (driver != null) driver.quit();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@Test
|
|
200
|
+
public void recordedFlowTest() {
|
|
201
|
+
driver.get("https://app.example.com/login");
|
|
202
|
+
WebElement field = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#email")));
|
|
203
|
+
field.clear();
|
|
204
|
+
field.sendKeys("user@example.com");
|
|
205
|
+
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button[type='submit']"))).click();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Logs
|
|
213
|
+
|
|
214
|
+
Debug logs: `/tmp/selenium-mcp.log`
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Roadmap
|
|
219
|
+
|
|
220
|
+
- [ ] Self-healing locators (TestHeal integration)
|
|
221
|
+
- [ ] TestFlow export
|
|
222
|
+
- [ ] Page Object Model generation
|
|
223
|
+
- [ ] Cucumber/Gherkin step generation
|
|
224
|
+
- [ ] CI/CD config generator (GitHub Actions, Jenkins)
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
MIT
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Selenium MCP Server ๐ค๐
|
|
2
|
+
|
|
3
|
+
A Python-based **Model Context Protocol (MCP)** server for Selenium WebDriver automation.
|
|
4
|
+
Built for AI assistants like Claude Desktop โ with first-class support for generating
|
|
5
|
+
**Java TestNG** and **JUnit 5** test scripts.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
| Category | Tools |
|
|
12
|
+
|----------------|-------------------------------------------------------------------|
|
|
13
|
+
| **Browser** | start, navigate, screenshot, page source, title, URL, JS exec |
|
|
14
|
+
| **Elements** | click, type, find, hover, drag-drop, select, scroll, wait |
|
|
15
|
+
| **Assertions** | title, URL, text, visibility, attribute, page content, count |
|
|
16
|
+
| **Codegen** | Generate Python pytest ยท Java TestNG ยท Java JUnit 5 test scripts |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Clone
|
|
24
|
+
git clone https://github.com/yourname/selenium-mcp
|
|
25
|
+
cd selenium-mcp
|
|
26
|
+
|
|
27
|
+
# Install dependencies
|
|
28
|
+
pip install -r requirements.txt
|
|
29
|
+
|
|
30
|
+
# Or install as a package
|
|
31
|
+
pip install -e .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**requirements.txt**
|
|
35
|
+
```
|
|
36
|
+
mcp>=1.0.0
|
|
37
|
+
selenium>=4.6.0
|
|
38
|
+
```
|
|
39
|
+
> Selenium 4.6+ ships with **Selenium Manager** โ no separate driver manager needed.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Configure Claude Desktop
|
|
44
|
+
|
|
45
|
+
Edit `claude_desktop_config.json`:
|
|
46
|
+
|
|
47
|
+
**macOS/Linux:** `~/.config/claude-desktop/config.json`
|
|
48
|
+
**Windows:** `%APPDATA%\claude-desktop\config.json`
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"selenium-mcp": {
|
|
54
|
+
"command": "python",
|
|
55
|
+
"args": ["/absolute/path/to/selenium-mcp/src/server.py"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Restart Claude Desktop.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Usage with Claude
|
|
66
|
+
|
|
67
|
+
### Browser automation
|
|
68
|
+
```
|
|
69
|
+
"Start Chrome browser, go to https://github.com, search for selenium, click the first result"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Assertion example
|
|
73
|
+
```
|
|
74
|
+
"Navigate to https://example.com and assert the page title contains 'Example Domain'"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Java codegen โ the killer feature
|
|
78
|
+
```
|
|
79
|
+
"Generate a Java TestNG test class for everything we just did"
|
|
80
|
+
```
|
|
81
|
+
Claude will produce a ready-to-run Java class with WebDriverWait, @BeforeMethod,
|
|
82
|
+
@Test, @AfterMethod โ drop it straight into your Maven/Gradle project.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Tool Reference
|
|
87
|
+
|
|
88
|
+
### Browser Tools
|
|
89
|
+
| Tool | Description |
|
|
90
|
+
|--------------------|------------------------------------------|
|
|
91
|
+
| `start_browser` | Start Chrome or Firefox |
|
|
92
|
+
| `navigate` | Go to URL |
|
|
93
|
+
| `take_screenshot` | Capture page as base64 PNG |
|
|
94
|
+
| `get_page_title` | Return page title |
|
|
95
|
+
| `get_current_url` | Return current URL |
|
|
96
|
+
| `get_page_source` | Return full HTML source |
|
|
97
|
+
| `execute_script` | Run JavaScript |
|
|
98
|
+
| `go_back/forward` | Browser history navigation |
|
|
99
|
+
| `refresh` | Reload current page |
|
|
100
|
+
| `switch_to_window` | Switch between tabs/windows |
|
|
101
|
+
| `close_browser` | Quit the browser |
|
|
102
|
+
|
|
103
|
+
### Element Tools
|
|
104
|
+
| Tool | Description |
|
|
105
|
+
|---------------------|-----------------------------------------|
|
|
106
|
+
| `find_element` | Find element, return tag/text/state |
|
|
107
|
+
| `find_elements` | Find all matching elements |
|
|
108
|
+
| `click` | Click with explicit wait |
|
|
109
|
+
| `type_text` | Clear + type into input |
|
|
110
|
+
| `get_text` | Get visible text |
|
|
111
|
+
| `get_attribute` | Get any attribute value |
|
|
112
|
+
| `select_option` | Select from `<select>` dropdown |
|
|
113
|
+
| `hover` | Mouse hover |
|
|
114
|
+
| `double_click` | Double click |
|
|
115
|
+
| `right_click` | Context menu click |
|
|
116
|
+
| `drag_and_drop` | Drag source โ target |
|
|
117
|
+
| `is_displayed` | Check visibility |
|
|
118
|
+
| `is_enabled` | Check enabled state |
|
|
119
|
+
| `wait_for_element` | Wait: visible/clickable/present/hidden |
|
|
120
|
+
| `scroll_to_element` | Scroll element into view |
|
|
121
|
+
| `clear_field` | Clear input field |
|
|
122
|
+
|
|
123
|
+
### Assertion Tools
|
|
124
|
+
| Tool | Description |
|
|
125
|
+
|----------------------------|-------------------------------------|
|
|
126
|
+
| `assert_title` | Page title equals/contains |
|
|
127
|
+
| `assert_url` | URL equals/contains |
|
|
128
|
+
| `assert_text` | Element text equals/contains |
|
|
129
|
+
| `assert_element_visible` | Element is visible |
|
|
130
|
+
| `assert_element_not_visible` | Element is hidden/absent |
|
|
131
|
+
| `assert_attribute` | Element attribute value |
|
|
132
|
+
| `assert_page_contains` | Body text contains string |
|
|
133
|
+
| `assert_element_count` | Count of matching elements |
|
|
134
|
+
|
|
135
|
+
### Codegen Tools
|
|
136
|
+
| Tool | Description |
|
|
137
|
+
|-------------------------|----------------------------------------------|
|
|
138
|
+
| `generate_python_test` | Generate pytest class from session |
|
|
139
|
+
| `generate_java_testng` | Generate Java TestNG class from session |
|
|
140
|
+
| `generate_java_junit5` | Generate Java JUnit 5 class from session |
|
|
141
|
+
| `get_session_log` | View recorded actions |
|
|
142
|
+
| `clear_session_log` | Reset the session recording |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Java Output Example
|
|
147
|
+
|
|
148
|
+
After a session: navigate โ fill login form โ click submit
|
|
149
|
+
|
|
150
|
+
```java
|
|
151
|
+
// Generated by selenium-mcp
|
|
152
|
+
package com.tests.selenium;
|
|
153
|
+
|
|
154
|
+
import org.testng.annotations.*;
|
|
155
|
+
import org.openqa.selenium.*;
|
|
156
|
+
import org.openqa.selenium.chrome.ChromeDriver;
|
|
157
|
+
import org.openqa.selenium.support.ui.*;
|
|
158
|
+
import java.time.Duration;
|
|
159
|
+
|
|
160
|
+
public class LoginTest {
|
|
161
|
+
|
|
162
|
+
private WebDriver driver;
|
|
163
|
+
private WebDriverWait wait;
|
|
164
|
+
|
|
165
|
+
@BeforeMethod
|
|
166
|
+
public void setUp() {
|
|
167
|
+
driver = new ChromeDriver();
|
|
168
|
+
driver.manage().window().maximize();
|
|
169
|
+
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@AfterMethod
|
|
173
|
+
public void tearDown() {
|
|
174
|
+
if (driver != null) driver.quit();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@Test
|
|
178
|
+
public void recordedFlowTest() {
|
|
179
|
+
driver.get("https://app.example.com/login");
|
|
180
|
+
WebElement field = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#email")));
|
|
181
|
+
field.clear();
|
|
182
|
+
field.sendKeys("user@example.com");
|
|
183
|
+
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button[type='submit']"))).click();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Logs
|
|
191
|
+
|
|
192
|
+
Debug logs: `/tmp/selenium-mcp.log`
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Roadmap
|
|
197
|
+
|
|
198
|
+
- [ ] Self-healing locators (TestHeal integration)
|
|
199
|
+
- [ ] TestFlow export
|
|
200
|
+
- [ ] Page Object Model generation
|
|
201
|
+
- [ ] Cucumber/Gherkin step generation
|
|
202
|
+
- [ ] CI/CD config generator (GitHub Actions, Jenkins)
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "seleniumboot-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A Python MCP server for Selenium WebDriver โ browser automation and Java TestNG/JUnit5 codegen"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Panjatan", email = "panjatan.tech@gmail.com" }]
|
|
13
|
+
keywords = ["selenium", "mcp", "test-automation", "webdriver", "testng", "junit", "model-context-protocol"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Topic :: Software Development :: Testing",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"mcp>=1.0.0",
|
|
25
|
+
"selenium>=4.6.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/seleniumboot/selenium-mcp"
|
|
30
|
+
Repository = "https://github.com/seleniumboot/selenium-mcp"
|
|
31
|
+
Issues = "https://github.com/seleniumboot/selenium-mcp/issues"
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
seleniumboot-mcp = "selenium_mcp.server:main"
|
|
35
|
+
|
|
36
|
+
[tool.setuptools.packages.find]
|
|
37
|
+
where = ["src"]
|
|
File without changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Selenium MCP Server
|
|
3
|
+
A Python-based MCP server for Selenium WebDriver automation.
|
|
4
|
+
Serves both Python and Java test automation users.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
import tempfile
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from mcp.server import Server
|
|
12
|
+
from mcp.server.stdio import stdio_server
|
|
13
|
+
from mcp.types import Tool, TextContent, ImageContent
|
|
14
|
+
|
|
15
|
+
from selenium_mcp.tools.browser_tools import BrowserTools
|
|
16
|
+
from selenium_mcp.tools.element_tools import ElementTools
|
|
17
|
+
from selenium_mcp.tools.assertion_tools import AssertionTools
|
|
18
|
+
from selenium_mcp.tools.codegen_tools import CodegenTools
|
|
19
|
+
|
|
20
|
+
_log_path = Path(tempfile.gettempdir()) / "selenium-mcp.log"
|
|
21
|
+
logging.basicConfig(
|
|
22
|
+
filename=str(_log_path),
|
|
23
|
+
level=logging.DEBUG,
|
|
24
|
+
format="%(asctime)s [%(levelname)s] %(message)s"
|
|
25
|
+
)
|
|
26
|
+
log = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
app = Server("selenium-mcp")
|
|
29
|
+
|
|
30
|
+
browser = BrowserTools()
|
|
31
|
+
element = ElementTools(browser)
|
|
32
|
+
assertion = AssertionTools(browser)
|
|
33
|
+
codegen = CodegenTools(browser)
|
|
34
|
+
|
|
35
|
+
ALL_TOOLS = [
|
|
36
|
+
*browser.get_tools(),
|
|
37
|
+
*element.get_tools(),
|
|
38
|
+
*assertion.get_tools(),
|
|
39
|
+
*codegen.get_tools(),
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
TOOL_HANDLERS = {
|
|
43
|
+
**browser.get_handlers(),
|
|
44
|
+
**element.get_handlers(),
|
|
45
|
+
**assertion.get_handlers(),
|
|
46
|
+
**codegen.get_handlers(),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@app.list_tools()
|
|
51
|
+
async def list_tools() -> list[Tool]:
|
|
52
|
+
return ALL_TOOLS
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@app.call_tool()
|
|
56
|
+
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
|
57
|
+
log.info(f"Tool called: {name} | args: {arguments}")
|
|
58
|
+
handler = TOOL_HANDLERS.get(name)
|
|
59
|
+
if not handler:
|
|
60
|
+
return [TextContent(type="text", text=f"Unknown tool: {name}")]
|
|
61
|
+
try:
|
|
62
|
+
result = await handler(arguments)
|
|
63
|
+
if isinstance(result, str) and result.startswith("screenshot:base64:"):
|
|
64
|
+
b64 = result[len("screenshot:base64:"):]
|
|
65
|
+
return [ImageContent(type="image", data=b64, mimeType="image/png")]
|
|
66
|
+
return [TextContent(type="text", text=result)]
|
|
67
|
+
except Exception as e:
|
|
68
|
+
log.error(f"Tool error [{name}]: {e}")
|
|
69
|
+
return [TextContent(type="text", text=f"Error: {str(e)}")]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def main():
|
|
73
|
+
async with stdio_server() as (r, w):
|
|
74
|
+
await app.run(r, w, app.create_initialization_options())
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
asyncio.run(main())
|
|
File without changes
|