seleniumbase-mcp 1.2.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase-mcp
3
- Version: 1.2.3
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,7 +55,7 @@ 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.5
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"
@@ -23,12 +23,11 @@ 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 check_state for an immediate, non-waiting state check.
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
32
  - Use assert_condition when the agent needs to verify an expected condition
34
33
  and treat failure as an assertion error.
@@ -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 as e:
209
- if _sb is not None:
210
- try:
211
- _sb.quit()
212
- except Exception:
213
- pass
214
- _sb = None
215
-
216
- return (
217
- f"Error starting browser: "
218
- f"{e.__class__.__name__} - {str(e).strip()}"
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,14 +282,12 @@ 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, or navigation history ->
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 check_state.
290
+ - Need an immediate state check -> use check_for_condition.
279
291
  - Need to wait for a condition -> use wait_for.
280
292
  - Need to verify an expected condition -> use assert_condition.
281
293
 
@@ -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 check_state.
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, or navigation history ->
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 check_state.
533
+ use check_for_condition.
524
534
  - Need to wait for content to appear -> use wait_for.
525
535
  """
526
536
  sb = _get_sb()
@@ -568,7 +578,7 @@ def get_attributes(
568
578
  - Need to discover multiple matching elements or inspect their text ->
569
579
  use 'find_elements'.
570
580
  - Need visible text or HTML content -> use 'get_content'.
571
- - Need to check presence or visibility -> use 'check_state'.
581
+ - Need to check presence or visibility -> use 'check_for_condition'.
572
582
 
573
583
  This is a read-only operation and does not modify the element.
574
584
  """
@@ -582,7 +592,7 @@ def get_attributes(
582
592
 
583
593
  @mcp.tool()
584
594
  @handle_sb_errors
585
- def check_state(
595
+ def check_for_condition(
586
596
  check: Literal["present", "visible", "count", "text_visible"] = "visible",
587
597
  selector: str = "body",
588
598
  text: str | None = None,
@@ -610,7 +620,7 @@ def check_state(
610
620
  count. Missing elements do not cause an exception for these checks.
611
621
 
612
622
  Tool selection:
613
- - Immediate yes/no/count observation -> use check_state.
623
+ - Immediate yes/no/count observation -> use check_for_condition.
614
624
  - Wait until a state becomes true/false -> use wait_for.
615
625
  - Verify an expected condition and fail when it is not met ->
616
626
  use assert_condition.
@@ -970,8 +980,9 @@ def wait_for(
970
980
  Use this tool when the page is dynamic and an automation step must wait
971
981
  for a condition before continuing.
972
982
 
973
- Unlike check_state, this tool intentionally waits. Unlike assert_condition,
974
- its purpose is synchronization rather than validating a test expectation.
983
+ Unlike check_for_condition, this tool intentionally waits.
984
+ Unlike assert_condition, its purpose is synchronization
985
+ rather than validating a test expectation.
975
986
 
976
987
  Args:
977
988
  state:
@@ -990,7 +1001,7 @@ def wait_for(
990
1001
  A confirmation when the requested condition is reached.
991
1002
 
992
1003
  Tool selection:
993
- - Check current state immediately -> use check_state.
1004
+ - Check current state immediately -> use check_for_condition.
994
1005
  - Wait for a state/content transition -> use wait_for.
995
1006
  - Verify an expected value/condition -> use assert_condition.
996
1007
  """
@@ -1038,9 +1049,10 @@ def assert_condition(
1038
1049
  ) -> str:
1039
1050
  """Verify an expected browser condition and fail when it is not met.
1040
1051
 
1041
- Use this tool for explicit verification. Unlike check_state, which simply
1042
- reports the current state, assert_condition treats a failed expectation
1043
- as an error. Unlike wait_for, URL/title checks do not wait.
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.
1044
1056
 
1045
1057
  Args:
1046
1058
  check:
@@ -1067,7 +1079,7 @@ def assert_condition(
1067
1079
  fails; the MCP error wrapper converts it to a descriptive result.
1068
1080
 
1069
1081
  Tool selection:
1070
- - Just inspect current state -> use check_state.
1082
+ - Just inspect current state -> use check_for_condition.
1071
1083
  - Wait for a condition to become true -> use wait_for.
1072
1084
  - Verify that an expected condition is true -> use assert_condition.
1073
1085
  """
@@ -1201,6 +1213,24 @@ def manage_storage(
1201
1213
  ) -> Any:
1202
1214
  """Get or set a key in localStorage or sessionStorage.
1203
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
+
1204
1234
  Args:
1205
1235
  key: Storage key to read or modify.
1206
1236
  value: Value to store when action="set". Required for set.
@@ -1219,27 +1249,6 @@ def manage_storage(
1219
1249
  Storage belongs to the current page origin. Values from one website
1220
1250
  are not generally available to another origin.
1221
1251
  """
1222
- sb = _get_sb()
1223
-
1224
- if action not in ("get", "set"):
1225
- return "Error: action must be 'get' or 'set'."
1226
-
1227
- if action == "set" and value is None:
1228
- return "Error: value is required when action='set'."
1229
-
1230
- if storage == "local":
1231
- if action == "get":
1232
- return sb.get_local_storage_item(key)
1233
- sb.set_local_storage_item(key, value)
1234
- return f"Set localStorage[{key!r}]"
1235
-
1236
- if storage == "session":
1237
- if action == "get":
1238
- return sb.get_session_storage_item(key)
1239
- sb.set_session_storage_item(key, value)
1240
- return f"Set sessionStorage[{key!r}]"
1241
-
1242
- return f"Error: unknown storage '{storage}'. Use 'local' or 'session'."
1243
1252
 
1244
1253
 
1245
1254
  # ---------------------------------------------------------------------------
@@ -1453,8 +1462,8 @@ def solve_captcha() -> str:
1453
1462
  1. Inspect the page with get_content when you need to determine
1454
1463
  whether CAPTCHA-related controls are present.
1455
1464
  2. Call solve_captcha to attempt the interaction.
1456
- 3. Use get_page_info, get_content, check_state, or manage_cookies
1457
- 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.
1458
1467
 
1459
1468
  Returns:
1460
1469
  A message confirming that the CAPTCHA interaction was attempted, not
@@ -1521,22 +1530,51 @@ def save_output(
1521
1530
  @mcp.tool()
1522
1531
  @handle_sb_errors
1523
1532
  def run_javascript(expression: str) -> Any:
1524
- """Evaluate arbitrary JavaScript in the current page context.
1533
+ """Evaluate a JavaScript expression in the current page context.
1525
1534
 
1526
1535
  Use this only when the required browser operation cannot be accomplished
1527
1536
  through the higher-level SeleniumBase tools.
1528
1537
 
1529
- The expression is evaluated through the Chrome DevTools Protocol
1530
- Runtime.evaluate mechanism. Promise results are awaited and values are
1531
- returned by value.
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.
1532
1554
 
1533
1555
  Args:
1534
- expression: JavaScript expression to evaluate in the current page
1535
- context.
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.
1536
1570
 
1537
1571
  Returns:
1538
- The JavaScript evaluation result when it can be represented across
1539
- 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.
1540
1578
 
1541
1579
  Security:
1542
1580
  This provides unrestricted JavaScript execution in the current browser
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase-mcp
3
- Version: 1.2.3
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,7 +55,7 @@ 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.5
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"
@@ -1,4 +1,4 @@
1
- seleniumbase[mcp]>=4.53.5
1
+ seleniumbase[mcp]>=4.53.6
2
2
  mcp[cli]<3.0.0,>=2.1.1
3
3
 
4
4
  [deploy]
@@ -70,7 +70,7 @@ if sys.argv[-1] == "publish":
70
70
 
71
71
  setup(
72
72
  name="seleniumbase-mcp",
73
- version="1.2.3",
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.5",
143
+ "seleniumbase[mcp]>=4.53.6",
144
144
  "mcp[cli]>=2.1.1,<3.0.0",
145
145
  ],
146
146
  extras_require={
@@ -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
- '''result = await client.call_tool("get_title", {})
49
- assert not result.is_error
50
- assert result.content[0].text == "MCP Test"
51
-
52
- result = await client.call_tool(
53
- "assert_text",
54
- {"text": "Hello MCP"},
55
- )
56
- assert not result.is_error'''
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