Skip to content

Commit 1aa89a9

Browse files
committed
Update the MCP Server
1 parent 7ea1bbf commit 1aa89a9

4 files changed

Lines changed: 106 additions & 88 deletions

File tree

‎mcp_servers/README.md‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,23 +146,31 @@ claude mcp add seleniumbase-mcp -- uv run seleniumbase-mcp
146146

147147
(run from inside this folder, for the same reason as above.)
148148

149+
## Selectors
150+
151+
Most tools accept a `selector` argument. Behavior varies slightly by tool, so check a tool's own docstring when it matters:
152+
153+
- **CSS selectors** are preferred and supported by every tool that takes a selector.
154+
- **XPath** is accepted by several (not all) tools. Some tools go through SeleniumBase's XPath-to-CSS conversion first; expressions that can't be converted (e.g. `contains(...)`) aren't supported by those tools.
155+
- **SeleniumBase's visible-text selector** syntax, e.g. `a:contains("Sign in")`, is accepted by several tools (including `click`, when not using `all_matches`) but not all of them — `find_elements`, for example, only supports CSS/XPath.
156+
149157
## Tools exposed
150158

151-
Tools here are grouped around a shared `selector` convention: `selector` args accept a CSS selector, or visible text (e.g. `a:contains("Sign in")`). Several near-identical one-off tools (e.g. separate click/hover/drag/wait/cookie/storage variants) have been consolidated into a single tool with a `mode`/`action`/`state`/`check` parameter, so there are fewer near-neighbor tools to disambiguate between while every underlying capability stays available.
159+
Tools here are grouped around a shared `selector` convention. Several near-identical one-off tools (e.g. separate click/hover/drag/wait/cookie/storage variants) have been consolidated into a single tool with a `mode`/`action`/`state`/`check` parameter, so there are fewer near-neighbor tools to disambiguate between while every underlying capability stays available.
152160

153161
| Group | Tool(s) |
154162
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
155163
| Session | `start_browser(url, headless, use_chromium, browser_executable_path, incognito, guest, ad_block, proxy)`, `close_browser` |
156164
| Navigation | `navigate`, `manage_history(action: back/forward/reload/list)`, `get_page_info` (running status, url, title, origin, user agent in one call) |
157-
| Finding & reading | `find_elements(selector, timeout, include_html)`, `get_content(selector, output_format: text/html/urls, include_shadow_dom)`, `get_attributes`, `check_condition(check: present/visible, text)` |
158-
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_action(selector1, selector2, action: none/click/drag_and_drop)`, `type_text(mode: fill_input/append/fast_type/set_value/clear_only)`, `select_option(by: text/value/index)`, `focus(action: scroll_to_element/focus/highlight)` |
165+
| Finding & reading | `find_elements(selector, timeout, include_html)`, `get_content(selector, output_format: text/html/urls, timeout)`, `get_attributes(selector, attribute, timeout)`, `check_condition(check: present/visible, text)` |
166+
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_action(selector1, selector2, action: none/click/drag_and_drop)`, `type_text(mode: fill_input/append/fast_type/set_value/clear_only)`, `select_option(by: text/value/index)`, `focus(action: scroll_to_element/focus/highlight, timeout)` |
159167
| Waiting | `wait_for(state: present/visible/not_visible/absent/seconds_passed, text)` |
160168
| Assertions | `assert_condition(check: element_present/element_visible/text_visible/title/url/url_contains)` |
161169
| Cookies & storage | `manage_cookies(action: get_all/clear/save/load)`, `manage_storage(storage: local/session, action: get/set)` |
162170
| Scrolling | `scroll(direction: up/down/top/bottom, amount)` |
163171
| Windows & tabs | `manage_window(action: get_rect/set_rect/maximize/minimize)`, `manage_tabs(action: list/open/switch/switch_newest/close_active)` |
164172
| Captcha | `solve_captcha` |
165-
| Output & misc | `save_output(format: screenshot/html/pdf)`, `run_javascript`, |
173+
| Output & misc | `save_output(format: screenshot/html/pdf)`, `run_javascript` |
166174

167175
## Design notes / things to adapt for your use case
168176

@@ -178,19 +186,25 @@ Tools here are grouped around a shared `selector` convention: `selector` args ac
178186

179187
- **Navigation and history live in one tool: `manage_history`.** What used to be `navigate_history` is now `manage_history`, and it gained a fourth action: `"list"`, which returns the browser's navigation history as `{"position": <0-indexed current entry>, "entries": [...]}`, where each entry has `id`, `url`, `user_typed_url`, `title`, and `transition_type`. `"back"`, `"forward"`, and `"reload"` behave as before. This is the only way to retrieve navigation history now — `get_page_info` doesn't return it.
180188

181-
- **Content reading is consolidated into one tool.** `get_content` replaces what used to be three separate reads: page/element text, page/element HTML, and page-linked URLs. Pick the mode with `output_format` (`"text"`, `"html"`, or `"urls"`) rather than calling a dedicated `get_page_content` or `get_all_urls` tool — those no longer exist. Likewise, there's no standalone `get_user_agent` tool anymore; the User-Agent string is one of the fields returned by `get_page_info`.
189+
- **`get_content` always reads from an element, not the whole document.** `selector` now defaults to `"body"` rather than `None`/whole-page, and there's no `include_shadow_dom` option anymore — `get_content` no longer calls `get_page_source` at all. `output_format="html"` returns a single element's outer HTML (`get_element_html`), and `output_format="urls"` returns URLs discovered within that element (`get_all_urls(selector=...)`), rather than the full raw page source including shadow roots. If you need the complete page source (shadow DOM included), that capability isn't exposed by any tool here currently. `get_content` also gained a `timeout` parameter (default 5s) for waiting on the target element.
190+
191+
- **`get_attributes` and `focus` now take a `timeout`.** Both default to 5 seconds and wait for the target element the same way most other interaction tools do; previously neither exposed a timeout.
182192

183193
- **`check_condition` is deliberately narrow.** Its `check` parameter only accepts `"present"` or `"visible"` — there's no built-in `"count"` check anymore; call `find_elements` and read the returned `count` field instead. Passing `text` checks whether that text is visible within `selector` and takes priority over `check` when both are given — so `check_condition(text="Sign in")` behaves differently from `check_condition(check="visible")`, not as two variants of the same check. Note that an empty string for `text` (or for `wait_for`'s `selector`/`text`) is treated as not provided, since both tools now branch on truthiness rather than on `is not None`.
184194

185-
- **`find_elements` defaults to a fast, non-raising lookup.** Its default `timeout` is 0.5 seconds (not 5, unlike most other tools here), and a failed lookup returns `{"count": 0, "matches": []}` instead of raising — there is no error string on a miss, just an empty result. Pass a longer `timeout` explicitly if the elements you're looking for may still be loading.
195+
- **`find_elements` catches its own lookup failures.** Its default `timeout` is 0.5 seconds (not 5, unlike most other tools here). A failed or empty lookup never raises: no matches returns `{"count": 0, "matches": []}`, and an actual lookup error (e.g. an unsupported selector) returns `{"count": 0, "matches": [], "error": "<details>"}` — the error lives inside the returned dict rather than surfacing as a top-level string from `handle_sb_errors`. Pass a longer `timeout` explicitly if the elements you're looking for may still be loading.
196+
197+
- **`wait_seconds` was folded into `wait_for`.** There's no standalone `wait_seconds` tool anymore. Use `wait_for(state="seconds_passed", timeout=<seconds>)` instead — it ignores `selector`/`text` and blocks for the full `timeout` duration. All other `wait_for` states behave as before.
198+
199+
- **Hover, click-after-hover, and drag-and-drop share one tool.** `hover_action(selector1, selector2, action)` replaces the earlier separate `hover` and `drag_and_drop` tools. `action="none"` hovers `selector1` only; `action="click"` hovers `selector1` then clicks `selector2` (useful for dropdown/submenu items revealed by hovering); `action="drag_and_drop"` drags `selector1` onto `selector2`. (`selector2` is required when `action` is `"click"` or `"drag_and_drop"`.)
186200

187-
- **Hover, clicking after hover, and drag-and-drop share one tool.** `hover_action(selector1, selector2, action)` replaces the earlier separate `hover` and `drag_and_drop` tools. `action="none"` hovers `selector1` only; `action="click"` hovers `selector1` then clicks `selector2` (useful for dropdown/submenu items revealed by hovering); `action="drag_and_drop"` drags `selector1` onto `selector2`. (`selector2` is required when `action` is `"click"` or `"drag_and_drop"`.)
201+
- **Non-activating element actions are `focus`.** What used to be `act_on_element` is now `focus(selector, action, timeout)`, with actions `scroll_to_element` (the default), `focus`, and `highlight` — note the default action is scrolling the element into view, not focusing it. None of these actions click, type into, select from, or otherwise activate the element; use `click`, `type_text`, `select_option`, or `hover_action` for that.
188202

189-
- **Non-activating element actions are `focus`.** What used to be `act_on_element` is now `focus(selector, action)`, with actions `scroll_to_element` (the default), `focus`, and `highlight` — note the default action is scrolling the element into view, not focusing it. None of these actions click, type into, select from, or otherwise activate the element; use `click`, `type_text`, `select_option`, or `hover_action` for that.
203+
- **`scroll`'s `amount` isn't capped at 100.** Relative up/down scrolling by more than 100% of the viewport height is allowed (e.g. `amount=200` scrolls roughly two viewport heights); negative amounts are rejected for `"up"`/`"down"`.
190204

191205
- **Elements don't cross the wire as handles.** In native CDP Mode, `find_element()` returns a live object with its own methods (`el.click()`, `el.get_html()`, ...). MCP tools can only return JSON-serializable data, so `find_elements` resolves each match immediately to a plain dict (`tag_name`, `text`, and optionally `html`) instead of returning a handle you could call further methods on. If you need to act on one of several matches, use `click(selector, nth=...)` (acts by position) rather than "find, then click" as two separate steps.
192206

193-
- **CAPTCHA-solving.** `solve_captcha` handles supported challenge types (e.g. Cloudflare Turnstile).
207+
- **CAPTCHA-solving.** `solve_captcha` attempts to detect and interact with several challenge types over CDP (e.g. Cloudflare Turnstile, reCAPTCHA, hCaptcha, DataDome Slider, FriendlyCaptcha), including slider-style drag interactions, without guaranteeing success.
194208

195209
- **Security.** `run_javascript` runs arbitrary JS, and `manage_storage` can expose authentication/session secrets; `manage_cookies` and `save_output` accept filenames/folders that can touch the filesystem. This server can also drive a real browser to real sites — don't expose it over an untrusted network transport; stdio + local trust (the default here) is the safe setup.
196210

‎mcp_servers/pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "seleniumbase-mcp"
3-
version = "1.3.1dev0"
3+
version = "1.3.2dev0"
44
description = "MCP server exposing SeleniumBase CDP Mode as tools for MCP clients."
55
readme = "README.md"
66
requires-python = ">=3.10"

0 commit comments

Comments
 (0)