Content
# apsim-mcp
An MCP server that lets an LLM drive the [APSIM Next Gen](https://www.apsim.info) farming-systems simulator with plain language. Any [MCP](https://modelcontextprotocol.io)-capable client should work in principle — it has only been tested with Claude (Claude Desktop and Claude Code).
Open a bundled model, a crop, a pasture, a plantation, a bare soil-water balance or your own `.apsimx` file, then inspect it, edit any node, attach weather and soil, add the outputs you want, run it (single runs or factorials), and read the results back. Each model is a session that records every edit, so what's reported is what **actually** ran.
This tool is a thin driver, not a data pipeline: **you supply the inputs.** Bring a complete `.apsimx`, or wire in your own weather (`.met`) and soil, and it will proceed to work with what is provided.
> [!Note]
>Beware that commerical LLMs (Claude/GPT) aren't natively the best drivers of APSIM, so some skeptisism and careful review of outputs is recommended.
<p align="center">
<img src="docs/demo.gif" alt="Driving a maize nitrogen factorial through apsim-mcp and plotting the yield distributions" width="100%">
</p>
<p align="center">
<sub>A session driven in Claude Code: open the Maize example, set the clock to 1961–2000, run a nitrogen-rate factorial, read the per-season yields, and render a ridgeline of the yield distributions.</sub>
</p>
## Tools
Work any model through a session:
| Tool | What it does |
|---|---|
| `list_models(filter?)` | List bundled example models to open. |
| `open_model(source, source_type?)` | Load an example or a `.apsimx` file; returns its structure. |
| `inspect(session_id, path?, node_type?)` | The whole structure, one node's parameters, or every node of a type. |
| `edit(session_id, node_path, changes)` | Set properties on a node (a manager, a soil layer, the clock). |
| `set_weather(session_id, …)` | Attach your own `.met`, or fetch NASA POWER climate for a point. |
| `set_soil(session_id, lat, lon)` | Fetch a SoilGrids profile for a point. |
| `list_variables(session_id, node_path)` | List a node's reportable members (`LAI`, `SWmm`) to build `add_output` expressions without guessing. |
| `add_output(session_id, variables, …)` | Add report variables so a run produces the outputs you need. |
| `run_model(session_id, factors?)` | Run; returns a manifest of the result tables. Pass `factors` to run a factorial. |
| `run_points(source, points, …)` | Run a base model at many georeferenced points; returns one metric per point as a mappable table. |
| `read_output(session_id, …)` | Read results — summarise, page rows, resample, aggregate, or write a CSV. |
| `save_model(session_id, path)` | Write the configured model to a `.apsimx` file. |
| `close_model(session_id)` | Close the session and free its scratch. |
Most tools are read-only or touch only the local engine; `save_model` writes a file you name, and
`set_weather`/`set_soil` reach the network only when you ask them to fetch.
## Setup
The pure tier (tool logic and tests) needs only Python. The engine tier adds APSIM to simulate.
Pure tier:
```bash
python -m venv .venv && .venv/bin/pip install -e ".[dev]" # Windows: .venv\Scripts\pip
python -m pytest -q
```
Engine tier:
1. Install [APSIM Next Gen](https://registration.apsim.info) (free, non-commercial; ships its own
.NET). A standard install is auto-detected; set `APSIM_BIN_PATH` if not.
2. `pip install -e ".[engine,serve]"`
3. Optional `.env`: `APSIM_MCP_WORKDIR` (a local, non-cloud-synced dir; defaults to temp) and
`APSIM_MCP_UPLOAD_DIR` (a directory to allow reading and saving your own `.apsimx` files under).
4. `apsim-mcp-doctor` checks the install and lists anything missing.
Connect it to any MCP client by pointing that client at the `apsim-mcp` console script (untested
outside Claude). For Claude: install [uv](https://docs.astral.sh/uv/), then
`/plugin marketplace add Briggs599/apsim-mcp`, install `apsim-mcp`, and restart — or add the
`apsim-mcp` console script to `claude_desktop_config.json` by its full path.
## Usage
Ask in plain language; the model picks and chains the tools.
- **Drive any model.** "Open the Maize example, attach my weather file D:\wagga.met, add daily soil
water and drainage as outputs, run it, and summarise the drainage." The model chains `open_model` →
`set_weather` → `add_output` → `run_model` → `read_output`, and can `save_model` the result to
reopen or share.
- **Compare treatments.** Give `run_model` a `factors` list, say nitrogen rate crossed with sowing
date, to run the whole factorial in one call. Each result row is tagged with its treatment, so
`read_output(mode='aggregate', group_by=['N'])` compares them.
- **Your own file.** Point `open_model` at a `.apsimx` path (set `APSIM_MCP_UPLOAD_DIR` first). It
runs exactly the weather, soil and management you built into it.
## Architecture
You talk to the model in plain language; it calls the tools over MCP (stdio) and reads the results
back. The server is a thin two-tier stack using a pure **session layer** over a lazily-loaded **engine**.
Nothing touches APSIM until a tool runs a model.
```mermaid
flowchart TB
U["You — plain language"]
C["LLM · MCP client<br/>tested with Claude Desktop / Code"]
U <--> C
subgraph server["apsim-mcp server · MCP over stdio"]
direction TB
T["13 tools:<br/>list_models · open_model · inspect · edit<br/>set_weather · set_soil · list_variables · add_output<br/>run_model · run_points · read_output · save_model · close_model"]
P["Session layer — primitives.py<br/>loaded models · edit log · bounded output"]
E["Engine, lazily loaded — engine.py<br/>apsimNGpy → APSIM Next Gen / .NET"]
T --> P --> E
end
C <-->|"tool calls / JSON results"| T
E -->|"runs the model"| R["APSIM run<br/>results DB → manifest"]
R -->|"read_output"| P
Y["Your files:<br/>.apsimx · .met · soil"] --> P
E -.->|"optional fetch"| NASA["NASA POWER climate"]
E -.->|"optional fetch"| SG["SoilGrids soil"]
```
## Links
- APSIM Next Gen: [apsim.info](https://www.apsim.info) — register/download at
[registration.apsim.info](https://registration.apsim.info)
- apsimNGpy (the Python driver): [apsimngpy.readthedocs.io](https://apsimngpy.readthedocs.io)
- Optional data fetchers: [NASA POWER](https://power.larc.nasa.gov) climate ·
[SoilGrids / ISRIC](https://soilgrids.org) soil
## Licence
Code is Apache-2.0 (see [LICENSE](LICENSE)). APSIM, via apsimNGpy, is free for non-commercial use
under its own licence. The optional NASA POWER climate and SoilGrids soil data are CC BY 4.0 or
public domain.