Skip to content

Commit a6b3147

Browse files
committed
refactor(drivers): improve session management and cleanup
1 parent e5dd94d commit a6b3147

File tree

3 files changed

+52
-35
lines changed

3 files changed

+52
-35
lines changed

linkedin_mcp_server/drivers/chrome.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import logging
1010
import os
11+
import shutil
12+
import tempfile
1113
from typing import Dict, Optional
1214

1315
from linkedin_scraper.exceptions import (
@@ -32,13 +34,19 @@
3234
# Global driver storage to reuse sessions
3335
active_drivers: Dict[str, webdriver.Chrome] = {}
3436

37+
# Store user data directories for cleanup
38+
user_data_dirs: Dict[str, str] = {}
39+
3540
logger = logging.getLogger(__name__)
3641

3742

38-
def create_chrome_driver() -> webdriver.Chrome:
43+
def create_chrome_driver(session_id: str = "default") -> webdriver.Chrome:
3944
"""
4045
Create a new Chrome WebDriver instance with proper configuration.
4146
47+
Args:
48+
session_id: Unique identifier for the session (used for cleanup)
49+
4250
Returns:
4351
webdriver.Chrome: Configured Chrome WebDriver instance
4452
@@ -63,6 +71,14 @@ def create_chrome_driver() -> webdriver.Chrome:
6371
chrome_options.add_argument("--disable-extensions")
6472
chrome_options.add_argument("--disable-background-timer-throttling")
6573

74+
# Create a unique user data directory to avoid conflicts
75+
user_data_dir = tempfile.mkdtemp(prefix="linkedin_mcp_chrome_")
76+
chrome_options.add_argument(f"--user-data-dir={user_data_dir}")
77+
logger.debug(f"Using Chrome user data directory: {user_data_dir}")
78+
79+
# Store the user data directory for cleanup
80+
user_data_dirs[session_id] = user_data_dir
81+
6682
# Set user agent (configurable with sensible default)
6783
user_agent = getattr(config.chrome, "user_agent", DEFAULT_USER_AGENT)
6884
chrome_options.add_argument(f"--user-agent={user_agent}")
@@ -213,7 +229,7 @@ def get_or_create_driver(authentication: str) -> webdriver.Chrome:
213229

214230
try:
215231
# Create new driver
216-
driver = create_chrome_driver()
232+
driver = create_chrome_driver(session_id)
217233

218234
# Login to LinkedIn
219235
login_to_linkedin(driver, authentication)
@@ -245,7 +261,7 @@ def get_or_create_driver(authentication: str) -> webdriver.Chrome:
245261

246262
def close_all_drivers() -> None:
247263
"""Close all active drivers and clean up resources."""
248-
global active_drivers
264+
global active_drivers, user_data_dirs
249265

250266
for session_id, driver in active_drivers.items():
251267
try:
@@ -254,8 +270,21 @@ def close_all_drivers() -> None:
254270
except Exception as e:
255271
logger.warning(f"Error closing driver {session_id}: {e}")
256272

273+
# Clean up user data directory
274+
if session_id in user_data_dirs:
275+
try:
276+
user_data_dir = user_data_dirs[session_id]
277+
if os.path.exists(user_data_dir):
278+
shutil.rmtree(user_data_dir)
279+
logger.debug(f"Cleaned up user data directory: {user_data_dir}")
280+
except Exception as e:
281+
logger.warning(
282+
f"Error cleaning up user data directory for session {session_id}: {e}"
283+
)
284+
257285
active_drivers.clear()
258-
logger.info("All Chrome WebDriver sessions closed")
286+
user_data_dirs.clear()
287+
logger.info("All Chrome WebDriver sessions closed and cleaned up")
259288

260289

261290
def get_active_driver() -> Optional[webdriver.Chrome]:

linkedin_mcp_server/server.py

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
from fastmcp import FastMCP
1212

13-
from linkedin_mcp_server.drivers.chrome import active_drivers
1413
from linkedin_mcp_server.tools.company import register_company_tools
1514
from linkedin_mcp_server.tools.job import register_job_tools
1615
from linkedin_mcp_server.tools.person import register_person_tools
@@ -31,42 +30,25 @@ def create_mcp_server() -> FastMCP:
3130
@mcp.tool()
3231
async def close_session() -> Dict[str, Any]:
3332
"""Close the current browser session and clean up resources."""
34-
session_id = "default" # Using the same default session
33+
from linkedin_mcp_server.drivers.chrome import close_all_drivers
3534

36-
if session_id in active_drivers:
37-
try:
38-
active_drivers[session_id].quit()
39-
del active_drivers[session_id]
40-
return {
41-
"status": "success",
42-
"message": "Successfully closed the browser session",
43-
}
44-
except Exception as e:
45-
return {
46-
"status": "error",
47-
"message": f"Error closing browser session: {str(e)}",
48-
}
49-
else:
35+
try:
36+
close_all_drivers()
37+
return {
38+
"status": "success",
39+
"message": "Successfully closed the browser session and cleaned up resources",
40+
}
41+
except Exception as e:
5042
return {
51-
"status": "warning",
52-
"message": "No active browser session to close",
43+
"status": "error",
44+
"message": f"Error closing browser session: {str(e)}",
5345
}
5446

5547
return mcp
5648

5749

5850
def shutdown_handler() -> None:
5951
"""Clean up resources on shutdown."""
60-
for session_id, driver in list(active_drivers.items()):
61-
try:
62-
driver.quit()
63-
del active_drivers[session_id]
64-
except Exception as e:
65-
logger.error(
66-
f"Error closing driver during shutdown: {e}",
67-
extra={
68-
"session_id": session_id,
69-
"exception_type": type(e).__name__,
70-
"exception_message": str(e),
71-
},
72-
)
52+
from linkedin_mcp_server.drivers.chrome import close_all_drivers
53+
54+
close_all_drivers()

linkedin_mcp_server/setup.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import logging
99
import os
10+
import tempfile
1011
from contextlib import contextmanager
1112
from typing import Dict, Iterator
1213

@@ -119,6 +120,11 @@ def temporary_chrome_driver() -> Iterator[webdriver.Chrome]:
119120
# chrome_options.add_argument("--disable-gpu")
120121
# chrome_options.add_argument("--window-size=3456,2234")
121122

123+
# Create a unique user data directory to avoid conflicts
124+
user_data_dir = tempfile.mkdtemp(prefix="linkedin_mcp_setup_")
125+
chrome_options.add_argument(f"--user-data-dir={user_data_dir}")
126+
logger.debug(f"Using Chrome user data directory for setup: {user_data_dir}")
127+
122128
driver = None
123129
try:
124130
# Create temporary driver

0 commit comments

Comments
 (0)