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:
@@ -123,6 +123,7 @@ class ScraplingMCPServer:
|
|||||||
async def open_session(
|
async def open_session(
|
||||||
self,
|
self,
|
||||||
session_type: SessionType,
|
session_type: SessionType,
|
||||||
|
session_id: Optional[str] = None,
|
||||||
headless: bool = True,
|
headless: bool = True,
|
||||||
google_search: bool = True,
|
google_search: bool = True,
|
||||||
real_chrome: bool = False,
|
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.
|
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_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 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 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.
|
: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 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.
|
: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(
|
common_kwargs: Dict[str, Any] = dict(
|
||||||
wait=wait,
|
wait=wait,
|
||||||
proxy=proxy,
|
proxy=proxy,
|
||||||
@@ -211,7 +217,6 @@ class ScraplingMCPServer:
|
|||||||
|
|
||||||
await session.start()
|
await session.start()
|
||||||
|
|
||||||
session_id = uuid4().hex[:12]
|
|
||||||
entry = _SessionEntry(session=session, session_type=session_type)
|
entry = _SessionEntry(session=session, session_type=session_type)
|
||||||
self._sessions[session_id] = entry
|
self._sessions[session_id] = entry
|
||||||
|
|
||||||
|
|||||||
@@ -177,6 +177,25 @@ class TestSessionManagement:
|
|||||||
with pytest.raises(ValueError, match="not found"):
|
with pytest.raises(ValueError, match="not found"):
|
||||||
await server.fetch(url=test_url, session_id=session_id)
|
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:
|
class TestNormalizeCredentials:
|
||||||
"""Test the _normalize_credentials helper"""
|
"""Test the _normalize_credentials helper"""
|
||||||
|
|||||||
Reference in New Issue
Block a user