Letting a model touch a production firewall is only reasonable if the plumbing is right, and that is where this one puts its weight: every destructive tool needs an explicit confirm, a config revision is snapshotted first, and the response hands you back the exact one-line rollback. The `dry_run` preview and `verify_descr` guard against the classic mistake — deleting the right-numbered but wrong rule after IDs shift. Setup has one real gotcha, the pfSense self-signed CA: export it and set `PFSENSE_CA_FILE`, because turning verification off leaves the credential exposed to anyone on the path.
An MCP server that connects Claude Desktop, Claude Code and other MCP clients to a pfSense firewall through its REST API. You describe what you want; it makes the API calls, validates inputs, and runs every change through a guardrail pipeline that backs up the config and can roll it back.
- 333 tools across every major subsystem — firewall rules, aliases, NAT, VPN (OpenVPN, IPsec, WireGuard), routing, DNS, DHCP, certificates, users, interfaces, system, services, logs, traffic shaping and packages
- A confirmation gate on destructive operations: the 52 delete/reboot/halt tools require `confirm=True`, and a config revision is captured before each one
- A one-line rollback returned with every destructive change, as `restore_config_backup(revision_id=…)`
- Rate limiting, positive input validation (IP/port/MAC/CIDR), path-traversal and XSS screening, and secrets redacted from logs and echoed API errors
- A `dry_run=True` preview of any destructive operation, and a `verify_descr` check that guards against deleting the wrong rule after an ID shift
- A read-only mode via `MCP_READ_ONLY=true` exposing only the read/search/diagnose tools, and a `MCP_ALLOWED_TOOLS` allowlist
Python 3.11+ and a pfSense instance with the REST API v2 package installed. Run without cloning via `uvx --from git+https://github.com/gensecaihq/pfsense-mcp-server pfsense-mcp-server`, or clone and `pip install -r requirements.txt`. `PFSENSE_URL` and an auth method — `basic`, `api_key` or `jwt` — are set in `.env` or the client's env block, with the matching `PFSENSE_USERNAME`/`PFSENSE_PASSWORD` or `PFSENSE_API_KEY`. Because pfSense uses a self-signed CA that Python does not trust by default, export the CA and point `PFSENSE_CA_FILE` at it; `VERIFY_SSL=false` also connects but leaves the firewall unauthenticated. The pyproject names the package `pfsense-mcp-server` at 1.0.0. The README urges REST API package v2.10.0+, which fixes a command-injection flaw in the interface-group endpoints.
One command plus a key — uvx --from git+https://github.com/gensecaihq/pfsense-mcp-server pfsense-mcp-server, then supply credentials
