seleniumbase-mcp 1.2.2__tar.gz → 1.2.4__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.
- {seleniumbase_mcp-1.2.2/seleniumbase_mcp.egg-info → seleniumbase_mcp-1.2.4}/PKG-INFO +6 -6
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/README.md +2 -2
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/cdp_server.py +166 -111
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/driver_server.py +32 -9
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/pyproject.toml +1 -1
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/sb_server.py +20 -15
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4/seleniumbase_mcp.egg-info}/PKG-INFO +6 -6
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/seleniumbase_mcp.egg-info/requires.txt +3 -3
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/setup.py +4 -4
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/tests/test_mcp.py +21 -10
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/LICENSE +0 -0
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/seleniumbase_mcp.egg-info/SOURCES.txt +0 -0
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/seleniumbase_mcp.egg-info/dependency_links.txt +0 -0
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/seleniumbase_mcp.egg-info/entry_points.txt +0 -0
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/seleniumbase_mcp.egg-info/top_level.txt +0 -0
- {seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seleniumbase-mcp
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: MCP servers exposing SeleniumBase as tools for MCP clients.
|
|
5
5
|
Home-page: https://github.com/seleniumbase/seleniumbase-mcp
|
|
6
6
|
Author: Michael Mintz
|
|
@@ -55,15 +55,15 @@ Classifier: Topic :: Utilities
|
|
|
55
55
|
Requires-Python: >=3.10
|
|
56
56
|
Description-Content-Type: text/markdown
|
|
57
57
|
License-File: LICENSE
|
|
58
|
-
Requires-Dist: seleniumbase[mcp]>=4.53.
|
|
58
|
+
Requires-Dist: seleniumbase[mcp]>=4.53.6
|
|
59
59
|
Requires-Dist: mcp[cli]<3.0.0,>=2.1.1
|
|
60
60
|
Provides-Extra: deploy
|
|
61
61
|
Requires-Dist: build>=1.0.0; extra == "deploy"
|
|
62
62
|
Requires-Dist: twine>=7.0.0; extra == "deploy"
|
|
63
63
|
Provides-Extra: uv
|
|
64
|
-
Requires-Dist: uv>=0.12.
|
|
64
|
+
Requires-Dist: uv>=0.12.9; extra == "uv"
|
|
65
65
|
Provides-Extra: dev
|
|
66
|
-
Requires-Dist: uv>=0.12.
|
|
66
|
+
Requires-Dist: uv>=0.12.9; extra == "dev"
|
|
67
67
|
Dynamic: author
|
|
68
68
|
Dynamic: author-email
|
|
69
69
|
Dynamic: classifier
|
|
@@ -281,9 +281,9 @@ in the loop at all. Reference:
|
|
|
281
281
|
| Session | `start_browser(url, headless, use_chromium, browser_executable_path, incognito, guest, ad_block, proxy)`, `close_browser` |
|
|
282
282
|
| Navigation | `navigate`, `navigate_history(action: back/forward/reload)`, `get_page_info` (running status, url, title, origin, user agent, history in one call) |
|
|
283
283
|
| Finding & reading | `find_elements(selector, timeout, include_html)`, `get_content(selector, output_format: text/html/urls, include_shadow_dom)`, `get_attributes`, `check_state(check: present/visible/count/text_visible)` |
|
|
284
|
-
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_with_action(selector1, selector2, action: none/click/drag_and_drop)`, `
|
|
284
|
+
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_with_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_on(action: scroll_to_element/focus/highlight)` |
|
|
285
285
|
| Waiting | `wait_for(state: present/visible/not_visible/absent, text)` |
|
|
286
|
-
| Assertions | `
|
|
286
|
+
| Assertions | `assert_condition(check: element_present/element_visible/text_visible/title/url/url_contains)` |
|
|
287
287
|
| Cookies & storage | `manage_cookies(action: get_all/clear/save/load)`, `manage_storage(storage: local/session, action: get/set)` |
|
|
288
288
|
| Scrolling | `scroll(direction: up/down/top/bottom, amount)` |
|
|
289
289
|
| Windows & tabs | `manage_window(action: get_rect/set_rect/maximize/minimize)`, `manage_tabs(action: list/open/switch/switch_newest/close_active)` |
|
|
@@ -201,9 +201,9 @@ in the loop at all. Reference:
|
|
|
201
201
|
| Session | `start_browser(url, headless, use_chromium, browser_executable_path, incognito, guest, ad_block, proxy)`, `close_browser` |
|
|
202
202
|
| Navigation | `navigate`, `navigate_history(action: back/forward/reload)`, `get_page_info` (running status, url, title, origin, user agent, history in one call) |
|
|
203
203
|
| Finding & reading | `find_elements(selector, timeout, include_html)`, `get_content(selector, output_format: text/html/urls, include_shadow_dom)`, `get_attributes`, `check_state(check: present/visible/count/text_visible)` |
|
|
204
|
-
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_with_action(selector1, selector2, action: none/click/drag_and_drop)`, `
|
|
204
|
+
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_with_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_on(action: scroll_to_element/focus/highlight)` |
|
|
205
205
|
| Waiting | `wait_for(state: present/visible/not_visible/absent, text)` |
|
|
206
|
-
| Assertions | `
|
|
206
|
+
| Assertions | `assert_condition(check: element_present/element_visible/text_visible/title/url/url_contains)` |
|
|
207
207
|
| Cookies & storage | `manage_cookies(action: get_all/clear/save/load)`, `manage_storage(storage: local/session, action: get/set)` |
|
|
208
208
|
| Scrolling | `scroll(direction: up/down/top/bottom, amount)` |
|
|
209
209
|
| Windows & tabs | `manage_window(action: get_rect/set_rect/maximize/minimize)`, `manage_tabs(action: list/open/switch/switch_newest/close_active)` |
|
|
@@ -23,16 +23,15 @@ access to the underlying browser-automation capabilities without
|
|
|
23
23
|
having to choose between multiple near-identical tools.
|
|
24
24
|
|
|
25
25
|
Tool-selection philosophy:
|
|
26
|
-
- Use get_page_info for browser/page metadata such as URL, title, origin
|
|
27
|
-
and navigation history.
|
|
26
|
+
- Use get_page_info for browser/page metadata such as URL, title, or origin.
|
|
28
27
|
- Use get_content for reading visible text or HTML.
|
|
29
28
|
- Use find_elements for discovering and inspecting multiple matching
|
|
30
29
|
elements as structured data.
|
|
31
|
-
- Use
|
|
30
|
+
- Use check_for_condition for an immediate, non-waiting state check.
|
|
32
31
|
- Use wait_for when the agent needs to wait for a condition to become true.
|
|
33
|
-
- Use
|
|
34
|
-
treat failure as an assertion error.
|
|
35
|
-
- Use click/
|
|
32
|
+
- Use assert_condition when the agent needs to verify an expected condition
|
|
33
|
+
and treat failure as an assertion error.
|
|
34
|
+
- Use click/type_text/select_option/hover_with_action/focus_on for
|
|
36
35
|
interactions and element positioning.
|
|
37
36
|
"""
|
|
38
37
|
from __future__ import annotations
|
|
@@ -93,7 +92,7 @@ def start_browser(
|
|
|
93
92
|
"""Launch a persistent SeleniumBase Pure CDP Mode browser session.
|
|
94
93
|
|
|
95
94
|
This must be called before browser interaction tools such as navigate,
|
|
96
|
-
get_content, click,
|
|
95
|
+
get_content, click, type_text, or find_elements. The same browser
|
|
97
96
|
session remains active across subsequent MCP tool calls until
|
|
98
97
|
close_browser is called or the server process exits.
|
|
99
98
|
|
|
@@ -205,18 +204,33 @@ def start_browser(
|
|
|
205
204
|
f"(url={url!r}, headless={effective_headless}, "
|
|
206
205
|
f"use_chromium={use_chromium})"
|
|
207
206
|
)
|
|
208
|
-
except Exception
|
|
209
|
-
if
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
207
|
+
except Exception:
|
|
208
|
+
# Retry once if the first launch attempt fails.
|
|
209
|
+
# (A retry helped when testing on Glama's MCP Inspector.)
|
|
210
|
+
try:
|
|
211
|
+
if _sb is not None:
|
|
212
|
+
try:
|
|
213
|
+
_sb.quit()
|
|
214
|
+
except Exception:
|
|
215
|
+
pass
|
|
216
|
+
_sb = None
|
|
217
|
+
_sb = sb_cdp.Chrome(url, **kwargs)
|
|
218
|
+
return (
|
|
219
|
+
f"Started Pure CDP Mode browser "
|
|
220
|
+
f"(url={url!r}, headless={effective_headless}, "
|
|
221
|
+
f"use_chromium={use_chromium})"
|
|
222
|
+
)
|
|
223
|
+
except Exception as e:
|
|
224
|
+
if _sb is not None:
|
|
225
|
+
try:
|
|
226
|
+
_sb.quit()
|
|
227
|
+
except Exception:
|
|
228
|
+
pass
|
|
229
|
+
_sb = None
|
|
230
|
+
return (
|
|
231
|
+
f"Error starting browser: "
|
|
232
|
+
f"{e.__class__.__name__} - {str(e).strip()}"
|
|
233
|
+
)
|
|
220
234
|
|
|
221
235
|
|
|
222
236
|
@mcp.tool()
|
|
@@ -268,16 +282,14 @@ def get_page_info() -> dict | str:
|
|
|
268
282
|
- title: The current document title.
|
|
269
283
|
- origin: The current page origin (scheme, host, and port).
|
|
270
284
|
- user_agent: The browser's current User-Agent string.
|
|
271
|
-
- history: The browser navigation history for the current session.
|
|
272
285
|
|
|
273
286
|
Tool selection:
|
|
274
|
-
- Need URL, title, origin, User-Agent
|
|
275
|
-
use get_page_info.
|
|
287
|
+
- Need URL, title, origin, or User-Agent -> use get_page_info.
|
|
276
288
|
- Need visible page text or HTML -> use get_content.
|
|
277
289
|
- Need information about matching elements -> use find_elements.
|
|
278
|
-
- Need an immediate state check -> use
|
|
290
|
+
- Need an immediate state check -> use check_for_condition.
|
|
279
291
|
- Need to wait for a condition -> use wait_for.
|
|
280
|
-
- Need to verify an expected condition -> use
|
|
292
|
+
- Need to verify an expected condition -> use assert_condition.
|
|
281
293
|
|
|
282
294
|
Unlike a dedicated browser-status tool, get_page_info is the single
|
|
283
295
|
source of browser/page metadata. If no browser session is active, it
|
|
@@ -296,7 +308,6 @@ def get_page_info() -> dict | str:
|
|
|
296
308
|
"title": _sb.get_title(),
|
|
297
309
|
"origin": _sb.get_origin(),
|
|
298
310
|
"user_agent": _sb.get_user_agent(),
|
|
299
|
-
"history": _sb.get_navigation_history(),
|
|
300
311
|
}
|
|
301
312
|
except Exception as e:
|
|
302
313
|
return {
|
|
@@ -436,7 +447,7 @@ def find_elements(
|
|
|
436
447
|
use get_content.
|
|
437
448
|
- Need to click one of several matches -> use click with nth.
|
|
438
449
|
- Need to know whether an element is present/visible ->
|
|
439
|
-
use
|
|
450
|
+
use check_for_condition.
|
|
440
451
|
|
|
441
452
|
Note:
|
|
442
453
|
Element handles cannot be persisted across MCP calls. If you find
|
|
@@ -512,15 +523,14 @@ def get_content(
|
|
|
512
523
|
URLs before navigating to them.
|
|
513
524
|
|
|
514
525
|
Tool selection:
|
|
515
|
-
- Need URL, title, origin, User-Agent
|
|
516
|
-
use get_page_info.
|
|
526
|
+
- Need URL, title, origin, or User-Agent -> use get_page_info.
|
|
517
527
|
- Need visible text -> use output_format="text".
|
|
518
528
|
- Need page or element HTML -> use output_format="html".
|
|
519
529
|
- Need URLs from the page or an element -> use output_format="urls".
|
|
520
530
|
- Need structured information about matching elements ->
|
|
521
531
|
use find_elements.
|
|
522
532
|
- Need to check whether an element is present or visible ->
|
|
523
|
-
use
|
|
533
|
+
use check_for_condition.
|
|
524
534
|
- Need to wait for content to appear -> use wait_for.
|
|
525
535
|
"""
|
|
526
536
|
sb = _get_sb()
|
|
@@ -549,15 +559,26 @@ def get_attributes(
|
|
|
549
559
|
) -> Any:
|
|
550
560
|
"""Read HTML attributes from a matching element.
|
|
551
561
|
|
|
562
|
+
Use this tool when you need the value of one or more HTML attributes
|
|
563
|
+
such as href, src, value, class, id, name, type, aria-label, or data-*.
|
|
564
|
+
|
|
552
565
|
Args:
|
|
553
566
|
selector: CSS selector or SeleniumBase text-matching selector for
|
|
554
567
|
the target element.
|
|
555
568
|
attribute: Specific HTML attribute to retrieve. When omitted, return
|
|
556
|
-
all
|
|
569
|
+
all HTML attributes of the element as a dictionary.
|
|
557
570
|
|
|
558
571
|
Returns:
|
|
559
572
|
The requested attribute value, or a dictionary containing all
|
|
560
|
-
attributes when attribute is omitted.
|
|
573
|
+
HTML attributes of the element when attribute is omitted.
|
|
574
|
+
|
|
575
|
+
Tool selection:
|
|
576
|
+
- Need one or more HTML attribute values from a specific element ->
|
|
577
|
+
use this tool.
|
|
578
|
+
- Need to discover multiple matching elements or inspect their text ->
|
|
579
|
+
use 'find_elements'.
|
|
580
|
+
- Need visible text or HTML content -> use 'get_content'.
|
|
581
|
+
- Need to check presence or visibility -> use 'check_for_condition'.
|
|
561
582
|
|
|
562
583
|
This is a read-only operation and does not modify the element.
|
|
563
584
|
"""
|
|
@@ -571,7 +592,7 @@ def get_attributes(
|
|
|
571
592
|
|
|
572
593
|
@mcp.tool()
|
|
573
594
|
@handle_sb_errors
|
|
574
|
-
def
|
|
595
|
+
def check_for_condition(
|
|
575
596
|
check: Literal["present", "visible", "count", "text_visible"] = "visible",
|
|
576
597
|
selector: str = "body",
|
|
577
598
|
text: str | None = None,
|
|
@@ -580,7 +601,7 @@ def check_state(
|
|
|
580
601
|
|
|
581
602
|
Use this tool when you need an observation of the current state and do
|
|
582
603
|
NOT want to wait for a condition. For waiting behavior, use wait_for.
|
|
583
|
-
For an expectation that should fail as an assertion, use
|
|
604
|
+
For an expectation that should fail as an assertion, use assert_condition.
|
|
584
605
|
|
|
585
606
|
Args:
|
|
586
607
|
check:
|
|
@@ -599,10 +620,10 @@ def check_state(
|
|
|
599
620
|
count. Missing elements do not cause an exception for these checks.
|
|
600
621
|
|
|
601
622
|
Tool selection:
|
|
602
|
-
- Immediate yes/no/count observation -> use
|
|
623
|
+
- Immediate yes/no/count observation -> use check_for_condition.
|
|
603
624
|
- Wait until a state becomes true/false -> use wait_for.
|
|
604
625
|
- Verify an expected condition and fail when it is not met ->
|
|
605
|
-
use
|
|
626
|
+
use assert_condition.
|
|
606
627
|
|
|
607
628
|
Note:
|
|
608
629
|
Except for count's short lookup, this tool does not wait for elements
|
|
@@ -784,62 +805,64 @@ def hover_with_action(
|
|
|
784
805
|
|
|
785
806
|
@mcp.tool()
|
|
786
807
|
@handle_sb_errors
|
|
787
|
-
def
|
|
808
|
+
def type_text(
|
|
788
809
|
selector: str,
|
|
789
810
|
text: str = "",
|
|
790
811
|
mode: Literal[
|
|
791
|
-
"
|
|
812
|
+
"fill_input",
|
|
792
813
|
"append",
|
|
793
|
-
"set_value",
|
|
794
814
|
"fast_type",
|
|
795
|
-
"
|
|
796
|
-
|
|
815
|
+
"set_value",
|
|
816
|
+
"clear_only",
|
|
817
|
+
] = "fill_input",
|
|
797
818
|
timeout: int | float | None = 7,
|
|
798
819
|
) -> str:
|
|
799
|
-
"""
|
|
820
|
+
"""Fill, append, fast-type, directly set, or clear a form control.
|
|
800
821
|
|
|
801
822
|
Use this tool for input elements, textareas, and contenteditable elements.
|
|
802
823
|
|
|
803
824
|
Args:
|
|
804
825
|
selector: CSS selector or SeleniumBase selector identifying the
|
|
805
826
|
input, textarea, or contenteditable element.
|
|
806
|
-
text: Text to enter or set.
|
|
827
|
+
text: Text to enter or set. Not used when mode="clear_only".
|
|
807
828
|
mode:
|
|
808
|
-
- "
|
|
809
|
-
- "append": Keep the existing value and
|
|
829
|
+
- "fill_input": Clear the field and then type text normally.
|
|
830
|
+
- "append": Keep the existing value and add text as keystrokes.
|
|
831
|
+
- "fast_type": Clear the field and type text without pauses.
|
|
810
832
|
- "set_value": Set the value directly and immediately. This can
|
|
811
833
|
be useful for fast form filling but does not simulate normal
|
|
812
|
-
key events.
|
|
813
|
-
|
|
814
|
-
- "
|
|
834
|
+
key events. It can also be used to handle input sliders,
|
|
835
|
+
e.g. 'input[type="range"]'.
|
|
836
|
+
- "clear_only": Empty the text field; text is ignored.
|
|
815
837
|
timeout: Maximum seconds to wait for the target element.
|
|
816
838
|
|
|
817
839
|
Tool selection:
|
|
818
|
-
- Normal
|
|
819
|
-
- Add text without clearing -> mode="append".
|
|
820
|
-
-
|
|
821
|
-
-
|
|
822
|
-
- Empty a field -> mode="
|
|
840
|
+
- Normal text entry to replace existing text -> mode="fill_input".
|
|
841
|
+
- Add text without clearing the field first -> mode="append".
|
|
842
|
+
- Fast typing to replace existing text -> mode="fast_type".
|
|
843
|
+
- Directly set a value (e.g. input slider) -> mode="set_value".
|
|
844
|
+
- Empty a field of all text -> mode="clear_only".
|
|
823
845
|
"""
|
|
824
846
|
sb = _get_sb()
|
|
825
847
|
|
|
826
|
-
if mode == "
|
|
848
|
+
if mode == "fill_input":
|
|
827
849
|
sb.type(selector, text, timeout=timeout)
|
|
828
850
|
elif mode == "append":
|
|
829
851
|
sb.send_keys(selector, text, timeout=timeout)
|
|
830
|
-
elif mode == "set_value":
|
|
831
|
-
sb.set_value(selector, text, timeout=timeout)
|
|
832
852
|
elif mode == "fast_type":
|
|
833
853
|
sb.fast_type(selector, text, timeout=timeout)
|
|
834
|
-
elif mode == "
|
|
854
|
+
elif mode == "set_value":
|
|
855
|
+
sb.set_value(selector, text, timeout=timeout)
|
|
856
|
+
elif mode == "clear_only":
|
|
835
857
|
sb.clear_input(selector, timeout=timeout)
|
|
836
858
|
else:
|
|
837
859
|
return (
|
|
838
860
|
f"Error: unknown mode '{mode}'. "
|
|
839
|
-
"Use '
|
|
861
|
+
"Use 'fill_input', 'append', 'fast_type', "
|
|
862
|
+
"'set_value', or 'clear_only'."
|
|
840
863
|
)
|
|
841
864
|
|
|
842
|
-
return f"
|
|
865
|
+
return f"type_text(mode={mode!r}) done for {selector}"
|
|
843
866
|
|
|
844
867
|
|
|
845
868
|
@mcp.tool()
|
|
@@ -915,7 +938,7 @@ def focus_on(
|
|
|
915
938
|
- Focus an element -> use focus_on(action="focus").
|
|
916
939
|
- Highlight element for debugging -> use focus_on(action="highlight").
|
|
917
940
|
- Click -> use click.
|
|
918
|
-
- Type into a
|
|
941
|
+
- Type text into a text field -> use type_text.
|
|
919
942
|
- Hover -> use hover_with_action.
|
|
920
943
|
"""
|
|
921
944
|
sb = _get_sb()
|
|
@@ -957,8 +980,9 @@ def wait_for(
|
|
|
957
980
|
Use this tool when the page is dynamic and an automation step must wait
|
|
958
981
|
for a condition before continuing.
|
|
959
982
|
|
|
960
|
-
Unlike
|
|
961
|
-
its purpose is synchronization
|
|
983
|
+
Unlike check_for_condition, this tool intentionally waits.
|
|
984
|
+
Unlike assert_condition, its purpose is synchronization
|
|
985
|
+
rather than validating a test expectation.
|
|
962
986
|
|
|
963
987
|
Args:
|
|
964
988
|
state:
|
|
@@ -977,9 +1001,9 @@ def wait_for(
|
|
|
977
1001
|
A confirmation when the requested condition is reached.
|
|
978
1002
|
|
|
979
1003
|
Tool selection:
|
|
980
|
-
- Check current state immediately -> use
|
|
1004
|
+
- Check current state immediately -> use check_for_condition.
|
|
981
1005
|
- Wait for a state/content transition -> use wait_for.
|
|
982
|
-
- Verify an expected value/condition -> use
|
|
1006
|
+
- Verify an expected value/condition -> use assert_condition.
|
|
983
1007
|
"""
|
|
984
1008
|
sb = _get_sb()
|
|
985
1009
|
|
|
@@ -1009,11 +1033,11 @@ def wait_for(
|
|
|
1009
1033
|
|
|
1010
1034
|
@mcp.tool()
|
|
1011
1035
|
@handle_sb_errors
|
|
1012
|
-
def
|
|
1036
|
+
def assert_condition(
|
|
1013
1037
|
check: Literal[
|
|
1014
1038
|
"element_present",
|
|
1015
1039
|
"element_visible",
|
|
1016
|
-
"
|
|
1040
|
+
"text_visible",
|
|
1017
1041
|
"title",
|
|
1018
1042
|
"url",
|
|
1019
1043
|
"url_contains",
|
|
@@ -1025,24 +1049,26 @@ def assert_that(
|
|
|
1025
1049
|
) -> str:
|
|
1026
1050
|
"""Verify an expected browser condition and fail when it is not met.
|
|
1027
1051
|
|
|
1028
|
-
Use this tool for explicit verification. Unlike
|
|
1029
|
-
|
|
1030
|
-
|
|
1052
|
+
Use this tool for explicit verification. Unlike check_for_condition,
|
|
1053
|
+
which simply reports True or False on the current state,
|
|
1054
|
+
assert_condition treats a failed expectation as an error.
|
|
1055
|
+
Unlike wait_for, URL/title checks do not wait.
|
|
1031
1056
|
|
|
1032
1057
|
Args:
|
|
1033
1058
|
check:
|
|
1034
1059
|
- "element_present": Verify selector identifies a present element.
|
|
1035
1060
|
- "element_visible": Verify selector identifies a visible element.
|
|
1036
|
-
- "
|
|
1037
|
-
whole HTML document when selector is omitted.
|
|
1061
|
+
- "text_visible": Verify expected text is visible within selector,
|
|
1062
|
+
or within the whole HTML document when selector is omitted.
|
|
1038
1063
|
- "title": Verify the exact page title.
|
|
1039
1064
|
- "url": Verify the exact current URL.
|
|
1040
1065
|
- "url_contains": Verify that the current URL contains expected.
|
|
1041
1066
|
selector: Element selector for element_present, element_visible, and
|
|
1042
|
-
|
|
1043
|
-
expected: Expected text/title/URL value for
|
|
1044
|
-
url_contains.
|
|
1045
|
-
exact: For check="
|
|
1067
|
+
text_visible checks.
|
|
1068
|
+
expected: Expected text/title/URL value for text_visible, title, url,
|
|
1069
|
+
and url_contains.
|
|
1070
|
+
exact: For check="text_visible", require exact text
|
|
1071
|
+
rather than a substring.
|
|
1046
1072
|
timeout: Maximum seconds to wait for element/text checks.
|
|
1047
1073
|
|
|
1048
1074
|
Returns:
|
|
@@ -1053,16 +1079,18 @@ def assert_that(
|
|
|
1053
1079
|
fails; the MCP error wrapper converts it to a descriptive result.
|
|
1054
1080
|
|
|
1055
1081
|
Tool selection:
|
|
1056
|
-
- Just inspect current state -> use
|
|
1082
|
+
- Just inspect current state -> use check_for_condition.
|
|
1057
1083
|
- Wait for a condition to become true -> use wait_for.
|
|
1058
|
-
- Verify that an expected condition is true -> use
|
|
1084
|
+
- Verify that an expected condition is true -> use assert_condition.
|
|
1059
1085
|
"""
|
|
1060
1086
|
sb = _get_sb()
|
|
1061
1087
|
|
|
1062
1088
|
if check in ("element_present", "element_visible") and selector is None:
|
|
1063
1089
|
return f"Error: check='{check}' requires value for `selector`."
|
|
1064
1090
|
|
|
1065
|
-
if check in (
|
|
1091
|
+
if check in (
|
|
1092
|
+
"text_visible", "title", "url", "url_contains"
|
|
1093
|
+
) and expected is None:
|
|
1066
1094
|
return f"Error: check='{check}' requires value for `expected`."
|
|
1067
1095
|
|
|
1068
1096
|
if check == "element_present":
|
|
@@ -1073,13 +1101,13 @@ def assert_that(
|
|
|
1073
1101
|
sb.assert_element_visible(selector, timeout=timeout)
|
|
1074
1102
|
return f"Confirmed {selector} is visible."
|
|
1075
1103
|
|
|
1076
|
-
if check == "
|
|
1104
|
+
if check == "text_visible":
|
|
1077
1105
|
target = selector or "html"
|
|
1078
1106
|
if exact:
|
|
1079
1107
|
sb.assert_exact_text(expected, target, timeout=timeout)
|
|
1080
1108
|
else:
|
|
1081
1109
|
sb.assert_text(expected, target, timeout=timeout)
|
|
1082
|
-
return f"Confirmed text in {target}."
|
|
1110
|
+
return f"Confirmed visible text {expected} in {target}."
|
|
1083
1111
|
|
|
1084
1112
|
if check == "title":
|
|
1085
1113
|
sb.assert_title(expected)
|
|
@@ -1095,7 +1123,8 @@ def assert_that(
|
|
|
1095
1123
|
|
|
1096
1124
|
return (
|
|
1097
1125
|
f"Error: unknown check '{check}'. Use 'element_present', "
|
|
1098
|
-
|
|
1126
|
+
"'element_visible', 'text_visible', 'title', 'url', "
|
|
1127
|
+
"or 'url_contains'."
|
|
1099
1128
|
)
|
|
1100
1129
|
|
|
1101
1130
|
|
|
@@ -1184,6 +1213,24 @@ def manage_storage(
|
|
|
1184
1213
|
) -> Any:
|
|
1185
1214
|
"""Get or set a key in localStorage or sessionStorage.
|
|
1186
1215
|
|
|
1216
|
+
Use this tool when the browser workflow needs to inspect or modify
|
|
1217
|
+
JavaScript Web Storage belonging to the current page origin.
|
|
1218
|
+
|
|
1219
|
+
Tool selection:
|
|
1220
|
+
- Need localStorage/sessionStorage -> use this tool.
|
|
1221
|
+
- Need cookies or authentication cookies -> use manage_cookies.
|
|
1222
|
+
- Need arbitrary JavaScript or storage operations not covered here ->
|
|
1223
|
+
use run_javascript.
|
|
1224
|
+
- Need visible page content or HTML -> use get_content.
|
|
1225
|
+
- Need an element's HTML attributes -> use get_attributes.
|
|
1226
|
+
|
|
1227
|
+
When not to use:
|
|
1228
|
+
- Do not use this tool for HTTP cookies; use manage_cookies instead.
|
|
1229
|
+
- Do not use this tool for arbitrary page JavaScript;
|
|
1230
|
+
use run_javascript when a higher-level tool is insufficient.
|
|
1231
|
+
- Do not use this tool to inspect values from another origin;
|
|
1232
|
+
storage is scoped to the current page origin.
|
|
1233
|
+
|
|
1187
1234
|
Args:
|
|
1188
1235
|
key: Storage key to read or modify.
|
|
1189
1236
|
value: Value to store when action="set". Required for set.
|
|
@@ -1202,27 +1249,6 @@ def manage_storage(
|
|
|
1202
1249
|
Storage belongs to the current page origin. Values from one website
|
|
1203
1250
|
are not generally available to another origin.
|
|
1204
1251
|
"""
|
|
1205
|
-
sb = _get_sb()
|
|
1206
|
-
|
|
1207
|
-
if action not in ("get", "set"):
|
|
1208
|
-
return "Error: action must be 'get' or 'set'."
|
|
1209
|
-
|
|
1210
|
-
if action == "set" and value is None:
|
|
1211
|
-
return "Error: value is required when action='set'."
|
|
1212
|
-
|
|
1213
|
-
if storage == "local":
|
|
1214
|
-
if action == "get":
|
|
1215
|
-
return sb.get_local_storage_item(key)
|
|
1216
|
-
sb.set_local_storage_item(key, value)
|
|
1217
|
-
return f"Set localStorage[{key!r}]"
|
|
1218
|
-
|
|
1219
|
-
if storage == "session":
|
|
1220
|
-
if action == "get":
|
|
1221
|
-
return sb.get_session_storage_item(key)
|
|
1222
|
-
sb.set_session_storage_item(key, value)
|
|
1223
|
-
return f"Set sessionStorage[{key!r}]"
|
|
1224
|
-
|
|
1225
|
-
return f"Error: unknown storage '{storage}'. Use 'local' or 'session'."
|
|
1226
1252
|
|
|
1227
1253
|
|
|
1228
1254
|
# ---------------------------------------------------------------------------
|
|
@@ -1436,8 +1462,8 @@ def solve_captcha() -> str:
|
|
|
1436
1462
|
1. Inspect the page with get_content when you need to determine
|
|
1437
1463
|
whether CAPTCHA-related controls are present.
|
|
1438
1464
|
2. Call solve_captcha to attempt the interaction.
|
|
1439
|
-
3. Use get_page_info, get_content,
|
|
1440
|
-
to inspect resulting page/session state.
|
|
1465
|
+
3. Use get_page_info, get_content, check_for_condition,
|
|
1466
|
+
or manage_cookies to inspect resulting page/session state.
|
|
1441
1467
|
|
|
1442
1468
|
Returns:
|
|
1443
1469
|
A message confirming that the CAPTCHA interaction was attempted, not
|
|
@@ -1504,22 +1530,51 @@ def save_output(
|
|
|
1504
1530
|
@mcp.tool()
|
|
1505
1531
|
@handle_sb_errors
|
|
1506
1532
|
def run_javascript(expression: str) -> Any:
|
|
1507
|
-
"""Evaluate
|
|
1533
|
+
"""Evaluate a JavaScript expression in the current page context.
|
|
1508
1534
|
|
|
1509
1535
|
Use this only when the required browser operation cannot be accomplished
|
|
1510
1536
|
through the higher-level SeleniumBase tools.
|
|
1511
1537
|
|
|
1512
|
-
The expression is evaluated through
|
|
1513
|
-
Runtime.evaluate
|
|
1514
|
-
|
|
1538
|
+
The expression is evaluated through Chrome DevTools Protocol
|
|
1539
|
+
Runtime.evaluate in the currently active page. It executes with access
|
|
1540
|
+
to the page's JavaScript context, including DOM APIs, browser storage,
|
|
1541
|
+
and other same-origin page resources available to JavaScript.
|
|
1542
|
+
|
|
1543
|
+
Tool selection:
|
|
1544
|
+
- Prefer click, type_text, select_option, hover_with_action,
|
|
1545
|
+
focus_on, scroll, and other higher-level tools for normal browser
|
|
1546
|
+
interactions.
|
|
1547
|
+
- Prefer get_content, get_attributes, and find_elements for reading
|
|
1548
|
+
page content or element information.
|
|
1549
|
+
- Prefer manage_storage for ordinary localStorage/sessionStorage
|
|
1550
|
+
reads and writes.
|
|
1551
|
+
- Prefer manage_cookies for browser cookie operations.
|
|
1552
|
+
- Use this tool when a required operation needs arbitrary JavaScript
|
|
1553
|
+
that the higher-level tools do not expose.
|
|
1515
1554
|
|
|
1516
1555
|
Args:
|
|
1517
|
-
expression: JavaScript expression
|
|
1518
|
-
|
|
1556
|
+
expression: A JavaScript expression or executable JavaScript code
|
|
1557
|
+
evaluated in the current page. It may reference standard browser
|
|
1558
|
+
globals such as document and window and may use DOM APIs.
|
|
1559
|
+
|
|
1560
|
+
Examples:
|
|
1561
|
+
- "document.title"
|
|
1562
|
+
- "document.querySelector('button')?.textContent"
|
|
1563
|
+
- "localStorage.getItem('theme')"
|
|
1564
|
+
- "document.body.classList.contains('dark')"
|
|
1565
|
+
- "document.querySelector('#slider').value = '50'"
|
|
1566
|
+
|
|
1567
|
+
The expression should produce a value when a result is needed.
|
|
1568
|
+
JavaScript that returns a Promise is supported and its resolved
|
|
1569
|
+
value is returned.
|
|
1519
1570
|
|
|
1520
1571
|
Returns:
|
|
1521
|
-
The JavaScript evaluation result when it can be
|
|
1522
|
-
the MCP boundary.
|
|
1572
|
+
The JavaScript evaluation result when it can be serialized and
|
|
1573
|
+
returned across the MCP boundary. Primitive values, arrays, plain
|
|
1574
|
+
objects, and null are generally suitable return values. DOM objects,
|
|
1575
|
+
functions, symbols, and other non-serializable JavaScript values may
|
|
1576
|
+
not be returned directly; extract the needed property or convert the
|
|
1577
|
+
value to a serializable form first.
|
|
1523
1578
|
|
|
1524
1579
|
Security:
|
|
1525
1580
|
This provides unrestricted JavaScript execution in the current browser
|
|
@@ -252,6 +252,7 @@ def type_text(
|
|
|
252
252
|
) -> str:
|
|
253
253
|
"""Type text into an input field / textarea.
|
|
254
254
|
Raises an exception if the element isn't found within the timeout.
|
|
255
|
+
Optionally clear the text field first. (Default: True)
|
|
255
256
|
Args:
|
|
256
257
|
selector: The selector for the field.
|
|
257
258
|
text: The text to type.
|
|
@@ -260,9 +261,10 @@ def type_text(
|
|
|
260
261
|
d = _get_driver()
|
|
261
262
|
if clear_first:
|
|
262
263
|
d.type(selector, text, timeout=timeout)
|
|
264
|
+
return f"Typed {text} into {selector} after clearing the field."
|
|
263
265
|
else:
|
|
264
|
-
d.
|
|
265
|
-
|
|
266
|
+
d.send_keys(selector, text, timeout=timeout)
|
|
267
|
+
return f"Typed {text} into {selector}"
|
|
266
268
|
|
|
267
269
|
|
|
268
270
|
@mcp.tool()
|
|
@@ -287,11 +289,14 @@ def select_option_by_value(dropdown_selector: str, option: str) -> str:
|
|
|
287
289
|
|
|
288
290
|
@mcp.tool()
|
|
289
291
|
@handle_sb_errors
|
|
290
|
-
def select_option_by_index(
|
|
292
|
+
def select_option_by_index(
|
|
293
|
+
dropdown_selector: str,
|
|
294
|
+
option: str | int,
|
|
295
|
+
) -> str:
|
|
291
296
|
"""Select a <select> dropdown option by its 0-based index.
|
|
292
297
|
Raises an exception if the element or option aren't found
|
|
293
298
|
within the default timeout, which is 7 seconds."""
|
|
294
|
-
_get_driver().select_option_by_index(dropdown_selector, option)
|
|
299
|
+
_get_driver().select_option_by_index(dropdown_selector, int(option))
|
|
295
300
|
return f"Selected index '{option}' in {dropdown_selector}"
|
|
296
301
|
|
|
297
302
|
|
|
@@ -330,15 +335,33 @@ def switch_to_default_content() -> str:
|
|
|
330
335
|
|
|
331
336
|
@mcp.tool()
|
|
332
337
|
@handle_sb_errors
|
|
333
|
-
def assert_text(
|
|
334
|
-
|
|
338
|
+
def assert_text(
|
|
339
|
+
text: str,
|
|
340
|
+
selector: str | None = None,
|
|
341
|
+
timeout: int | float | None = 7,
|
|
342
|
+
) -> str:
|
|
343
|
+
"""Assert that text is visible on the page, or within a specific element.
|
|
335
344
|
Raises an error (returned as a tool error to the client) if not found."""
|
|
336
345
|
d = _get_driver()
|
|
337
346
|
if selector:
|
|
338
|
-
d.assert_text(text, selector)
|
|
347
|
+
d.assert_text(text, selector, timeout=timeout)
|
|
348
|
+
return f"Confirmed text '{text}' is visible in selector {selector}."
|
|
339
349
|
else:
|
|
340
|
-
d.assert_text(text)
|
|
341
|
-
|
|
350
|
+
d.assert_text(text, timeout=timeout)
|
|
351
|
+
return f"Confirmed text '{text}' is visible."
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
@mcp.tool()
|
|
355
|
+
@handle_sb_errors
|
|
356
|
+
def assert_element(
|
|
357
|
+
selector: str,
|
|
358
|
+
timeout: int | float | None = 7
|
|
359
|
+
) -> str:
|
|
360
|
+
"""Assert that an element is visible on the page.
|
|
361
|
+
Raises an error (returned as a tool error to the client) if not found."""
|
|
362
|
+
d = _get_driver()
|
|
363
|
+
d.assert_element(selector, timeout=timeout)
|
|
364
|
+
return f"Confirmed '{selector}' is present."
|
|
342
365
|
|
|
343
366
|
|
|
344
367
|
# ---------------------------------------------------------------------------
|
|
@@ -410,22 +410,27 @@ def context_click(selector: str) -> str:
|
|
|
410
410
|
|
|
411
411
|
@mcp.tool()
|
|
412
412
|
@handle_sb_errors
|
|
413
|
-
def type_text(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
413
|
+
def type_text(
|
|
414
|
+
selector: str,
|
|
415
|
+
text: str,
|
|
416
|
+
clear_first: bool = True,
|
|
417
|
+
timeout: int | float | None = 7,
|
|
418
|
+
) -> str:
|
|
419
|
+
"""Type text into an input field / textarea.
|
|
420
|
+
Raises an exception if the element isn't found within the timeout.
|
|
421
|
+
Optionally clear the text field first. (Default: True)
|
|
422
|
+
Args:
|
|
423
|
+
selector: The selector for the field.
|
|
424
|
+
text: The text to type.
|
|
425
|
+
clear_first: Clear the field's existing contents before typing.
|
|
426
|
+
timeout: The maximum time to wait for an element in seconds.
|
|
426
427
|
"""
|
|
427
|
-
|
|
428
|
-
|
|
428
|
+
if clear_first:
|
|
429
|
+
_get_sb().type(selector, text, timeout=timeout)
|
|
430
|
+
return f"Typed {text} into {selector} after clearing the field."
|
|
431
|
+
else:
|
|
432
|
+
_get_sb().send_keys(selector, text, timeout=timeout)
|
|
433
|
+
return f"Typed {text} into {selector}"
|
|
429
434
|
|
|
430
435
|
|
|
431
436
|
@mcp.tool()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seleniumbase-mcp
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: MCP servers exposing SeleniumBase as tools for MCP clients.
|
|
5
5
|
Home-page: https://github.com/seleniumbase/seleniumbase-mcp
|
|
6
6
|
Author: Michael Mintz
|
|
@@ -55,15 +55,15 @@ Classifier: Topic :: Utilities
|
|
|
55
55
|
Requires-Python: >=3.10
|
|
56
56
|
Description-Content-Type: text/markdown
|
|
57
57
|
License-File: LICENSE
|
|
58
|
-
Requires-Dist: seleniumbase[mcp]>=4.53.
|
|
58
|
+
Requires-Dist: seleniumbase[mcp]>=4.53.6
|
|
59
59
|
Requires-Dist: mcp[cli]<3.0.0,>=2.1.1
|
|
60
60
|
Provides-Extra: deploy
|
|
61
61
|
Requires-Dist: build>=1.0.0; extra == "deploy"
|
|
62
62
|
Requires-Dist: twine>=7.0.0; extra == "deploy"
|
|
63
63
|
Provides-Extra: uv
|
|
64
|
-
Requires-Dist: uv>=0.12.
|
|
64
|
+
Requires-Dist: uv>=0.12.9; extra == "uv"
|
|
65
65
|
Provides-Extra: dev
|
|
66
|
-
Requires-Dist: uv>=0.12.
|
|
66
|
+
Requires-Dist: uv>=0.12.9; extra == "dev"
|
|
67
67
|
Dynamic: author
|
|
68
68
|
Dynamic: author-email
|
|
69
69
|
Dynamic: classifier
|
|
@@ -281,9 +281,9 @@ in the loop at all. Reference:
|
|
|
281
281
|
| Session | `start_browser(url, headless, use_chromium, browser_executable_path, incognito, guest, ad_block, proxy)`, `close_browser` |
|
|
282
282
|
| Navigation | `navigate`, `navigate_history(action: back/forward/reload)`, `get_page_info` (running status, url, title, origin, user agent, history in one call) |
|
|
283
283
|
| Finding & reading | `find_elements(selector, timeout, include_html)`, `get_content(selector, output_format: text/html/urls, include_shadow_dom)`, `get_attributes`, `check_state(check: present/visible/count/text_visible)` |
|
|
284
|
-
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_with_action(selector1, selector2, action: none/click/drag_and_drop)`, `
|
|
284
|
+
| Interacting | `click(selector, nth, all_matches, only_if_visible, parent_selector, timeout, scroll)`, `hover_with_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_on(action: scroll_to_element/focus/highlight)` |
|
|
285
285
|
| Waiting | `wait_for(state: present/visible/not_visible/absent, text)` |
|
|
286
|
-
| Assertions | `
|
|
286
|
+
| Assertions | `assert_condition(check: element_present/element_visible/text_visible/title/url/url_contains)` |
|
|
287
287
|
| Cookies & storage | `manage_cookies(action: get_all/clear/save/load)`, `manage_storage(storage: local/session, action: get/set)` |
|
|
288
288
|
| Scrolling | `scroll(direction: up/down/top/bottom, amount)` |
|
|
289
289
|
| Windows & tabs | `manage_window(action: get_rect/set_rect/maximize/minimize)`, `manage_tabs(action: list/open/switch/switch_newest/close_active)` |
|
|
@@ -70,7 +70,7 @@ if sys.argv[-1] == "publish":
|
|
|
70
70
|
|
|
71
71
|
setup(
|
|
72
72
|
name="seleniumbase-mcp",
|
|
73
|
-
version="1.2.
|
|
73
|
+
version="1.2.4",
|
|
74
74
|
description="MCP servers exposing SeleniumBase as tools for MCP clients.",
|
|
75
75
|
long_description=long_description,
|
|
76
76
|
long_description_content_type="text/markdown",
|
|
@@ -140,7 +140,7 @@ setup(
|
|
|
140
140
|
],
|
|
141
141
|
python_requires=">=3.10",
|
|
142
142
|
install_requires=[
|
|
143
|
-
"seleniumbase[mcp]>=4.53.
|
|
143
|
+
"seleniumbase[mcp]>=4.53.6",
|
|
144
144
|
"mcp[cli]>=2.1.1,<3.0.0",
|
|
145
145
|
],
|
|
146
146
|
extras_require={
|
|
@@ -149,10 +149,10 @@ setup(
|
|
|
149
149
|
"twine>=7.0.0",
|
|
150
150
|
],
|
|
151
151
|
"uv": [
|
|
152
|
-
"uv>=0.12.
|
|
152
|
+
"uv>=0.12.9",
|
|
153
153
|
],
|
|
154
154
|
"dev": [
|
|
155
|
-
"uv>=0.12.
|
|
155
|
+
"uv>=0.12.9",
|
|
156
156
|
],
|
|
157
157
|
},
|
|
158
158
|
entry_points={
|
|
@@ -25,7 +25,6 @@ async def test_server(name: str, command: str) -> None:
|
|
|
25
25
|
assert "start_browser" in tools
|
|
26
26
|
assert "close_browser" in tools
|
|
27
27
|
assert "navigate" in tools
|
|
28
|
-
# assert "get_title" in tools
|
|
29
28
|
|
|
30
29
|
result = await client.call_tool(
|
|
31
30
|
"start_browser",
|
|
@@ -45,15 +44,27 @@ async def test_server(name: str, command: str) -> None:
|
|
|
45
44
|
)
|
|
46
45
|
assert not result.is_error
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
assert
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
result = result.structured_content["result"]
|
|
48
|
+
assert "<title>MCP Test</title>" in result
|
|
49
|
+
|
|
50
|
+
if name == "seleniumbase-sb" or name == "seleniumbase-driver":
|
|
51
|
+
result = await client.call_tool("get_title", {})
|
|
52
|
+
assert not result.is_error
|
|
53
|
+
assert result.content[0].text == "MCP Test"
|
|
54
|
+
|
|
55
|
+
result = await client.call_tool(
|
|
56
|
+
"assert_text",
|
|
57
|
+
{"text": "Hello MCP"},
|
|
58
|
+
)
|
|
59
|
+
assert not result.is_error
|
|
60
|
+
else:
|
|
61
|
+
result = await client.call_tool(
|
|
62
|
+
"get_content", {
|
|
63
|
+
"selector": "title",
|
|
64
|
+
"output_format": "text"
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
assert result.content[0].text == "MCP Test"
|
|
57
68
|
|
|
58
69
|
result = await client.call_tool("close_browser", {})
|
|
59
70
|
assert not result.is_error
|
|
File without changes
|
|
File without changes
|
{seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/seleniumbase_mcp.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{seleniumbase_mcp-1.2.2 → seleniumbase_mcp-1.2.4}/seleniumbase_mcp.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|