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

Related MCP server: Flappy MCP Server

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.

Available Tools

1 tool
xfoil.compute_polarC

Run XFOIL for an airfoil at specified Reynolds angle of attack sweep. Input airfoil coordinates or NACA code plus sweep parameters. Returns lift/drag polar tables and solver metadata.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
csvYesCSV text containing XFOIL polar data

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions that the tool 'Returns lift/drag polar tables and solver metadata,' which hints at output but lacks details on performance (e.g., computational cost, error handling, or runtime behavior). For a tool involving complex simulations, this is insufficient to inform safe and effective use.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded, with two sentences that efficiently cover purpose and output. Every sentence adds value, avoiding redundancy. It could be slightly more structured for clarity but remains appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (simulation with multiple parameters) and no annotations, the description is moderately complete but has gaps. It mentions output types, which aligns with the presence of an output schema, but lacks behavioral context and detailed parameter guidance. For a tool with such technical depth, more context would be beneficial.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds minimal parameter semantics beyond the schema, mentioning 'airfoil coordinates or NACA code plus sweep parameters' and 'Reynolds angle of attack sweep,' which loosely maps to schema fields. However, with 0% schema description coverage, it doesn't fully compensate by explaining parameter roles, formats, or interactions, leaving gaps in understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Run XFOIL for an airfoil at specified Reynolds angle of attack sweep.' It specifies the verb ('Run XFOIL'), resource ('airfoil'), and scope ('polar sweep'), though it doesn't differentiate from siblings as none exist. The description is specific but could be slightly more precise about the computational nature.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, prerequisites, or constraints. It mentions input options ('airfoil coordinates or NACA code') but lacks explicit usage context, such as typical scenarios or limitations, leaving the agent with minimal operational direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

B3.1/5.0
Disambiguation5/5

With only one tool, there is no possibility of ambiguity or overlap between tools. The tool's purpose is clearly defined as computing aerodynamic polars using XFOIL, leaving no room for confusion with other tools.

Naming Consistency5/5

The single tool follows a clear verb_noun pattern (compute_polar), and there are no other tools to create inconsistency. The naming is straightforward and descriptive, adhering to a consistent convention.

Tool Count2/5

One tool is too few for a server named 'XFOIL MCP Server', which suggests a broader scope for aerodynamic analysis. While the tool covers a core function, the lack of additional tools (e.g., for airfoil geometry manipulation, result visualization, or batch processing) makes the set feel incomplete and limited in utility.

Completeness2/5

The tool provides polar computation, but the server likely aims to support aerodynamic workflows. There are significant gaps, such as tools for generating or modifying airfoil coordinates, analyzing specific points, or handling multiple analyses, which limits the server's ability to cover the domain comprehensively.

Maintenance

ActivityInactive
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

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/Three-Little-Birds/xfoil-mcp'

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