Skip to main content
Glama

xfoil-mcp - Aerodynamic polars on-call for your MCP agents

TL;DR: Wrap XFOIL in an MCP-native service so agents can request lift/drag/moment polars without touching shell scripts.

Table of contents

  1. What it provides

  2. Quickstart

  3. Run as a service

  4. Agent playbook

  5. Stretch ideas

  6. Accessibility & upkeep

  7. Contributing

What it provides

Scenario

Value

Quick experiments

Compute lift/drag/moment polars from an airfoil file or NACA code without launching XFOIL manually.

MCP integration

STDIO/HTTP transports that follow the Model Context Protocol so ToolHive or other clients can call XFOIL programmatically.

Audit trail

Responses include on-disk work directories and metadata so you can trace which inputs produced a given polar.

Quickstart

1. Install dependencies

uv pip install "git+https://github.com/Three-Little-Birds/xfoil-mcp.git"

Download XFOIL from the official MIT site and place the executable on your PATH (or point to it explicitly):

export XFOIL_BIN=/path/to/xfoil

2. Compute your first polar

from pathlib import Path
from io import StringIO

import pandas as pd

from xfoil_mcp import PolarRequest, compute_polar

airfoil_path = Path("examples/naca2412.dat")  # bundled sample airfoil
request = PolarRequest(
    airfoil_name="naca2412",
    airfoil_data=airfoil_path.read_text(encoding="utf-8"),
    alphas=[-2 + 0.5 * i for i in range(29)],  # -2 .. 12 in 0.5° steps
    reynolds=1.2e6,
    mach=0.08,
)
response = compute_polar(request)

polar_csv_path = Path("polar.csv")
polar_csv_path.write_text(response.csv, encoding="utf-8")
print("CSV stored at", polar_csv_path)

Inspect the first few rows:

df = pd.read_csv(StringIO(response.csv), comment="#")
print(df.head())
  • The bundled examples/naca2412.dat follows cosine-spaced sampling (identical to XFOIL's PANE output) so you can drop it into your own scripts without re-gridding.

  • The CSV header is normalised to alpha, CL, CD, CM. XFOIL may append extra columns (e.g. CDp, Cl/Cd, transition locations); those appear after the first four fields and remain untouched.

Run as a service

CLI (STDIO / Streamable HTTP)

uvx xfoil-mcp  # runs the MCP over stdio
# or python -m xfoil_mcp
python -m xfoil_mcp --transport streamable-http --host 0.0.0.0 --port 8000 --path /mcp

Use python -m xfoil_mcp --describe to view metadata and exit.

Tip (macOS/Linux): building XFOIL natively requires XQuartz/X11 headers. To avoid that setup, run the quickstart inside the repo's Docker recipe:

docker run --rm -v "$PWD/extern/xfoil-mcp:/workspace/xfoil-mcp" python:3.13-slim bash -lc '
  set -euo pipefail
  apt-get update && apt-get install -y --no-install-recommends xfoil build-essential \
    && pip install --no-cache-dir pandas /workspace/xfoil-mcp \
    && python - <<"PY"
from pathlib import Path
from io import StringIO
import pandas as pd
from xfoil_mcp import PolarRequest, compute_polar

airfoil_path = Path("examples/naca2412.dat")
request = PolarRequest(
    airfoil_name="naca2412",
    airfoil_data=airfoil_path.read_text(encoding="utf-8"),
    alphas=[-2 + 0.5 * i for i in range(29)],
    reynolds=1.2e6,
    mach=0.08,
)
response = compute_polar(request)
print(pd.read_csv(StringIO(response.csv), comment="#").head())
PY
'

Handling failures

compute_polar raises RuntimeError when XFOIL fails to emit a polar (common causes: laminar separation, too few iterations, or Reynolds numbers below ~5e4). The stderr/stdout from XFOIL is preserved in the exception message—increase ITER, seed a better initial airfoil mesh, or adjust alpha_start_deg/alpha_step_deg in response. Non-zero exit codes that still produce a polar are annotated in the CSV with a leading # xfoil exit code ... comment so you can decide whether to discard or accept the run.

FastAPI (REST)

uv run uvicorn xfoil_mcp.fastapi_app:create_app --factory --port 8001

Browse http://127.0.0.1:8001/docs to test requests and download CSVs.

python-sdk tool (STDIO / MCP)

from mcp.server.fastmcp import FastMCP
from xfoil_mcp.tool import build_tool

mcp = FastMCP("xfoil-mcp", "XFOIL polar analysis")
build_tool(mcp)

if __name__ == "__main__":
    mcp.run()

Launch:

uv run mcp dev examples/xfoil_tool.py

Connect any MCP-compatible agent (Cursor, Claude Desktop, Windsurf, ...) and ask for polars on demand.

ToolHive smoke test

Requires XFOIL_BIN pointing to the XFOIL executable:

export XFOIL_BIN=/path/to/xfoil
uvx --with 'mcp==1.20.0' python scripts/integration/run_xfoil.py
# ToolHive 2025+ defaults to Streamable HTTP; match that transport when registering
# the workload manually to avoid the legacy SSE proxy failures.

Agent playbook

  • Batch sweeps - iterate through a directory of .dat files and persist each polar to object storage.

  • Optimisation loops - embed the tool inside a genetic algorithm; typed responses keep mutation + evaluation deterministic.

  • Visualisation - feed response.csv_path into Plotly or Matplotlib to plot Cl vs. Cd without manual parsing.

Stretch ideas

  1. Compare multiple foils by merging CSVs into a parquet dataset for notebook analysis.

  2. Pair with ctrltest-mcp to explore control implications from polar derivatives.

  3. Schedule nightly polars via CI and publish artefacts for downstream agents.

Accessibility & upkeep

  • Tests mock XFOIL so they run quickly: uv run pytest.

  • Use uv run ruff check . before submitting changes.

Contributing

  1. Fork and uv pip install --system -e .[dev].

  2. Run the formatting and test suite.

  3. Open a PR with before/after polar snippets so reviewers can verify quickly.

MIT license - see LICENSE.

Install Server
A
security – no known vulnerabilities
A
license - permissive license
A
quality - confirmed to work

Resources

Looking for Admin?

Admins can modify the Dockerfile, update the server description, and track usage metrics. If you are the server author, to access the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yevheniikravchuk/xfoil-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server