AWS Builder Center
Give Your AI Agent an HPC Cluster Through MCP Tools

Give Your AI Agent an HPC Cluster Through MCP Tools

Wire a generative AI agent to an OpenFOAM cluster on AWS PCS so it can run real-time CFD simulations and act on the results in seconds.

Give Your AI Agent an HPC Cluster Through MCP Tools

Most agent demos stop at "the model called an API and got some JSON back." That's fine when the tool is a weather lookup. It falls apart the moment the agent needs to actually simulate something — run a fluid dynamics model, sweep an ensemble of scenarios, and come back with a physically grounded answer while a real-world operation is still in progress.
I wanted an agent that could do exactly that: take a proposed engineering plan, run it through a real  computational fluid dynamics (CFD)  solver on a proper HPC cluster, and hand back optimization and risk numbers fast enough to matter during a live, minute-by-minute operation. The interesting part isn't the physics — it's the plumbing. How do you give a language model a supercomputer without letting it anywhere near the supercomputer?
This post walks through the pattern I landed on: the agent only ever calls tools; the tools drive the cluster. It's a clean separation that keeps the model safe, the cluster fast, and the whole thing cheap when nobody's using it.

The problem with the obvious approach

The naive design is to let the agent SSH into a head node and run commands. Don't. An LLM with shell access to your HPC scheduler is a bad day waiting to happen — prompt injection, runaway job submission, and zero audit trail all live down that road.
The other trap is latency. If you back your simulations with  AWS Batch , every job pays a cold-start tax — instance provisioning, container pull, container start, queue delay. That's 3–7 minutes of overhead per job before a single cell of your mesh is solved. Perfect for overnight batch runs. Useless when your operation updates every 60 seconds and you need a prediction before the next cycle begins.
Real-time simulation has two hard requirements that push you toward a persistent HPC cluster:
  1. Sub-10-second job start. Warm compute nodes, no container pull, no provisioning wait.
  1. A shared, fast filesystem. So each cycle can restart from the previous cycle's checkpoint instead of rebuilding state from scratch.

The architecture

Here's the shape of it. The agent lives in a container and speaks only to a GraphQL API. Behind that API, functions translate intent into scheduler commands. The cluster does the heavy lifting and writes results to object storage, which the agent reads back through another tool.
Plain text
Agent tool ──GraphQL──▶ API ──▶ Function ──(SSM RunShellScript)──▶ Login node ──sbatch──▶ SLURM
│
OpenFOAM runs on shared FS ◀────┘
│
results copied to object store ◀┘
│
Agent tool ──GraphQL──▶ API ──▶ Function ──(read object store)─────────┘
Every layer here maps to a managed AWS service:
Layer
Service
Why
Cluster + scheduler
 AWS Parallel Computing Service (PCS) 
Managed
 SLURM 
; persistent login node, auto-scaling compute
Shared filesystem
 FSx for Lustre 
Sub-second checkpoint reads; auto-syncs to S3
Compute
 Hpc7g (Graviton) with EFA 
Cost-efficient arm64 cores with a low-latency
 Elastic Fabric Adapter 
interconnect for MPI
Cluster access
 AWS Systems Manager Run Command 
Runs  sbatch  on the login node — no open SSH, full CloudTrail audit
Agent-facing API
 AWS AppSync 
GraphQL front door; resolvers are functions, auth is scoped
Solver
 OpenFOAM 
Open-source CFD, runs the actual simulation
The key design decision: the agent's tools call GraphQL, and GraphQL resolvers — not the model — hold the credentials and the cluster commands. The model can ask for a simulation. It cannot decide how that simulation reaches the scheduler. That boundary is the whole security story.

Why MCP is the right seam

 The Model Context Protocol (MCP)  gives you a standard way to expose these capabilities as tools the model can discover and call. Instead of hard-coding one bespoke integration, you define a handful of well-named tools with typed inputs and let the agent compose them. In this system the tool surface looks like:
  •  evaluate-treatment-plan  — submit a plan as a 3-D CFD simulation, poll to completion, return optimization and risk metrics.
  •  run-ensemble-simulation  — fan one base plan out to ~10 concurrent geological-scenario simulations.
  •  interpret-pressure-response  — match an observed real-world pressure curve against the ensemble.
  •  assess-screen-out-risk  — score the risk of the operation failing and estimate lead time before it does.
Each tool is a thin GraphQL client. The agent reasons about which tool to call and what to pass; the resolver behind it does the privileged work. If you're running your agent on  Amazon Bedrock AgentCore , these tools plug straight into its runtime, and the same MCP tool definitions work whether the model is Claude on  Amazon Bedrock  or something you host yourself.
The abstraction pays off in a second way: your tools return decision-ready data, not raw solver output.  getCfdResults  reads a  metrics.json  from object storage — it never touches the cluster. The model sees clean numbers, not gigabytes of VTK field files.

What actually happens on a submit

When  evaluate-treatment-plan  fires, the resolver:
  1. Generates a SLURM batch script for the requested case (steady-state or transient  pimpleFoam ).
  1. Finds the running login node by EC2 tag.
  1. Runs  sbatch  on it via SSM  AWS-RunShellScript  — no SSH session, everything logged.
  1. Stores the returned SLURM job ID on a DynamoDB record.
The tool then polls a  getCfdJobStatus  operation, which walks  squeue → scontrol → sacct  and finally checks the S3 result prefix to map the job to a state. When results land,  FSx for Lustre auto-exports  the  /fsx  changes back to S3, and the results tool reads them directly.
Here's the abbreviated SLURM script the resolver generates for a real-time restart cycle — note it restarts from the latest checkpoint rather than cold-starting the mesh:
Bash
#!/bin/bash
#SBATCH --job-name=cfd-realtime
#SBATCH --nodes=1
#SBATCH --time=00:15:00
#SBATCH --output=/fsx/simulations/%j/slurm-%j.out

source /opt/openfoam/etc/bashrc
cd /fsx/simulations/$SIM_ID

# Restart from the most recent written time step
LATEST=$(foamListTimes -latestTime)
cat > system/controlDict.overrides <<EOF
startFrom latestTime;
startTime $LATEST;
endTime $((LATEST + 600)); # predict 10 minutes ahead
EOF

# Solve — MPI ranks capped to match mesh size (see perf note below)
mpirun -np 8 pimpleFoam -parallel

# Compute decision metrics and push to object storage
python3 /fsx/scripts/calculate_metrics.py --sim-id $SIM_ID
aws s3 cp results/ s3://$BUCKET/cfd-simulations/$SIM_ID/results/ --recursive

The performance surprise

The first version of this took ~18 minutes per simulation. That's not real-time by any definition. Profiling turned up a counterintuitive culprit: too much parallelism.
For a small mesh (a few thousand cells), running the solver across 64 MPI ranks meant each rank owned only ~60 cells — and the MPI communication overhead completely dominated the actual math. Capping ranks at 8 dropped the solver time from ~6 minutes to 3 seconds. Two other cuts — skipping VTK conversion (the metrics script reads OpenFOAM field files directly) and reducing write frequency — took the rest.
Phase
Before
After
Solver ( pimpleFoam )
~6 min
~3 s
 reconstructPar 
~5 min
~50 s
VTK conversion
~3 min
skipped
Total (warm node)
~15 min
~1.5 min
The lesson generalizes well beyond CFD: match your parallelism to your problem size. More cores is not more speed once communication cost exceeds per-rank compute. Measure before you scale out.

Cost: know what's always-on before you commit

The economics are the part that makes this deployable — but only if you're honest about what runs at rest. The compute node group is configured  min=0, max=10  and  scales to zero  when idle, so the expensive  hpc7g  cores cost nothing between operations.
 AWS PCS pricing  has two service fees on top of the underlying EC2. Both bill by the hour:
  • Cluster controller fee — charged for the managed SLURM controller whether or not a single compute node is running. It scales with controller size: Small is $0.5825/hour ($425/month), Medium is $3.2579/hour ($2,346/month), Large is $6.5426/hour. A real-time demo like this one runs comfortably on a Small controller.
  • Node management fee — $0.08 per instance-hour (standard tier) for every EC2 instance PCS launches in a node group. This does scale to zero with your compute.
So the real always-on floor for a persistent, scale-to-zero cluster is roughly:
Always-on component
Rough monthly cost
PCS controller (Small)
~$425
 FSx for Lustre 
(1.2 TB PERSISTENT_1)
~$170
Login node ( t3.medium )
~$30
Call it ~$600/month at idle, before you run a single simulation. The  min=0  compute group and the $0.08/instance-hour node fee are what stay near zero between operations.
That trade — a fixed monthly floor for the controller and shared filesystem, in exchange for sub-10-second job starts when warm — is what makes real-time, agent-driven simulation practical. You're paying to keep the scheduler and checkpoints warm, not the compute. Just don't budget it as "free when idle," and check the  pricing page  for your controller size and region before you commit.

Takeaways

  • Never give the model the keys. The agent calls tools; the tools (GraphQL resolvers) hold the credentials and issue the cluster commands. SSM Run Command beats open SSH — it's auditable and needs no inbound ports.
  • Persistent clusters beat Batch for real-time. Cold-start latency kills minute-by-minute loops. A warm PCS/SLURM cluster with FSx for Lustre restarts from checkpoints in seconds.
  • MCP tools should return decisions, not data. Read results from object storage and hand the model clean metrics — keep the field files out of the context window.
  • Right-size parallelism. For small meshes, fewer MPI ranks is dramatically faster. Profile before scaling out.
  • Scale to zero, but budget the floor. A  min=0  compute node group keeps expensive cores near zero when idle — but the PCS controller fee and FSx bill around the clock. Know your always-on floor (~$600/month here) before you commit.
If you're building agents that need to reach into serious compute — CFD, finite-element, Monte Carlo, genomics — this tool-in-front-of-a-cluster pattern is the one I'd reach for again.

Related reading

Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article