Aspen Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Aspen Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
通过自然语言操控 Aspen Plus 进行化工流程模拟——参数调优、批量运行、读取结果,全部由 AI 代理完成。
你在 GUI 里搭好流程拓扑 → MCP 接管参数调优和运行分析MCP 不负责画流程图。 你需要在 Aspen Plus GUI 中手动放置模块和物流(或用 connect/connect_port 工具通过代码建立连接),然后 MCP 用来:
# 1. 克隆或解压项目
cd aspen-mcp
# 2. 创建虚拟环境
python -m venv venv
# 3. 激活虚拟环境并安装依赖
venv\Scripts\pip install -e .
# 4. 启动(验证安装)
venv\Scripts\aspen-mcp启动后 MCP 服务器会通过 stdio 通信,适用于任何支持 MCP 协议的客户端(如 Reasonix、Claude Desktop、VS Code)。
在 reasonix.toml 中添加:
[[plugins]]
name = "aspen-mcp"
command = "path\\to\\aspen-mcp\\venv\\Scripts\\python.exe"
args = ["-m", "aspen_mcp.server"]{
"mcpServers": {
"aspen-mcp": {
"command": "path\\to\\aspen-mcp\\venv\\Scripts\\python.exe",
"args": ["-m", "aspen_mcp.server"]
}
}
}<!-- 保持原有工具总览内容不变 -->
| 工具 | 说明 |
|---|---|
open_file(path) | 打开 .apw 文件 |
new_simulation() | 创建空白新模拟(复制纯净模板到临时文件,避开 InitNew COM 稳定性问题) |
close_file() | 关闭当前文件 |
run() | 运行模拟(同步) |
run_async() | 异步运行 |
stop_simulation() | 停止当前运行 |
save(path?) | 保存文件 |
reinit() | 重置结果(重新运行前调用) |
reinit_and_run() | Reinit + Run 一步完成(推荐) |
status() | 查看连接和引擎状态 |
probe() | 诊断 COM 状态(app / root / tree 三级检查) |
visible(show) | 显示/隐藏 Aspen 窗口 |
batch_refresh(off) | 开关 GUI 刷新(批量操作加速) |
run_script(path) | 在 Aspen 内部执行 Python 脚本 |
| 工具 | 说明 |
|---|---|
list_all_blocks() | 列出所有模块 |
list_all_streams() | 列出所有物流 |
explore(path) | 探索数据树节点 |
add_block(name, type) | 添加模块(如 HEATER, ICON1) |
remove_block(name) | 删除模块 |
add_stream(name) | 添加物流 |
remove_stream(name) | 删除物流 |
connect(source, dest, stream?) | 连接源块→目标块(自动创建流) |
connect_port(block, port, stream) | 连接到指定端口(用于非标准端口) |
disconnect(stream_name) | 断开流并从流程中移除 |
list_block_ports(block) | 查看块的端口和连接情况 |
flowsheet_topology() | 显示流程拓扑:源块 --[流名]--> 目标块 |
⚠️ 注意:`set_param` 只适用于模块参数,物流参数必须用 `set_stream_param`。 详情见下方"流股参数设置"章节。
| 工具 | 说明 |
|---|---|
get_block(name) | 读取模块规格和结果 |
block_status(name) | 读取模块收敛状态(BLKSTAT / PER_ERROR / PROPSTAT) |
set_param(block, param, value) | 设置模块参数 |
get_stream(name) | 读取物流属性(温度、压力、流量等) |
set_stream_param(name, param, value) | 设置物流参数(如 TEMP, PRES, TOTAL) |
set_stream_composition(name, component, flow) | 设置物流中某组分的摩尔流量 |
get_stream_composition_info(name) | 读取物流组成信息 |
| 工具 | 说明 |
|---|---|
list_components() | 列出所有组分 |
add_component(id) | 添加组分(如 WATER, ETHANOL) |
remove_component(id) | 删除组分 |
get_property_method() | 读取当前全局物性方法 |
set_property_method(method) | 设置物性方法(如 NRTL, PENG-ROB) |
| 工具 | 说明 |
|---|---|
list_reaction_sets() | 列出所有反应集 |
add_reaction_set(name, type) | 创建反应集(POWERLAW/LHHW/EQUILIBRIUM) |
remove_reaction_set(name) | 删除反应集 |
add_reaction(set, no, reactants, products, phase, exponents?) | 添加反应及计量系数 |
remove_reaction(set, no) | 删除单个反应 |
| 工具 | 说明 |
|---|---|
sensitivity(block, variable, values) | 手动灵敏度分析 |
export_report_file(path) | 导出 .rep 报告 |
generate_input_summary(path) | 导出输入摘要 (.bkp) |
find_incomplete_inputs() | 扫描未填写的输入节点 |
diagnose(keywords) | 搜索收敛故障知识库 |
search_convergence_knowledge(keywords) | 详细收敛知识搜索 |
| 工具 | 说明 |
|---|---|
get_value(path) | 按反斜杠路径读值(如 `\\Data\\Streams\\3\\Output\\RES_TEMP`) |
set_value(path, value) | 按反斜杠路径写值 |
| 工具 | 说明 |
|---|---|
flowsheet_topology() | 展示完整拓扑:源块 --[流名]--> 目标块 |
add_side_duty(block, stage, duty) | 设置 RadFrac 侧线换热器热负荷 |
remove_side_duty(block, stage) | 删除 RadFrac 侧线换热器 |
open_file("甲醇.apw")
run()
status()set_param("HEATER", "TEMP", 150)
set_param("HEATER", "PRES", 5)
run()
get_stream("C-OUT")⚠️ 重要:`set_param` 只能设模块参数,物流参数必须用 `set_stream_param`。 详情见下方"流股参数设置"章节。
# 步骤1:添加模块
add_block("MIXER", "MIXER")
add_block("REACTOR", "RPLUG")
add_block("SEP", "FLASH2")
# 步骤2:添加物流并连接
connect("MIXER", "REACTOR", "FEED")
connect("REACTOR", "SEP", "R-OUT")
# 步骤3:设参数(模块用 set_param,物流用 set_stream_param)
set_param("MIXER", "TEMP", 100)
set_param("REACTOR", "LENGTH", 5)
# 物流参数必须用 set_stream_param(通过 MIXED 子节点写入)
set_stream_param("FEED", "TEMP", 150)
set_stream_param("FEED", "PRES", 5)
set_stream_param("FEED", "TOTAL", 100)
# 步骤4:运行并看结果(先用 reinit 清缓存,再 run)
reinit()
run()
get_stream("R-OUT")更方便的替代:直接用 `reinit_and_run()` 一步完成。
# 添加新组分
add_component("METHANE")
add_component("ETHANOL")
# 查看现有组分
list_components()
# 切换物性方法
set_property_method("NRTL")
get_property_method()先删块,再清物流。 绝不能反过来。
✅ 正确:
remove_block B1 # 块先删,连接自动断裂
disconnect CL2 # 清理残余孤儿物流
disconnect H2O❌ 错误(会导致 COM 服务器异常,无法恢复):
disconnect CL2 # 块还在但进料少了一条 → 块变无效
disconnect H2O # 块完全孤零零
remove_block B1 # 💥 COM 服务器异常原理:Mixer 等块要求至少有一条连接才能存在。全拔光后再删块,Aspen 内部校验不通过,COM 直接崩。
| 错误现象 | 含义 | 应对 |
|---|---|---|
尚未调用 CoInitialize。 | 子线程未初始化 COM | 修复代码即可,不致命 |
发生意外。 + (0, None, ...) | 参数/操作型错误 | 可重试,COM 状态不受影响 |
服务器出现异常情况。 | COM 服务器状态已脏 | ❌ 立即 close_file → open_file |
远程过程调用失败。 | Aspen Plus 未运行 | 检查 Aspen Plus 是否已打开 |
对象没有连接到服务器 | COM 代理已过期(InitNew / 进程重启后) | 调用 reconnect() 或重启 MCP 插件 |
`close_file() → open_file()` 可解决绝大多数 COM 稳定性问题。 _is_dead() 机制会检测引用失效并自动 reconnect,但某些情况下仍需要手动恢复。
1. open_file → reinit_and_run # 稳定状态
2. set_property_method # 先改物性
3. add/remove_component # 改组分
4. 先加自己的块(模板的 B1 先留着) # 保证流程至少有一个块
5. add_stream + connect # 搭自己的流程
6. 设参数(模块用 set_param,物流用 set_stream_param)
7. remove_block B1 + disconnect 孤儿 # 最后删模板残留
8. run / reinit_and_runHEATER 默认 HEATOPT=CONST-DUTY(按热负荷计算)。要用温度设参需先改为 CONST-TEMP:
aspen.set_value(r"\Data\Blocks\PREHEAT\Input\HEATOPT", "CONST-TEMP")以下为原有内容,保持不变
save() — 原地保存(覆盖当前文件) save("路径.apw") — 另存为新文件 两种方式均已验证可用。保存后 Aspen 会临时持有文件锁,不影响保存结果。
物流连接不走 Connections(只读),而走 `Block → Ports → {port名} → Elements.Add(流名)`。
F(IN) 输入物流、P(OUT) 输出物流、V(OUT) 汽相出口、L(OUT) 液相出口list_block_ports("模块名") 查看组分通过 Components → Specifications → Input → TYPE 表操作。该表为 2 列:列 0 为组分标签,列 1 为组分类型(Aspen Plus 自动填充 CONV)。只需用 InsertRow + SetLabel(0,0) 设置名称即可,不要手动设置第 2 列(会导致该值被当作新增组分名)。 长名称组分(>8字符)会自动生成短标签并写入 ANAME,Aspen 自动从数据库解析别名。 重复名称会自动追加编号后缀确保唯一。
set_property_method("NRTL") 会同时写 GBASEOPSET 和 GOPSETNAME 两个节点。 建议先设好物性方法再添加模块,避免模块级 OPSETNAME 与全局设置冲突。
⚠️ 重要:`add_reaction` 函数创建 2D 计量系数表(COEF/COEF1)时,标签设置有时会失败。 如果计量系数写入后验证为空(COEF\\1 下的 Elements 为空或值为 None),需要手动补填。 下面提供了两种方式,推荐用方式二(手动填表),更可靠。#### 方式一:用工具函数(快速,但不一定写进去)
add_reaction_set("R-METH", "POWERLAW")
add_reaction("R-METH", 1, reactants={"CO2":1, "H2":4}, products={"CH4":1, "H2O":2}, phase="V")
# 设动力学
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\PRE_EXP\1").SetValue(0, 1.0e8)
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\ACT_ENERGY\1").SetValue(0, 14300)运行后必须验证计量系数是否写入:
coef = aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\COEF\1")
print(f"COEF Count={coef.Elements.Count}") # 应为 >0,且能读到组分名#### 方式二:手动填表(推荐,100%可靠)
完整示例 —— 在一个已打开的模拟中添加甲烷化副反应:
from aspen_mcp.tools.components import tool_add_component
from aspen_mcp.tools.reactions import *
# 1. 添加新组分(原文件有的组分不需要再加)
tool_add_component("CH4")
# 2. 创建反应集
rxns = aspen.find_node(r"\Data\Reactions\Reactions")
rxns.Elements.Add("R-METH!POWERLAW")
# 3. 设置反应类型和相态
rt = aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\REACTYPE")
rt.Elements.InsertRow(0, 0)
rt.Elements.SetLabel(0, 0, False, "1")
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\REACTYPE\1").SetValue(0, "KINETIC")
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\PHASE\1").SetValue(0, "V")
# 4. 填充 COEF(反应物计量系数,正值 = 消耗)
coef1 = aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\COEF\1")
for i in range(2): coef1.Elements.InsertRow(0, i)
coef1.Elements.SetLabel(0, 0, False, "CO2")
coef1.Elements.SetLabel(1, 0, False, "MIXED")
coef1.Elements.SetLabel(0, 1, False, "H2")
coef1.Elements.SetLabel(1, 1, False, "MIXED")
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\COEF\1\CO2\MIXED").SetValue(0, 1.0)
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\COEF\1\H2\MIXED").SetValue(0, 4.0)
# 5. 填充 COEF1(产物计量系数)
coef1_1 = aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\COEF1\1")
for i in range(2): coef1_1.Elements.InsertRow(0, i)
coef1_1.Elements.SetLabel(0, 0, False, "CH4")
coef1_1.Elements.SetLabel(1, 0, False, "MIXED")
coef1_1.Elements.SetLabel(0, 1, False, "H2O")
coef1_1.Elements.SetLabel(1, 1, False, "MIXED")
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\COEF1\1\CH4\MIXED").SetValue(0, 1.0)
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\COEF1\1\H2O\MIXED").SetValue(0, 2.0)
# 6. 设动力学参数
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\PRE_EXP\1").SetValue(0, 1.0e8)
aspen.find_node(r"\Data\Reactions\Reactions\R-METH\Input\ACT_ENERGY\1").SetValue(0, 14300)#### 分配反应集到反应器模块
RPLUG/RCSTR 通过 RXN_ID 表分配反应集。必须先清空再添加:
rxn_id = aspen.find_node(r"\Data\Blocks\RPLUG\Input\RXN_ID")
els = rxn_id.Elements
# 清空所有现有行
while els.Count > 0: els.RemoveRow(0, 0)
# 添加第一个反应集
els.InsertRow(0, 0)
aspen.find_node(r"\Data\Blocks\RPLUG\Input\RXN_ID\#0").SetValue(0, "R-1")
# 添加第二个反应集(可有多个)
els.InsertRow(0, 1)
aspen.find_node(r"\Data\Blocks\RPLUG\Input\RXN_ID\#1").SetValue(0, "R-METH")RXN_ID 表不支持 SetLabel(会报错"该维度无标签"),直接用 #0, #1 索引路径赋值。
#### 读取反应结果
反应器出口的详细组成在 Streams → {name} → Output → MOLEFLOW → MIXED → {组分名}:
mf = aspen.find_node(r"\Data\Streams\R-OUT\Output\MOLEFLOW")
for i in range(10):
c = mf.Elements(0).Elements(i) # Elements(0) = MIXED 子流
if c.Value and float(c.Value) > 0:
print(f" {c.Name} = {c.Value}")总摩尔流量变化(R-IN vs R-OUT)可以判断反应是否发生:若出口总摩尔数 < 入口,说明发生了分子数减少的反应。
#### 温度对反应的影响
RPLUG 的 TYPE 参数决定温度模式:
ADIABATIC — 绝热(不设温度,由反应热决定)T-SPEC — 指定温度剖面(需要设 TEMP)CONSTANT-T — 恒温(注意:CONSTANT-T 不是有效值,实际用 T-SPEC)设温度:aspen.find_node(r"\Data\Blocks\RPLUG\Input\TEMP").SetValue(0, 350.0)
大批量改参数前调 batch_refresh(True) 关闭 GUI 刷新,改完再 batch_refresh(False) 恢复。
`set_param` 只能设模块参数。 物流参数(TEMP、PRES、TOTAL 等)必须用专门的 `set_stream_param` 工具。
为什么需要专用工具?Aspen COM 的流股参数节点都有一个 MIXED 子节点:
Data\Streams\H2O\Input\TEMP ← 直接 SetValue 会报 AE_UNDERSPEC
Data\Streams\H2O\Input\TEMP\MIXED ← 必须在这里写入值set_stream_param 自动处理这个逻辑——它尝试通过 MIXED 子节点写入,失败时回退到直接 SetValue。
✅ 正确用法:
set_stream_param("H2O", "TEMP", 140)
set_stream_param("H2O", "PRES", 1)
set_stream_param("H2O", "TOTAL", 200)❌ 错误用法(会报 AE_UNDERSPEC):
set_param("H2O", "TEMP", 140) # set_param 走 Blocks 路径,找不到 H2O
aspen.set_value(...) # 直接 SetValue 不行修改参数或拓扑后,运行的正确流程是:
reinit() → 清空旧计算结果和引擎缓存
run() → 执行计算或一步到位:
reinit_and_run() → Reinit() + Run2(0) 组合实测验证: Reinit() 可以强制 Aspen 引擎在下一步 Run2() 时重建计算顺序(Calculation Order)和撕裂流股(Tear Streams),不需要人工手动运行。
之前有用户反馈"必须在 GUI 中手动运行一次后才能自动运行"——这个问题的原因是:
SetValue 写入失败(AE_UNDERSPEC),实际参数没写入Reinit() 步骤,旧缓存与修改后的拓扑不匹配解决这两个问题后,模拟可以完全通过 COM 自动化运行,无需人工干预。
new_simulation() 纯净模板 ✅new_simulation() 不再使用 InitNew()(在 MCP 长进程中 COM 引用不稳定),而是:
close_file()(安全关闭已打开文件)%TEMP%(带 PID 后缀,唯一文件名)open_file() 打开副本模板初始状态:
add_component 添加)set_property_method 更改)new_simulation() → close_file + 复制模板 + open_file
add_component(...) → 添加组分
add_block / connect → 搭建流程拓扑
reinit_and_run() → 运行⚠️ 首次使用 `new_simulation()` 前:如果已有文件打开,工具会自动关闭后再创建空白模拟。
MCP 服务器持有一个全局 Aspen Plus COM 会话。每次重启 Reasonix(或 MCP 插件)会丢失之前的所有状态,需要重新 open_file 或 new_simulation。 同一进程内的文件切换(close + open_file / new_simulation)可正常进行,不受影响。
项目 docs/blocks/ 目录下有 70 种 Aspen Plus 模块的详细参数文档(含 Input 路径、Output 路径、典型设置、注意事项),来源于 Aspen Plus v15 官方模板。
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.