firefox-mcp
Enables AI applications to drive the user's own Firefox browser, including signed-in sites and profile, through tabs. It supports navigation, page interaction, form filling, snapshots, screenshots, tab management, console and network inspection, and waiting for page conditions.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
MCP for Firefox
Lets AI apps (Claude Code, Cursor, VS Code, Claude Desktop…) use your own Firefox: your signed-in sites and your profile, in tabs of their own. Everything runs on your computer.
It's Browser MCP for Firefox, with the same browser tool and command language, so prompts written for it carry over. The way it drives the browser had to be rebuilt, because Browser MCP relies on chrome.debugger, which Firefox doesn't have (what that changes).
AI app ──stdio──▶ firefox-mcp ──▶ daemon (one per user, on 127.0.0.1) ──▶ extension ──▶ your tabsInstall
You need Node.js 20 or later and Firefox 140 or later.
1. Build it
npm install
npm run build2. Load the extension. It isn't on addons.mozilla.org, so pick one:
How | Lasts | |
Try it |
| Until Firefox restarts |
Nightly or Developer Edition | Set | Permanently |
Regular Firefox | Get it signed by Mozilla as an unlisted add-on: | Permanently |
3. Add the server to your AI app's MCP config
{
"mcpServers": {
"firefox": {
"command": "node",
"args": ["/path/to/firefox-mcp/dist/server/index.js"]
}
}
}For Claude Code: claude mcp add firefox -- node /path/to/firefox-mcp/dist/server/index.js
4. Approve it. Ask the AI app to do something in the browser. The first time, the toolbar button shows !. Open it, check that the six-digit code matches the one the AI app shows, and click Allow. That's once per computer.
Related MCP server: Cloudflare Playwright MCP
What agents can do
One tool, browser, takes command lines and runs them in order, stopping at the first error:
goto https://example.com/login
fill getByLabel('Email') "ada@example.com"
fill getByLabel('Password') "…" --submit
wait --text "Welcome"
snapshot -iNavigate |
|
Act |
|
Look |
|
Debug |
|
Tabs |
|
Wait |
|
Targets are refs from a snapshot (e12, or f1e3 in an iframe), locators (getByRole('button', { name: 'Go' }), getByLabel, getByText, getByPlaceholder, getByTestId, .first(), .nth(i), .filter({ hasText }), frameLocator('#f').getByText('…')) or CSS. They reach into shadow roots, closed ones too, and cross-origin iframes. fill and upload are the exception: they look only in the page itself unless the target is a ref or goes through frameLocator, so a password meant for the page can't land in an ad's or a widget's iframe. help <command> prints the details.
What Firefox does differently
Firefox's extension API has no way to send real input, attach a debugger or answer a dialog, so these work differently from Browser MCP:
What happens here | What that means | |
Clicks and keys | Synthesized, so | A site that checks |
Typing |
| Works with React and rich editors |
Key effects | Done by the extension: Enter submits, Tab moves focus, arrows move the caret, and so on | Browser shortcuts don't work |
Hover | Mouse events only | Menus that listen for them open; CSS |
Dialogs |
| A page can't be left waiting on a dialog |
Popups | A link or | The page gets no |
Background tabs | Agents work in the background, where Firefox slows timers to about 1 s and stops animation frames | A page that seems stuck may need |
| Runs in the extension's isolated world, and says so | It sees the DOM; the page's own variables are under |
File pickers | Files are set directly on the input, and pickers a click opens are intercepted | |
Accessibility tree | Computed from the DOM, as extensions can't read Firefox's own | Close to the real one, but names ignore CSS |
Firefox makes up for some of that with APIs of its own: tabs.captureTab takes screenshots of background tabs without bringing them forward, filterResponseData lets request --body read responses as they pass, and hooks installed with exportFunction run without touching the page's world, so a page's CSP doesn't affect them and it can't forge what they report.
The extension uses Manifest V2 on purpose: only a persistent background page keeps the connection to the server open, and Firefox continues to support it.
Not supported yet: several Firefox profiles at once (a second one is told another is connected; Browser MCP supports this).
Security
This gives AI apps the use of your signed-in browser, so it's worth knowing what stands in the way:
You approve each server, by matching a code. The extension then checks a signature on every connection, so a program that takes over the port can't drive your browser.
The extension enforces the rules, whatever the server asks: no browser pages, extension pages, local files or Mozilla's add-on and account sites, and nothing while you've pressed Stop. Private windows are only reachable if you turn on Run in Private Windows for the extension.
Web pages can't reach the daemon. It only listens on
127.0.0.1, checksHostagainst DNS rebinding, takes onlymoz-extension://origins on the extension's socket, and requires a token for everything else.Your other tabs are left alone unless an agent selects one. Nothing is injected and no requests are watched until a tab is claimed. Tabs in use are in a tab group named after the AI app.
Passwords and credentials are kept out of transcripts where their names give them away: password fields are masked in snapshots, typed text isn't echoed, and request details hide headers, URL parameters, form fields and JSON keys named like credentials (cookies, tokens, keys, passwords, sessions). A credential under some other name, or in a response body, still shows.
get valueandevalcan still read what a page can.
What it doesn't protect against yet:
Files on your computer.
uploadsends the page any file you can read, andscreenshot --pathwrites wherever it's told, replacing what's there. An agent talked into it by a page could use either, so check the paths in those steps before you approve them.evalin the isolated world. Under a strict CSP,evalruns with the extension's reach: itsfetchandXMLHttpRequestcan read other sites with your cookies. A page can make that happen without a CSP, and in the page's own world it can replaceeval, see the agent's code and forge the answer.Other accounts on the same computer. Every account can reach
127.0.0.1. Another account's program can pose as the extension to the daemon, seeing what agents type and feeding them made-up pages, or take the daemon's port before it starts and pose as the daemon to AI apps, getting its token and reading and writing your files through them. Use it on a computer you don't share.
The risk that remains is prompt injection. Pages are untrusted, and a malicious one can try to talk the AI into misusing your logged-in sessions. The server tells agents not to follow instructions from pages, but that isn't a guarantee. Watch what agents do on sites that matter, and press Stop if something looks wrong.
Reviewers should know: eval runs code supplied by the local server, which is why this may not pass review for a listed addons.mozilla.org add-on. Unlisted signing (above) is the expected route.
Development
npm run build # dist/server, dist/extension
npm run typecheck
npm test # unit tests
npm run test:e2e # real Firefox, through the real MCP server
npm run lint:extension # web-ext lintThe end-to-end tests run Firefox headless with a temporary profile, a temporary server home and random ports, so they never touch your own Firefox or daemon. They find Firefox in the usual places; set FIREFOX_BINARY to pick one and FIREFOX_HEADED=1 to watch.
Folder | |
| The extension ↔ daemon protocol, and pairing |
| The stdio process ( |
| The connection, the tab rules ( |
| What runs in pages: the snapshot and accessibility tree, locators, input, and the hooks |
The server keeps its key, token and log in ~/.firefox-mcp (FIREFOX_MCP_HOME to change it). The daemon exits ten minutes after the last AI app leaves.
License
Apache-2.0. The command language and pairing design come from Browser MCP; see NOTICE. This project isn't affiliated with or endorsed by Browser MCP or Mozilla.
This server cannot be deployed
Maintenance
Related MCP Connectors
Let AI agents use your real, signed-in Chrome: tabs, clicks, forms, screenshots and video.
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
Connect AI agents to your own Chrome with scoped access, approvals, and verified task results.
Let your AI agent operate any website through a real, logged-in browser session.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to control a browser through a set of tools, allowing them to perform web automation tasks like navigation, typing, clicking, and taking screenshots.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to control a browser through a set of tools, allowing them to perform web automation tasks like navigation, typing, clicking, and taking screenshots.Apache 2.0
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to control a browser through a set of tools, allowing them to perform web automation tasks like navigation, typing, clicking, and taking screenshots.Apache 2.0
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to control a browser through a set of tools, allowing them to perform web automation tasks like navigation, typing, clicking, and taking screenshots.Apache 2.0