Skip to content

Fix: Resolve browser multiplication issue in Puppeteer MCP server #2307

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

zitrono
Copy link

@zitrono zitrono commented Jul 8, 2025

Problem

The Puppeteer MCP server was creating multiple Chrome browser instances with each tool call instead of reusing existing instances, leading to resource exhaustion and performance issues.

Symptoms

  • Chrome process count growing with each Puppeteer tool call
  • System resource exhaustion (memory, CPU)
  • Performance degradation over time
  • Multiple browser windows opening in non-headless mode

Root Cause

The ensureBrowser() function had several critical issues:

  1. Flawed browser restart logic: New browsers were launched without properly closing existing ones
  2. No browser health validation: Dead browser instances were not detected
  3. Missing process cleanup: Orphaned Chrome processes accumulated
  4. Race conditions: Multiple concurrent tool calls could trigger multiple browser launches

Solution

This PR implements a comprehensive fix with the following improvements:

1. Browser Health Monitoring

  • Added isBrowserHealthy() function to validate browser connectivity and responsiveness
  • Checks both connection status and ability to retrieve pages with timeout protection

2. Launch Concurrency Protection

  • Implemented browserLaunching flag to prevent concurrent browser launches
  • Ensures only one browser launch can occur at a time
  • Subsequent calls wait for the launch to complete

3. Enhanced Graceful Cleanup

  • Improved browser closing with 5-second timeout protection
  • Falls back to process-level cleanup if graceful close fails
  • Added 500ms delay after cleanup to ensure proper resource release

4. Process Signal Handlers

  • Added handlers for SIGINT, SIGTERM, SIGHUP, and uncaught exceptions
  • Ensures proper cleanup on server shutdown
  • Prevents orphaned processes on unexpected exits

5. Chrome Process Cleanup

  • Implemented cleanupChromeProcesses() to kill orphaned Chrome instances
  • Uses platform-specific commands to ensure cleanup
  • Called on both normal and error paths

Testing

Tested the fix extensively:

  • ✅ Multiple rapid tool calls (navigate, screenshot, evaluate)
  • ✅ Verified stable browser count (no multiplication)
  • ✅ Tested server restart scenarios
  • ✅ Confirmed backward compatibility
  • ✅ All existing functionality preserved

Before Fix

  • Started with 6 Chrome processes
  • After 4 tool calls: 15 processes
  • After 7 tool calls: 15+ processes (continuously growing)

After Fix

  • Stable at 15 processes regardless of tool call count
  • Proper reuse of existing browser instance
  • Clean shutdown with no orphaned processes

Breaking Changes

None - this is a backward-compatible bug fix that maintains all existing APIs and behavior.

Notes

  • The fix is applied to the TypeScript source in the archive-servers branch
  • The compiled JavaScript output has been tested and verified
  • The same issue likely affects the npm-published version of @modelcontextprotocol/server-puppeteer

🤖 Generated with Claude Code

Co-Authored-By: Claude [email protected]

This commit fixes a critical issue where multiple Chrome browser instances
were being created with each tool call instead of reusing existing instances,
leading to resource exhaustion and performance degradation.

Root Cause:
- Flawed browser restart logic in ensureBrowser() function
- No browser health validation before reuse
- Missing process cleanup for orphaned Chrome instances
- Lack of concurrency protection during browser launches

Solution:
- Added browser health monitoring with isBrowserHealthy() function
- Implemented launch concurrency protection using browserLaunching flag
- Enhanced graceful browser cleanup with timeouts
- Added comprehensive process signal handlers (SIGINT, SIGTERM, etc.)
- Implemented Chrome process cleanup for orphaned instances

Testing:
- Tested with multiple rapid tool calls (navigate, screenshot, evaluate)
- Verified stable browser count with no multiplication
- Confirmed backward compatibility
- All existing functionality preserved

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@olaservo
Copy link
Member

Hi @zitrono , the Puppeteer reference server has been archived and is no longer being maintained, so I would recommend maintaining your own fork instead. Thanks!

@olaservo olaservo closed this Jul 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants