Selenium MCP Server
Provides web automation capabilities through Selenium WebDriver, enabling AI assistants to navigate web pages, interact with elements, take screenshots, execute JavaScript, manage browser logs, and handle local storage.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Selenium MCP Servernavigate to https://example.com and take a screenshot"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Selenium MCP Server
A Model Context Protocol (MCP) server that provides web automation capabilities through Selenium WebDriver. This server allows AI assistants to interact with web pages by providing tools for navigation, element interaction, taking screenshots, and more.
Related MCP server: Algonius Browser
1.1. Quick Start
1.1.1. Using Installed Package (Recommended)
# Install
pip install mcp-server-selenium
# Run
python -m mcp_server_selenium --port 9222 --user_data_dir /tmp/chrome-debug1.1.2. Using Source Code (Development)
# Clone and setup
git clone https://github.com/PhungXuanAnh/selenium-mcp-server.git
cd selenium-mcp-server
uv sync
# Run
PYTHONPATH=src python -m mcp_server_selenium --port 9222 --user_data_dir /tmp/chrome-debug2. Features
Web Navigation: Navigate to URLs with timeout control and page readiness checking
Multiple Tabs: List, open, switch, and close browser tabs by window handle
Element Discovery & Interaction: Find elements by multiple criteria (text, class, ID, attributes, XPath) and interact with them through clicking and input value setting
Advanced Element Querying: Get single elements, multiple elements with pagination, and direct child nodes with comprehensive filtering options
Screenshots: Capture named PNG screenshots of the active tab in the default workspace location or an explicit output directory
Element Styling: Retrieve CSS styles and computed style information for any element
JavaScript Execution: Execute custom JavaScript code in browser console with optional console output capture
Browser Logging: Access console logs (with level filtering) and network request logs (with URL filtering and error filtering)
Local Storage Management: Complete CRUD operations for browser local storage (add, read, update, delete)
iFrame Support: Work with elements inside iframes using iframe ID or name targeting
XPath Support: Use XPath expressions for precise element targeting
Chrome Browser Control: Connect to existing Chrome instances or automatically start new ones
3. Available Tools
The default compact profile is documented in Compact Profile (Default).
The explicit --tool-profile legacy compatibility fallback provides the following 23
tools with their original names and call contracts.
3.1. Navigation and Page Management
navigate(url, timeout)- Navigate to a specified URL with Chrome browsercheck_page_ready(wait_seconds)- Check if the current page is fully loaded with optional waitlist_tabs()- List all browser tabs and identify the active tabopen_tab(url=None)- Open a new tab and optionally navigate it to a URLswitch_tab(handle)- Switch to a tab using a handle returned bylist_tabsclose_tab(handle=None)- Close a specific tab, or the active tab when no handle is providedtake_screenshot(file_name, directory="tmp/selenium-screenshot")- Take a screenshot of the active tab. A descriptivefile_nameis required;.pngis added when omitted. When the Agent knows its current workspace path, it should prefer an absolutedirectoryinside that workspace so the destination does not depend on the MCP server cwd. Otherwise, omitdirectoryto use the configured workspace default. Existing files receive a numeric suffix instead of being overwritten.
3.2. Element Interaction
get_an_element(text, class_name, id, attributes, element_type, in_iframe_id, in_iframe_name, return_html, xpath)- Get an element identified by various criteriaget_elements(text, class_name, id, attributes, element_type, in_iframe_id, in_iframe_name, page, page_size, return_html, xpath)- Get multiple elements with pagination supportget_direct_children(text, class_name, id, attributes, element_type, in_iframe_id, in_iframe_name, return_html, xpath, page, page_size)- Get all direct child nodes of an element with paginationclick_to_element(text, class_name, id, attributes, element_type, in_iframe_id, in_iframe_name, element_index, xpath)- Click on an element identified by various criteriaset_value_to_input_element(text, class_name, id, attributes, element_type, input_value, in_iframe_id, in_iframe_name, xpath)- Set a value to an input element
3.3. Element Styling
get_style_an_element(text, class_name, id, attributes, element_type, in_iframe_id, in_iframe_name, return_html, xpath, all_styles, computed_style)- Get style information for an element
3.4. JavaScript Execution
run_javascript_in_console(javascript_code)- Execute JavaScript without intentionally reading buffered console logsrun_javascript_and_get_console_output(javascript_code)- Drain old console logs, execute JavaScript, then return its value and newly captured console output
3.5. Browser Logs
get_console_logs(log_level)- Read and consume browser console logs with optional level filteringget_network_logs(filter_url_by_text, only_errors_log)- Read and consume performance logs as network events with optional filteringget_response(request_id)- Retrieve a response body using a request ID fromget_network_logs
3.6. Local Storage Management
local_storage_add(key, string_value, object_value, create_empty_string, create_empty_object)- Add or update a key-value pair in browser's local storagelocal_storage_read(key)- Read a value from browser's local storage by keylocal_storage_read_all()- Read all key-value pairs from browser's local storagelocal_storage_remove(key)- Remove a key-value pair from browser's local storagelocal_storage_remove_all()- Remove all key-value pairs from browser's local storage
3.7. Compact Profile (Default)
The compact profile is the default and exposes the same browser capabilities through 10
tools and a smaller tools/list payload. It remains under evaluation; use
--tool-profile legacy when an existing client still depends on the original 23 names.
Legacy removal, if ever planned, will be announced as a separate breaking lifecycle
change. Legacy names are not advertised as compact aliases because aliases would keep
their schemas in Agent context.
Start it with:
python -m mcp_server_selenium
# Explicit compatibility fallback
python -m mcp_server_selenium --tool-profile legacyAll compact calls share one browser session and global active tab. A reliable default workflow is:
tabs(list) -> navigate -> wait_for -> query_elements -> interact_element -> take_screenshotUse only fields relevant to an action. The 23 legacy names map to compact as follows:
Legacy tool | Compact call |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Query, then |
| Query, then |
|
|
|
|
| Query, then |
Compact quick example
Each line is one JSON arguments object for the workflow step in the same order:
{"action":"list"}
{"url":"https://example.com","wait_until":"network_idle","timeout":30,"quiet_ms":500}
{"condition":"element","state":"visible","selector":{"type":"css","value":"#login"},"timeout":10}
{"action":"one","selector":{"type":"css","value":"#login"}}
{"action":"click","element_ref":"el_VALUE_FROM_QUERY"}
{"file_name":"login-result","mode":"full_page"}tabs(action="list") also reports the active handle, URL/title/readyState of every
tab, Chrome and ChromeDriver versions, and the absolute download directory. open
activates its new tab; switch requires a listed handle; close accepts a handle or the
active tab but never the final tab. Serialize tab-sensitive calls.
Selectors, waits, and references
query_elements and element/text wait_for accept one discriminated selector:
{"type":"xpath","value":"//button[@type='submit']"}
{"type":"css","value":"form.login button.primary","frame":"payment-frame"}
{"type":"fields","value":{"element_type":"input","id":"email","attribute:data-test":"login-email"}}
{"type":"fields","value":{"element_type":"article","role":"article","accessible_name":"Assistant message"}}
{"type":"ref","value":"el_VALUE_FROM_QUERY"}Fields combine with AND; role and accessible_name use Selenium's computed
accessibility values. frame tries iframe ID, then name. For ordered nested traversal,
use up to eight options.scope steps; frame steps support CSS/ID/name and shadow steps
enter open shadow roots:
{"action":"one","selector":{"type":"css","value":"button.allow"},"options":{"scope":[{"type":"frame","value":"payment-frame","by":"id"},{"type":"shadow","value":"#permission-host","by":"css"}]}}XPath is supported in documents/frames; use CSS or fields inside shadow roots. Query
pages are 1-based;
the default sizes are 3 for many and 5 for children, with a maximum of 50. one
requires exactly one match and children exactly one parent. Every result element has an
opaque element_ref. Queries include hidden DOM matches and report visible separately.
Refs store locator specifications, not WebElements, and re-resolve after same-document
rerenders while the exact locator still matches one element. They expire after 1,800
seconds and become invalid after a tab/document change, full navigation, or a zero/multiple
current match; query again in those cases.
wait_for.condition supports:
Condition | Required/action fields |
| `state="interactive |
|
|
|
|
|
|
| optional |
|
|
|
|
For a selector-free text wait, the observed value is the complete
document.body.innerText. With a selector, it is every matched element's .text joined
with newline characters. Therefore match="equals" compares that entire exact string,
including browser-produced whitespace and newlines; use contains for a fragment.
Network-response waits peek without consuming diagnostic events. Take a baseline
latest_cursor from browser_logs, trigger the request, then wait after that cursor:
{"condition":"network_response","timeout":30,"options":{"cursor":120,"filters":{"url_regex":"/api/build(?:\\?|$)","method":"GET","resource_type":"Fetch","status":200},"json_predicate":{"partial":false}}}network_idle ignores long-lived EventSource/WebSocket requests but normal polling creates
fresh finite requests; declare only known polling routes in ignore_url_regexes or prefer
network_response. timeout is the deadline for the complete tool call/composed wait,
not for each poll or clause. timeout and poll_interval are seconds; quiet_ms is
milliseconds. Success and
timeout responses include elapsed time, URL, ready state, and the last observation.
navigate.wait_until accepts initiated, interactive, complete, or network_idle;
completed policies return the final URL after redirects, while initiated explicitly
reports that navigation remains pending.
Interactions, actionability, style, and artifacts
All actions except viewport/nested scroll require element_ref. Action-specific fields are:
Action | Additional fields |
| none; returns CSS/geometry/hit-test/blocker/inert/animation/scroll-ancestor diagnostics |
| optional `options.click_mode="native |
| none |
|
|
|
|
| `option_by="value |
| existing absolute or workspace-relative |
| optional container ref; direction/amount/start/end, |
Click defaults to WebDriver native click. It re-resolves the ref, centers it, waits for a
stable actionable hit-test, and retries stale/intercepted/temporarily non-interactable
states within the one overall timeout. Failure reports the covering element and reasons
such as hidden, offscreen, inert, animation, or pointer-events:none. Actions/offset and
DOM JavaScript click are explicit choices; JavaScript is never a silent fallback.
type appends by default and set_value replaces. target_kind="auto|form_control|contenteditable"
and input_mode="auto|keyboard|dom" support inputs, textareas, and ProseMirror-style
contenteditable roots. DOM rich-text insertion dispatches cancelable beforeinput, then
input/change; input_type="insertFromPaste" supplies synthetic paste semantics without
reading or changing the system clipboard. Verification is on by default and compares
.value or rendered editor text; a mismatch returns input_postcondition_failed.
ok=true means the requested browser command completed and any declared postcondition
passed. It does not assert application intent. execution reports the actual strategy and
reported events; observed separately reports URL, target state, focus/selection, bounded
DOM mutations, effect_observed, and always application_outcome="not_asserted".
scroll is server-controlled rather than a long-running page loop. It can operate on one
container ref or scan bounded nested containers, stop when a selector/ref is truly visible
by viewport hit-test, and use direction="both" for a down-then-up sweep.
get_element_style(element_ref, ...) requires one ref. return_html=true returns only
bounded inner/outer HTML and overrides the style flags. Otherwise all_styles and
computed_style independently add their bounded sections; both false returns element
metadata only.
Screenshots use mode="viewport|full_page|element"; element mode requires a ref. Names
are safe PNG basenames and collisions get numeric suffixes. Directories may be absolute
or workspace-relative without traversal. Chrome downloads default to
<workspace>/tmp/selenium-downloads; configure them with --download_dir.
Logs, JavaScript, storage, and sensitive data
Console/network log calls accept mode="peek|consume", cursor, limit (1-100), and
since_timestamp (epoch milliseconds). peek preserves returned entries; consume
removes them. Continue with next_cursor. Buffers and cursors are browser-session local
and bounded. Console levels are blank/ALL, DEBUG, INFO, WARNING, ERROR, or
SEVERE (ERROR aliases Chrome SEVERE). Network filters support URL regex, HTTP
method, resource type, request ID, and status in addition to legacy URL-text/error filters.
Correlated metadata lets response/finished events filter on original request properties.
Redaction is on by default for credentials, sensitive query values, and request
body/header text; redact=false is an explicit sensitive-data opt-in.
{"action":"console","mode":"peek","cursor":0,"limit":20,"log_level":"ERROR"}
{"action":"network","mode":"consume","cursor":0,"limit":50,"filter_url_by_text":"/api/","redact":true}
{"action":"network","mode":"peek","event_type":"response","filters":{"url_regex":"/api/build","method":"GET","resource_type":"Fetch","status":200},"redact":true}
{"action":"response","request_id":"CDP_REQUEST_ID"}Response bodies can expire or be evicted from Chrome's CDP buffer; error envelopes give a stable reason code and retry hint. Bodies themselves may contain sensitive data.
run_javascript awaits Promises and returns bounded typed values for undefined, null,
primitives, DOM elements, arrays/objects, circular/max-depth values, and exceptions.
capture_console=false never reads logs. true returns only newly generated entries and
keeps older entries in the broker. Example:
{"javascript_code":"return await Promise.resolve(document.querySelector('h1'))","capture_console":false,"timeout":30}Storage add requires key plus a value or explicit empty-value flag; object mode wins
over string mode. read/remove require key; read_all/remove_all need no extra
field. localStorage is scoped to the active page origin.
Treat screenshots, uploads, downloads, response bodies, raw logs, tabs, and localStorage
as potentially sensitive. They can contain credentials, PHI, or data from another origin
in the shared session. Use explicit artifact paths and redact=false only when authorized.
Complete compact action examples
Each line below is one complete JSON arguments object for the named tool. Replace handle, reference, request-ID, path, URL, and expected-text placeholders with observed values.
tabs
{"action":"list"}
{"action":"open","url":"https://example.com"}
{"action":"switch","handle":"TAB_HANDLE_FROM_LIST"}
{"action":"close","handle":"TAB_HANDLE_FROM_LIST"}navigate
{"url":"https://example.com","wait_until":"initiated","timeout":30}
{"url":"https://example.com","wait_until":"interactive","timeout":30}
{"url":"https://example.com","wait_until":"complete","timeout":30}
{"url":"https://example.com","wait_until":"network_idle","timeout":30,"quiet_ms":500}wait_for
{"condition":"ready","state":"complete","timeout":10}
{"condition":"url","value":"/dashboard","match":"contains","timeout":10}
{"condition":"element","state":"visible","selector":{"type":"css","value":"#login"},"timeout":10}
{"condition":"text","state":"present","value":"Welcome","selector":{"type":"css","value":"main"},"match":"contains","timeout":10}
{"condition":"network_idle","quiet_ms":500,"timeout":10}
{"condition":"network_idle","quiet_ms":500,"timeout":10,"options":{"ignore_url_regexes":["/api/poll(?:\\?|$)"]}}
{"condition":"network_response","timeout":30,"options":{"cursor":120,"filters":{"url_regex":"/api/build","method":"GET","status":200},"json_predicate":{"partial":false}}}
{"condition":"all","timeout":30,"options":{"conditions":[{"condition":"element","state":"visible","selector":{"type":"css","value":"main"}},{"condition":"network_response","options":{"cursor":120,"filters":{"url_regex":"/api/build"}}}]}}
{"condition":"any","timeout":30,"options":{"conditions":[{"condition":"text","state":"present","value":"Done"},{"condition":"url","value":"/complete"}]}}query_elements
{"action":"one","selector":{"type":"css","value":"#login"}}
{"action":"many","selector":{"type":"fields","value":{"element_type":"button"}},"page":1,"page_size":10}
{"action":"children","selector":{"type":"ref","value":"el_PARENT_FROM_QUERY"},"page":1,"page_size":10}
{"action":"one","selector":{"type":"fields","value":{"element_type":"article","role":"article","accessible_name":"Assistant message"}}}
{"action":"one","selector":{"type":"css","value":"button.allow"},"options":{"scope":[{"type":"frame","value":"app-frame","by":"id"},{"type":"shadow","value":"#gate-host"}]}}interact_element
{"action":"inspect","element_ref":"el_FROM_QUERY"}
{"action":"click","element_ref":"el_FROM_QUERY"}
{"action":"click","element_ref":"el_FROM_QUERY","options":{"click_mode":"actions","offset":{"x":0,"y":0},"stability_ms":100}}
{"action":"click","element_ref":"el_FROM_QUERY","options":{"click_mode":"javascript"}}
{"action":"clear","element_ref":"el_FROM_QUERY"}
{"action":"type","element_ref":"el_FROM_QUERY","input_value":"hello"}
{"action":"set_value","element_ref":"el_FROM_QUERY","input_value":"hello"}
{"action":"set_value","element_ref":"el_FROM_QUERY","input_value":"hello","options":{"target_kind":"contenteditable","input_mode":"auto","clear_existing":true,"verify_after_input":true}}
{"action":"press_key","element_ref":"el_FROM_QUERY","key":"ENTER"}
{"action":"select_option","element_ref":"el_FROM_QUERY","option_by":"value","option_value":"active"}
{"action":"hover","element_ref":"el_FROM_QUERY"}
{"action":"scroll_into_view","element_ref":"el_FROM_QUERY"}
{"action":"scroll","element_ref":"el_SCROLL_CONTAINER","timeout":10,"options":{"direction":"down","amount":400,"until_visible":{"type":"ref","value":"el_TARGET"},"max_steps":20}}
{"action":"scroll","timeout":10,"options":{"direction":"both","amount":500,"until_visible":{"type":"css","value":"button.allow"},"include_nested_scroll_containers":true,"max_steps":30}}
{"action":"upload_file","element_ref":"el_FROM_QUERY","file_path":"/absolute/path/to/file.txt"}take_screenshot
{"file_name":"page","mode":"viewport"}
{"file_name":"full-page","mode":"full_page"}
{"file_name":"component","mode":"element","element_ref":"el_FROM_QUERY"}browser_logs
{"action":"console","mode":"peek","cursor":0,"limit":20,"log_level":"ERROR"}
{"action":"network","mode":"peek","cursor":0,"limit":20,"event_type":"response","filter_url_by_text":"/api/","redact":true}
{"action":"network","mode":"peek","event_type":"response","filters":{"url_regex":"/api/build","method":"GET","resource_type":"Fetch","status":200},"redact":true}
{"action":"response","request_id":"CDP_REQUEST_ID"}local_storage
{"action":"add","key":"settings","object_value":{"theme":"dark"}}
{"action":"read","key":"settings"}
{"action":"remove","key":"settings"}
{"action":"read_all"}
{"action":"remove_all"}get_element_style
{"element_ref":"el_FROM_QUERY","all_styles":false,"computed_style":false}
{"element_ref":"el_FROM_QUERY","all_styles":true,"computed_style":true}
{"element_ref":"el_FROM_QUERY","return_html":true}run_javascript
{"javascript_code":"return document.title","capture_console":false,"timeout":30}
{"javascript_code":"console.warn('probe'); return location.href","capture_console":true,"timeout":30}4. Installation
4.1. Prerequisites
Python 3.10 or higher
Chrome browser installed
4.2. Installation Options
You can use this MCP server in two ways:
4.2.1. Option A: Install as Python Package (Recommended)
Install directly from PyPI:
pip install mcp-server-seleniumOr using uv:
uv add mcp-server-selenium4.2.2. Option B: Run from Source Code
Clone this repository:
git clone https://github.com/PhungXuanAnh/selenium-mcp-server.git
cd selenium-mcp-serverInstall dependencies using uv:
uv syncOr using pip with virtual environment:
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -e .4.3. Chrome Setup
The MCP server can work with Chrome in two ways:
Connect to existing Chrome instance (recommended): Start Chrome with debugging enabled:
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debugAuto-start Chrome: The server can automatically start Chrome if no instance is found.
5. Usage
5.1. Running the MCP Server
5.1.1. Option A: From Installed Package
After installing via pip/uv, you can run the server directly:
# Basic usage with the default 10-tool compact surface
python -m mcp_server_selenium
# Use the original 23 tool names for compatibility
python -m mcp_server_selenium --tool-profile legacy
# With custom Chrome debugging port and user data directory
python -m mcp_server_selenium --port 9222 --user_data_dir /tmp/chrome-debug
# With verbose logging
python -m mcp_server_selenium --port 9222 --user_data_dir /tmp/chrome-debug -v
# Using the installed command (if available)
selenium-mcp-server --port 9222 --user_data_dir /tmp/chrome-debug -v5.1.2. Option B: From Source Code
When running from source, ensure the Python path includes the src directory:
# Navigate to the project directory
cd /path/to/selenium-mcp-server
# Activate virtual environment (if using one)
source .venv/bin/activate
# Run with proper Python path
PYTHONPATH=src python -m mcp_server_selenium --port 9222 --user_data_dir /tmp/chrome-debug -v
# Or using uv (recommended for development)
uv run python -m mcp_server_selenium --port 9222 --user_data_dir /tmp/chrome-debug -v5.2. Using MCP Inspector for Testing
5.2.1. Start Inspector Server
For development and testing, you can use the MCP inspector:
From Source Code:
# Using uv (recommended)
uv run mcp dev src/mcp_server_selenium/__main__.py
# Or with make command
make inspector
# With custom options
uv run mcp dev src/mcp_server_selenium/__main__.py --port 9222 --user_data_dir /tmp/chrome-debug --verboseFrom Installed Package:
# Create a wrapper script or use directly
mcp dev python -m mcp_server_selenium5.2.2. Access Inspector Interface
Open your browser and navigate to: http://127.0.0.1:6274/#tools

Check logs:
tailf /tmp/selenium-mcp.log5.2.3. Command Line Options
--port: Chrome remote debugging port (default: 9222)--user_data_dir: Chrome user data directory (default: auto-generated in /tmp)--workspace_root: Base directory for relative screenshot directories (default: the server startup directory). It is optional; absolute screenshot directories do not use it.--tool-profile: Agent-visible tool surface:compact(default) orlegacycompatibility fallback--download_dir: Chrome download directory; defaults to<workspace_root>/tmp/selenium-downloads-v, --verbose: Increase verbosity (use multiple times for more details)
5.3. Using with MCP Clients
The server communicates via stdio and follows the Model Context Protocol specification. You can integrate it with MCP-compatible AI assistants or clients.
5.3.1. Configuration Examples
For Claude Desktop (claude_desktop_config.json):
Using installed package:
{
"mcpServers": {
"selenium": {
"command": "python",
"args": [
"-m", "mcp_server_selenium",
"--port", "9222",
"--user_data_dir", "/tmp/chrome-debug-claude"
],
"env": {}
}
}
}For VS Code Copilot (.vscode/mcp.json):
Using installed package:
{
"servers": {
"selenium-installed": {
"command": "python",
"args": [
"-m", "mcp_server_selenium",
"--user_data_dir=/home/user/.config/google-chrome-selenium-mcp",
"--port=9225"
]
}
}
}Using source code directly:
{
"servers": {
"selenium-source": {
"command": "/path/to/selenium-mcp-server/.venv/bin/python",
"args": [
"-m", "mcp_server_selenium",
"--user_data_dir=/home/user/.config/google-chrome-selenium-mcp-source",
"--workspace_root=/path/to/workspace",
"--port=9226"
],
"env": {
"PYTHONPATH": "/path/to/selenium-mcp-server/src"
}
}
}
}Alternative source code configuration using full path:
{
"servers": {
"selenium-source-alt": {
"command": "/path/to/selenium-mcp-server/.venv/bin/python",
"args": [
"/path/to/selenium-mcp-server/src/mcp_server_selenium/__main__.py",
"--user_data_dir=/home/user/.config/google-chrome-selenium-mcp-alt",
"--port=9227"
]
}
}
}Omit --tool-profile to use the default compact surface. Add "--tool-profile", "legacy" to a client's server args only when it requires the original 23 tool names.
5.3.2. Debug
VS Code Copilot MCP Status:
If you open the .vscode/mcp.json file, you can see the MCP server status at the bottom of VS Code.

View MCP Logs:
In VS Code: Open Command Palette → "Developer: Show Logs..." → "MCP: selenium"
Check log file:
tail -f /tmp/selenium-mcp.log
6. Examples
6.1. Basic Web Automation
Navigate to a website:
Tool:
navigateURL:
https://example.com
Take a screenshot:
Tool:
take_screenshotFile name:
example-homeDirectory: prefer
<absolute-workspace-path>/tmp/selenium-screenshot; omit it when the workspace path is unavailableResult: Screenshot saved to
<absolute-workspace-path>/tmp/selenium-screenshot/example-home.png
Fill a form:
Legacy tool:
set_value_to_input_elementArguments:
xpath="//*[@id='email']",input_value="user@example.com"
Click a button:
Legacy tool:
click_to_elementArguments:
xpath="//button[@type='submit']"
Execute JavaScript:
Tool:
run_javascript_in_consoleCode:
return document.title;Result: Returns the page title
JavaScript with console output:
Tool:
run_javascript_and_get_console_outputCode:
console.log('Hello from browser'); return window.location.href;Result: Shows both console output and return value
6.2. Advanced Usage
Check page loading: Use
check_page_ready; query the target again when dynamic content is expectedGet page information: Use
run_javascript_in_consolewith explicit return expressionsElement inspection: Use
get_an_element,get_elements, orget_style_an_elementJavaScript automation: Use
run_javascript_in_consolefor complex DOM manipulation and data extractionJavaScript debugging: Use
run_javascript_and_get_console_outputto capture console logs for debugging
6.2.1. JavaScript Examples
Extract page data:
// Tool: run_javascript_in_console
var links = Array.from(document.querySelectorAll('a')).slice(0, 5).map(a => ({
text: a.textContent.trim(),
href: a.href
}));
return links;Page performance monitoring:
// Tool: run_javascript_and_get_console_output
console.time('Page Analysis');
var stats = {
title: document.title,
links: document.querySelectorAll('a').length,
images: document.querySelectorAll('img').length,
scripts: document.querySelectorAll('script').length
};
console.timeEnd('Page Analysis');
console.log('Page stats:', stats);
return stats;Form automation:
// Tool: run_javascript_in_console
document.querySelector('#username').value = 'testuser';
document.querySelector('#password').value = 'password123';
document.querySelector('#login-form').submit();
return 'Form submitted successfully';7. Logging
The server logs all operations to /tmp/selenium-mcp.log with rotation. Use the -v flag to increase console verbosity:
-v: INFO level logging-vv: DEBUG level logging
8. Troubleshooting
8.1. Common Issues
8.1.1. Installation-Related Issues
Package not found (installed package):
# Verify installation
pip list | grep mcp-server-selenium
# or
python -c "import mcp_server_selenium; print('OK')"Module not found (source code):
# Ensure PYTHONPATH is set correctly
export PYTHONPATH=/path/to/selenium-mcp-server/src
# or run from project root with:
PYTHONPATH=src python -m mcp_server_selenium8.1.2. Runtime Issues
Chrome not starting: Ensure Chrome is installed and accessible from PATH
Port conflicts: Use a different port with
--portoptionPermission errors: Ensure the user data directory is writable
Element not found: Increase wait times or use more specific selectors
JavaScript execution errors: Check browser console for syntax errors or security restrictions
Console output not captured: Ensure the JavaScript code runs successfully before checking console logs
8.1.3. Configuration Issues
MCP Client Connection Problems:
Verify the command path is correct (use
which pythonto find Python executable)For source code: Ensure PYTHONPATH environment variable is set
For installed package: Ensure the package is installed in the same Python environment as the MCP client
Check MCP client logs for detailed error messages
9. Architecture
FastMCP: Uses the FastMCP framework for MCP protocol implementation
Selenium WebDriver: Chrome WebDriver for browser automation
Synchronous Design: All operations are synchronous for reliability
Chrome DevTools Protocol: Connects to Chrome via remote debugging protocol
10. Contributing
Fork the repository
Create a feature branch
Make your changes
Add tests if applicable
Submit a pull request
10.1. Testing
Run the focused tests without starting Chrome:
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests -p "test_*.py" -vRun the MCP stdio end-to-end test, which starts the real server and Chrome with an isolated temporary profile:
.venv/bin/python tests/mcp_stdio_e2e.py -v11. Support
For issues and questions:
Create an issue in the repository
Check the logs at
/tmp/selenium-mcp.logUse verbose logging for debugging
12. Documentation
See Available Tools, including the complete compact migration table, and Examples.
13. Reference
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for Mint — AI-powered QA that runs your app in a real browser on every PR.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
Hosted MCP server connecting AI assistants to 9,000+ apps and 40,000+ actions via Zapier.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceAn MCP Server that enables AI assistants to interact with your local browsers.3,60754MIT

Algonius Browserofficial
AlicenseNot gradedqualityCmaintenanceAn open-source MCP server that provides browser automation capabilities to external AI systems, enabling navigation, DOM interaction, and web content extraction.20Apache 2.0- AlicenseAqualityCmaintenanceExposes Selenium WebDriver as an MCP server, enabling AI agents and LLMs to control real browsers for automation tasks like navigation, element interaction, and screenshot capture.223MIT
- AlicenseAqualityDmaintenanceA MCP server that gives AI assistants full browser control, enabling navigation, clicking, form filling, and screenshots via any MCP client.8MIT
Appeared in Searches
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/PhungXuanAnh/selenium-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server