AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Browserland

mcp-johnconnornpc-browserland · by JohnConnorNPC

Browserland is a tiled multi server terminal in browser with MCP

No reviews yet
0 installs
31 views
0.0% view→install

Install

$ agentstack add mcp-johnconnornpc-browserland

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-johnconnornpc-browserland)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Browserland? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Browserland

A web-based terminal desktop that launches, streams, and recovers a fleet of headless shells — and the AI coding agents running inside them.

Point a browser at the broker and you get a full windowed desktop of live terminals: tile them, tab them, split them, and drag them across virtual desktops. Each terminal is a real PTY running on some machine, streamed to the browser over a WebSocket.

The shells keep running even when no browser is attached. Close the tab, come back tomorrow, and the screen heals from a snapshot — exactly where you left it.

The name says it plainly: a whole little desktop — windows, terminals, and your fleet of AI coding agents — living entirely in a browser tab. (webterm is the Python package and module name.)

Browserland also exposes an MCP server, letting LLM harnesses drive the terminals directly — including full-screen TUIs.

What is this?

Browserland is two small programs and a browser:

  • Agents (producers) are headless processes that own a real terminal —

pty.openpty on Linux, ConPTY/WinPTY on Windows. An agent runs a command (bash, cmd.exe, an AI coding agent, anything), keeps a ring buffer of recent output, and streams the terminal over a single WebSocket.

  • The broker is a small web server. Agents register with it; browsers

connect to it. It relays bytes both ways, serves the desktop UI, and can spawn new agents on demand from a list of pre-approved profiles.

  • The browser renders the desktop — a tiling window manager over

xterm.js — and sends your keystrokes back to the PTY.

The wire format is a deliberately small set of JSON frames over one WebSocket, so any producer that speaks them can register with the broker — Browserland's own agent is just the reference implementation.

┌─────────┐  binary ANSI + JSON   ┌────────┐  /ws?session=  ┌─────────┐
│  agent  │ ──────────────────▶  │ broker │ ──────────────────▶ │ browser │
│ (PTY +  │ ◀──────────────────  │        │ ◀────────────────── │ xterm.js│
│ ConPTY/ │  input/resize/       └────────┘  input/paste/resize └─────────┘
│ openpty)│  snapshot_please
└─────────┘

Because the PTY lives in the agent, not the browser, terminals survive browser reloads and even broker restarts — the agent reconnects with backoff and the browser's attach triggers a snapshot redraw from the ring buffer.

Screenshots

The desktop with tiled and floating terminals

Features

  • In-browser tiling window manager (niri-style): floating and tiled

windows, a virtual-desktop pager, and a taskbar — all in the page, no native app.

  • Nested tabs and splits: any tile can hold a tab group, and tabs can hold

splits, via a recursive cell model. Build the layout you want by dragging.

text editor, a file manager, and a task manager — backed by a sandboxed /file/* API.

  • Cross-platform PTY: Linux pty.openpty; Windows auto-selects ConPTY or

WinPTY (ConPTY when a console window exists for correct Ctrl-C handling, WinPTY for headless processes).

  • AI agent fleet: detects the foreground coding agent in each window

(claude / codex / grok / opencode), tracks live OSC title + working directory, and surfaces per-window git status.

  • Multi-host: attach the same UI to additional brokers (e.g. another machine

over Tailscale), with per-host status chips in the taskbar.

  • Single active-browser lease: exactly one browser drives input at a time,

so two open tabs never fight over the keyboard.

  • Opt-in MCP / AI agent access: an MCP client or AI harness can list,

observe, drive, and launch terminals — including live interactive TUIs and the console you're working in — under per-window access modes you control. See [MCP & AI agent access](#mcp--ai-agent-access) below.

  • Token auth, no open RCE: one token gates non-loopback access and doubles

as the UI password; launching is profiles-only (the client can never supply a raw command), with a loopback exemption for local use.

MCP & AI agent access

The broker exposes a token-gated /mcp/* HTTP API and ships a stdio MCP server (webterm.mcptool), so any MCP client or AI harness can list, observe, drive, and launch terminals. The agents are just producers; the broker stays the sole authority — every MCP call is gated by the same per-window access modes and the master enable switch.

  • Interactive TUIs, as plain textread_screen renders the current

screen of a live terminal by replaying its PTY ring buffer through pyte, so a harness can read full-screen apps (btop, htop, vim, less) — not just line-oriented scrollback — and send_input types into them. Without pyte the read falls back to a dependency-free in-house renderer that still returns a bounded rendered grid (degraded: true is now reserved for a rare last-ditch raw decode).

  • The live session you're working inlist_terminals enumerates running

sessions (id, title, cwd, agent, kind, cols/rows, mode), so a harness can attach to the exact console a person is using right now, read its state, and (in readwrite) drive it. Sessions persist across browser reloads and broker restarts, so the handle stays valid.

Tools

Each tool maps to a broker endpoint and returns its JSON. Window ids are namespaced ":" strings so one server can front several brokers (see Multi-host below); with a single broker the host is default ("default:12345").

| Tool | Endpoint | Notes | |---|---|---| | mcp_info(host?) | GET /mcp/info | feature flags (allow_launch, default_mode). Omit host → dict keyed by host name | | list_terminals | GET /mcp/terminals | {"terminals":[…], "errors":{host:msg}}: all hosts merged, each terminal's host set to the config name (broker's machine hostname preserved as machine_host) + namespaced id; a down host lands in errors without sinking the rest | | list_profiles(host?) | GET /mcp/profiles | launchable profile names + default. Omit host → dict keyed by host name | | read_screen(id) | POST /mcp/read | screen rendered as a bounded plain-text grid (pyte, or a dependency-free fallback) | | send_input(id, data) | POST /mcp/input | target window must be in readwrite mode; newlines are sent as Enter (CR) so commands run (incl. on PowerShell) | | send_keys(id, keys) | POST /mcp/input | send control/escape keys["C-c"], ["Esc"], ["Up","Enter"] — that plain text can't express | | launch_terminal(profile?, cols=80, rows=24, title?, cwd?, host?) | POST /mcp/launch | broker must have allow_launch enabled; host required when multiple hosts are configured |

Multi-host. Pass --hosts (or $BROWSERLAND_MCP_HOSTS) a JSON array of {name, url, token} descriptors to serve N brokers from one server process; every id-taking tool routes on the ":…" prefix. The single --broker-url/--token form is the one-host shorthand (default). See [webterm/mcptool/README.md](webterm/mcptool/README.md) for details.

> The send_input tool maps newlines in data to a carriage return — the > byte a real Enter key sends — so a line submits on PowerShell/PSReadLine (which > treats a bare line-feed as a soft continuation) and on a Unix shell alike. The > raw POST /mcp/input endpoint stays verbatim: drive it directly to send a > literal LF or hand-crafted control/escape bytes.

Safety / enabling

Access is layered and opt-in — nothing is reachable until you turn it on:

  • Master enable is off by default; while off, every /mcp/* call returns

403 mcp_disabled.

  • Per-window mode is off / read / readwrite, with a global

default_mode for new windows. off hides a window entirely; read allows observation; readwrite additionally allows send_input.

  • allow_launch is a separate gate for launch_terminal.
  • The MCP token is a bearer secret distinct from the browser auth_token

(the UI password): the broker pins it with WEB_TERMINAL_MCP_TOKEN (or the webterm_mcp.json sidecar), and the MCP client passes the same secret via BROWSERLAND_MCP_TOKEN (as the harness examples below show).

Register with a harness

claude mcp add browserland \
  --env BROWSERLAND_MCP_TOKEN=… \
  --env BROWSERLAND_MCP_URL=http://127.0.0.1:4445 \
  -- python -m webterm.mcptool

Any other stdio MCP client (Hermes, your own, …) registers the same way — point it at the launch command and pass the two env vars:

{
  "mcpServers": {
    "browserland": {
      "command": "python",
      "args": ["-m", "webterm.mcptool"],
      "env": {
        "BROWSERLAND_MCP_TOKEN": "…",
        "BROWSERLAND_MCP_URL": "http://127.0.0.1:4445"
      }
    }
  }
}

Or run the server directly, talking to the local broker:

BROWSERLAND_MCP_TOKEN=… python -m webterm.mcptool
BROWSERLAND_MCP_TOKEN=… browserland-mcp --broker-url http://127.0.0.1:4445

For the full HTTP contract, error table, and config sidecar, see [docs/TECHNICAL.md](docs/TECHNICAL.md) and [webterm/mcptool/README.md](webterm/mcptool/README.md).

Quick start

You need Python ≥ 3.9. Install from a checkout:

pip install -e .

Windows

# broker (default 127.0.0.1:4445)
python -m webterm.broker

# an agent running cmd.exe, registered with the local broker
python -m webterm.agent -- cmd.exe

# then open http://127.0.0.1:4445/ and click the session (or "new terminal")

Windows agents also need a PTY backend: pip install -e ".[windows]" (pulls in pywinpty).

Linux

./launchers/run-broker.sh                  # broker
./launchers/run-agent.sh -- bash -l        # agent

The launcher scripts bootstrap a virtualenv with the runtime dependencies on first run. Then open http://127.0.0.1:4445/.

Install & extras

pip install -e .                       # core: broker + agent
pip install -e ".[windows]"            # + pywinpty (Windows PTY backend)
pip install -e ".[pyte]"               # + pyte (tier-2 snapshot rendering)
pip install -e ".[procs]"              # + psutil (task manager, agent badge, live cwd)
pip install -e ".[mcp]"                # + the stdio MCP server (Python ≥ 3.10)
pip install -e ".[dev]"                # + pytest for the test suite

psutil (the procs extra) is best-effort: it powers the task-manager process list, the foreground-agent badge, and live-cwd tracking. Without it the agent still runs and still destroys windows — those three views just degrade (empty list / no badge / no cwd).

Mix and match, e.g. pip install -e ".[pyte,mcp,dev]". The mcp extra requires Python ≥ 3.10 (the MCP SDK), while everything else runs on Python ≥ 3.9. See [MCP & AI agent access](#mcp--ai-agent-access) for running the server.

Project layout

| Path | What | |---|---| | webterm/agent/ | Headless producer: PTY backends, output ring buffer, OSC-title sniffer, reconnecting WebSocket client | | webterm/broker/ | Web server: desktop UI (ui.py assembles the served page from ordered *.html/*.css/*.js fragments), /ws relay, producer WS, session list, profiles-only launch | | webterm/mcptool/ | The shipped stdio MCP server wrapping the broker's /mcp/* API | | webterm/protocol.py | The single source of truth for the JSON frame shapes | | launchers/ | venv-bootstrapping run scripts (and systemd units) for both OSes | | tests/ | pytest suite: protocol, snapshots, agent↔broker integration, real-PTY round trips |

Documentation

The full engineering reference lives in [docs/TECHNICAL.md](docs/TECHNICAL.md):

  • the complete wire protocol and frame semantics,
  • the full auth model (every surface, token precedence, CORS),
  • every HTTP endpoint including the MCP HTTP contract and its error table,
  • access modes, the MCP config sidecar, and the shipped MCP server, and
  • deployment notes (systemd units, multi-host over Tailscale, testing).

License

Released under the MIT License — see [LICENSE](LICENSE).

not the.primeagen@gmail.com but hi :)

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.