Skip to content

Native Messaging Protocol

The native messaging host is the bridge between the Firefox extension and external tooling. It uses Firefox’s standard native messaging protocol over stdin/stdout.

Every message is framed with a 4-byte little-endian unsigned integer length prefix, followed by a UTF-8 JSON payload.

┌──────────────────┬─────────────────────────────┐
│ Length (4 bytes) │ JSON payload (UTF-8) │
│ Little-endian │ { "command": "ping", ... } │
│ uint32 │ │
└──────────────────┴─────────────────────────────┘
  1. Read exactly 4 bytes from stdin.
  2. Interpret as a uint32 in little-endian byte order — this is the payload length.
  3. Read exactly that many bytes.
  4. Decode as UTF-8 and parse as JSON.
  1. Serialize the response object to a JSON string.
  2. Encode as UTF-8 into a byte buffer.
  3. Write a 4-byte little-endian uint32 of the buffer length to stdout.
  4. Write the buffer to stdout.
DirectionLimitEnforced by
Host to Extension1 MBNative host (protocol.js) throws if exceeded
Extension to Host4 GBProtocol spec (validated against uint32 max)
Socket buffer10 MBNative host memory guard

The 1 MB host-to-extension limit is the practical constraint. Screenshot data is kept under this limit through JPEG compression (60% quality) and downscaling (50% by default).

Commands sent from the MCP server to the host (via Unix socket), then forwarded to the extension:

{
"command": "navigate",
"tabId": 42,
"url": "https://example.com",
"agentId": "agent_a1b2c3d4e5f6..._12345",
"timeout": 30000
}
FieldRequiredDescription
commandYesOne of the whitelisted command names
tabIdVariesTarget tab (required for most page interaction commands)
agentIdAutoInjected by MCP server; used for ownership checks
timeoutNoPer-operation timeout in ms (5000-300000, default: 150000)
{
"success": true,
"tabId": 42,
"title": "Example Domain",
"url": "https://example.com"
}

Error responses:

{
"success": false,
"error": "OWNERSHIP: Cannot navigate tab 42 (owned by agent_e7f8...)"
}

All MCP tools accept an optional timeout parameter that controls how long the system waits for a response from Firefox.

  • Minimum: 5,000 ms (5 seconds)
  • Maximum: 300,000 ms (5 minutes)
  • Default: 150,000 ms (2.5 minutes)

The timeout covers the full round-trip: MCP server to host, host to extension, extension processing, and the return path. If the timeout expires, the MCP server returns an error without waiting further.

The native messaging host is registered with Firefox through a JSON manifest file.

Location:

  • macOS: ~/.mozilla/native-messaging-hosts/claudezilla.json
  • Linux: ~/.mozilla/native-messaging-hosts/claudezilla.json
  • Windows: Registry key pointing to the manifest file

Manifest contents:

{
"name": "claudezilla",
"description": "Claudezilla Native Messaging Host",
"path": "/absolute/path/to/claudezilla/host/index.js",
"type": "stdio",
"allowed_extensions": ["claudezilla@boot.industries"]
}
FieldDescription
nameMust match the name used in browser.runtime.connectNative()
pathAbsolute path to the host executable (the Node.js entry point)
typeAlways stdio — communication over stdin/stdout
allowed_extensionsOnly the Claudezilla extension ID is permitted to connect

The native host also runs a Unix domain socket server (or named pipe on Windows) for the MCP server to connect to.

  • Path: Platform-dependent, resolved by ipc.js (typically in XDG_RUNTIME_DIR or system temp)
  • Auth: 32-byte random hex token written to a file on host startup; MCP server reads and presents it on connection
  • Permissions: Socket and token file set to 0600 (owner-only access)

The socket carries the same JSON message format but without the 4-byte length prefix — messages are newline-delimited JSON over the socket connection.