LABSCO SUMMARY
`--safe` is the flag to reach for first, because unsafe is the default.
Started plain, the server will happily trigger, pause and modify things in your Airflow instance; --safe restricts it to GET requests, which is the right posture for anything pointed at production while you are still learning what the model does with it. Hierarchical discovery is the other default worth keeping — Airflow's API is large enough that a flat tool list crowds out the conversation.
What it is
An MCP server for Apache Airflow 3. It fetches the OpenAPI spec from your Airflow instance at startup and turns it into tools, so the surface tracks the API your deployment actually exposes. Two switches shape it: an operation mode that can restrict everything to read-only, and a discovery mode that groups tools by category — DAGs, tasks, connections and so on — rather than exposing all of them at once.
What you get
- Airflow's own API surface as tools — DAGs, tasks, connections and the rest of the categories your instance exposes — generated from the spec at
${base_url}/openapi.json - Safe mode with
--safe, which allows only read-only GET operations and makes modification impossible;--unsafeis the default and allows everything - Hierarchical discovery by default: browse categories first and then pick a tool, which keeps a large API manageable;
--static-toolsexposes everything immediately for programmatic use - A folder of Markdown guides mounted as read-only MCP resources — each top-level
.mdor.markdownfile becomes afile:///<slug>resource, titled from its first heading - Both transports: stdio for direct process communication, and Streamable HTTP with
--httpfor web deployments and multiple clients
Requirements
An Airflow 3 instance and a JWT token — Airflow 3.0 dropped cookie and basic auth, so a valid token is the only way in. Run it with uvx airflow-mcp-server, passing --base-url and --auth-token, or set AIRFLOW_BASE_URL and AUTH_TOKEN. --base-url must be the root Airflow URL with no /api/v2 suffix, because the server appends the OpenAPI path itself. --http switches to Streamable HTTP with --port (default 3000) and --host (default localhost); --sse still exists but is deprecated in favour of HTTP. --resources-dir, or AIRFLOW_MCP_RESOURCES_DIR, points at the Markdown guides, and the list refreshes on restart. Pagination defaults to 100 items, changed via maximum_page_limit in the [api] section of airflow.cfg. Published to PyPI as airflow-mcp-server and registered as io.github.abhishekbhakat/airflow-mcp-server.
Setup effort
One command plus a key — uvx airflow-mcp-server --safe --base-url http://localhost:8080 --auth-token <YOUR_AUTH_TOKEN>, then supply credentials
USE CASES
01
Asking why a DAG run failed
Browse to the DAG and task categories, read the run and task state through read-only calls, with the server started in safe mode.
02
Giving an assistant production visibility without risk
Run with --safe so every mutating operation is off the table, and hand out a JWT scoped no wider than you need.
03
Serving one Airflow to several clients
Start it with --http on a port instead of one stdio process per client, and skip the deprecated SSE transport.
04
Teaching the assistant your team's runbooks
Point the resources directory at your Markdown guides; each becomes a read-only resource the client can read alongside the live API.
BEFORE YOU INSTALL
What to know first
Requires
- uvx on PATH
- AUTH_TOKEN in your environment
- AIRFLOW_BASE_URL in your environment
Where it runs
The documented client runs the server on your machine.
INSTALLATION
Connect your client
Server setup
TERMINAL
uvx airflow-mcp-server --safe --base-url http://localhost:8080 --auth-token <YOUR_AUTH_TOKEN>MCP Clients
Claude Desktop
CLAUDE DESKTOP · JSON
{
"mcpServers": {
"airflow-mcp-server": {
"command": "uvx",
"args": [
"airflow-mcp-server",
"--base-url",
"http://localhost:8080",
"--auth-token",
"<YOUR_JWT_TOKEN>"
]
}
}
}http://localhost:8080 is a local Airflow 3 instance; for another one, use its root URL (without /api/v2). <YOUR_JWT_TOKEN> is your Airflow JWT. This block starts in unsafe mode, the default, which allows changes to your Airflow; add "--safe" to args, as the command above does, to allow only read-only (GET) operations.