Skip to content

fix: allow standalone browser MCP startup#7

Merged
skulidropek merged 2 commits into
mainfrom
fix/standalone-browser-network-fallback
May 24, 2026
Merged

fix: allow standalone browser MCP startup#7
skulidropek merged 2 commits into
mainfrom
fix/standalone-browser-network-fallback

Conversation

@skulidropek
Copy link
Copy Markdown
Member

Summary

  • fall back from missing container: network namespace to Docker bridge mode so browser-connection --project dg-my-project no longer fails with Docker status 125
  • publish deterministic per-project localhost ports for bridge-mode browser containers and probe both host ports and Docker bridge IPs
  • return the actually reachable CDP/noVNC URLs to the MCP server so tools and noVNC point at the same running browser session
  • document standalone startup behavior and update URL invariants/tests

Verification

  • cargo fmt --check
  • cargo test --locked
  • cargo clippy --locked --all-targets -- -D warnings
  • runtime: target/debug/docker-git-browser-connection start --project dg-my-project returned http://172.18.0.16:9223 and http://172.18.0.16:6080/vnc.html?... because 127.0.0.1 host ports are not reachable from this containerized Docker host
  • runtime: curl CDP /json/version succeeded against the resolved URL
  • runtime: noVNC page loaded against the resolved URL
  • runtime: MCP stdio browser_navigate/browser_evaluate/browser_snapshot succeeded and X11 framebuffer screenshot showed "MCP noVNC unified OK"
  • runtime: WebSocket upgrade to /websockify returned HTTP 101 and RFB 003.008

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Deterministic per-project browser port allocation for consistent runtime configuration
    • Enhanced browser connection endpoint resolution with improved fallback handling for container networking
  • Bug Fixes

    • Improved container network mode detection with fallback when referenced containers are unavailable
    • Conditional port publishing to prevent conflicts in container and host networking modes
  • Documentation

    • Updated browser connection documentation with improved usage examples and health-check URLs
  • Chores

    • Pinned dependency versions to exact releases for reproducible builds

Walkthrough

This PR refactors browser container provisioning to support deterministic per-project port allocation and runtime-resolved endpoints. The core change introduces BrowserPorts for port assignment, BrowserRuntime to carry resolved CDP/noVNC URLs, network inspection with fallback logic, and endpoint probing that returns URLs instead of just success indicators.

Changes

Browser Port Allocation and Runtime Resolution

Layer / File(s) Summary
Port allocation foundation
src/lib.rs
BrowserPorts struct with vnc/novnc/cdp fields; compute_browser_ports(project_id) derives ports from a hash-based offset; BrowserSpec extended with ports field computed in the resolver-based constructor.
URL rendering and session validation
src/lib.rs
render_novnc_url_for_ports and render_cdp_url_for_ports helpers construct localhost URLs from port structs; is_single_browser_session updated to validate by URL shape (noVNC path + scheme) rather than exact CDP match.
BrowserRuntime structure and network inspection
src/browser.rs
BrowserRuntime struct carries container_name, novnc_url, and cdp_url; network inspection helpers determine effective network mode with fallback from container: to bridge when the referenced container isn't running; should_publish_ports controls whether ports are published to 127.0.0.1.
Container provisioning refactor
src/browser.rs
ensure_browser_container returns BrowserRuntime with resolved endpoints; handles existing containers by inspecting effective network mode and recomputing URLs; adds docker_dynamic for variable-arity Docker command construction.
Container startup with conditional port publishing
src/browser.rs
docker run command construction dynamically builds arguments and conditionally publishes VNC/noVNC/CDP ports to 127.0.0.1 only when appropriate (avoiding publication for container: and host network modes).
Readiness probing with endpoint resolution
src/browser.rs
noVNC probe candidates generation and runtime_urls helper compute both endpoints; CDP readiness probing returns the resolved base URL via cdp_version_url_to_base; wait_for_novnc polls candidate URLs until successful or timeout, returning the working URL.
BrowserConnection integration
src/lib.rs, src/browser.rs
BrowserConnection::start_browser uses runtime result from ensure_browser_container for resolved endpoints; get_novnc_url and get_cdp_url compute URLs dynamically from project_id via deterministic port computation. Unit test added for effective_network_mode fallback behavior.
Test suite updates
tests/browser_invariants.rs, tests/cli_status.rs
browser_invariants.rs imports port-specific URL renderers, updates invariant assertion using spec.ports, adds test verifying distinct localhost URLs for different project IDs. cli_status.rs computes expected URLs dynamically from computed ports instead of hardcoded literals and adds invariant-check assertion.
Documentation and dependencies
README.md, Cargo.toml, changelog.d/...
README updated to document standalone browser-connection usage with container fallback and dynamic health-check guidance; "Runtime flow" diagram describes URL resolution generically. Cargo.toml pins clap (4.4.18), tempfile (3.10.1), proptest (1.4.0); changelog records pinning and Cargo.lock v3 regeneration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ProverCoderAI/rust-browser-connection#4: The refactor of BrowserConnection/DockerBrowserShell endpoint resolution and port-aware URL computation is directly upstream of the browser-connection MCP server implementation.
  • ProverCoderAI/rust-browser-connection#2: Both PRs refactor the same core browser-connection implementation (container provisioning, URL rendering, and readiness probing) with this PR building on the foundation established there.

Poem

🐰 Per-project ports now dance with grace,
Endpoints resolved at runtime's pace,
Network modes fall back with care,
Docker's bridge is always there—
URLs rendered, tests all pass! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: allow standalone browser MCP startup' directly relates to the main objective of enabling browser-connection to work in standalone/containerized environments by implementing network fallback logic.
Description check ✅ Passed The description comprehensively addresses the changeset, outlining the network fallback mechanism, port allocation strategy, URL resolution approach, and documentation updates with detailed verification steps.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/standalone-browser-network-fallback

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/lib.rs (2)

48-59: 💤 Low value

Port collision risk with 400 possible offsets.

The hash modulo 400 means different project IDs can collide to the same ports. If two projects with colliding hashes run simultaneously on the same host, they'll conflict. The inline comment acknowledges this ("usually map to different offsets"), so this appears intentional.

If collision avoidance becomes important, consider widening the offset range or adding runtime port availability checks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib.rs` around lines 48 - 59, compute_browser_ports currently uses hash %
400 which risks port collisions; update compute_browser_ports (and related
constants BROWSER_VNC_PORT, BROWSER_NOVNC_PORT, BROWSER_CDP_PORT) to reduce
collisions by either increasing the offset space (e.g., use hash % 2000 or a
configurable MAX_OFFSET) or implement a runtime availability probe: compute an
initial offset from normalize_project_container_name, then test the candidate
ports (vnc/novnc/cdp) for availability and, if any are in use, increment the
offset (wrapping within the allowed range) until a free triplet is found or
return an error; ensure the probe logic is placed in or called from
compute_browser_ports and document the new MAX_OFFSET/config option.

215-218: 💤 Low value

Function name may mislead after logic change.

is_single_browser_session now only validates URL shapes (noVNC path present, CDP uses HTTP/HTTPS scheme) rather than verifying both URLs point to the same session. The name suggests session identity verification, but the implementation is a format check.

Consider renaming to are_valid_browser_urls or similar, or documenting that "single session" is an assumption based on URL validity rather than an enforced invariant.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib.rs` around lines 215 - 218, The function is_single_browser_session no
longer checks session identity and only validates URL shapes; rename the
function to are_valid_browser_urls (or another clear name) and update all
callers to use are_valid_browser_urls(cdp_url, novnc_url), or alternatively keep
the existing name but add a doc comment on is_single_browser_session that
explicitly states it only checks novnc_url contains "/vnc.html" and cdp_url
starts with "http://" or "https://" (i.e., a format check, not identity
verification); update any unit tests and references to match the new name or
documentation to avoid misleading semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 55: The curl health-check example uses a Host header port 9222 that
doesn't match the URL port 9593; update the example curl command (the line
starting with "curl -H 'Host: 127.0.0.1:9222'
http://127.0.0.1:9593/json/version") so the Host header port is 9593 (e.g.,
"Host: 127.0.0.1:9593") to match the CDP port shown earlier.

---

Nitpick comments:
In `@src/lib.rs`:
- Around line 48-59: compute_browser_ports currently uses hash % 400 which risks
port collisions; update compute_browser_ports (and related constants
BROWSER_VNC_PORT, BROWSER_NOVNC_PORT, BROWSER_CDP_PORT) to reduce collisions by
either increasing the offset space (e.g., use hash % 2000 or a configurable
MAX_OFFSET) or implement a runtime availability probe: compute an initial offset
from normalize_project_container_name, then test the candidate ports
(vnc/novnc/cdp) for availability and, if any are in use, increment the offset
(wrapping within the allowed range) until a free triplet is found or return an
error; ensure the probe logic is placed in or called from compute_browser_ports
and document the new MAX_OFFSET/config option.
- Around line 215-218: The function is_single_browser_session no longer checks
session identity and only validates URL shapes; rename the function to
are_valid_browser_urls (or another clear name) and update all callers to use
are_valid_browser_urls(cdp_url, novnc_url), or alternatively keep the existing
name but add a doc comment on is_single_browser_session that explicitly states
it only checks novnc_url contains "/vnc.html" and cdp_url starts with "http://"
or "https://" (i.e., a format check, not identity verification); update any unit
tests and references to match the new name or documentation to avoid misleading
semantics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c0f4306-f05c-48bf-9469-2eeb56f5c450

📥 Commits

Reviewing files that changed from the base of the PR and between 614339f and 48c5b47.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • README.md
  • changelog.d/20260524_141210_browser_connection_mcp.md
  • src/browser.rs
  • src/lib.rs
  • tests/browser_invariants.rs
  • tests/cli_status.rs

Comment thread README.md
open http://127.0.0.1:6080/vnc.html?autoconnect=true\&resize=remote\&path=websockify
# Use the CDP/noVNC URLs printed by `start`; in containerized Docker hosts the
# module may choose the browser container IP instead of 127.0.0.1 host ports.
curl -H 'Host: 127.0.0.1:9222' http://127.0.0.1:9593/json/version
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Port mismatch in Host header and URL.

The curl health check uses port 9222 in the Host header but port 9593 in the URL. Based on the example output at line 47, the CDP port for this project is 9593, so the Host header should match.

📝 Proposed fix
-curl -H 'Host: 127.0.0.1:9222' http://127.0.0.1:9593/json/version
+curl -H 'Host: 127.0.0.1:9593' http://127.0.0.1:9593/json/version
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
curl -H 'Host: 127.0.0.1:9222' http://127.0.0.1:9593/json/version
curl -H 'Host: 127.0.0.1:9593' http://127.0.0.1:9593/json/version
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 55, The curl health-check example uses a Host header port
9222 that doesn't match the URL port 9593; update the example curl command (the
line starting with "curl -H 'Host: 127.0.0.1:9222'
http://127.0.0.1:9593/json/version") so the Host header port is 9593 (e.g.,
"Host: 127.0.0.1:9593") to match the CDP port shown earlier.

@skulidropek skulidropek merged commit 396d264 into main May 24, 2026
14 checks passed
@skulidropek skulidropek deleted the fix/standalone-browser-network-fallback branch May 24, 2026 15:16
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.

1 participant