Skip to content

Commit 4c54cb7

Browse files
authored
Merge pull request #4509 from seleniumbase/mcp-server-patch-18
MCP Server: Patch 18
2 parents ddd0f04 + df6fc93 commit 4c54cb7

6 files changed

Lines changed: 61 additions & 30 deletions

File tree

‎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.9dev0"
3+
version = "1.3.10dev0"
44
description = "MCP server exposing SeleniumBase CDP Mode as tools for MCP clients."
55
readme = "README.md"
66
requires-python = ">=3.10"

‎mcp_servers/server.py‎

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@
6565
"""
6666
from __future__ import annotations
6767
import atexit
68+
import os
6869
import sys
6970
from functools import wraps
71+
from pathlib import Path
7072
from typing import Any, Literal
7173
from mcp.server import MCPServer
7274
from mcp.server.mcpserver.exceptions import ToolError
@@ -1016,6 +1018,15 @@ def type_text(
10161018
Returns:
10171019
A confirmation message after the operation succeeds;
10181020
otherwise the error handler returns the resulting failure.
1021+
1022+
Notes:
1023+
Including "\\n" in your `text` (except in "set_value" mode) will
1024+
simulate pressing the "Enter" key, which is useful for submitting
1025+
forms or triggering search inputs without needing a separate click.
1026+
1027+
Tool selection:
1028+
- Need to update text that appears in a text field -> use this tool.
1029+
- Need to update the value of a <select> element -> use select_option.
10191030
"""
10201031
sb = _get_sb()
10211032

@@ -1398,11 +1409,13 @@ def assert_condition(
13981409
# Cookies & storage
13991410
# ---------------------------------------------------------------------------
14001411

1401-
@mcp.tool(title="Manage Cookies")
1402-
# Annotations intentionally omitted: 'get_all' is a pure read, 'clear' is
1403-
# destructive, and 'save'/'load' are file/session I/O -- no single
1404-
# read_only_hint or destructive_hint value would be accurate for the whole
1405-
# tool.
1412+
@mcp.tool(
1413+
title="Manage Cookies",
1414+
annotations=ToolAnnotations(
1415+
idempotent_hint=True,
1416+
open_world_hint=True,
1417+
),
1418+
)
14061419
@handle_sb_errors
14071420
def manage_cookies(
14081421
action: Literal["get_all", "clear", "save", "load"] = "get_all",
@@ -1417,16 +1430,16 @@ def manage_cookies(
14171430
14181431
Args:
14191432
action:
1420-
- "get_all": Return all cookies currently available to the browser,
1421-
including attributes such as name, value, domain, path, expiry,
1422-
and security flags.
1433+
- "get_all": Return all cookies currently available to the
1434+
browser, including attributes such as name, value, domain,
1435+
path, expiry, and security flags.
14231436
- "clear": Delete all cookies from the current browser session.
1424-
- "save": Save current cookies to filename. The file may be
1425-
created or overwritten.
1437+
- "save": Save current cookies to filename.
14261438
- "load": Load cookies from filename into the current browser
14271439
session.
14281440
1429-
filename: Filesystem path used by save/load.
1441+
filename: The name of the file to save/load cookies from.
1442+
Will be sanitized and saved in a restricted directory.
14301443
Ignored for get_all and clear.
14311444
14321445
Returns:
@@ -1440,36 +1453,54 @@ def manage_cookies(
14401453
identifiers, and other private information. Only inspect, save,
14411454
load, or share cookies when explicitly authorized.
14421455
1443-
`filename` is passed to SeleniumBase's cookie persistence methods and
1444-
can access the filesystem available to the MCP server. Use only
1445-
trusted, authorized paths. The save action may overwrite an existing
1446-
file.
1447-
14481456
Notes:
14491457
Loading saved cookies does not guarantee restoration of a login.
14501458
Cookies may be expired, invalidated, domain/path restricted, or
1451-
dependent on other browser state.
1459+
dependent on other browser state. Navigate to the relevant site when
1460+
necessary so the browser has the appropriate origin for the cookies.
14521461
1453-
When not to use:
1454-
- Do not use this tool to load cookies if the cookie origin does
1455-
not match the origin of the current page.
1462+
Tool selection:
1463+
- Need cookies or authentication cookies -> use this tool.
1464+
- Need localStorage/sessionStorage -> use manage_storage.
1465+
- Need arbitrary JavaScript or storage operations not covered here ->
1466+
use run_javascript.
1467+
- Need visible page content or HTML -> use get_content.
1468+
- Need an element's HTML attributes -> use get_attributes.
14561469
"""
14571470
sb = _get_sb()
14581471

1472+
# Define a safe sandbox directory for cookies
1473+
cookie_dir = Path("./saved_cookies")
1474+
cookie_dir.mkdir(parents=True, exist_ok=True)
1475+
14591476
if action == "get_all":
14601477
return sb.get_all_cookies()
14611478

14621479
if action == "clear":
14631480
sb.clear_cookies()
14641481
return "Cookies cleared."
14651482

1483+
# Security: Force isolation to prevent path traversal
1484+
# (e.g., "../../../etc/passwd")
1485+
safe_filename = os.path.basename(filename)
1486+
if not safe_filename.endswith(".txt"):
1487+
safe_filename += ".txt"
1488+
1489+
# Use pathlib's division operator to join paths
1490+
safe_path = cookie_dir / safe_filename
1491+
14661492
if action == "save":
1467-
sb.save_cookies(name=filename)
1468-
return f"Cookies saved to {filename}"
1493+
sb.save_cookies(name=str(safe_path))
1494+
return f"Cookies saved safely to {safe_path.name}"
14691495

14701496
if action == "load":
1471-
sb.load_cookies(name=filename)
1472-
return f"Cookies loaded from {filename}"
1497+
if not safe_path.exists():
1498+
return (
1499+
f"Error: Could not load. {safe_path.name} does not "
1500+
"exist in the cookie directory."
1501+
)
1502+
sb.load_cookies(name=str(safe_path))
1503+
return f"Cookies loaded from {safe_path.name}"
14731504

14741505
return (
14751506
f"Error: unknown action '{action}'. "

‎requirements.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ filelock>=4.0.0
1111
fasteners>=0.20
1212
mycdp>=1.4.0
1313
pynose>=1.5.5
14-
platformdirs>=4.11.9
14+
platformdirs>=4.11.10
1515
typing-extensions>=4.16.0
1616
sbvirtualdisplay>=1.4.0
1717
MarkupSafe>=3.0.3

‎seleniumbase/__version__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.54.9"
2+
__version__ = "4.54.10"

‎server.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "io.github.seleniumbase/seleniumbase",
44
"title": "SeleniumBase MCP",
55
"description": "Stealthy browser automation, testing, and web-scraping via CDP Mode.",
6-
"version": "4.54.9",
6+
"version": "4.54.10",
77
"repository": {
88
"url": "https://github.com/seleniumbase/SeleniumBase",
99
"source": "github"
@@ -13,7 +13,7 @@
1313
{
1414
"registryType": "pypi",
1515
"identifier": "seleniumbase",
16-
"version": "4.54.9",
16+
"version": "4.54.10",
1717
"transport": {
1818
"type": "stdio"
1919
},

‎setup.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@
177177
'fasteners>=0.20',
178178
'mycdp>=1.4.0',
179179
'pynose>=1.5.5',
180-
'platformdirs>=4.11.9',
180+
'platformdirs>=4.11.10',
181181
'typing-extensions>=4.16.0',
182182
'sbvirtualdisplay>=1.4.0',
183183
'MarkupSafe>=3.0.3',

0 commit comments

Comments
 (0)