协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
ansys-fluent-mcp【开发与工程】Drive an ANSYS Fluent solver session through the standalone `ansys-fluent-mcp` MCP server. USE WHEN the user asks to load a case/mesh, inspect physics, change settings, run iterations, or query results — and the chat client is connected directly to the MCP (VS Code Copilot, Cursor, Claude Desktop). EXPOSES a 22-tool surface: `session_status`, `connec…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
ansys-fluent-mcp MCP server. USE WHEN the user asks to load a
case/mesh, inspect physics, change settings, run iterations, or
query results — and the chat client is connected directly to the
MCP (VS Code Copilot, Cursor, Claude Desktop). EXPOSES a 22-tool
surface: session_status, connect, disconnect, find_api,
get_help, get_state,
get_targeted_context, list_named_objects, find_named_object,
select_named_objects, summarize_setup, simulation_report,
solver_status, run_code, validate_code, screenshot,
mesh_quality, list_fields, compare_files.
This is a STATELESS leaf: there is no plan/journal/rollback and no
propose_step / finalize planning machinery — run_code mutates
the live solver immediately. DO NOT USE FOR generic Python /
CFD-theory questions unrelated to Fluent.This skill targets the tool surface that ansys-fluent-mcp ships.
The server gives you composable primitives — discovery, state read,
schema discovery, validation, sandboxed execution — and you build
everything else by chaining them. It is stateless: each call stands alone, there
is no plan builder, journal, or undo.
| Tool | One-line purpose |
|---|---|
session_status | Are we connected? Which backend? |
connect(ip?, port?, ...) | Launch a local Fluent session or attach to a running one. |
disconnect | Tear down the session. |
solver_status | Is the solver busy iterating? |
find_api(query, limit?, kind?) | Lexical (or, if configured, semantic) search over the Fluent settings tree. Returns ranked paths + signatures. |
get_help(path) | Per-node help text. |
get_state(path, projection?) | Read any settings path. path is a STRING. |
get_targeted_context(...) | Trimmed live-context snapshot for a specific intent. |
list_named_objects(path) | Enumerate the keys of a NamedObject collection. |
find_named_object(path, name, fuzzy?) | Exact or fuzzy name lookup. |
select_named_objects(path, where=[...]) | Filter a NamedObject collection by predicates. |
summarize_setup(scope?) | Compact digest of models / BCs / materials / numerics / reference values. |
simulation_report | Structured solution report on the loaded case. |
run_code(code) | Execute a sandboxed PyFluent Python snippet. This is your mutator. |
validate_code(code) | AST + signature check (no execution). Always run before run_code for untrusted code. |
screenshot(filename?, width?, height?) | Capture the active graphics window. |
mesh_quality(include_check?) | Live skewness / orthogonal-quality / aspect-ratio histograms (+ optional mesh.check()). Route every "show mesh quality" / "skewness" / "orthogonal quality" / "aspect ratio" / "check mesh" intent here. |
list_fields(scope?) | Enumerate scalar/vector fields available in the loaded case (pressure, velocity-magnitude, …). |
compare_files(path_a, path_b) | Diff two case/mesh files in two ephemeral PyFluent sessions; returns a markdown summary table per family. Live workspace session is not touched. |
That is the complete surface. There is no propose_step,
finalize, summarize_session, inspect_api, describe_command,
get_allowed_values, query_reports, validate_setup,
diagnose_divergence, or engineering-correlation helper
(compute_htc, lookup_emissivity, …) on this server. Don't call
them — they don't exist here.
For nearly every intent, the loop is:
1. Discover → find_api / get_help / list_named_objects / summarize_setup
2. Author → your host or user supplies PyFluent settings-API Python
3. Validate → validate_code (offline AST check)
4. Execute → run_code (mutates the live solver)
5. Verify → get_state / summarize_setup / simulation_report
Intent-to-code translation is not part of this leaf.
If a host wants to translate user intent into Python, it should do so
outside this server, then pass the resulting Python through
validate_code before calling run_code.
PyFluent has exactly five top-level path roots:
setup. | solution. | results. | file. | mesh.
setup.solution.* does not exist.
Use the mesh_quality tool — it returns structured skewness /
orthogonal-quality / aspect-ratio histograms and, when
include_check=true, also embeds the output of Fluent's
mesh.check():
mesh_quality(include_check=true)
Do NOT route these intents through run_code, simulation_report,
or summarize_setup — the dedicated tool already wraps the raw
PyFluent calls and normalises their output across versions.
list_fields(scope="any") # any | cell | node | face
Returns the flat list usable in report defs, contours, vectors.
compare_files(path_a="/abs/path/A.cas.h5", path_b="/abs/path/B.cas.h5")
Both files open in separate ephemeral PyFluent sessions with
lightweight_setup=true — your live workspace session is NOT
touched. Returns a markdown summary table in the summary field;
echo that string verbatim to the user.
These engineering correlations and material lookups are not on this server. Ground the value yourself (textbook / handbook) and use it in host-authored Python rather than calling a non-existent tool.
summarize_setup(scope='models') or summarize_setup(scope='bcs')
— don't dump the whole tree. Scoped output keeps client context
small and the response on-topic.
Author PyFluent settings-API Python, validate it with validate_code,
then execute it with run_code.
Always show the generated code to the user before run_code — it
mutates the solver immediately and there is no undo on this
server.
find_api(query="velocity inlet thermal temperature", kind="path")
Pick the most-specific match and then:
get_help(path="setup.boundary_conditions.velocity_inlet.<zone>.thermal.t")
list_named_objects(path="setup.boundary_conditions.velocity_inlet")
list_named_objects(path="setup.cell_zone_conditions.fluid")
list_named_objects(path="setup.materials.fluid")
For predicate filtering, use select_named_objects with where=[...].
get_state(path="setup.models.viscous.k_omega_model") — pass a
string, not a list. The result is the live value.
run_code(code="solver.solution.run_calculation.iterate(iter_count=200)")
There's no streaming progress on this surface — you'll get the
final residual snapshot. Use solver_status to confirm completion.
run_code(code="solver.file.read_case(file_name=r'<path>')")
run_code(code="solver.file.read_data(file_name=r'<path>')")
.tui.* calls from run_code. Always
solver.settings.* / solver.<root>.<path>... (the settings API
is what's available in 27.1)..list() / .list_properties() are void — they print only.
Use list_named_objects instead for programmatic discovery.run_code mutates the live solver. There is no journal /
rollback on this surface. Show the user the code before you run
it.'288.15 [K]', '1.225 [kg/m^3]', '1 [m/s]'. Bare numbers
silently break downstream report defs and BC values.get_state(path=...) takes a string, not a list. Same for
find_api(query=...)..tui.* calls of any kind, including via run_code.propose_step, finalize,
summarize_session, inspect_api, validate_setup) — they are
NOT part of this server.simulation_report,
summarize_setup, or hand-written run_code — call the
dedicated mesh_quality tool instead (it returns the structured
histograms directly and optionally wraps Fluent's mesh.check()).run_code with intent strings (it expects Python, not
executable code). Translate intent outside this leaf, validate the
resulting Python, then execute it with run_code.validate_code on host-authored Python for safety-critical
operations (model toggles, BC writes, file.write_*).This server is stateless. It deliberately ships no planner, no journal, no recipe registry, and no rollback. Multi-step plan construction, undo, retry policies, and "propose → confirm → apply" flows are the host's responsibility (VS Code Copilot, Cursor, Claude Desktop, or any custom agent that connects over MCP).
If the host has its own planner / agent loop, let it drive the discover → generate → validate → execute → verify cycle. This server will:
run_code)run_code runs an offline, stateless intent guard before
exec to catch a fixed set of Fluent-specific crash signatures. It is
NOT a planner — it inspects only the snippet you submitted. Disable
with FLUIDS_MCP_INTENT_GUARD=0 if your host wants full control.
When the guard fires, run_code returns one of these error codes:
error_code | Meaning | Correct response |
|---|---|---|
risk_blocked | Snippet matches a known crash signature (e.g. boundary rename to a name with whitespace; multiphase.number_of_phases = N int direct-assign; setup mutation while iterating). | Read the suggestion in stderr, rewrite the snippet, then call run_code again. Do NOT retry the same snippet. |
sequence_error | Intra-snippet use-before-create (e.g. gravity references expr_grav before the snippet creates setup.named_expressions["expr_grav"]). | Reorder the statements (define first, then reference) and re-submit. |
solver_disconnected | The Fluent gRPC channel died during the call (or just before it). | Call connect again, re-load the case/data file, then re-issue the work. The session is already marked disconnected — session_status will reflect that on the very next call. |
The blocking signatures (return risk_blocked / sequence_error)
are:
bc.rename.whitespace — boundary rename whose new name contains
whitespace. Use underscores instead ("oil_inlet", not "oil inlet").multiphase.number_of_phases.shape — direct integer assignment
to multiphase.number_of_phases. Use
multiphase.number_of_phases.number_of_eulerian_phases = N.seq.phase.material_before_rename — phase rename happens AFTER
the material assignment in the same snippet. Rename first, then
assign material to the new key.runtime.write_during_iter — setup.* mutation while the
solver is iterating. Interrupt first
(solver.solution.run_calculation.interrupt()), then write.seq.named_expr.use_before_create — a named expression is
referenced before it is created in the same snippet. Reorder, or
split into two run_code calls.reportdef.surface_field — a report definition is given a
surfaces field (attribute, .locations.surfaces, or a
create-dict key). Report definitions take surface_names=[...]
(surfaces is the graphics-object field).In addition, non-blocking advisories are returned in the
successful result's warnings list (they do NOT stop execution):
named_expr.missing_units — a named expression is created with a
bare number ({"definition": "9.81"}). Add a unit, e.g.
"9.81 [m s^-2]"; a unit-less number is dimensionless and fails
when consumed by a dimensioned slot.tui.usage — the snippet uses .tui.*. Prefer the
solver.settings.* tree, which the rest of this server validates
against.These exist purely to prevent today's most expensive failure modes from killing the gRPC channel (blocks) or silently mis-configuring the case (warnings); they do not constitute a planner and they do not cross-call each other.