MCP server for interacting with Fortinet FortiManager to query ADOMs, devices, interfaces, IPsec tunnels, SD-WAN health checks, and BGP neighbors
The server provides 7 well-intentioned tools for FortiManager operations with reasonable naming (verb_noun pattern) and generally solid descriptions. However, there are significant gaps: (1) NO input schemas are visible in the provided source code, all tools show {} or partial parameter definitions without formal JSON Schema, (2) output schemas are entirely undocumented, tool descriptions explain what fields MIGHT be returned (e.g., 'each with: name, ip, netmask...') but there is no formal output schema definition, (3) error handling is minimal, most tools raise RuntimeError with messages but provide no recovery guidance or error classification, (4) parameter descriptions lack format constraints and validation rules (e.g., 'adom' and 'device' parameters have no validation hint that they are case-sensitive or what format they must match). The tool names are clear and action-oriented (list_, get_, find_), and descriptions are moderately detailed (100-250 chars), which are positives. All tools are READ_ONLY, reducing the need for confirmation patterns. However, without visible input schemas and documented output schemas, the technical quality cannot exceed 'fair'.
Find a device across all ADOMs and return its details including ADOM membership. Queries the global device table instead of iterating ADOM by ADOM, making it much faster when there are many ADOMs.
Get live BGP neighbor status for a FortiGate device. Queries the device in real-time through FortiManager's proxy endpoint.
Get network interfaces for a FortiGate device managed by FortiManager. Reads interface configuration from FortiManager's stored config database.
Get live IPsec VPN tunnel status for a FortiGate device via FortiManager proxy. Queries the FortiGate in real-time through FortiManager's /sys/proxy/json endpoint, which proxies to FortiOS REST API /api/v2/monitor/vpn/ipsec. The device must be online and reachable from FortiManager.
Get live SD-WAN health check (SLA monitor) status for a FortiGate device. Queries the FortiGate in real-time through FortiManager's proxy endpoint. Returns the most recent latency, jitter, and packet loss measurement per SD-WAN interface per health check — the primary way to assess overlay link quality beyond simple tunnel up/down status.
No visible input schemas, all tools show @mcp.tool() decorators with parameters but no formal JSON Schema definitions (types, required fields, constraints, enums).
Output schemas are entirely undocumented. Tool descriptions mention return fields inline (e.g., 'Returns a list of interfaces, each with: name, ip, netmask...') but provide no formal output schema. LLMs need structured, typed output definitions to plan downstream calls and extract the right data.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 66 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 49 | - | v1 |
List all ADOMs (Administrative Domains) on FortiManager.
List all devices in a FortiManager ADOM.
Error handling is minimal and not recovery-focused. Tools raise RuntimeError with status codes (e.g., 'FortiManager API error (status -11)') but provide no guidance on next steps, retryability classification, or actionable recovery suggestions. LLMs receive raw error info with no context.
Parameters 'adom' and 'device' lack format constraints and validation hints in descriptions. Descriptions state only 'The ADOM name (e.g. fin-3001126209)' but do not clarify: case-sensitivity, allowed character set, minimum/maximum length, or what to do if the ADOM does not exist. Validation rules should be explicit.
Missing pagination support. list_adoms() and list_devices() return unbounded lists with no limit parameter, page/offset, or total_count. If an ADOM contains hundreds or thousands of devices, the response balloons and exhausts context. Should cap results at 50 and offer pagination.
find_device() returns an error dict {"error": "..."} on failure, but this is not a thrown exception or structured error response. The caller cannot distinguish 'device not found' (user-fixable) from 'API rate limited' (retryable) from 'no permission' (fatal). Error classification is missing.
Tool descriptions include example values (e.g., 'fin-3001126209', 'FGT-BRANCH-01', 'trv-sdwan-tre-lte') which LLMs may reuse literally in real calls. Should remove examples or move them to separate constraint/pattern fields.