feat(mcp): add optional session_id parameter to open_session

Allow users to specify a custom session_id when opening a browser session,
rather than always generating a random UUID. Useful for naming sessions
for easier management across multiple tool calls.

- Add session_id: Optional[str] = None parameter
- Validate session_id doesn't already exist before starting browser
- Fall back to uuid4().hex[:12] if not provided
- Add tests for custom session_id and duplicate detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jules Omlor
2026-04-14 01:17:52 -04:00
parent ced9a8d63c
commit 00897dad2f
2 changed files with 25 additions and 1 deletions
+6 -1
View File
@@ -123,6 +123,7 @@ class ScraplingMCPServer:
async def open_session(
self,
session_type: SessionType,
session_id: Optional[str] = None,
headless: bool = True,
google_search: bool = True,
real_chrome: bool = False,
@@ -152,6 +153,7 @@ class ScraplingMCPServer:
Use close_session to close the session when done, and list_sessions to see all active sessions.
:param session_type: The type of session to open. Use "dynamic" for standard Playwright browser, or "stealthy" for anti-bot bypass with fingerprint spoofing.
:param session_id: Optional custom session ID. If not provided, a random 12-character hex ID will be generated. Useful for naming sessions for easier management.
:param headless: Run the browser in headless/hidden (default), or headful/visible mode.
:param google_search: Enabled by default, Scrapling will set a Google referer header.
:param real_chrome: If you have a Chrome browser installed on your device, enable this, and the Fetcher will launch an instance of your browser and use it.
@@ -175,6 +177,10 @@ class ScraplingMCPServer:
:param solve_cloudflare: (Stealthy only) Solves all types of the Cloudflare's Turnstile/Interstitial challenges.
:param additional_args: (Stealthy only) Additional arguments to be passed to Playwright's context as additional settings.
"""
session_id = session_id or uuid4().hex[:12]
if session_id in self._sessions:
raise ValueError(f"Session '{session_id}' already exists. Use a different ID or close the existing session first.")
common_kwargs: Dict[str, Any] = dict(
wait=wait,
proxy=proxy,
@@ -211,7 +217,6 @@ class ScraplingMCPServer:
await session.start()
session_id = uuid4().hex[:12]
entry = _SessionEntry(session=session, session_type=session_type)
self._sessions[session_id] = entry
+19
View File
@@ -177,6 +177,25 @@ class TestSessionManagement:
with pytest.raises(ValueError, match="not found"):
await server.fetch(url=test_url, session_id=session_id)
@pytest.mark.asyncio
async def test_open_session_with_custom_id(self, server):
"""Test opening a session with a custom session_id"""
result = await server.open_session(session_type="dynamic", session_id="my-session", headless=True)
assert isinstance(result, SessionCreatedModel)
assert result.session_id == "my-session"
await server.close_session("my-session")
@pytest.mark.asyncio
async def test_open_session_duplicate_id_raises(self, server):
"""Test that opening a session with a duplicate session_id raises an error"""
await server.open_session(session_type="dynamic", session_id="dupe", headless=True)
with pytest.raises(ValueError, match="already exists"):
await server.open_session(session_type="dynamic", session_id="dupe", headless=True)
await server.close_session("dupe")
class TestNormalizeCredentials:
"""Test the _normalize_credentials helper"""