Repository navigation
Releases: valkyrianlabs/forti-mcp
Release list
v0.5.1 — Engine forti-cli 0.7.0: plan retention; the approval prompt shows stored bodies
Plans no longer pile up
forti-mcp now builds on forti-cli 0.7.0's engine:
- Once an apply has started executing a plan (whatever the outcome), the plan file and its approval
records are deleted. A small marker stays, soforti_applywith thatplan_idagain is refused as
already applied (policy_denied, reasonalready_applied), not "not found". A plan refused
before anything was sent (stale, approval required, read-only, tampered) is kept for a retry. - Plans never applied, rollback plans, the markers and approval records are deleted after the plan
retention period: 30 days, or what a person sets withforti home retention DAYS(1 to 3650). No
tool can change it. The purge runs on every plan and apply and never during an apply. - Through the same engine: monitor action bodies over 64 KiB are stored once by their SHA-256 instead
of inside the plan, and an action's apply record keeps the device's reply; a command the device
reports as failed inside a successful reply fails the operation (forti-cli 0.6.0).
Approval prompt
- A monitor action whose body the engine stored by digest showed
request body: (none)in the in-chat
approval prompt. It now shows the body's size and SHA-256, for example
request body: 20.0 MiB (20971520 bytes), stored by digest, sha256 9b1f…, and never the content.
Inline bodies are shown as before. - A
forti_applywithoperationsapproved through the modern-era retry kept itsplansummary in
the result: it is now taken before the apply, which deletes the plan.
v0.5.0 — One DHCP reservation at a time: child tables
forti_read and the operations of forti_plan and forti_apply take child tables: one table
attribute of an object, such as a DHCP server's reserved-address, entry by entry, without
rewriting the rest of the list.
forti_readtakeschild(the table attribute of the object named bykey) andchild_key
(one entry):{"resource": "system.dhcp/server", "key": 1, "child": "reserved-address"}.- Operations take
parent(the object's key) andchild;keyis then the entry's. A numeric id
left out ofcreateis assigned by the device and reported in the result, and the rollback plan
deletes exactly that entry. Only the one entry is re-checked before writing, so changes to the
other entries never make the plan stale. - The in-chat approval prompt names the object, the table attribute and the entry
(update system.dhcp/server "1" reserved-address "21"). - Webhook header secrets (
http-headersentries such asAuthorization) are redacted in results,
as other secrets are. - The tool schemas stay strict; every existing call works as before.
Built on the forti-cli 0.5.0 engine (forti-api 1.2.0). The agent skill that comes with
forti-cli (forti install mcp) describes them.
v0.4.1 — Bottles for every Mac on macOS 15 or later
- Homebrew pours a bottle on macOS 15 or later, on Apple silicon and Intel. forti-mcp 0.4.0 could
not be built on macOS 15, because forti-api 1.1.0 needed Xcode 26's C++ library; this release is
built on forti-api 1.1.1, which fixes that, with forti-cli 0.4.2's engine. - The
.debinstalls on its own again. It recommendsvalkyrianlabs-archive-keyringinstead of
depending on it: installs from the APT repository still get the keyring, and the package from a
GitHub release installs without the repository.
v0.4.0 — Approve changes in the conversation
forti-mcp 0.4 carries forti-cli 0.4.1's engine and makes a change one tool call with, in guarded
mode, one approval where you already are.
One call to make a change
forti_apply takes the operations themselves and plans and applies them in one call, as the
profile's mode allows; forti_plan remains for previewing. The result includes the plan's diff, so
the agent can report exactly what changed.
Guarded mode asks you in the chat
- With a client that supports MCP elicitation (Claude Code and Codex do), you get one prompt in the
conversation: the device, mode, risk and every attribute change, with an Apply these changes
checkbox. Approve and the change is applied, verified and reported in the same call. Decline or
dismiss it and nothing is applied, and the agent is told not to ask again. - The approval is recorded as
mcp:<client>:elicitationonly from your answer, never from anything
the model sends, and covers only the plan you were shown: a plan changed after it was shown is
refused. - No prompt support? The result names
forti approve <id>for your terminal, or keep
forti approve --watchrunning there.
Also
- Audit records name the client that applied a change (
mcp:claude-code), soforti historyshows
who did what. - Startup is back to about 6 ms.
- Homebrew pours a bottle on Apple silicon Macs running macOS 26 or later.
- APT packages depend on
valkyrianlabs-archive-keyring, which keeps the repository signing key
current through normal upgrades.
v0.3.0 — Resources as admins name them, clearer errors, a bottle and a lighter build
forti-mcp 0.3 carries forti-cli 0.3.1's engine.
For agents
forti_readandforti_discovertake resources the way FortiOS admins name them: the path
(firewall/address), FortiOS CLI words (firewall address), a last word only one resource has
(address), and a table object by its path (firewall/address/web). An ambiguous name returns
unknown_resourcewith the candidates inerror.details.candidates.- A misspelt attribute (in
fields,filteror a plan) comes back withdetails.suggestions
("did you mean color?"). - A read-only profile's refusal names the command a person runs to allow changes
(details.mode_command,forti profile mode NAME guarded). - An unknown profile, or several and no default, lists the profiles in
details.profiles. - A profile whose client certificate or CA bundle file is missing is reported before any request,
with what is missing (details.missing,details.path), instead of a TLS failure. - Profiles that use forti-cli 0.3's named client certificates (
~/.forti/certs/<name>/, issued by
the forti CA) work as before; a certificate can now be shared by several profiles.
Installing
- Homebrew installs pour a bottle on Apple silicon instead of compiling, and
forti-clinow installs
forti-mcp with it (Homebrew dependency, Debian Recommends). forti-mcp alone still works. - Building from source is fast: the engine's catalog comes from forti-api 1.1's runtime schema, so
no translation unit needs more than about 1.2 GB, and a full build with the tests takes about
10 seconds on an Apple silicon Mac.
v0.2.0 — The ~/.forti workspace
forti-mcp now builds on the forti-cli 0.2.0 engine. Everything forti keeps lives in one directory,
the forti home (~/.forti, or $FORTI_HOME), and that directory is also the recommended place
to run your AI agent.
One home for profiles, secrets, certificates and plans
forti-mcp reads its device profiles, file-stored credentials, client certificates, plans,
approvals and audit log from the forti home, the same one the forti CLI uses. forti home shows
every location.
Upgrading from 0.1: nothing breaks. An existing setup in ~/.config/forti (with state in
~/.local/state/forti) keeps working as long as ~/.forti/config.json does not exist. Run
forti home migrate (forti-cli 0.2.0) when you are ready to move it; Keychain items need no change.
The workspace: firewall tools only where you want them
forti install mcp --scope workspace
cd ~/.forti && claude # or: cd ~/.forti && codexforti install mcp --scope workspace registers forti-mcp in the forti home only, so an agent started
there gets the four FortiGate tools and an agent started in any other project does not. The
workspace also keeps secrets out of the agent's context: Claude Code deny rules for credentials/,
certificate passwords and keys and edits to config.json, a Codex permission profile that denies the
same paths to sandboxed commands, and an AGENTS.md that tells the agent the rules. Codex reads the
workspace's configuration once it trusts ~/.forti; --trust-codex-workspace adds that trust with
your consent. Registering the server by hand still works as before.
Client certificates and several FortiGates
- Profiles made with
forti cert createauthenticate with a client certificate kept in
~/.forti/certs/<profile>/, its password read from an owner-only file; forti-mcp uses them like
any other profile. - One forti-mcp serves every FortiGate in the forti home. The model names a device with the
profilefield offorti_discover,forti_readandforti_plan;--profilesets the default
for a registration. Each profile keeps its own mode.
Documentation
The docs are rewritten around the forti home: Connecting AI clients leads with the workspace,
Installation covers the home and migration, Security says where secrets and certificates live and
what the deny rules do, and a new guide, Several FortiGates, covers profiles per device.
v0.1.1 — Documentation in Payload Markdown
The forti-mcp documentation now uses Payload Markdown directives, so the published pages are easier
to scan and follow. The content is the same; only its presentation changed:
- Installation puts APT, Homebrew and the source build side by side in tabs.
- Connecting AI clients walks through setup as numbered steps, with Claude Code, Codex and
manual registration in tabs. - Safety and modes calls out what guarded mode does not stop and the limits of recovery after a
management lockout. - The overview page maps features and next pages as cards, and the reference pages have a table of
contents and cleaner tables.
The server itself is unchanged.
v0.1.0 — forti-mcp: FortiOS for AI clients
The first release of forti-mcp, an MCP server that lets an AI client (Claude Code, Codex or any
other MCP client) discover, read and change FortiGate configuration through the FortiOS REST API. It
never runs SSH or CLI commands.
- Native and on demand. The client starts
forti-mcpover stdio and it exits with the client: no
daemon, no network listener. It speaks MCP2026-07-28and theinitialize-based2025-11-25and
2025-06-18revisions. - Four tools.
forti_discover(profiles, device identity and mode, resource search, attributes),
forti_read(configuration and monitor data, bounded and paginated),forti_plan(validates a
change and records the diff, request bodies and risk tier) andforti_apply(executes a stored plan
by id). - The operator decides what may change. Each device profile's mode is set in
forti configure
and cannot be changed through MCP:read-only(default) refuses apply,guardedneeds you to run
forti plan approve <id>,autonomousapplies with drift detection, verification, an audit record
and a rollback plan. - Secrets stay out of the conversation. Device secrets in read results come back as
"<redacted>", and API tokens never appear in client configuration. - The same engine as
forti. forti-mcp compiles in the command engine of
forti-cli and installs on its own;
forti-mcp --versionnames the engine revision and forti-api version it was built from.
Install
- Debian/Ubuntu (amd64), from the ValkyrianLabs APT repository:
sudo apt install forti-mcp. - macOS (Homebrew):
brew install valkyrianlabs/tap/forti-mcp(builds from source).
Configure a device profile with forti configure and register the server with your AI client with
forti install mcp (both from forti-cli), or add the client entry by hand (README, "Setup").