Content
<!-- FortiGate MCP Server — FortiOS 8.0 REST API 管理服务器 — 279 MCP 工具 · 540+ API 方法 · 1023+ CMDB 端点 -->
<p align="center">
<img src="https://img.shields.io/badge/FortiGate-MCP%20Server-blue?style=for-the-badge&logo=fortinet&logoColor=white" alt="FortiGate MCP Server"/>
</p>
<h1 align="center">FortiGate MCP Server</h1>
<p align="center">
<strong>FortiGate Firewall Management Server based on Model Context Protocol (MCP)</strong>
</p>
<p align="center">
<img src="https://img.shields.io/badge/Python-3.11+-3776AB?style=flat-square&logo=python&logoColor=white"/>
<img src="https://img.shields.io/badge/MCP-1.0-green?style=flat-square"/>
<img src="https://img.shields.io/badge/API%20Methods-540+-blue?style=flat-square"/>
<img src="https://img.shields.io/badge/MCP%20Tools-279+-orange?style=flat-square"/>
<img src="https://img.shields.io/badge/Covered%20Modules-129+-purple?style=flat-square"/>
<img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square"/>
</p>
---
## Overview
The FortiGate MCP Server exposes FortiGate firewall management capabilities through the [Model Context Protocol](https://modelcontextprotocol.io/), allowing AI assistants and MCP-compatible tools to programmatically manage firewall policies, network objects, routing, VPNs, security profiles, user authentication, logs, monitoring, and more.
Built with **fully asynchronous Python**, it supports persistent HTTP connection pools and prioritizes secure default configurations.
**Supports all four API categories of FortiOS 8.0:**
| API Category | Path | Methods |
|--------|------|--------|
| Configuration | `/api/v2/cmdb/` | 480+ |
| Monitor | `/api/v2/monitor/` | 39 |
| Log | `/api/v2/log/` | 8 |
| Service | `/api/v2/service/` | 9 |
---
## Features
### Device Management
- Multi-device concurrent management
- API Token / username and password authentication
- Connection testing and health monitoring
- VDOM discovery and VDOM-based operations
### Firewall Policies
- Complete CRUD: IPv4/IPv6 policies, Security Policy, Proxy Policy, Multicast Policy, DoS Policy, Local-in Policy, Interface Policy, Shaping Policy, TTL Policy
- Policy details include address/service object resolution
- UTM Profile binding (IPS/AV/WF/DLP/SSL, etc.)
### Network Objects
- Address objects (IP subnets, IP ranges, FQDNs, wildcard FQDNs), address groups
- Service objects (TCP/UDP/SCTP), service groups
- Time scheduling (one-time, recurring, schedule groups)
- IPv6 addresses and address groups
### NAT and Traffic Management
- VIP/port mapping, VIP groups
- IP pools, Central SNAT Map
- IP translation, DNS translation
- Traffic shaping (shared + per-IP)
### Security Profiles
- IPS Sensor, DLP Sensor/Profile, Antivirus, Web Filter, DNS Filter, Email Filter
- SSL/SSH inspection, WAF, VoIP, Video Filter, Virtual Patch
- Application Control, CASB, SSH Filter, SCTP Filter
- Profile Group, Protocol Options
### VPN
- IPSec Phase1/Phase2 Interface (CRUD)
- SSL VPN Settings / Portal
- Monitoring: IPSec/SSL VPN status, connections
### User and Authentication
- Local users, user groups (CRUD)
- LDAP / RADIUS servers
- Authentication rules and schemes
### System and Network
- DHCP Server, SNMP Community
- Certificate management (CA/local)
- Firewall global settings, log settings
- Alert emails
### Routing and Interfaces
- Static route CRUD
- Routing table, BGP Neighbors/Paths monitoring
- Interface configuration updates
- ARP table, LLDP neighbors
### Monitoring
- IPSec/SSL VPN status and statistics
- SD-WAN Health Check / Members / SLA Log
- Firewall users, online users
- License status
- Log disk usage, FortiAnalyzer/FortiCloud status
- IPS performance statistics, FortiGuard communication statistics
- FortiView real-time statistics, GeoIP queries
- UTM application classification and lookup
### Tools
- Packet capture (Sniffer): list/create/update/delete
---
## Quick Start
### Environment Requirements
- Python 3.11+
- FortiGate device with API enabled
- API Token (recommended) or administrator account
### Installation
```bash
git clone https://github.com/wzs8768/fortigate-mcp-server.git
cd fortigate-mcp-server
# Method 1: pip
python -m venv .venv
source .venv/bin/activate
pip install -e .
# Method 2: uv (recommended, faster)
uv venv
source .venv/bin/activate
uv pip install -e .
```
### Configuration
Create a configuration file `config/config.json` (**file location**: `<project directory>/config/config.json`):
```json
{
"server": {
"host": "0.0.0.0",
"port": 8814,
"name": "fortigate-mcp-server",
"version": "2.0.0"
},
"fortigate": {
"devices": {
"FW-01": {
"host": "192.168.1.1",
"port": 443,
"api_token": "<FortiGate-API-Token>",
"vdom": "root",
"verify_ssl": false,
"timeout": 30
},
"FW-02": {
"host": "192.168.1.2",
"port": 443,
"api_token": "<FortiGate-API-Token>",
"vdom": "root",
"verify_ssl": false,
"timeout": 30
}
}
},
"auth": {
"require_auth": true,
"api_tokens": [
{"name": "hermes-local", "token": "<your-generated-token>"}
],
"allowed_origins": []
},
"logging": {
"level": "INFO",
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
"file": "logs/server.log",
"console": true
}
}
```
> Adapted and developed based on FortiOS 8.0; API differences may exist for other versions; please verify before use.
### Configuration Field Description
| Field | Description |
|------|------|
| `fortigate.devices` | List of managed FortiGate devices, each device has a named field |
| `fortigate.devices.<name>.api_token` | FortiGate device's API Token (generated on FortiGate). **Prioritized over username/password**; use `api_token` when both are configured |
| `fortigate.devices.<name>.username` / `password` | Username and password authentication (alternative; recommend using `api_token`) |
| `auth.api_tokens` | **MCP Server authentication token list**; clients provide tokens for server verification |
| `auth.api_tokens[].name` | Token name/label (e.g., `hermes-local`, `John Doe - claude`) |
| `auth.api_tokens[].token` | Token value; generate using `python3 -c "import secrets; print(secrets.token_urlsafe(32))"` |
| `logging.file` | Log file path; authentication logs record client names (e.g., `Auth OK — client=hermes-local`) |
### Start Service
**STDIO** (local connection; no network): `server.py`
```bash
export FORTIGATE_MCP_CONFIG=config/config.json
python -m src.fortigate_mcp.server
```
**HTTP / HTTPS** (network access): `server_http.py`
```bash
# HTTPS · SSE + Streamable HTTP (optional; requires self-signed certificate; see below)
python -m src.fortigate_mcp.server_http --host 0.0.0.0 --port 8814 \
--transport all --ssl-cert certs/server.crt --ssl-key certs/server.key
# HTTP · SSE + Streamable HTTP
python -m src.fortigate_mcp.server_http --host 0.0.0.0 --port 8815 --transport all
```
| `--transport` | Endpoint |
|---------------|------|
| `all` (recommended) | `/fortigate-mcp` + `/fortigate-mcp-sse` |
| `streamable-http` (CLI default) | `/fortigate-mcp` |
| `sse` | `/fortigate-mcp-sse` |
> `server_http.py` uses HTTP by default; add `--ssl-cert` + `--ssl-key` for HTTPS; **independent of `--transport`**; to provide both HTTP and HTTPS, run two processes with different ports.
**Self-signed Certificate (intranet testing):**
```bash
openssl req -x509 -newkey rsa:4096 -keyout certs/server.key \
-out certs/server.crt -days 3650 -nodes \
-subj "/CN=<your server IP>" -addext "subjectAltName=IP:<your server IP>"
```
**systemd Service (boot auto-start):**
```bash
cp contrib/fortigate-mcp.service ~/.config/systemd/user/
# Edit ExecStart line; set `--transport` / `--ssl-cert` / `--ssl-key` as needed
systemctl --user daemon-reload
systemctl --user enable --now fortigate-mcp
```
### Docker Deployment
No need to install Python environment; start with a single command:
```bash
# 1. Clone repository and prepare configuration
git clone https://github.com/wzs8768/fortigate-mcp-server.git
cd fortigate-mcp-server
# 2. Create config/config.json (see [configuration](#configuration) above)
# 3. Start (HTTP · :8815)
docker compose up -d
```
**HTTPS Mode:**
```bash
# 1. Generate self-signed certificate
openssl req -x509 -newkey rsa:4096 -keyout certs/server.key \
-out certs/server.crt -days 3650 -nodes \
-subj "/CN=<server IP>" -addext "subjectAltName=IP:<server IP>"
# 2. Edit docker-compose.yml; uncomment HTTPS port mapping; add command parameters:
# command: [..., "--ssl-cert", "/app/certs/server.crt", "--ssl-key", "/app/certs/server.key", "--port", "8814"]
docker compose up -d
```
**Container Features:**
| Feature | Description |
|------|------|
| Multi-stage build | builder + runtime; image optimized |
| Secure operation | non-root user `fgtmcp` |
| Health check | every 30 seconds `GET /health` |
| Resource limit | CPU 1 core / memory 512M |
| Log persistence | `./logs` directory mounted |
| Configuration mount | `config/`, `certs/` read-only mounted |
### MCP Client Integration
#### Scenario 1: Client and Server on the Same Machine (STDIO Mode)
Client directly starts a process; no need to pre-run the service:
```json
{
"mcpServers": {
"fortigate": {
"command": "python",
"args": ["-m", "src.fortigate_mcp.server"],
"env": { "FORTIGATE_MCP_CONFIG": "/path/to/config.json" }
}
}
}
```
Applicable to Claude Desktop, OpenCode, Codex CLI, and other STDIO transport clients.
#### Scenario 2: Client and Server on Different Machines (HTTP / HTTPS Mode)
> **Want to provide both HTTP and HTTPS?** Start two processes with different ports (e.g., HTTPS→8814, HTTP→8815); connect using the corresponding address.
```json
// HTTPS · Streamable HTTP
{ "url": "https://<server IP>:8814/fortigate-mcp", "transport": "streamable-http" }
// HTTPS · SSE
{ "url": "https://<server IP>:8814/fortigate-mcp-sse", "transport": "sse" }
// HTTP · Streamable HTTP
{ "url": "http://<server IP>:8815/fortigate-mcp", "transport": "streamable-http" }
// HTTP · SSE
{ "url": "http://<server IP>:8815/fortigate-mcp-sse", "transport": "sse" }
```
> ⚠️ Claude Desktop **only supports STDIO transport**; remote connection requires `mcp-remote` relay (see Windows configuration below); uses HTTPS.
Client configuration file locations:
| Client | Configuration File |
|--------|---------|
| Claude Desktop (macOS/Linux) | `~/.claude/claude_desktop_config.json` |
| Claude Desktop (Windows) | `%LOCALAPPDATA%\Packages\Claude_<random string>\LocalCache\Roaming\Claude\claude_desktop_config.json` |
| OpenCode | `~/.opencode/config.json` or `--mcp-config` parameter |
| Cursor | `~/.cursor/mcp_servers.json` |
| Codex CLI | `~/.codex/mcp_servers.json` |
| Hermes | `~/.hermes/config.yaml` → `mcp_servers` section |
| OpenClaw | `~/.openclaw/openclaw.json` → `mcp.servers` section |
#### Windows Claude Desktop (Self-Signed Certificate / TLS Skip Verification)
Windows Claude Desktop does not support directly setting `ssl_verify: false` in the configuration; use `mcp-remote` relay and set environment variables to bypass certificate verification:
**Prerequisite dependency: Install Node.js**
# PowerShell (Administrator)
winget install OpenJS.NodeJS.LTS
```
**Claude Desktop Configuration (JSON format, `claude_desktop_config.json`):**
> Configuration file path example: `C:\Users\<username>\AppData\Local\Packages\Claude_<random string>\LocalCache\Roaming\Claude\` (Windows Store version), can be located by entering `%LOCALAPPDATA%\Packages\` in the file explorer address bar.
```json
{
"mcpServers": {
"fortigate": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://<server IP>:8814/fortigate-mcp",
"--transport",
"streamable-http",
"--header",
"Authorization:${FORTIGATE_AUTH}"
],
"env": {
"NODE_TLS_REJECT_UNAUTHORIZED": "0",
"FORTIGATE_AUTH": "Bearer <your-shared-token>"
}
}
},
"coworkUserFilesPath": "C:\\Users\\<username>\\Claude",
"preferences": { "...": "..." }
}
```
> To use the existing `claude_desktop_config.json` file, simply merge the `mcpServers` block into it, keeping the rest of the configuration items unchanged.
> `NODE_TLS_REJECT_UNAUTHORIZED=0` skips TLS certificate verification, suitable for self-signed certificate environments. It is recommended to import the certificate into the system's trusted root for production environments.
#### Remote Access Security Hardening
The `auth` configuration has been provided in the [Configuration](#configuration) section (`config/config.json` → `auth.api_tokens`), and additional operation instructions are provided here:
**1. Generate Token:**
```bash
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
```
**2. Write to `config/config.json` `auth.api_tokens` array** (see the complete configuration example above).
**3. Multi-client Token Naming Example:**
```json
"auth": {
"require_auth": true,
"api_tokens": [
{"name": "hermes-local", "token": "<token-1>"},
{"name": "claude-win", "token": "<token-2>"},
{"name": "cursor-laptop", "token": "<token-3>"}
]
}
```
> It is also compatible with the old format (bare string): `"api_tokens": ["token1", "token2"]`, which is automatically marked as `(unnamed)`.
**4. Restart Service to Take Effect:** `systemctl --user restart fortigate-mcp`
**5. Claude Desktop Client Configuration - See the complete `claude_desktop_config.json` example in the [Windows Claude Desktop](#windows-claude-desktop-self-signed-certificate--tls-skipped-verification) section above.**
```
> In `--header "Authorization:${FORTIGATE_AUTH}"`, there is no space between `:` and `Bearer`, avoiding the parameter space bug in the Windows version of Claude Desktop.
Hermes Agent Configuration (YAML format, `~/.hermes/config.yaml`):
```yaml
mcp_servers:
fortigate:
url: https://<server IP>:8814/fortigate-mcp
enabled: true
ssl_verify: false
connect_timeout: 30
headers:
Authorization: "Bearer <your-shared-token>"
```
> Hermes HTTP configuration (no certificate required): change `url` to `http://<server IP>:8815/fortigate-mcp` and remove the `ssl_verify` line.
Codex CLI Configuration (TOML format, `~/.codex/config.toml` or project `.codex.toml`):
```toml
[mcp_servers.fortigate]
enabled = true
url = "http://<server IP>:8815/fortigate-mcp"
[mcp_servers.fortigate.http_headers]
Authorization = "Bearer <your-shared-token>"
Accept = "application/json, text/event-stream"
```
> ⚠️ Codex **must use HTTP (8815 port)** - Codex does not support skipping self-signed certificate verification, and HTTPS connections will fail due to certificate errors.
Cursor / OpenCode / OpenClaw, etc. JSON format clients (**HTTPS**):
Cursor / OpenCode:
```json
{
"mcpServers": {
"fortigate": {
"url": "https://<server IP>:8814/fortigate-mcp",
"transport": "streamable-http",
"headers": {
"Authorization": "Bearer <your-shared-token>"
}
}
}
}
```
OpenClaw (requires `rejectUnauthorized` field, `mcp.servers` block at the end of `openclaw.json`):
```json
{
"mcp": {
"servers": {
"FortiGate": {
"url": "https://<server IP>:8814/fortigate-mcp",
"transport": "streamable-http",
"rejectUnauthorized": false,
"headers": {
"Authorization": "Bearer <your-shared-token>"
}
}
}
}
}
```
---
## Tool List
> The following is a list of representative tools. The complete 279 tools cover 1023+ FortiOS API endpoints, including CMDB general CRUD, log query, monitoring, etc.
### Device Management (7)
`list_devices` `get_device_status` `test_device_connection` `add_device` `remove_device` `discover_vdoms` `list_vdoms`
### Firewall Policies (53)
`list_firewall_policies` `create/update/delete_firewall_policy` `get_firewall_policy_detail`
`list_security_policies` `create/update/delete_security_policy` `get_security_policy_detail`
`list_proxy_policies` `create/update/delete_proxy_policy` `get_proxy_policy_detail`
`list_proxy_addresses` `create/update/delete_proxy_address` `list_proxy_addrgrps` `create/update/delete_proxy_addrgrp`
`list_dos_policies` `create/update/delete_dos_policy`
`list_local_in_policies` `create/update/delete_local_in_policy`
`list_interface_policies` `create/update/delete_interface_policy`
`list_multicast_policies` `create/update/delete_multicast_policy`
`list_multicast_addresses` `create/update/delete_multicast_address`
`list_shaping_policies` `create/update/delete_shaping_policy` `list_shaping_profiles` `create/update/delete_shaping_profile`
`get_firewall_global` `update_firewall_global`
`list_sniffers` `create/update/delete_sniffer`
### Addresses and Address Groups (17)
`list_address_objects` `create/update/delete_address_object`
`list_addrgrps` `create/update/delete_addrgrp` `get_addrgrp_detail`
`list_wildcard_fqdn_custom` `create/update/delete_wildcard_fqdn_custom`
`list_wildcard_fqdn_group` `create/update/delete_wildcard_fqdn_group`
### Services and Service Groups (8)
`list_service_objects` `create/update/delete_service_object`
`list_service_groups` `create/update/delete_service_group`
### Schedule (12)
`list_schedule_onetime` `create/update/delete_schedule_onetime`
`list_schedule_recurring` `create/update/delete_schedule_recurring`
`list_schedule_group` `create/update/delete_schedule_group`
### NAT/VIP/Traffic Shaping (45)
`list_ippools` `create/update/delete_ippool`
`list_vipgrps` `create/update/delete_vipgrp`
`list_virtual_ips` `create/update/delete_virtual_ip` `get_virtual_ip_detail`
`list_central_snat_maps` `create/update/delete_central_snat_map` `get_central_snat_map_detail`
`list_traffic_shapers` `create/update/delete_traffic_shaper`
`list_per_ip_shapers` `create/update/delete_per_ip_shaper`
`list_ip_translations` `create/update/delete_ip_translation`
`list_dns_translations` `create/update/delete_dns_translation`
`list_ttl_policies` `create/update/delete_ttl_policy`
`list_decrypted_traffic_mirrors` `create/update/delete_decrypted_traffic_mirror`
### Security Profiles (44)
`list_ssl_ssh_profiles` `create/update/delete_ssl_ssh_profile`
`list_ssl_servers` `create/update/delete_ssl_server`
`list_ips_sensors` `create/update/delete_ips_sensor` `get_ips_sensor_detail`
`list_profile_groups` `create/update/delete_profile_group`
`list_profile_protocol_options` `create/update/delete_profile_protocol_options`
`list_dnsfilter_profiles` `create_dnsfilter_profile` `list_dnsfilter_domain_filters`
`list_dlp_sensors` `list_dlp_profiles` `get_dlp_settings`
`list_emailfilter_profiles`
`list_antivirus_profiles` `get_antivirus_settings`
`list_webfilter_profiles` `list_webfilter_urlfilters`
`list_waf_profiles` `list_voip_profiles` `list_videofilter_profiles` `list_virtual_patch_profiles`
`list_application_groups` `list_application_lists`
`list_ssh_filter_profiles` `list_sctp_filter_profiles`
`list_casb_profiles` `list_web_proxy_profiles` `list_diameter_filter_profiles`
### VPN (4)
`list_vpn_ipsec_phase1_interfaces` `list_vpn_ipsec_phase2_interfaces`
`get_vpn_ssl_settings` `list_vpn_ssl_web_portals`
### Users and Authentication (10)
`list_user_locals` `list_user_groups` `list_user_ldaps` `list_user_radiuses`
`get_user_setting` `list_auth_rules` `create_auth_rule` `list_auth_schemes` `get_auth_setting`
### Certificates (2)
`get_certificate_ca` `get_certificate_local`
### Routing and Interfaces (9)
`list_static_routes` `create/update/delete_static_route` `get_static_route_detail` `get_routing_table`
`list_interfaces` `get_interface_status` `update_interface`
`list_identity_based_routes` `create/update/delete_identity_based_route`
### System Management (3)
`list_system_dhcp_servers` `list_system_snmp_communities` `get_system_status`
### Switch Management (2)
`list_switch_acl_groups` `list_switch_8021x_policies`
### Logs (12)
`get_log_setting` `update_log_setting` `get_log_disk_setting` `update_log_disk_setting` `get_log_fortianalyzer_setting` `update_log_fortianalyzer_setting` `get_log_syslogd_setting` `update_log_syslogd_setting` `get_logs` `get_logs_raw` `monitor_log_current_disk_usage` `monitor_log_fortianalyzer`
### Monitoring (42)
**VPN Monitoring:** `monitor_vpn_ipsec` `monitor_vpn_ipsec_connection_count` `monitor_vpn_ssl` `monitor_vpn_ssl_stats`
**User Monitoring:** `monitor_user_firewall` `monitor_user_firewall_count` `monitor_user_banned` `monitor_user_fsso`
**SD-WAN:** `monitor_virtual_wan_health_check` `monitor_virtual_wan_members` `monitor_virtual_wan_sla_log`
**Routing:** `monitor_router_ipv4` `monitor_router_ipv6` `monitor_router_bgp_neighbors` `monitor_router_bgp_paths`
**Firewall:** `monitor_firewall_policy` `monitor_firewall_sessions` `monitor_firewall_policy_lookup` `monitor_firewall_acl` `monitor_firewall_acl6`
**System:** `monitor_system_status` `monitor_system_resource_usage` `monitor_system_performance_status` `monitor_system_interface` `monitor_system_current_admins` `monitor_system_firmware` `monitor_system_vm_information` `monitor_system_available_interfaces`
> `monitor_system_resource_usage` supports `scope` parameter: `"current"` (default, latest snapshot only) | `"global"` (full historical)
**Network:** `monitor_network_arp` `monitor_network_lldp_neighbors` `monitor_network_dns_latency` `monitor_network_reverse_ip_lookup`
**Security:** `monitor_ips_rate_based` `monitor_ips_session_performance` `monitor_fortiguard_service_stats` `monitor_webfilter_fortiguard_categories` `monitor_fortiview_realtime_stats`
**License/Registration:** `monitor_license_status` `monitor_registration_forticloud_status`
**UTM/Other:** `monitor_utm_app_lookup` `monitor_utm_application_categories` `monitor_utm_applications` `monitor_geoip_query`
**Generic:** `monitor_request` — covers all 39 `/api/v2/monitor/` GET/POST endpoints
### CMDB Generic CRUD (5)
`cmdb_list` `cmdb_get` `cmdb_create` `cmdb_update` `cmdb_delete`
### Others (4)
`health_check` `get_server_info` `get_alertemail_setting` `get_endpoint_control_settings`
---
## Architecture
```
fortigate-mcp-server/
├── src/fortigate_mcp/
│ ├── auth_middleware.py # Bearer Token authentication middleware
│ ├── server.py # STDIO MCP Server (FastMCP)
│ ├── server_http.py # HTTP MCP Server (FastMCP)
│ ├── config/
│ │ ├── loader.py # Configuration file loader
│ │ └── models.py # Pydantic configuration models
│ ├── core/
│ │ ├── fortigate.py # Asynchronous API client + device manager (540+ methods, 2600+ lines)
│ │ └── logging.py # Structured logging
│ ├── tools/
│ │ ├── base.py # Tool base class (error handling, formatting)
│ │ ├── definitions.py # Tool description constants
│ │ ├── cmdb.py # Generic CMDB CRUD tools (cover 1023+ endpoints)
│ │ ├── device.py # Device management tools
│ │ ├── firewall.py # Firewall policy tools
│ │ ├── network.py # Address/service/FQDN object tools
│ │ ├── routing.py # Routing and interface tools
│ │ ├── virtual_ip.py # VIP tools
│ │ ├── schedules.py # Schedule tools
│ │ ├── resources.py # IP pool/VIP group/SNAT/shaper tools
│ │ └── security.py # Security profile/user/authentication/VPN/system tools
│ └── formatting/
│ ├── formatters.py # MCP content formatting
│ └── templates.py # Response templates
├── config/
│ └── config.json # Device configuration example
├── tests/
├── README.md
└── LICENSE
```
### Design Principles
- **Fully Asynchronous**: All API calls use `httpx.AsyncClient`, persistent connection pool per device
- **Security First**: SSL verification enabled by default, CORS disabled by default (`allowed_origins: []`), enforced Bearer Token authentication
- **Clear Layering**: Configuration models, API clients, tool logic, and formatting are independent
- **Error Categorization**: FortiGate API errors mapped to human-readable information
---
## Security
| Setting | Default Value | Description |
|------|--------|------|
| `verify_ssl` | `true` | SSL certificate verification |
| `allowed_origins` | `[]` | No CORS (explicitly enable as needed) |
| `require_auth` | `true` | MCP Server enforces authentication (all clients must provide Bearer Token) |
**Production Environment Recommendations:**
- Use **API Token** instead of username and password
- Keep `verify_ssl: true` (except for self-signed certificate testing)
- Set explicit `allowed_origins` in HTTP mode
- Run in a trusted network or behind a reverse proxy
- Use environment variables for sensitive configurations
---
## Frequently Asked Questions
**Connection Refused**
- Confirm FortiGate device is reachable and API is enabled
- Check port 443 is not blocked by firewall
**Authentication Failed (401)**
- Verify API Token is valid and has sufficient permissions
- Confirm username and password are correct in username/password mode
**SSL Certificate Error**
- For self-signed certificates in testing: set `verify_ssl: false`
- In production: install a valid certificate on the FortiGate
**VDOM Not Found**
- Use `discover_vdoms` to view available VDOMs
- VDOM names are case-sensitive
**Policy Creation 500 Error**
- FortiOS 8.0 requires `"schedule": "always"` field
- Address/service objects containing `/` require URL encoding (handled internally)
---
## CI/CD
Automatic runs on every push to `main` branch (`.github/workflows/ci.yml`):
| Job | Description |
|-----|------|
| Lint | `ruff check src/` code style check |
| Build | `python -m build` package structure verification |
| Docker | `docker build` image build verification |
---
## License
MIT License. See [LICENSE](LICENSE)
## Acknowledgements
- [alpadalar/fortigate-mcp-server](https://github.com/alpadalar/fortigate-mcp-server) — Original project
- [Model Context Protocol](https://modelcontextprotocol.io/) — Protocol specification
- [FastMCP](https://gofastmcp.com/) — Python MCP Server framework
- [FortiGate Product Documentation](https://docs.fortinet.com/) — Official FortiGate documentation
- [httpx](https://www.python-httpx.org/) — Asynchronous HTTP client
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available