Skip to content

Configuration

All configuration is environment variables, read once at startup. Credentials never appear in a tool argument or a tool response, and the dataclass holding them excludes the secret fields from its repr, so a stray log line or a traceback cannot leak them either.

The common case. Two variables are enough.

Terminal window
FORTIGATE_HOST=fgt-edge1.example.com
FORTIGATE_TOKEN=your-token
VariableDefaultMeaning
FORTIGATE_HOSTHostname, or a full URL. Required for this style
FORTIGATE_TOKENREST API token. Preferred over username and password
FORTIGATE_USERNAMELegacy auth, used only when no token is set
FORTIGATE_PASSWORDLegacy auth, used only when no token is set
FORTIGATE_NAMEthe hostThe alias tools use for this appliance
FORTIGATE_VDOMrootWhich VDOM to query
FORTIGATE_PORTfrom the host URL, else the scheme defaultManagement port
FORTIGATE_VERIFY_SSLtrueVerify the appliance’s TLS certificate
FORTIGATE_TIMEOUT30Per-request timeout in seconds

A target with neither a token nor a complete username and password pair is a configuration error, raised by name at startup.

FORTIGATE_VERIFY_SSL accepts the spellings people actually write in a .env file. 1, true, yes, and on are true, case-insensitively. Everything else is false. There is no clever coercion here and no attempt to guess: a typo in this variable turns verification off, which is the failure direction you can detect rather than the one that silently succeeds.

fortigate-api wants host, port, and scheme as three separate arguments rather than one URL, and operators write the host every possible way, so all of them are normalized to the same thing.

You writeHostPortScheme
fgt.example.comfgt.example.comnonehttps
https://fgt.example.comfgt.example.comnonehttps
https://fgt.example.com:8443/fgt.example.com8443https
http://fgt.lab:8080fgt.lab8080http

A bare hostname is assumed to be HTTPS, which is the only sane default for a firewall management interface. An explicit FORTIGATE_PORT wins over a port embedded in the host URL.

Set FORTIGATE_TARGETS to a JSON object mapping a short alias to that appliance’s connection details. The keys become the target argument on every tool, so short and memorable beats descriptive.

Terminal window
FORTIGATE_TARGETS='{
"edge": {"host": "fgt-edge1.example.com", "token": "..."},
"branch": {"host": "fgt-br2.example.com", "token": "...", "verify_ssl": false},
"lab": {"host": "https://fgt.lab:8443", "username": "readonly", "password": "..."}
}'

Per-target keys, all optional except the host:

KeyDefaultMeaning
hostHostname or full URL. url is accepted as a synonym
tokenREST API token
username / passwordLegacy auth, used only when no token is set
portfrom the host URLManagement port. Wins over a port in host
vdomrootWhich VDOM to query
verify_ssltrueVerify the appliance’s TLS certificate
timeout30Per-request timeout in seconds

Malformed JSON here is a startup error naming the parse failure, rather than a silently empty target list.

They are not exclusive. FORTIGATE_TARGETS is read first, then FORTIGATE_HOST is added to the same registry if it is set. A single-appliance setup can therefore grow a second appliance by adding FORTIGATE_TARGETS without moving the first, which is the direction these configurations usually grow.

One consequence worth knowing: the single-appliance block is registered after the JSON block, so if FORTIGATE_NAME matches a key in FORTIGATE_TARGETS, the single-appliance settings win. Give them different names unless you mean the override.

With exactly one appliance configured, target can be omitted on every tool, and list_targets reports it as default_target.

With several, omitting target is an error whose message lists the valid aliases. That is a deliberate choice about how a model recovers. An error naming branch, edge, lab lets the next call be correct, where a silent pick of the first alphabetically would produce a confident answer about the wrong firewall.

An unknown alias fails the same way, listing what is configured.

The server still starts. An empty registry is not treated as a fatal error at import time, because an MCP client showing nothing but failed to connect tells an operator far less than a tool that answers with an explanation. The misconfiguration is reported through list_targets, through the first tool call that needs a target, and on stderr at startup for clients that surface server logs.

A session is opened per tool call rather than pooled. With token auth this costs nothing, because the token travels on every request and there is no login round-trip to amortize. With username and password there is one login per call, which is the price of never holding a stale session across an MCP server that may sit idle for hours between questions.

When verify_ssl is false, urllib3’s unverified-HTTPS warning is suppressed for the duration of that call. A lab appliance with a self-signed certificate is a deliberate configuration, not something worth warning about on every single request.