Skip to content
All posts
MCPFortiEDRPythonOpen Source

FortiEDR MCP Server: opening the EDR console to natural language

An open-source MCP server that connects 146 FortiEDR API endpoints to LLM assistants like Claude, designed for MSSP operations — why I built it and how it's designed.

Picture an MDR analyst at the 09:00 stand-up with dozens of MSSP customers on their plate. The question is simple: "Summarise the unhandled critical events across all tenants for the last 8 hours." The old way: open 35 tabs, filter each one, take notes — roughly 45 minutes. With FortiEDR MCP Server: one prompt, 30 seconds.

This post walks through the design decisions behind my open-source project (GitHub) that connects FortiEDR to LLM assistants via the Model Context Protocol.

Why MCP is the right layer

MCP is the standard bridge between LLM clients and external systems. You write the server once; Claude Desktop, Claude Code, Cursor, VS Code + Copilot, Windsurf — the same server works everywhere. Instead of rewriting the EDR integration per client, you invest in the protocol once.

I didn't write 146 endpoints by hand

The server ships 146 API tools auto-generated from FortiEDR's official Postman collection: events, inventory, threat hunting, policies, organizations, forensics, audit and more. The only hand-written part is the generation pipeline — when the API changes, the tools are regenerated. There is no dependency on the fortiedr Python SDK; an httpx-based async client with retry, rate-limit and timeout handling talks to the REST API directly.

The real value: composite tools

Raw endpoints are necessary but not sufficient — the questions analysts actually ask are usually a combination of several calls. So the server ships composite tools built for MSSP scenarios:

  • mssp_ioc_sweep — CISA just published a new APT hash; sweep the last 30 days across every tenant in parallel. The old way costs ~30 minutes of per-customer threat-hunting tabs; this is a single call.
  • mssp_event_summary_by_org — pulls event counts across all tenants in parallel and ranks them.
  • mdr_event_triage_brief — assembles all the context needed to make an FP/TP decision for an event in one shot.
  • mdr_monthly_report_data — gathers every piece of data needed for a monthly customer report in a single call.

Giving an LLM EDR privileges: three safety modes

Handing an LLM the power to isolate endpoints is not something to take lightly. That's why the server runs in three modes:

Safe     → READ_ONLY=true   | reporting, hunting (recommended for production)
Standard → writes enabled    | classify, comment, policy (Tier 1 analyst)
Full     → DESTRUCTIVE=true  | everything incl. isolation (senior / IR team)

The default recommendation is Safe: the LLM can read everything and break nothing. Destructive actions (like device isolation) don't even appear in the tool list unless explicitly enabled via a separate environment variable. The permission model is opt-in, not opt-out — the only sane default in an MDR environment.

A field note on setup

On the FortiEDR side the API user needs the Rest API role (the Admin role alone is not enough), and after creating the account you must log in to the console once and rotate the password — otherwise the API returns 401. These two details are by far the most common setup questions.

Wrapping up

The project is open source under MIT; it runs on Python 3.10+, installs with a plain pip install -e ., and the examples/ folder has ready-made configs for the popular clients. Feedback and issues are welcome: github.com/mehmetvatansever/fortiedr-mcp-server