How to Run Multiple Airflow Clusters with Different API Versions Simultaneously
Launch separate MCP server instances for each Airflow cluster, configuring each with its own AIRFLOW_API_BASE_URL and AIRFLOW_API_VERSION environment variables.
The mcp-airflow-api package is architected to connect to a single Airflow REST API instance per server process. To manage multiple clusters running different versions—such as Airflow 2.x using the v1 API and Airflow 3.x using the v2 API—you deploy isolated MCP server instances with version-specific configurations.
Understanding the Version-Aware Architecture
The server dynamically selects the appropriate tool set based on the AIRFLOW_API_VERSION environment variable at startup.
How the Server Selects API Tools
In src/mcp_airflow_api/mcp_main.py (lines 241-250), the entry point reads the API version and registers the corresponding tool suite:
api_version = get_api_version() # Reads AIRFLOW_API_VERSION, defaults to "v1"
if api_version == "v1":
from mcp_airflow_api.tools import v1_tools
v1_tools.register_tools(mcp_instance)
elif api_version == "v2":
from mcp_airflow_api.tools import v2_tools
v2_tools.register_tools(mcp_instance)
The v1 tool suite (v1_tools.py) registers the v1-specific request function and common tools compatible with Airflow 2.x. The v2 tool suite (v2_tools.py) registers the v2 request function and adds asset-related tools for Airflow 3.x features.
Environment-Based Configuration
The src/mcp_airflow_api/functions.py file handles version detection and URL construction:
get_api_version()(lines 61-73) returns the value ofAIRFLOW_API_VERSIONor defaults to"v1"construct_api_url()(lines 75-80) builds versioned endpoints:f"{base_url}/{version}{path}"
This ensures each server instance constructs requests appropriate for its configured Airflow cluster.
Configuring Multiple MCP Server Instances
To run multiple clusters simultaneously, launch separate processes with distinct environment configurations.
Command Line Deployment
Run two separate instances from the terminal, each targeting a different cluster:
# Instance 1 – Airflow 2.x cluster (v1 API)
AIRFLOW_API_BASE_URL=http://airflow-v1.example.com/api \
AIRFLOW_API_VERSION=v1 \
python -m mcp_airflow_api
# Instance 2 – Airflow 3.x cluster (v2 API)
AIRFLOW_API_BASE_URL=http://airflow-v2.example.com/api \
AIRFLOW_API_VERSION=v2 \
python -m mcp_airflow_api
Each process logs the version it loaded, confirming isolation:
INFO:root:Loading Airflow API v1 tools (Airflow 2.x)
INFO:root:Loading Airflow API v2 tools (Airflow 3.0+)
Docker Compose Setup
For production deployments, use Docker Compose to run isolated containers:
version: "3.9"
services:
mcp-v1:
image: ghcr.io/call518/mcp-airflow-api:latest
environment:
- AIRFLOW_API_BASE_URL=http://airflow-v1/api
- AIRFLOW_API_VERSION=v1
ports:
- "8001:8000"
mcp-v2:
image: ghcr.io/call518/mcp-airflow-api:latest
environment:
- AIRFLOW_API_BASE_URL=http://airflow-v2/api
- AIRFLOW_API_VERSION=v2
ports:
- "8002:8000"
Running docker compose up -d starts both servers simultaneously, each bound to a distinct port and Airflow cluster.
Programmatic Orchestration
To manage instances within a larger Python application:
import os
from subprocess import Popen
def start_mcp(base_url: str, version: str, port: int):
env = os.environ.copy()
env.update({
"AIRFLOW_API_BASE_URL": base_url,
"AIRFLOW_API_VERSION": version,
"FASTMCP_TYPE": "streamable-http",
"FASTMCP_PORT": str(port)
})
return Popen(["python", "-m", "mcp_airflow_api"], env=env)
# Launch Airflow 2.x (v1) instance
proc_v1 = start_mcp("http://airflow-v1/api", "v1", 8001)
# Launch Airflow 3.x (v2) instance
proc_v2 = start_mcp("http://airflow-v2/api", "v2", 8002)
Both processes run concurrently with isolated environments, enabling simultaneous management of heterogeneous Airflow deployments.
Key Implementation Files
| File | Role | Critical Sections |
|---|---|---|
src/mcp_airflow_api/mcp_main.py |
Entry point and version selection | Lines 241-250: Version-based tool registration |
src/mcp_airflow_api/functions.py |
Environment configuration and URL construction | get_api_version() (lines 61-73), construct_api_url() (lines 75-80) |
src/mcp_airflow_api/tools/v1_tools.py |
v1 API tool registration | Assigns airflow_request_v1 to common tools |
src/mcp_airflow_api/tools/v2_tools.py |
v2 API tool registration | Assigns airflow_request_v2 and adds asset tools |
src/mcp_airflow_api/tools/common_tools.py |
Core tool implementations | 43 shared tools (e.g., list_dags, get_health) |
Summary
- The mcp-airflow-api server operates against a single Airflow cluster per process, determined by the
AIRFLOW_API_VERSIONenvironment variable. - To run multiple Airflow clusters with different API versions simultaneously, launch separate server instances with distinct
AIRFLOW_API_BASE_URLandAIRFLOW_API_VERSIONconfigurations. - The version-aware registration logic in
mcp_main.pyautomatically loads the correct tool suite (v1 or v2) and request functions based on the environment. - Deployment options include command-line execution, Docker Compose for containerized isolation, or programmatic orchestration using Python subprocesses.
Frequently Asked Questions
Can a single MCP server instance connect to multiple Airflow clusters simultaneously?
No. The architecture is designed for one cluster per server process. The get_api_version() function in functions.py reads AIRFLOW_API_VERSION once at startup, and mcp_main.py registers only the corresponding tool set. To manage multiple clusters, run separate instances with unique environment configurations.
What happens if I specify an invalid API version?
The server defaults to "v1" if AIRFLOW_API_VERSION is unset or contains an unrecognized value. This fallback is implemented in get_api_version() within functions.py. However, tool registration in mcp_main.py explicitly checks for "v1" or "v2", so invalid versions may result in no tools being registered or unexpected behavior.
Do I need different Docker images for v1 and v2 API support?
No. The same ghcr.io/call518/mcp-airflow-api:latest image supports both API versions. The version-specific behavior is determined entirely by the AIRFLOW_API_VERSION environment variable at runtime. Use the same image with different environment configurations for each cluster.
How do I handle authentication when running multiple instances?
Each instance manages its own authentication independently via environment variables. Set AIRFLOW_API_AUTH_TYPE (Basic or JWT), AIRFLOW_API_USERNAME, AIRFLOW_API_PASSWORD, or AIRFLOW_API_TOKEN uniquely for each instance. The functions.py module reads these per-process, ensuring isolated credentials for each Airflow cluster connection.
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 →