# wisdem-mcp **Repository Path**: openminds/wisdem-mcp ## Basic Information - **Project Name**: wisdem-mcp - **Description**: Agent 驱动的风力机总体设计 MCP 服务,底层为 NREL WISDEM 4.2.8(纯 PyPI wheel 依赖,零源码侵入)。通过标准 MCP 协议向任意 Agent(Claude、Cursor 等)暴露风机设计与评估能力:Agent 选择参考机型模板、修改设计参数、提交评估/优化作业、读取 AEP 与各部件质量等结果,形成"设计 → 评估 → 迭代"的自动闭环。 - **Primary Language**: Python - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-16 - **Last Updated**: 2026-10-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: WISDEM, MCP ## README # wisdem-mcp Agent 驱动的风力机总体设计 MCP 服务,底层为 NREL [WISDEM](https://github.com/NLRWindSystems/WISDEM) 4.2.8(纯 PyPI wheel 依赖,零源码侵入)。 通过标准 MCP 协议向任意 Agent(Claude、Cursor 等)暴露风机设计与评估能力:Agent 选择参考机型模板、修改设计参数、提交评估/优化作业、读取 AEP 与各部件质量等结果,形成"设计 → 评估 → 迭代"的自动闭环。 ## 功能特性 - **异步作业**:`submit_run` 立即返回 `job_id`,WISDEM 在独立子进程中执行,长任务(优化可达数十分钟)不阻塞 MCP 连接;状态落盘,服务重启后仍可查询历史作业 - **秒级气动粗筛**:`mode="aero"` 用 CCBlade 直连(纯查表 BEM,不经 OpenMDAO 模型图),1–10 秒返回 Cp 峰值、功率/推力曲线,适合 Agent 大范围扫描设计空间后再用 `analysis` 精算;`corr3d=True` 可叠加 3D 旋转修正 - **自备翼型数据接入**:`prepare_polar` 把有限攻角区间的风洞/CFD 极线按 Viterna 方法外插到全圆(±180°),返回可拼入 geometry.yaml 的 windIO 翼型条目 - **设计变量直传**:基于 WISDEM 官方预留的黑盒钩子 `overridden_values`,Agent 修改参数无需拼写 YAML - **固定优化模式**:`optimization` 提供两种模式——`default`(设计变量叶轮直径,基线 ±15%,目标 LCOE)与 `rotor`(rotor-only:设计变量叶片扭角+弦长,塔架/传动链按基线固定,目标 AEP) - **Schema 校验**:提交前可用 `validate_inputs` 按三份官方 Schema(几何/建模/分析)校验 YAML 输入 - **结构化结果**:自动提取 AEP、叶轮直径、叶片/塔架/机舱/发电机质量等关键指标(键名含单位后缀) - **详细数据提取**:除摘要结果外,`get_output` 可按需读取 WISDEM 全量输出(npz 归档,1800+ 键):气动功率/推力/Cp 曲线、叶片沿展向的弦长/EI/应变分布、塔架截面与频率、传动链部件等 - **参考模板内置**:NREL 5MW 与 IEA 3.4/10/15/22MW 官方参考机型开箱即用 ## 系统架构 ``` Agent (MCP 客户端) │ stdio / streamable HTTP ▼ FastMCP 4 服务 ── list_templates / validate_inputs / prepare_polar / submit_run / get_status / get_results / get_output │ │ ▼ ▼ JobManager WISDEM 库 (uv sync 安装) │ │ ▼ ▼ jobs// ◄────── worker 子进程: mode=analysis/optimization → run_wisdem(run_only / run_driver) status.json / mode=aero → CCBlade 直连 BEM(秒级粗筛) results.json / worker.log / outputs/ ``` ## 环境要求 - Windows / Linux / macOS - [uv](https://docs.astral.sh/uv/)(环境构建与运行的标准方式) - WISDEM 的 PyPI wheel 覆盖 cp311–cp315,含预编译 Fortran 扩展,无需本地编译器 ## 安装 ```powershell git clone <本仓库> wisdem-mcp cd wisdem-mcp uv sync ``` `uv sync` 依据 `uv.lock` 精确复现环境(198 个锁定包,Python 版本由 `.python-version` 锁定 3.12),并将本项目以 editable 模式装入,CLI 入口 `wisdem-mcp` 随之可用。 > **注意**:`.python-version` 必须保存为 UTF-8 **无 BOM** 编码——若带 BOM,uv 会报 `Ignoring unsupported Python request ... in version file` 并可能回退到其他 Python 版本。 ### 国内镜像加速 若 `uv sync` 因默认 PyPI 源或代理镜像超时失败(如 `uv.agentsmirror.com` 报 `error decoding response body` / `operation timed out`),可临时指定镜像: ```powershell # 包索引:清华 TUNA $env:UV_DEFAULT_INDEX = "https://pypi.tuna.tsinghua.edu.cn/simple" # Python 解释器下载:上海交大 SJTU(仅当需要下载新 Python 版本时) $env:UV_PYTHON_INSTALL_MIRROR = "https://mirror.sjtu.edu.cn/github-release/astral-sh/python-build-standalone/" uv sync ``` 长期使用可将以上两个环境变量写入系统环境变量,或在 `%APPDATA%\uv\uv.toml`(Linux/macOS 为 `~/.config/uv/uv.toml`)中配置: ```toml [[index]] url = "https://pypi.tuna.tsinghua.edu.cn/simple" default = true python-install-mirror = "https://mirror.sjtu.edu.cn/github-release/astral-sh/python-build-standalone/" ``` > 若全局 `uv.toml` 中配置过失效的 `python-downloads-json-url`(如指向 `uv.agentsmirror.com`),建议删除该行,以免影响 Python 版本发现。 ## 启动服务 ```powershell # stdio(供 MCP 客户端直连) uv run wisdem-mcp # streamable HTTP(远程 Agent / 多客户端) uv run wisdem-mcp --transport http --port 8000 ``` MCP 客户端配置示例(stdio)——通过 `uv run` 启动,自动使用 `uv sync` 对齐过的环境: ```json { "mcpServers": { "wisdem-design": { "command": "uv", "args": ["run", "--directory", "e:\\myWorkspace\\wisdem-mcp", "wisdem-mcp"] } } } ``` > 说明:`uv` 的进度信息写入 stderr,不会污染 stdio 的 JSON-RPC 通道;若追求最简启动链路,也可直连 `.venv\Scripts\wisdem-mcp.exe` 绝对路径。 ## MCP 工具 | 工具 | 说明 | |---|---| | `list_templates()` | 列出内置参考机型模板、基线参数与可修改的设计变量 | | `validate_inputs(geometry, modeling, analysis)` | 三份 YAML 字符串按 WISDEM Schema 校验,返回结构化错误 | | `prepare_polar(alpha, cl, cd, re, cdmax?, ar?, nalpha?, name?)` | 翼型极线预处理:有限攻角区间(±90° 内,≥3 点)按 **Viterna 方法外插到全圆 ±180°**,返回可拼入 geometry.yaml 的 windIO 翼型条目 YAML(`airfoil_yaml`)与点数/区间摘要;`ar` 提供时按 `cdmax = 1.11 + 0.018*AR` 自动推算锚点,否则用 `cdmax`(默认 1.5);`nalpha` 控制每段外插点数(默认 25,全圆约 180 点) | | `submit_run(template, design_changes, mode, opt_mode?, corr3d?)` | 提交作业,立即返回 `job_id`。`mode`: `analysis`(单点评估,约 0.5–2 分钟)、`optimization`(固定优化模式,见 `opt_mode`,数十分钟级)或 `aero`(秒级气动粗筛:CCBlade 直连,仅支持 `hub_height_user`/`rotor_diameter_user`/`rated_power` 三个修改键,其余键记入 `ignored_design_changes`;返回 `cp_max`、`power_at_11ms_mw`、`thrust_at_11ms_kn`、`wind_speed_at_rated_mps`;2D 极线无 3D 修正、无预锥/倾角/变桨,仅供粗筛,精确值用 `analysis`)。`corr3d` 仅 aero 生效:`True` 时逐站应用 3D 旋转修正(`Polar.correction3D`,失速延迟,叶根 <5% 半径段跳过),更接近真实气动。`opt_mode`(仅 optimization 生效)选固定优化模式——`default` 设计变量叶轮直径(基线 ±15%)+ 目标 LCOE;`rotor` rotor-only 设计变量叶片扭角+弦长(叶轮直径 DV 关闭,塔架/传动链固定),目标固定 `AEP` | | `get_status(job_id)` | 查询状态(queued/running/succeeded/failed)与日志尾部 | | `get_results(job_id)` | 读取结果,每项为 `{key, value}`:如 `rated_power_kw: 5000`、`aep_kwh`、`lcoe_usd_mwh`、`rotor_diameter_m`、`blade_mass_kg`、`tower_mass_kg`、`generator_mass_kg` 等(键名含单位后缀) | | `get_output(job_id, keys?, prefix?)` | 读取详细输出(npz 归档,1800+ 键)。三种用法:① keys 与 prefix 都留空 → 返回**输出数据目录**(按气动/叶片结构/塔架/整机/传动链分类的键前缀地图);② 只给 `prefix` → 键发现,`prefix` 支持**通配符匹配**(`*`/`?`,如 `rotorse.rp.powercurve.*`、`*stress*`;不含通配符时按子串匹配);③ 传入 `keys` 列表 → 返回数值(标量或数组)。值为 WISDEM 原始 SI 单位,单位含在键名后缀(`P_W`=瓦、`stress_Pa`=帕、`chord_m`=米) | `get_output` 常用键前缀(完整目录内置于服务,调用时 keys/prefix 均留空即可获取): | 前缀 | 内容 | |---|---| | `aero` | 气动粗筛(mode=aero 作业):`U_m_s`/`Omega_rpm`/`P_W`/`T_N`/`Cp` 功率曲线数组 | | `rotorse.rp.powercurve` | 气动:功率/推力/Cp/Cm 曲线与额定工况点(`rated_V_m/s`、`rated_Omega_rpm`、`rated_pitch_deg`) | | `rotorse.rc` | 叶片几何分布:弦长/扭角/预弯(沿展向数组) | | `rotorse.rs` | 叶片结构:截面刚度(EI 等)、应变、模态频率、设计约束裕度 | | `towerse` | 塔架:直径/壁厚分布、一阶频率、载荷与应力分布 | | `drivese` | 传动链:主轴/齿轮箱/发电机/轮毂部件质量与尺寸 | | `tcons` | 整机约束:叶尖挠度、频率裕度等 | 用法:先 `get_output(job_id)`(keys 留空)查看数据目录,或用通配符 `prefix`(如 `towerse.tower.f*_Hz`、`*strain*`)检索键名,再把所需键放入 `keys` 取值,例如: ```json { "keys": ["rotorse.rp.powercurve.V_m/s", "rotorse.rp.powercurve.P_W", "rotorse.rc.chord_m", "towerse.tower.f1_Hz"] } ``` `design_changes` 示例(键为 WISDEM OpenMDAO 提升变量名): ```json { "configuration.hub_height_user": 100.0, "configuration.rated_power": 16000000.0 } ``` 当前已知可用键:`configuration.hub_height_user`(轮毂高度 m)、`configuration.rotor_diameter_user`(叶轮直径 m)、`configuration.rated_power`(额定功率 W)、`configuration.lifetime`(设计寿命 年)。扩展方式:在 `src/wisdem_mcp/worker.py` 的候选键表与模板元数据中追加。 ## 翼型极线预处理(prepare_polar)与 3D 修正 **背景**:WISDEM/CCBlade 需要**全圆极线**(±180°)查表。内置模板的翼型数据已在数据上游用 AirfoilPreppy 完成外插;自备风洞/CFD 极线通常只有 −10°~+30° 有效区间,直接进 YAML 会在 BEM 深失速区退化成线性外推。 **`prepare_polar` 用途**:底层调用 `wisdem.ccblade.Polar`(AirfoilPreppy 的 4.x 移植版)做 Viterna 全圆外插,返回 windIO 翼型条目 YAML,打通"自备翼型 → 自定义 geometry.yaml → validate_inputs → submit_run"闭环: ```json { "alpha": [-10, -5, 0, 5, 10, 15, 20], "cl": [...], "cd": [...], "re": 8000000, "cdmax": 1.5, "name": "my_airfoil" } ``` 返回的 `airfoil_yaml` 拼入自定义 geometry.yaml 顶层 `airfoils` 列表,并在 `blade.outer_shape.airfoils` 中按 `spanwise_position` 引用 `my_airfoil`。 **aero 模式的 `corr3d` 开关**:内置模板极线为纯 2D 数据(描述注明 "no 3D correction"),`submit_run(mode="aero", corr3d=True)` 时 worker 逐站调用 `Polar.correction3D`(DuSelig 升力修正,与 WISDEM 运行时的 `Airfoil3DCorrection` 组件同源;叶根 <5% 半径段跳过)后查表。对 nrel5mw 基线影响约 ΔCp +0.0003(3D 修正主要作用于失速区,最优叶尖速比附近影响小);设计点在失速边界附近时建议开启。 ## optimization 固定优化模式详解 `optimization` 模式提供两种固定预设,经 `opt_mode` 选择,由服务端(`jobs.py` 的 `_apply_optimization`)注入模板 `analysis.yaml` 的 `merit_figure` / `design_variables` / `driver` 段。 ### default 模式(默认) | 项 | 值 | |---|---| | 设计变量 | `rotor_diameter`(叶轮直径,1 个标量),取模板基线 ±15% | | 目标函数 | `LCOE`(度电成本,USD/MWh,结果键 `lcoe_usd_mwh`) | | 求解器 | SLSQP,tol=1e-3,max_iter=15,forward 差分梯度 | | 预计耗时 | 约 30–60 分钟 | ### rotor-only 模式(`opt_mode="rotor"`) 只优化**叶片气动外形**:整机尺寸、塔架、传动链、叶片结构层铺全部按基线固定。 **设计变量(共 16 个,均在叶片气动外形层)** | 设计变量 | 几何含义 | 优化设置 | |---|---|---| | `blade.aero_shape.twist` | 叶片扭角分布(°),沿展向 | 8 个控制点(`n_opt=8`)样条插值到全部分析站;单点限幅 ±5°(`max_increase`/`max_decrease`);全展向参与(`index_start=0`/`index_end=0`) | | `blade.aero_shape.chord` | 叶片弦长分布(m),沿展向 | 8 个控制点;乘性限幅 +10%/−10% | - 翼型展向排布 `af_positions` 不参与优化(翼型族固定) - 叶轮直径 DV 关闭(`rotor_diameter.flag=false`)→ 结果中的 `rotor_diameter_m` 应与基线一致,可用来核对配置生效 - 叶片结构层铺(`structure`)不动,但质量/刚度随几何变化重新计算,结构载荷仍进入整机平衡 **目标函数:AEP(年发电量)** - 对应 WISDEM `merit_figure: AEP`,输出键 `rotorse.rp.AEP`(kWh),结果键 `aep_kwh` - 由功率曲线按模板风况(geometry.yaml 的 wind_resource 段,Weibull/IEC 风区)概率加权积分得到;优化器内部以最小化 −AEP 实现"最大化" - 合理预期:只动叶片剖面几何、不放大风轮时,AEP 收益来自更均匀的展向载荷与更优的局部攻角分布,典型在 1% 量级——该模式的价值更多在**快速对比叶片气动方案**,而非替代整机优化 **求解与运行规模** | 项 | 值 | |---|---| | 求解器 | SLSQP,tol=1e-3,max_iter=30,forward 差分梯度 | | 每次迭代 | 16 个 DV → 1 次基准 + 16 次差分 = 17 次整机评估 | | 预计耗时 | 1–2 小时 | **提交示例:** ```json { "template": "nrel5mw", "mode": "optimization", "opt_mode": "rotor" } ``` **结果键**:`aep_kwh`(优化后 AEP)、`blade_mass_kg`(几何变化引起的质量变化)、`rotor_diameter_m`(应等于基线,用于核对)等;优化中间轨迹见作业目录 `wisdem.log`。 ## 内置模板 | 模板 | 叶轮直径 | 轮毂高度 | 额定功率 | 类型 | |---|---|---|---|---| | `nrel5mw` | 126 m | 90 m | 5 MW | 陆上 | | `iea3p4` | 130 m | 110 m | 3.4 MW | 陆上 | | `iea10` | 198 m | 119 m | 10 MW | 海上直驱 | | `iea15mw` | 240 m | 150 m | 15 MW | 海上直驱 | | `iea22` | 284 m | 170 m | 22 MW | 海上直驱 | 模板均取自 WISDEM v4.2.8 `examples/02_reference_turbines`,已逐个运行标定;新增模板只需在 `src/wisdem_mcp/templates/` 下建子目录,放入 geometry/modeling/analysis 三个 YAML 与 `template.json` 元数据,服务自动发现。 ## 本地测试 ```powershell # 端到端冒烟:提交 NREL 5MW 评估作业并轮询至完成 uv run python scripts/smoke.py nrel5mw configuration.hub_height_user 100 # MCP 传输层测试:内存客户端调用工具 uv run python scripts/client_test.py # 详细输出提取测试:对最近一次成功作业调用 get_output uv run python scripts/output_test.py # aero 快速气动粗筛模式测试:提交 → 轮询 → 断言 → get_output 读取功率曲线 uv run python scripts/aero_test.py # 固定优化模式测试:default/rotor 注入 + 参数校验 + 端到端 rotor 短作业 uv run python scripts/opt_mode_test.py # 翼型极线预处理 + aero 3D 修正测试:prepare_polar 单元/非法输入 + corr3d 端到端对比 uv run python scripts/polar_test.py ``` ## 项目结构 ``` wisdem-mcp\ ├── pyproject.toml # 依赖与 CLI 入口 ├── uv.lock # 锁定 198 个包,uv sync 精确复现环境 ├── .python-version # Python 3.12 ├── src\wisdem_mcp\ │ ├── server.py # FastMCP 4 服务(6 个工具) │ ├── jobs.py # 作业管理:异步提交、subprocess 隔离、状态落盘 │ ├── worker.py # WISDEM 执行子进程与结果提取(含 aero 模式 CCBlade 直连) │ └── templates\ # 参考机型模板(geometry/modeling/analysis + 元数据) ├── scripts\smoke.py # 端到端冒烟测试 ├── scripts\client_test.py # MCP 客户端测试 ├── scripts\output_test.py # get_output 详细数据提取测试 ├── scripts\aero_test.py # aero 快速气动粗筛模式测试 ├── scripts\opt_mode_test.py # 固定优化模式(default/rotor)测试 └── jobs\ # 运行时作业目录(gitignore) ``` ## License Apache-2.0