Skip to main content
Glama

Foam-Agent

Describe a flow problem in your own words. Foam-Agent picks the solver, writes the case files, runs them on pinned Foundation OpenFOAM v10, works the debug loop when the solve diverges, and plots the residuals while it runs.

The model is yours — your Claude Code, Cursor, Codex or OpenCode subscription. The container holds OpenFOAM, a local tutorial index and local embeddings, and never calls an LLM.

Everything is pinned to Foundation OpenFOAM v10 and tested as one unit — the tutorial index, the skill references and the container toolchain. ESI OpenFOAM is not a second runtime: translate_case_to_esi is a best-effort export for taking a finished case elsewhere, not a target you can work in.

The Foam-Agent shell: Projects and Conversations on the left, the agent's turn in the middle with its tool calls expanded, residuals plotting on the right

One window: the Conversation, the tool calls it made, and the Case's residuals while it solves.

Quick start

1. Serve the shell

git clone https://github.com/KasperHonore/Foam-Agent.git
cd Foam-Agent
git lfs pull
just up

Needs Python 3.10+, Node 20+ with npm, and just. No pip install — the host serves from the standard library, run as a module off packages/host/src. just up builds the frontend and opens http://127.0.0.1:8760, bound to loopback only.

git lfs pull is not optional: the FAISS tutorial indices ship via git-lfs, and without it you get pointer stubs and silently empty retrieval. The Setup panel checks for exactly that.

The shell serves with no Docker and no agent CLI. You can look round before installing either. What each one adds is below.

2. Start the OpenFOAM container

This is what actually runs a solve.

docker build -f packages/mcp/docker/Dockerfile -t foamagent:latest .    # first build: ~10 min, ~10 GB

mkdir -p ~/foamagent/runs
docker run -d --name foamagent-mcp --init --restart unless-stopped -p 7860:7860 \
  -v "$HOME/foamagent/runs:/home/openfoam/Foam-Agent/runs" \
  foamagent:latest python -m foamagent_mcp.fastmcp_server --transport http --host 0.0.0.0 --port 7860

Build rather than pull on this branch. The published ghcr.io/kasperhonore/foamagent:latest image is only ever pushed from main (docker-publish.yml triggers on branches: [main]), so it predates everything here. The Setup panel's tool-lockstep check opens a real connection to the server and diffs its tool list against the host's table, so a stale image shows up as a red row rather than as a confusing failure mid-run.

--init gives the container a real init as PID 1. Detached work orphans its process there when it finishes; without an init that reaps, every finished run lingers as a <defunct> entry until the container restarts. Nothing breaks without it — the Setup panel warns if your container predates the flag.

3. Give it an agent seat

Install one of Claude Code, Cursor, Codex or OpenCode, then open Setup → Agents, pick one and press Check this works. The check spawns the CLI, completes an ACP handshake and records that it worked from this machine.

Nothing ever spawns a CLI without a click, and a failure names the step it died at — spawn, initialize or session/new — with the CLI's own stderr passed through untouched. Which step failed is the diagnosis: authentication is enforced at session/new, so a failure there means sign in, while one at initialize means the CLI itself is broken.

Then type into the composer:

Simulate lid-driven cavity flow at Re=1000

The landing: a greeting, one composer with agent and project pills, and five starting-point cards

The starting points fill the composer and never send. The pills lock at first send — a Conversation's agent is fixed for its life.

Related MCP server: COMSOL MCP Server

What you get

A three-pane application: Conversations on the left, chat in the middle, instruments on the right.

Surface

What it is

Landing

One composer, and five starting points that fill it and never send. The pills on it pick the agent and the Project, and lock at first send — a Conversation's agent is fixed for its life.

Chat

The transcript, streamed. Tool calls fold into groups with a plain-English trigger line and a running clock: used 5 tools · 12.0s — waiting on bash 6.0s.

Consent cards

Before anything executes, a card in the conversation shows the facts the host computed: the payload verbatim, core count, what gets overwritten, the SLURM ask, what the last run cost. Buttons are the agent's own options in its own order. Dismissing denies — Escape answers no.

Dashboard

Bound to a Case. Overview with solve progress and a stall notice, residuals on a log scale, parameters with provenance, a per-Case comparison column, the run console. Tabs are absent when the Case has nothing behind them, not greyed out.

Library

The Project's shelf of geometry and meshes. Uploaded material and material the Project's own Cases produced are separated, because you can remove one and not the other. Delete means archive.

Scene

A 2D cut with mesh line-work and velocity arrows; 3D geometry and streamlines in the run console.

Search

Ctrl/Cmd+K searches Project, Case and Conversation names plus the full text of every transcript, in one answer.

Setup

A live board — git-lfs, Docker, image, container, version lockstep, runs mount, orphan reaping, tool lockstep, agent CLIs — polled every 15s, with two one-click fixes and fixed argv behind them.

A consent card: the tool name, the payload verbatim, what gets overwritten, what the last run cost, and Allow / Allow for This Session / Reject

A consent card. The host computes the facts — the payload verbatim, what gets overwritten, what the last run cost — and the buttons are the agent's own options in its own order.

The Library's cross-project overview: three geometry files shelved under Cavity study, and two projects whose shelves are empty

The Library, across every Project. An empty shelf says what would fill it.

Two things there are worth calling out, because they are the product's own arguments rather than features.

Runs are detached, and the app says so. A solve is launched with start_case in its own session, streams to files rather than pipes, and outlives the host process. Stop the agent mid-turn and you get told plainly: you stopped the agent, not the Case — the run was left going, and its outcome lands on the dashboard whether or not anyone is watching. Restart the host and it re-adopts the live runs it finds.

Setup repair is a conversation, not a wizard. When the board is red and you have a proven seat, a row appears offering to work through it with your agent. It opens a Conversation seeded with the entire board verbatim — green rows included — plus a briefing on what the agent cannot observe from where it sits.

Skills only, without the application

This repo is for people who want the application. Everything above assumes you cloned it and ran just up.

If you would rather not — you already live in your CLI, and you want the CFD skills there and nothing else — there is exactly one other supported way in, and it is built from two published artifacts: the skills, installed with npx skills add, and the container image, pulled from GHCR. No clone involved; what you build around those two is your own. You give up the dashboard, the Library, the consent cards and the Setup board; you keep the skills, the container and the 34 tools. (A clone opened directly in your CLI is neither route — the checkout is for developing Foam-Agent.)

1. Install the skills into your CLI.

npx skills add KasperHonore/Foam-Agent

This installs the four skills (foam, foam-onboard, foam-setup, foam-runs) and the three subagent roles into Claude Code, Cursor or OpenCode.

2. Start the container. No clone here, so pull the published image rather than building it:

mkdir -p ~/foamagent/runs
docker pull ghcr.io/kasperhonore/foamagent:latest
docker tag ghcr.io/kasperhonore/foamagent:latest foamagent:latest
docker run -d --name foamagent-mcp --init --restart unless-stopped -p 7860:7860 \
  -v "$HOME/foamagent/runs:/home/openfoam/Foam-Agent/runs" \
  foamagent:latest python -m foamagent_mcp.fastmcp_server --transport http --host 0.0.0.0 --port 7860

3. Point your CLI at the server, so the skills have hands. The server speaks HTTP MCP on localhost:7860:

CLI

Where it goes

Claude Code

claude mcp add --transport http foamagent http://localhost:7860/mcp

Cursor

~/.cursor/mcp.json{"mcpServers": {"foamagent": {"url": "http://localhost:7860/mcp"}}}

Codex

~/.codex/config.toml[mcp_servers.foamagent] with url = "http://localhost:7860/mcp"

OpenCode

opencode.json{"mcp": {"foamagent": {"type": "remote", "url": "http://localhost:7860/mcp", "enabled": true}}}

Then say what you want: simulate flow over a cylinder at Re=40. Your runs land in the same ~/foamagent/runs the application uses, so you can switch between the two whenever you like.

Two caveats, stated rather than discovered. This repo now has well-known skills directories (.claude/skills and friends), but they hold the vendored engineering-process skills, not the CFD skills, which live in agents/ — so exactly what a given skills version picks up from that mix has not been pinned down against the current tree. And foam-setup on this path has no bundled doctor, so diagnose-my-server is degraded; run foamagent-doctor from a clone instead. Making this route first-class — a publish target the CLI reads unambiguously — is its own workstream.

The CFD skills live in exactly one place, agents/, so a skill change is a one-file diff. (The skill trees under .agents/, .claude/ and .vibe/ are a separate family — engineering-process skills for developing this repo, vendored from mattpocock/skills, not the CFD skills.) When the application opens a Conversation it copies those canonical bytes into whatever layout your harness reads, and a manifest-backed refresh replaces what moved upstream while never touching what you edited.

The 34 tools are catalogued in packages/mcp/README.md, together with local non-Docker installation. Environment variables are documented in AGENTS.md; sample prompts and meshes are in examples/.

How a Case gets built

"Simulate dam break with two fluids"
        │
        ▼
  PLAN        find_similar_case → closest v10 tutorial as reference
        │
        ▼
  GENERATE    write_case_file × N → 0/, system/, constant/, Allrun
        │
        ▼
  RUN         start_case → detached solve ──────► VISUALIZE (PyVista → PNG)
        │                                             ▲
        ▼ errors                                      │
  DEBUG       foam-debugger: diagnose → rewrite → rerun (until converged)

Every Case lands in its own directory under ~/foamagent/runs, with full logs, and gets a row in ~/foamagent/runs/ledger.md — the run ledger the server maintains as a side effect of the run lifecycle. The ledger is a Markdown table you can read yourself; skills may write only its Notes column.

There is also an agentless loop worth knowing: pick a Case in the sider, press Run, approve the disclosure. No agent, no tokens.

Your work lives outside the clone

~/foamagent/                     # FOAMAGENT_HOME
├─ runs/                         # bind-mounted into the container
│  ├─ ledger.md                  #   the run ledger — one row per Case
│  ├─ preferences.json           #   your standing CFD defaults
│  └─ <Project>/                 #   a Project is a directory; there is no registry
│     ├─ .library/               #     the Library's shelf
│     └─ <Case>/                 #     0/, constant/, system/, logs, dashboard/
└─ state/                        # host-owned, and structurally unreachable from a
                                 # session — the container's mount IS the runs root

One runs directory serves every clone and every Project, so git pull cannot reach your work — not because it is gitignored, but because it is not in the tree. Transcripts live under state/, never inside a Case, so a Case you share carries no chat logs. FOAMAGENT_HOME moves the root; the Setup panel and your -v mount must agree on it.

Nothing persisted under the runs root names the machine it was written on. That is what makes a Project portable.

Vocabulary

The words below are load-bearing — they are the same ones the code, the issues and the tests use. CONTEXT.md is the full glossary.

  • Project — a directory holding the Cases of one piece of work; the Conversation's working directory, and the only grouping the model has.

  • Case — one OpenFOAM case directory and its one ledger row.

  • Conversation — one chat thread with an agent, held in a Project. Disposable by design; its Case is fixed when it opens.

  • Asset — a file or mesh directory in a Project. Geometry and meshes shelve in the Library; anything else is still @-mentionable.

  • Seat — one agent CLI seen from your chair: is it installed, is it your chosen one, has a handshake ever completed here.

Study and Run are deliberately not entities.

Development

just test          # both suites — ~3,600 tests, no conditional skip on either half
just typecheck     # tsc --noEmit, strict — the one automated gate the frontend has
just e2e           # the ten-minute e2e: no image, no Docker, no CLI, no secrets

just test and just typecheck assume just web has installed the frontend, same as just up does. The layering contract runs separately, exactly as CI runs it:

PYTHONPATH=packages/core/src:packages/mcp/src:packages/host/src lint-imports

CONTRIBUTING.md has the real workflow, including the evidence standard for browser-driven work — a pure module with tests, a live browser drive, and a written UNVERIFIED boundary. CI gates exactly one of those three, which is why the other two are written down. AGENTS.md documents the architecture for coding agents working on this repo.

Troubleshooting

First stop is the Setup panel, or foamagent-doctor for the same checks without an agent. For everything else — disk space, custom meshes, updating, ESI vs Foundation — see the FAQ.

Problem

Cause

The page answers 503

The shell isn't built. just web, or just just up.

MCP connection refused

Container not running.

First retrieval call takes minutes

One-time ~1.2 GB embedding model download inside the container — not a hang.

Retrieval returns nothing

git lfs pull before building the image.

Tool lockstep red

Your image is older than your clone. Rebuild it.

Share your simulation

Ran something interesting? Open a "Share your simulation" issue — prompt, solver and a picture is all it takes. Real cases shape which skills and error-playbook entries get improved next.

Credits

Foam-Agent began as a hard fork of csml-rpi/Foam-Agent by Yue et al. It is developed independently and PRs land here, not upstream.

The fork has since replaced the original end to end: the self-contained LangGraph pipeline that made its own LLM calls has been removed, the MCP server rewritten, and the host application, browser shell and Library built new. What is inherited and still in use is the OpenFOAM v10 tutorial corpus the retrieval index is built from, and the rules-based ESI translation module.

The original pipeline is preserved at the legacy-pipeline git tag for a future harness-vs-harness-less comparison. Upstream's FoamBench evaluation reached 100% on 110 tasks with Claude Opus 4.6 at 25 correction loops — that figure benchmarks upstream's removed pipeline, not this fork. This fork has no published benchmark of its own.

Citation

If you use Foam-Agent in research, please cite the upstream papers:

@article{yue2025foam,
  title={Foam-Agent: Towards Automated Intelligent CFD Workflows},
  author={Yue, Ling and Somasekharan, Nithin and Zhang, Tingwen and Cao, Yadi and Chen, Zhangze and Di, Shimin and Pan, Shaowu},
  journal={arXiv preprint arXiv:2505.04997},
  year={2025}
}

@article{somasekharan2026cfdllmbench,
    title={CFDLLMBench: A Benchmark Suite for Evaluating Large Language Models in Computational Fluid Dynamics},
    author={Somasekharan, Nithin and Yue, Ling and Cao, Yadi and Li, Weichao and Emami, Patrick and Bhargav, Pochinapeddi Sai and Acharya, Anurag and Xie, Xingyu and Pan, Shaowu},
    journal={Journal of Data-centric Machine Learning Research},
    year={2026},
    url={https://openreview.net/forum?id=kTcH1MnkjY}
}

License

MIT — see LICENSE.

A
license - permissive license
-
quality - not tested
A
maintenance

Maintenance

Maintainers
5hResponse time
Release cycle
Releases (12mo)
Commit activity
Issues opened vs closed

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • OCR, transcription, file extraction, and image generation for AI agents via MCP.

  • Free public MCP for AI agents — 193 tools, 44 workflows. No API key.

View all MCP Connectors

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/KasperHonore/Foam-Agent'

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