MCP Hub
Back to servers

@fulldecent/firefox-devtools-mcp

Requires Setup

Model Context Protocol (MCP) server for Firefox DevTools automation (fork with Firefox management tools)

npm162/wk
Stars
1
Updated
Mar 25, 2026
Validated
Apr 15, 2026

Quick Install

npx -y @fulldecent/firefox-devtools-mcp

@fulldecent/firefox-devtools-mcp

npm version License: MIT

Model Context Protocol server for automating Firefox via WebDriver BiDi (through Selenium WebDriver). Works with Claude Code, Claude Desktop, Cursor, Cline and other MCP clients.

Note: this MCP server requires a local Firefox browser installation and cannot run on cloud hosting services. Use npx @fulldecent/firefox-devtools-mcp@latest to run locally, or use Docker with the provided Dockerfile.

How this differs from upstream

This package is a fork of firefox-devtools-mcp (by freema) via @padenot/firefox-devtools-mcp. The following features are added on top of immediate upstream:

  • Tabs are identified with robust UUIDs in all functions (instead of ephemeral tab index number). This means you can have multiple agents all accessing their own tabs in the same browser profile simultaneously.

The goal is to upstream features that prove useful.

Requirements

  • Node.js ≥ 20.19.0
  • Firefox 100+ installed (auto‑detected, or pass --firefox-path)

Install and use with Claude Code

Recommended: use npx so you always run the latest published version from npm.

Option A — Claude Code CLI

claude mcp add firefox-devtools npx @fulldecent/firefox-devtools-mcp@latest

Pass options either as args or env vars:

# Headless + viewport via args
claude mcp add firefox-devtools npx @fulldecent/firefox-devtools-mcp@latest -- --headless --viewport 1280x720

# Or via environment variables
claude mcp add firefox-devtools npx @fulldecent/firefox-devtools-mcp@latest \
  --env START_URL=https://example.com \
  --env FIREFOX_HEADLESS=true

Option B — edit Claude Code settings JSON

Add to your Claude Code config file:

  • macOS: ~/Library/Application Support/Claude/Code/mcp_settings.json
  • Linux: ~/.config/claude/code/mcp_settings.json
  • Windows: %APPDATA%\Claude\Code\mcp_settings.json
{
  "mcpServers": {
    "firefox-devtools": {
      "command": "npx",
      "args": ["-y", "@fulldecent/firefox-devtools-mcp@latest", "--headless", "--viewport", "1280x720"],
      "env": {
        "START_URL": "about:home"
      }
    }
  }
}

Option C — helper script (local dev build)

npm run setup
# Choose Claude Code; the script saves JSON to the right path

Try it with MCP Inspector

npx @modelcontextprotocol/inspector npx @fulldecent/firefox-devtools-mcp@latest --start-url https://example.com --headless

Then call tools like:

  • list_pages, navigate_page (pass pageId from list_pages)
  • take_snapshot then click_by_uid / fill_by_uid
  • list_network_requests (always‑on capture), get_network_request
  • screenshot_page, list_console_messages

CLI options

You can pass flags or environment variables (names on the right):

FlagEnvironment variableDescription
--firefox-pathAbsolute path to Firefox binary
--headlessFIREFOX_HEADLESS=trueRun without UI
--viewport 1280x720Initial window size
--profile-pathUse a specific Firefox profile
--firefox-argExtra Firefox arguments (repeatable)
--start-urlSTART_URLOpen this URL on start
--accept-insecure-certsACCEPT_INSECURE_CERTS=trueIgnore TLS errors
--pref name=valueSet Firefox preference at startup (repeatable, requires MOZ_REMOTE_ALLOW_SYSTEM_ACCESS=1)
--env KEY=VALUEPass environment variables to Firefox (repeatable)
--output-filePath for Firefox output redirection

Note on --pref: when Firefox runs in WebDriver BiDi mode, it applies RecommendedPreferences that modify browser behavior for testing. The --pref option allows overriding these defaults when needed (e.g., for Firefox development, debugging, or testing scenarios that require production-like behavior).

Example: --pref "browser.ml.enable=true" enables Firefox's ML/AI features. This is essential when using this MCP server to develop or test AI-powered features like Smart Window, since RecommendedPreferences disables it by default.

Tool reference

All page-aware tools require an explicit pageId parameter — the stable window handle returned by list_pages. This handle is assigned by Firefox at tab-creation time and does not change if other tabs are opened or closed, making it safe to hold across multi-step workflows.

Page management

ToolDescription
list_pagesList open tabs. Returns stable pageId for each tab.
new_pageOpen new tab at URL. Returns pageId of the new tab.
navigate_pageNavigate a tab to a URL.
close_pageClose a tab.

list_pages — no parameters

new_page

ParameterTypeRequiredDescription
urlstringyesTarget URL

navigate_page

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
urlstringyesTarget URL

close_page

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages

DOM snapshot

UIDs are stable identifiers for DOM elements within a single snapshot. They become invalid after page navigation or DOM changes — call take_snapshot again to get fresh UIDs.

ToolDescription
take_snapshotCapture DOM snapshot with stable UIDs for element interaction.
resolve_uid_to_selectorResolve a UID to its CSS selector.
clear_snapshotClear snapshot cache.

take_snapshot

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
maxLinesnumbernoMaximum lines to display (default: 100)
includeAttributesbooleannoInclude ARIA attributes (default: false)
includeTextbooleannoInclude text content (default: true)
maxDepthnumbernoMaximum tree depth for traversal
includeAllbooleannoInclude all visible elements without relevance filtering, useful for Vue/Livewire/Alpine.js apps (default: false)
selectorstringnoCSS selector to scope snapshot to a specific subtree (e.g., #app)

resolve_uid_to_selector

ParameterTypeRequiredDescription
uidstringyesUID from snapshot

clear_snapshot — no parameters

Input interaction

All input tools require valid UIDs from the current snapshot.

ToolDescription
click_by_uidClick an element.
hover_by_uidHover over an element.
fill_by_uidFill a text input or textarea (clears existing value first).
drag_by_uid_to_uidDrag one element to another via HTML5 drag events.
fill_form_by_uidFill multiple form fields at once.
upload_file_by_uidUpload a file to a file input.

click_by_uid

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
uidstringyesElement UID from current snapshot
dblClickbooleannoDouble-click instead of single click (default: false)

hover_by_uid

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
uidstringyesElement UID from current snapshot

fill_by_uid

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
uidstringyesInput element UID from current snapshot
valuestringyesText to fill

drag_by_uid_to_uid

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
fromUidstringyesSource element UID
toUidstringyesTarget element UID

fill_form_by_uid

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
elementsarrayyesArray of { uid: string, value: string } objects

upload_file_by_uid

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
uidstringyesFile input element UID from current snapshot
filePathstringyesLocal file path (absolute or relative)

Network monitoring

Network requests are captured automatically. Use list_network_requests to browse and get_network_request to inspect individual requests in detail.

list_network_requests

ParameterTypeRequiredDescription
limitnumbernoMaximum number of requests (default: 50)
sinceMsnumbernoOnly show requests from last N milliseconds
urlContainsstringnoFilter by URL substring (case-insensitive)
methodstringnoHTTP method filter (e.g., GET, POST)
statusnumbernoExact HTTP status code filter
statusMinnumbernoMinimum status code
statusMaxnumbernoMaximum status code
isXHRbooleannoFilter to XHR/fetch requests only
resourceTypestringnoFilter by resource type (case-insensitive)
sortBystringnoSort field: timestamp (default), duration, or status
detailstringnoDetail level: summary (default), min, or full
formatstringnoOutput format: text (default) or json

get_network_request

ParameterTypeRequiredDescription
idstringnoRequest ID from list_network_requests (primary lookup)
urlstringnoURL as fallback lookup (exact match)
formatstringnoOutput format: text (default) or json

Either id or url must be provided. If multiple requests match a URL, an error is returned listing the matching IDs.

Console

list_console_messages

ParameterTypeRequiredDescription
levelstringnoFilter by level: debug, info, warn, or error
limitnumbernoMax messages to return (default: 50)
sinceMsnumbernoOnly show messages from the last N milliseconds
textContainsstringnoFilter by text content (case-insensitive)
sourcestringnoFilter by source (case-insensitive)
formatstringnoOutput format: text (default) or json

All filters are combined with AND logic.

clear_console_messages — no parameters. Returns count of cleared messages.

Screenshots

Returns a native MCP image content item (PNG) for GUI clients, or saves to disk when saveTo is provided.

screenshot_page

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
saveTostringnoFile path to save screenshot instead of returning image data

screenshot_by_uid

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
uidstringyesElement UID from current snapshot
saveTostringnoFile path to save screenshot instead of returning image data

Screenshot tip for Claude Code: base64 image data consumes significant context. Use the saveTo parameter to save screenshots to disk, then view the file with Claude Code's read tool.

Script evaluation

evaluate_script — execute JavaScript in page context.

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
functionstringyesJS function string (e.g., () => document.title). Max 16 KB.
argsarraynoArray of objects with uid field to pass as function arguments
timeoutnumbernoExecution timeout in milliseconds (default: 5000)

evaluate_chrome_script — evaluate JavaScript in the current chrome (privileged) context. Requires MOZ_REMOTE_ALLOW_SYSTEM_ACCESS=1.

ParameterTypeRequiredDescription
expressionstringyesJavaScript expression to evaluate in chrome context

Chrome context (privileged)

These tools require MOZ_REMOTE_ALLOW_SYSTEM_ACCESS=1 environment variable.

list_chrome_contexts — no parameters. Lists privileged browsing contexts with their IDs.

select_chrome_context

ParameterTypeRequiredDescription
contextIdstringyesChrome browsing context ID from list_chrome_contexts

Firefox management

get_firefox_info — no parameters. Returns Firefox configuration: binary path, headless status, viewport, profile path, start URL, arguments, environment variables, preferences, output file path and size.

get_firefox_output — retrieve Firefox stdout/stderr output (including MOZ_LOG).

ParameterTypeRequiredDescription
linesnumbernoNumber of recent log lines (default: 100, max: 10000)
grepstringnoFilter log lines containing this string (case-insensitive)
sincenumbernoOnly show logs from last N seconds

restart_firefox — restart Firefox with different configuration. All current tabs will be closed.

ParameterTypeRequiredDescription
firefoxPathstringnoNew Firefox binary path
profilePathstringnoFirefox profile path
envarraynoEnvironment variables in KEY=VALUE format (e.g., ["MOZ_LOG=HTMLMediaElement:5"])
headlessbooleannoRun in headless mode
startUrlstringnoURL to navigate to after restart
prefsobjectnoFirefox preferences object (values are auto-typed)

Firefox preferences (runtime)

These tools require MOZ_REMOTE_ALLOW_SYSTEM_ACCESS=1.

set_firefox_prefs

ParameterTypeRequiredDescription
prefsobjectyesMap of preference names to values. true/false strings become booleans, integer strings become numbers, everything else stays as strings.

get_firefox_prefs

ParameterTypeRequiredDescription
namesarrayyesArray of preference names to read (e.g., ["browser.tabs.drawInTitlebar"])

WebExtension management

install_extension

ParameterTypeRequiredDescription
typestringyesExtension data type: archivePath (.xpi/.zip), base64 (encoded data), or path (unpacked directory)
pathstringconditionalFile path to extension archive or directory (required for archivePath/path types)
valuestringconditionalBase64-encoded extension data (required for base64 type)
permanentbooleannoInstall permanently (requires signed extension). Default: false (temporary install).

uninstall_extension

ParameterTypeRequiredDescription
idstringyesExtension ID (e.g., addon@example.com)

list_extensions — requires MOZ_REMOTE_ALLOW_SYSTEM_ACCESS=1.

ParameterTypeRequiredDescription
idsarraynoFilter by exact extension IDs
namestringnoFilter by partial name match (case-insensitive)
isActivebooleannoFilter by enabled/disabled status
isSystembooleannoFilter by system/built-in vs. user-installed

Utilities

accept_dialog

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
promptTextstringnoText to enter for prompt dialogs

dismiss_dialog

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages

navigate_history

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
directionstringyesback or forward

set_viewport_size

ParameterTypeRequiredDescription
pageIdstringyesStable tab ID from list_pages
widthnumberyesWidth in pixels
heightnumberyesHeight in pixels

Local development

npm install
npm run build

# Run with Inspector against local build
npx @modelcontextprotocol/inspector node dist/index.js --headless --viewport 1280x720

# Or run in dev with hot reload
npm run inspector:dev

Troubleshooting

  • Firefox not found: pass --firefox-path "/Applications/Firefox.app/Contents/MacOS/firefox" (macOS) or the correct path on your OS.
  • First run is slow: Selenium sets up the BiDi session; subsequent runs are faster.
  • Stale UIDs after navigation: take a fresh snapshot (take_snapshot) before using UID tools.
  • Windows 10 — MCP error -32000: connection closed:
    • Solution 1: call using cmd (see https://github.com/modelcontextprotocol/servers/issues/1082#issuecomment-2791786310)

      {
        "mcpServers": {
          "firefox-devtools": {
            "command": "cmd",
            "args": ["/c", "npx", "-y", "@fulldecent/firefox-devtools-mcp@latest"]
          }
        }
      }
      
    • Solution 2: use the absolute path to npx:

      {
        "mcpServers": {
          "firefox-devtools": {
            "command": "C:\\nvm4w\\nodejs\\npx.ps1",
            "args": ["-y", "@fulldecent/firefox-devtools-mcp@latest"]
          }
        }
      }
      

      Adjust the path to match your installation. The extension might be .cmd, .bat, or .exe rather than .ps1. Use double backslashes (\\) as required by JSON.

Versioning

Use @latest with npx for the newest release.

License

MIT

Reviews

No reviews yet

Sign in to write a review