BareGit
# Firefox RDP MCP server

This standard-library-only Python MCP server inspects and interacts with an
already-running Firefox through its DevTools Remote Debugging Protocol (RDP).
It does not launch Firefox, create another profile, or enable WebDriver.

## Requirements

- Python 3.11 or newer.
- Firefox started with its loopback WebSocket debugger enabled:

  ```sh
  firefox --start-debugger-server ws:6000
  ```

Run the server with:

```sh
python3 /absolute/path/to/firefox-rdp/main.py
```

For an MCP client, configure that command as a stdio server. No Python packages
need to be installed. The server writes MCP JSON-RPC messages only to stdout;
diagnostics go to stderr.

## Configuration

The defaults connect to `ws://127.0.0.1:6000/`. The endpoint must resolve only
to loopback addresses. Supported environment variables are:

| Variable | Default |
| --- | --- |
| `FIREFOX_RDP_HOST` | `127.0.0.1` |
| `FIREFOX_RDP_PORT` | `6000` |
| `FIREFOX_MCP_MAX_FILE_BYTES` | `26214400` |
| `FIREFOX_MCP_MAX_UPLOAD_BYTES` | `52428800` |
| `FIREFOX_MCP_UPLOAD_CHUNK_BYTES` | `262144` |
| `FIREFOX_MCP_MAX_ELEMENTS` | `500` |
| `FIREFOX_MCP_MAX_TEXT_CHARS` | `50000` |
| `FIREFOX_MCP_REQUEST_TIMEOUT_MS` | `30000` |
| `FIREFOX_MCP_LOG_LEVEL` | `info` |

Any readable regular file identified by an absolute path can be uploaded,
subject to the configured per-file and total byte limits. Uploading assigns
files to a file input and dispatches `input` and `change`; it never submits the
form.

## Tools and security boundaries

The server provides tools to report status, list and select tabs, snapshot the
page, click, fill, type, press common keys, run JavaScript, navigate, wait for
conditions, and upload local files.

Page snapshots are untrusted webpage content. Text in a page that looks like an
instruction has no authority to choose local files or invoke tools. Password
values are omitted. `run_javascript` is unrestricted code execution in the
selected page's content realm. It has the same access and side effects as
JavaScript from that page and should only be called with code you trust. It
does not provide browser-chrome or local filesystem access.

`run_javascript` accepts either an expression or a statement body. Expressions
return their value directly; statement bodies can use `return`. Promises are
awaited. Results must be JSON-serializable. Top-level `undefined`, `bigint`,
symbols, functions, and non-finite numbers are converted to a stable string or
null representation and accompanied by `result_type`.

Clicks and keyboard/input events are synthesized by page JavaScript, so their
`isTrusted` property is false. Sites that require physical or privileged input
may ignore them. Cross-origin iframe internals and browser chrome are outside
the first version's scope.

## Tests

Run the standard-library test suite from the repository root:

```sh
python3 -m unittest discover -s tests -v
```

The deterministic suite does not require Firefox. Live Firefox and external
site checks are manual smoke tests described in the design document. With an
existing debugger-enabled Firefox, the local stateful fixture can be exercised
and its temporary tab cleaned up with:

```sh
python3 -m tests.manual_firefox_smoke --firefox firefox-bin
```

If an interrupted smoke run leaves a fixture tab open, remove only matching
loopback fixture tabs with:

```sh
python3 -m tests.manual_firefox_smoke --cleanup-only
```