Security Best Practices When Deploying MCP-Airflow-API: A Complete Guide
Enable Bearer token authentication, use strong randomly generated secrets, terminate TLS at a reverse proxy, and restrict network access to trusted clients when deploying MCP-Airflow-API in production.
MCP-Airflow-API is a Model Context Protocol (MCP) server that wraps the Apache Airflow REST API into natural-language tools. When exposing this server over HTTP, following security best practices when deploying MCP-Airflow-API becomes critical to protect your Airflow instance and prevent unauthorized access to DAGs and task metadata.
Enable Authentication for Remote Deployments
The server supports Bearer-token authentication specifically for the streamable-http transport mode. In src/mcp_airflow_api/mcp_main.py, the environment variable REMOTE_AUTH_ENABLE triggers the instantiation of a StaticTokenVerifier that validates incoming requests against a pre-shared secret【/cache/repos/github.com/call518/mcp-airflow-api/main/src/mcp_airflow_api/mcp_main.py#L38-L45】.
When enabled, the secret key is read from REMOTE_SECRET_KEY (or the --secret-key CLI flag) and used to build a static token map【/cache/repos/github.com/call518/mcp-airflow-api/main/src/mcp_airflow_api/mcp_main.py#L45-L53】.
Configure Bearer Token Authentication
Set the following environment variables before starting the server:
export REMOTE_AUTH_ENABLE=true
export REMOTE_SECRET_KEY="$(openssl rand -base64 48)"
If REMOTE_AUTH_ENABLE is unset, the server defaults to false and emits a warning when streamable-http is used, making the fail-closed behavior explicit【/cache/repos/github.com/call518/mcp-airflow-api/main/src/mcp_airflow_api/mcp_main.py#L58-L62】.
Secure Secret Management
Generate Strong Random Secrets
The repository recommends a 32-character random secret minimum for REMOTE_SECRET_KEY【/cache/repos/github.com/call518/mcp-airflow-api/main/README.md#L52-L66】. Use cryptographically secure random generation:
# Generate a 64-byte (512-bit) key
openssl rand -base64 48
Externalize Secrets from Code
Never commit secrets to version control. The repository provides an .env.example file that you should copy to .env and populate with real values:
cp .env.example .env
# Edit .env with your secrets
echo ".env" >> .gitignore
For containerized deployments, inject secrets via Docker Secrets, Kubernetes Secrets, or a secrets manager like HashiCorp Vault.
Transport Layer Security
Terminate TLS at a Reverse Proxy
MCP-Airflow-API does not terminate TLS internally; it is designed to run behind a reverse proxy such as NGINX, Traefik, or Caddy. Configure your proxy to handle HTTPS and forward to the internal FASTMCP_PORT (default 8000).
Example NGINX configuration:
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/ssl/certs/mcp.crt;
ssl_certificate_key /etc/ssl/private/mcp.key;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Internal Port Configuration
The server listens on the port specified by FASTMCP_PORT (default 8000). Bind this to localhost only if running without a reverse proxy, though the reverse-proxy approach is strongly preferred for TLS.
Network Isolation and Access Control
Restrict Ingress to Trusted Networks
In production, limit exposure of the HTTP endpoint to trusted networks only. Deploy within an internal VPC, behind a VPN, or use firewall rules to restrict source IPs.
Client IP Whitelisting
If your infrastructure supports it, configure your load balancer or reverse proxy to whitelist specific client IPs that are authorized to connect to the MCP server.
Operational Security Practices
Regular Secret Rotation
Rotate REMOTE_SECRET_KEY regularly (e.g., every 30 days). After updating the secret, restart the server so the new token map takes effect【/cache/repos/github.com/call518/mcp-airflow-api/main/src/mcp_airflow_api/mcp_main.py#L65-L73】.
Kubernetes example for zero-downtime rotation:
apiVersion: v1
kind: Secret
metadata:
name: mcp-airflow-secret
type: Opaque
data:
REMOTE_SECRET_KEY: <base64-encoded-new-key>
kubectl apply -f secret.yaml
kubectl rollout restart deployment/mcp-server
Monitoring and Logging
Enable logging with MCP_LOG_LEVEL=INFO or higher to capture authentication failures. Monitor logs for 401 Unauthorized responses, which indicate potential brute-force attempts or misconfigured clients【/cache/repos/github.com/call518/mcp-airflow-api/main/README.md#L11-L14】.
Fail-Closed Defaults
The server implements fail-closed defaults: if REMOTE_AUTH_ENABLE is unset, authentication remains disabled but the server emits a clear warning when streamable-http transport is selected【/cache/repos/github.com/call518/mcp-airflow-api/main/src/mcp_airflow_api/mcp_main.py#L58-L62】. This makes the security posture explicit to operators.
Deployment Examples
Docker Compose with Authentication
services:
mcp-server:
build:
context: .
dockerfile: Dockerfile.MCP-Server
environment:
- FASTMCP_TYPE=streamable-http
- FASTMCP_PORT=8000
- REMOTE_AUTH_ENABLE=true
- REMOTE_SECRET_KEY=${REMOTE_SECRET_KEY}
ports:
- "127.0.0.1:8000:8000"
Store the secret in a .env file excluded from version control.
Kubernetes Secret Rotation
As shown in the operational security section, use kubectl rollout restart after updating the Kubernetes Secret to apply new credentials without manual pod deletion.
NGINX TLS Termination
Place the NGINX configuration shown earlier in /etc/nginx/conf.d/mcp-airflow-api.conf and reload NGINX to encrypt all traffic to the MCP server.
Summary
- Enable Bearer token authentication by setting
REMOTE_AUTH_ENABLE=trueand generating a strongREMOTE_SECRET_KEYwhen usingstreamable-httptransport. - Use stdio transport for local development to avoid network exposure entirely.
- Terminate TLS at a reverse proxy (NGINX, Traefik, Caddy) since the server does not handle HTTPS internally.
- Externalize secrets using environment variables, Docker Secrets, or Kubernetes Secrets—never commit credentials to version control.
- Rotate secrets regularly (every 30 days) and restart the server to load new token maps.
- Monitor logs for
401 Unauthorizederrors to detect unauthorized access attempts. - Restrict network access to trusted VPCs, VPNs, or whitelisted client IPs.
Frequently Asked Questions
Do I need authentication if I run MCP-Airflow-API locally?
No. When using the default stdio transport mode, the server runs as a child process of your local client with no network exposure, making authentication unnecessary. Only enable REMOTE_AUTH_ENABLE when using streamable-http transport for remote access【/cache/repos/github.com/call518/mcp-airflow-api/main/src/mcp_airflow_api/mcp_main.py#L75-L81】.
How long should my REMOTE_SECRET_KEY be?
The repository recommends a minimum of 32 characters, but you should generate a cryptographically secure random string of at least 48 bytes (64 base64 characters) using openssl rand -base64 48. Store this in an environment variable or secrets manager, never in your codebase【/cache/repos/github.com/call518/mcp-airflow-api/main/README.md#L52-L66】.
Can MCP-Airflow-API handle HTTPS termination internally?
No. The server is designed to run behind a reverse proxy such as NGINX, Traefik, or Caddy. Configure your proxy to handle TLS termination and forward decrypted traffic to the server's FASTMCP_PORT (default 8000). This architecture keeps the Python server simple while ensuring encrypted transport.
What happens if I forget to enable authentication on a public deployment?
If REMOTE_AUTH_ENABLE is unset or false while using streamable-http, the server will start without authentication but emit a clear warning in the logs. However, this leaves your Airflow instance exposed to anyone who can reach the endpoint. Always verify REMOTE_AUTH_ENABLE=true is set before exposing the server to untrusted networks【/cache/repos/github.com/call518/mcp-airflow-api/main/src/mcp_airflow_api/mcp_main.py#L58-L62】.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →