Lazy MCP Broker
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Lazy MCP Brokerlist the cached tools from the Playwright MCP server"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Lazy MCP Broker
A localhost MCP lifecycle broker that keeps reviewed tool schemas available while scaling expensive stdio MCP servers and browsers to zero when idle.
This repository is a deliberately narrow reference implementation for a hard operational case: several long-lived AI clients share browser-heavy MCP servers across WSL and Windows, but those servers must not stay resident, leak processes, or lose session isolation.
Status: working reference deployment, not a drop-in universal gateway. The checked-in
config.jsonand systemd unit contain deployment-specific absolute paths. Replace them before using this on another machine.
The problem
Registering Playwright, Chrome DevTools, and similar MCP servers directly in every agent process creates several problems:
every client starts or owns its own expensive backend;
Chromium, Windows Chrome, Node, and receiver processes can survive cancellation or transport failure;
browser state must be isolated per MCP session while some backends must remain singleton;
a health endpoint can be green even when
npx, the browser executable, or the real MCP call path is broken;killing processes by executable name is unsafe on a workstation with unrelated Chrome, Node, Codex, or browser sessions;
keeping all heavy servers alive wastes memory and process slots even when only their tool schemas are needed.
Lazy MCP Broker keeps one small HTTP service alive, serves validated cached tool
catalogs without starting upstreams, and starts only the backend that receives a
real tools/call. After a bounded idle period, that backend and every process it
owns must return to zero.
Related MCP server: wsl-mcp
Why build this when MCP gateways already exist?
There are good existing projects. Use them when their model fits:
Project | What it is good at | Why this repository still exists |
Broad, container-oriented MCP orchestration, isolation, credentials, policy, logging, and lifecycle management. | This deployment must supervise host processes on both sides of WSL, including Windows Chrome identified through | |
A full aggregator, orchestrator, middleware, and gateway with namespaces and a management surface. | That is a broader control plane. This project is intentionally a small localhost process supervisor with fixed reviewed configuration, stable per-backend URLs, no database, and no remote multi-user surface. | |
Bridging stdio MCP servers to Streamable HTTP/SSE and connecting between MCP transports. | Transport conversion alone does not provide this broker's per-session/singleton scopes, bounded FIFO dispatch, idle scale-to-zero, generation invalidation, or exact cross-OS process cleanup. | |
Reducing schema/context cost by exposing four gateway tools and loading selected servers on demand. | Its proxy-tool model changes how the model discovers and calls tools ( |
So the claim is not “other gateways do not work.” The missing combination for this deployment was:
native cached schemas at stable HTTP MCP endpoints;
no heavy process on
initializeortools/list;per-session browser isolation plus singleton backends;
bounded queues, calls, cancellation, shutdown, and recovery;
fail-closed ownership cleanup across Linux/WSL and Windows;
an installed-service probe that makes real tool calls and then proves scale-to-zero.
If you need a general enterprise gateway, start with Docker MCP Gateway or
MetaMCP. If you only need transport conversion, use mcp-proxy. If replacing
native tools with a small lazy gateway API is acceptable, RaiAnsar's
mcp-gateway is simpler. This project is for the narrower lifecycle and process
ownership problem above.
Architecture
Hermes CLI 1 ─┐
Hermes CLI 2 ─┼─ Streamable HTTP → broker :8788
Gateway ──────┘ │
├─ Playwright MCP + Linux Chromium
│ per session, lazy
├─ Chrome DevTools MCP + Windows Chrome
│ per session, lazy
└─ Agentation MCP
singleton, lazyThe request flow is:
initialize / tools/list
→ validate and return cached catalog
→ do not start an upstream process
tools/call
→ validate the tool against the reviewed catalog
→ resolve the session or singleton backend instance
→ enqueue within a bounded FIFO
→ cold-start one upstream generation if needed
→ execute with a deadline
→ return the MCP result
idle / cancellation / timeout / crash / service shutdown
→ stop accepting work for the affected generation
→ bounded graceful MCP close
→ exact-generation POSIX cleanup
→ exact-marker Windows cleanup when configured
→ re-query ownership
→ stopped only when owned-process count is zeroLifecycle invariants
Generation isolation
Every cold start increments a generation. Async callbacks capture the instance and generation, so stale work from generation N cannot mutate generation N+1. A timeout, cancellation, or transport failure invalidates the active generation before recovery.
Fail-closed cleanup
A backend cannot silently move to stopped when cleanup is uncertain:
graceful close
→ POSIX exact-generation cleanup
→ Windows exact-marker query/terminate/re-query
→ zero verified: stopped
→ query failure or survivors: cleanup_failedcleanup_failed blocks new calls, previously queued calls, and replacement
generations. Graceful close has a sub-budget so it cannot consume the entire stop
deadline and prevent ownership cleanup.
Safe process ownership
Linux/WSL children carry exact LAZY_MCP_INSTANCE_ID and
LAZY_MCP_GENERATION environment markers. Their start identity is revalidated
immediately before signaling; pidfd is used when available.
Windows Chrome generations use an exact broker-generated command-line marker:
hermes-lazy-mcp\chrome-{instance_id}-{generation}The broker queries Win32_Process, retains bounded process identity fields,
revalidates PID plus creation timestamp before termination, and re-queries until
zero or deadline. It never runs broad taskkill, pkill chrome, or
name-matched Node cleanup.
Hard evidence deadline
The synthetic probe places blocking systemd and PowerShell evidence collection behind a dedicated process-group boundary. If the monotonic deadline expires, the whole helper group is killed and reaped. Cancelling a worker thread is not accepted as timeout proof.
Current reference backends
Backend | Scope | Idle timeout | Queue limit | Upstream |
Playwright | per MCP session | 120 s | 32 |
|
Chrome DevTools on Windows | per MCP session | 120 s | 32 |
|
Agentation | singleton | 60 s | 64 |
|
Package versions and catalogs are pinned so an upstream schema change cannot silently expose a new mutating tool.
Endpoints
http://127.0.0.1:8788/playwright/mcphttp://127.0.0.1:8788/chrome-devtools-win/mcphttp://127.0.0.1:8788/agentation/mcphttp://127.0.0.1:8788/healthhttp://127.0.0.1:8788/readyhttp://127.0.0.1:8788/status
/health proves event-loop liveness. /ready proves validated configuration,
catalogs, and running supervisors without launching a browser. Neither endpoint
claims that the real upstreams work. Use the synthetic probe for that.
Requirements
The reference deployment currently assumes:
Python 3.11+;
uvor another Python environment manager;Node.js and
npx;Linux with systemd user services;
WSL interop and Windows PowerShell for the Windows ownership backend;
installed Linux and Windows Chromium executables.
The core broker can run without Windows ownership mode, but the checked-in production configuration is specifically a WSL + Windows Chrome deployment.
Setup
1. Install Python dependencies
git clone https://github.com/trym-s/lazy-mcp-broker.git
cd lazy-mcp-broker
uv sync2. Adapt the reference configuration
Edit config.json and replace all machine-specific paths:
Linux
npxpath;Linux Chromium executable;
Windows home directory;
Windows Chromium executable;
catalog paths if the working directory changes.
Do not weaken the Windows ownership marker or replace it with executable-name matching.
3. Validate locally
PYTHONPATH=src uv run pytest -q
PYTHONPATH=src uv run python -m lazy_mcp_broker.server --config config.jsonIn another shell:
curl --fail http://127.0.0.1:8788/ready
curl --fail http://127.0.0.1:8788/status4. Install the user service
deploy/hermes-lazy-mcp-broker.service is a reference unit with absolute paths.
Copy it only after editing Environment=PYTHONPATH and ExecStart:
mkdir -p ~/.config/systemd/user
cp deploy/hermes-lazy-mcp-broker.service \
~/.config/systemd/user/hermes-lazy-mcp-broker.service
systemctl --user daemon-reload
systemctl --user enable --now hermes-lazy-mcp-broker.serviceThen point MCP clients at the stable endpoint URLs above.
Verification
Fast suite
PYTHONPATH=src uv run pytest -q
PYTHONPATH=src uv run python -m unittest scripts/test_real_harness.py -vInstalled-service synthetic proof
PYTHONPATH=src uv run python scripts/synthetic_probe.py \
--base http://127.0.0.1:8788 \
--output runtime-evidence/synthetic-latest.jsonThe probe:
requires a clean baseline;
makes harmless real Playwright, Windows Chrome DevTools, and Agentation calls;
observes the exact Chrome generation marker while active;
waits only the configured idle-plus-stop bound;
requires zero active and queued calls;
requires zero non-idle backend instances;
requires zero heavy broker-owned Linux processes;
requires zero Windows processes for every recorded marker;
requires unchanged broker PID and restart count.
The most recent controlled implementation run passed 47 tests, the harness suite, an exact-marker Windows decoy test, all three real backend calls, and final scale-to-zero. Raw runtime evidence is intentionally ignored by Git because it is machine-specific. See docs/REAL_WORLD_PROOF.md for the recorded acceptance evidence and its limitations.
Refreshing cached catalogs
After intentionally upgrading an upstream MCP package:
PYTHONPATH=src uv run python scripts/refresh_real_catalogs.pyReview every catalog diff before restarting the broker. A catalog includes the package name, pinned version, generation timestamp, schema digest, enabled tools, and explicitly excluded tools. Startup rejects catalog tampering or mismatch.
Security boundaries
The server is loopback-only and rejects unexpected Host/Origin values.
Backend commands, arguments, environment additions, and deadlines come from reviewed configuration, never client input.
Browser profiles are headless and isolated.
Chrome DevTools usage statistics and CrUX requests are disabled.
Network headers returned by Chrome DevTools are redacted.
Status and lifecycle logs omit raw arguments, credentials, URLs, page content, backend output, and full process command lines.
Queues are bounded; overload is explicit rather than unbounded memory growth.
Cleanup targets exact generation ownership, never global executable names.
This is not a remotely exposed multi-user gateway. There is no authentication
layer because the broker is designed to bind only to 127.0.0.1. Do not expose
port 8788 to a LAN or the internet without adding a real authentication and
authorization boundary.
Known limitations
config.jsonand the systemd unit are deployment-specific references, not an installer-generated portable configuration.The synthetic probe is currently specialized for the three reference backends.
Cached catalogs must be refreshed deliberately after upstream upgrades.
A literal Windows/WSL reboot acceptance run has not yet been recorded; service restart and user-service enablement have been verified.
A Hermes Agent one-shot shutdown path can emit
_watch_stdio_children was never awaited; it is upstream of this broker and remains unresolved here.
Documentation
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for Superserve sandboxes: create, exec, and manage Firecracker microVMs
A paid remote MCP for AI agent browser MCP session, built to return verdicts, receipts, usage logs,
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Hosted MCP server for task-first delegation to remote workstations and workers.
Related MCP Servers
- AlicenseAqualityAmaintenanceMCP server for SSH and local terminal access. Supports interactive commands, long-running processes, and TUI apps like tmux/zellij63MIT
- AlicenseNot gradedqualityDmaintenanceA MCP terminal management server with persistent sessions and terminal polling, optimized for Windows + WSL environments.151MIT
- FlicenseNot gradedqualityCmaintenanceProvides stateful development sessions for code-server, enabling persistent shells, background processes, sandboxed file operations, and file watching through MCP.-
- AlicenseNot gradedqualityBmaintenanceEnables multiple Claude Code sessions to share a single HTTP MCP endpoint, lazily spawning stdio MCP servers only when their tools are called, reducing idle processes and memory usage.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/trym-s/lazy-mcp-broker'
If you have feedback or need assistance with the MCP directory API, please join our Discord server