Hydrata MCP Server
OfficialIt builds, runs, and inspects ANUGA flood simulations on Hydrata Cloud end-to-end, from terrain import to results and observation comparison.
Projects: list, read (with map links), and create ANUGA projects with an EPSG projection.
Terrain: fetch a DEM from Hydrata's own sources (e.g. Copernicus GLO-30, GA 5 m LiDAR) or get a presigned URL to upload your own GeoTIFF, then poll the import.
Input layers: list, describe formats, write GeoJSON inline, attach an uploaded GeoJSON, or hand the user a browser upload link for big files (boundary, friction, inflow, rainfall, building, mesh region, culvert).
Time series: create, correct, list, and delete rain gauges, hydrographs, and tide/stage series.
Scenarios: create and inspect draft scenarios with mesh-triangle estimates and cost, and build the mesh/package (with spend gates and refusals surfaced).
Runs: start simulations, poll lightweight status, fetch full records, cancel, retry, and list runs.
Flood observations: create layers, add/edit/delete observations (flood marks, timed levels, gauge records, dry points), and attach photo links.
Comparison: compare historic runs against observations (bias, RMSE, NSE, tolerance), exclude observations with a reason, and save a project default tolerance.
Feedback: suggest a missing capability to the Hydrata team.
Safety/hand-off throughout: agent-key levels gate writes, presigned S3 links are elided, and every mutating tool returns a
ui_urlplussay_to_userso the engineer signs off in the map.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Hydrata MCP ServerStart flood simulation for scenario 'Coastal'."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
hydrata-mcp-server
MCP server for Hydrata Cloud — build ANUGA flood models from terrain and input layers, run simulations, track progress, and retrieve results through the Model Context Protocol.
Connect and authenticate
Endpoint: https://hydrata.com/mcp/ — Transport: Streamable HTTP.
Every tool call needs the caller's own hydrata.com credential: an agent key (Authorization: Bearer hk_…), a named, revocable grant at one of three levels (read < draft < launch) that the account owner creates — and can revoke, one at a time or all at once — on the site's Agent keys page (/agents/). The server holds no identity and no key store of its own: it checks only the shape of the credential (an hk_ prefix, or with the connect flow configured a JWT-shaped token) and forwards the one accepted Authorization header unchanged to the Hydrata REST API, where Django verifies it on every tool call (for a connect-flow token: signature, issuer, audience, expiry and the live grant; for an agent key: the stored hash and the live grant) — so results are scoped by the real user's project permissions and the key's level, and the audit trail names them. Every JSON-RPC request — initialize, tools/list and ping as well as tools/call — that does not carry exactly one accepted credential (an agent key, or with the one-click connect flow configured its access token) is answered with 401, a JSON-RPC error -32001 and WWW-Authenticate: Bearer realm="hydrata.com" (plus resource_metadata="…" when the connect flow is configured) before it reaches the MCP SDK: no Authorization header, HTTP Basic, or any other Bearer token such as a GeoNode OAuth token. Agent keys and connect-flow tokens both map to an agent grant, so both are subject to the grant's level, the account's pause switch, the spend limit and the agent activity log. The 401 on the first request is what tells an OAuth-aware client such as claude.ai that the server needs sign-in (TASK-3987), so the tool catalog is not served to a request without a credential of an accepted shape; for initialize, tools/list and ping that credential is checked for shape only, not verified. Each claim about this server's security behaviour is cited to code or a test in docs/security-model.md; to report a vulnerability see SECURITY.md. A body that is not JSON-RPC is left to the SDK's own error, and a GET is answered 405.
The server is not yet open to external accounts: there is no self-serve way to connect your own hydrata.com login to it today, and this README deliberately carries no client-side credential recipe. If you would like to use it, contact us at hydrata.com.
Related MCP server: SWATGenX MCP Server
Tools
Version 0.2.0 exposes thirty-six tools. The table below lists the original twenty-eight and suggest_capability; tools/list returns all of them. Of the original twenty-eight, eleven that read projects, inputs and scenarios and drive a run, eight that build a model from terrain and input layers the agent has already uploaded, six that record flood observations, and three that compare a historic run with them (Compare with observations). Every tool carries MCP annotations (a title; readOnlyHint on the eleven read tools; destructiveHint only on cancel_run and delete_observation).
Tool | Description |
| List ANUGA simulation projects (paginated) |
| Get one project — name, projection, visibility, your role, |
| Get a scenario's compact state — |
| Start a flood simulation (local/EC2/Batch backends); the returned run record has its presigned download links elided; hand-back link opens the run. A run over the agent key's monthly spend limit (default $0), or one Hydrata cannot price, is not started: the tool relays Hydrata's |
| Lightweight status poll (<50ms); |
| Full run details with timing, log and result layers; presigned |
| Cancel an in-flight simulation; hand-back link opens the scenario |
| Retry a failed simulation (rebuilds the scenario as a new run); hand-back link opens the scenario |
| List runs across a project (with status filter); presigned |
| Every input row of a project per kind (boundary, friction, inflow, rainfall, building, mesh region, culvert) — row id, title, dataset, WFS typename and whether it has features — so the agent never has to probe files |
| A project's time series — id, name, type, units, row count and first/last timestamp; the data rows are never returned |
| Create an ANUGA project with a name and EPSG projection; returns its |
| Return a presigned URL + key so the agent PUTs the terrain GeoTIFF itself (no file bytes pass through MCP) |
| Register the uploaded terrain; the import chain seeds the project's six default boundary/friction/inflow/rainfall/building/mesh-region rows (no culvert row: |
| Poll the terrain until it is ready (bounded; |
| Create a time series (rain gauge, hydrograph or tide/stage — |
| Attach a GeoJSON dataset the agent already uploaded as the project's boundary/friction/inflow/rainfall/building/mesh-region or culvert layer (kind |
| Create a draft scenario and return its mesh-triangle estimate and price ( |
| Build the scenario package; shows the estimate first and needs |
| Create a flood observation layer (project-level, never a scenario input) with its vertical datum ( |
| A project's flood observation layers, or one layer's observations — |
| Add Flood marks, Timed levels, Gauge records and Dry points (up to 200 per call; |
| Edit one observation (PATCH of the fields given; validated against the stored observation) |
| Delete one observation and its photos |
| Attach a photo to an observation as a reference link only (stored, never fetched); a photo FILE is refused with the UI path — the engineer uploads files in the photo strip on the observation's form in the map |
| How a historic run compares with the project's flood observations: |
| Exclude one observation from a run's comparison with the engineer's reason (required: the tool refuses a blank one and the agent must ask), or include it again; logged with user and reason; returns |
| Save the project's default comparison tolerance (metres, above 0 and at most 5; Editor+). |
| Tell the Hydrata team about something the person asked for that no tool can do (read-only; the reply gives the words to say to the person; 20 a day per person) |
The hand-back: the engineer signs off in the map
Every tool that changes something (create_project, finalize_terrain_upload, get_terrain, create_time_series, attach_input_layer, create_scenario, build_scenario, start_simulation, cancel_run, retry_run, the five flood observation writes, and the three comparison tools) also returns:
ui_url—https://<site>/catalogue/#/map/<base_map>?panel=…&layer=…&scenario=…&run=…, which opens the project map on the thing that changed (the Inputs panel framing the attached layer, the Hydrology panel, the scenario, the run);summary— numbers the engineer can check (feature count and bbox, elevation range, row count and time span, triangle estimate and price);say_to_user— the sentence the agent should relay.
The server's instructions tell the agent to hand the link to the user after each layer lands and to wait for the user before start_simulation. Refusals the user can fix in the map (no boundary, no External boundary edge) carry the link too. Every request the server forwards carries X-Hydrata-Client: mcp/<version> and X-Hydrata-Session: <uuid> — informational only (client-asserted), never used for authorship.
No tool accepts file contents inline. The agent moves the bytes itself — the terrain GeoTIFF to the presigned URL, a GeoJSON layer to the REST API upload endpoint — and hands the server the resulting key or upload id.
No read tool relays a presigned S3 URL. A run's result links are 6-hour capabilities carrying a temporary AWS credential, and the server forwards the caller's own credential rather than holding one, so a tool that echoed such a link would widen what an agent transcript is worth beyond what the caller asked for. Every read tool (and start_simulation) elides them, recursively, by key name (s3_*_url) and by value shape (any string carrying X-Amz-Signature / X-Amz-Security-Token, redacted in place so the rest of a log line survives); results stay viewable through the gn_layer_* WMS entries. presign_terrain_upload is the sole exception: its upload_url is the URL the caller explicitly asked for.
Typical workflow
Run a scenario that already exists:
list_projects → get_scenario → start_simulation → poll get_run_status → get_runImport a model and run it:
create_project → presign_terrain_upload → PUT the GeoTIFF → finalize_terrain_upload → get_terrain
→ create_time_series / attach_input_layer → create_scenario → build_scenario
→ start_simulation → poll get_run_status → get_runWhat is Hydrata?
Hydrata is a geospatial hydraulic modeling platform. It runs ANUGA flood simulations in the cloud — upload terrain data, configure scenarios, run simulations on managed compute (Celery, EC2, or AWS Batch), and visualise results on interactive maps.
ANUGA is an open-source hydrodynamic model developed by Geoscience Australia and the Australian National University. It solves the shallow water wave equations using finite volumes on an unstructured triangular mesh.
Development
git clone https://github.com/Hydrata/hydrata-mcp-server.git
cd hydrata-mcp-server
pip install -e ".[dev]"
pytest -vContributions welcome — see issues.
License
Available Tools
36 toolsadd_observation_photo_linkAttach a photo link to a flood observationAInspect
Attach a photo to a flood observation as a reference LINK (never a file).
MCP never uploads photo bytes. A local path, file:// URL or data: URI is refused: to upload a photo file, open the observation in the map and use the photo strip on its form (JPEG, PNG or HEIC, 25 MB, 10 per observation). The link counts toward the 10.
| Name | Required | Description | Default |
|---|---|---|---|
| fid | Yes | The observation's fid | |
| credit | No | Who took it / the rights holder (optional) | |
| caption | No | What the photo shows (optional, up to 500 characters) | |
| layer_id | Yes | The flood observation layer id | |
| project_id | Yes | The project ID | |
| reference_url | Yes | An http(s) link to the photo (stored, never fetched) | |
| public_consent | No | Show this photo to visitors of a public project (default false: members only) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly=false, destructive=false, idempotent=false, openWorld=false. The description adds substantive behavior beyond that: MCP never uploads bytes, non-http inputs are refused, and there is a 10-photo-per-observation cap that this link consumes. That is exactly the context an agent needs before calling a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The binding constraint (link, never file) is front-loaded in the first clause. The remaining sentences earn their place by explaining refusals and the escape hatch, though the JPEG/PNG/HEIC and 25 MB details describe the UI alternative rather than this tool and are mildly tangential.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description covers the mutation semantics, refusal cases, and quota interaction. The one gap is whether re-attaching the same link is deduplicated or duplicates the entry, which the false idempotentHint leaves ambiguous.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 7 parameters including the http(s) constraint on reference_url. The description adds no per-parameter syntax or format detail beyond what is in the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (attach) and resource (photo link on a flood observation) and immediately scopes it: 'as a reference LINK (never a file).' An agent can distinguish this from any byte-upload path without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when-not: local paths, file:// URLs and data: URIs are refused. It also routes the agent to the correct alternative for actual uploads (open the observation in the map, use the photo strip), including accepted formats and size/count limits.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_observationsAdd flood observations to a layerAInspect
Add flood observations (Flood mark, Timed level, Gauge record, Dry point) to a layer.
POSTs each observation to /projects//flood-observations//observations/
in order. The API validates every field: a row it refuses (400) is listed in
rejected with its problems and the rest still land; a refusal that is not
about the row (403 not an Editor, 404, 409) stops the batch and is reported in
stopped, with not_sent_count. Stages are on the LAYER's vertical datum.
Photos are not part of an observation: attach a link with add_observation_photo_link.
| Name | Required | Description | Default |
|---|---|---|---|
| srid | No | EPSG code for every geometry that does not carry its own `srid` (the projected CRS its eastings/northings are in, e.g. a UTM zone); omit for [lon, lat] (EPSG:4326) | |
| layer_id | Yes | The flood observation layer id (create_observation_layer / list_observations) | |
| project_id | Yes | The project ID | |
| observations | Yes | Observations, each the API write body: subtype (flood_mark | timed_level | gauge_record | dry_point), name (required: a short label, e.g. the survey mark id), geometry {type: Point, coordinates: [lon, lat]} (or native x/y with srid), value_kind (stage | depth) + stage_m or depth_m, uncertainty_grade (H/M/L) or uncertainty_m, bound (exact | at_least | at_most), observed_start/observed_end (ISO 8601; naive times read in entry_timezone, by default the project's own zone), mark_type, flood_name, source, licence, notes; a flood_mark or dry_point must say which flood it is: a date window (observed_start / observed_end) or flood_name (ask the user; never guess a date); a gauge_record needs data_timeseries_id (+ gauge_zero_m). At most 200 per call | |
| entry_timezone | No | IANA zone for naive observed_start/observed_end on rows that do not carry their own entry_timezone; omit to use the project's zone (derived from where the project is, reported back as entry_timezone). Give it only when the times were read elsewhere |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the mutation/idempotency profile; the description goes well beyond by disclosing partial-failure semantics (400 rows land in `rejected` with `problems` while the rest still succeed), fatal-batch errors (403/404/409 stop the batch and populate `stopped` with `not_sent_count`), the 200-row cap, and sequential POST ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then the endpoint/failure model, then the datum caveat and the photo alternative. Every sentence carries operational information; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a batch mutation tool with a rich schema and an output schema, the description supplies the missing behavioral contract (failure classification, limits, ordering) needed to call it correctly. Nothing an agent needs is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds non-schema context such as stages being referenced to the layer's vertical datum and the must-identify-the-flood rule for flood_mark/dry_point. Most remaining parameter detail is already carried by the very rich schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (add) and resource (flood observations) and enumerates the exact subtypes accepted. It clearly distinguishes itself from add_observation_photo_link by scoping photos out of the operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operating context: photos must go through add_observation_photo_link, and a flood_mark/dry_point requires a date window or flood_name ('ask the user; never guess a date'). It stops short of routing the agent to update_observation or list_observations for other workflows.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
attach_input_layerAttach an uploaded layer as a project inputAInspect
Attach a GeoJSON you uploaded to GeoNode as the project's boundary, friction, inflow, rainfall, building, mesh_region or culvert layer.
Only for a client that has a shell and an agent key. A connector agent with no shell (claude.ai) writes the layer inline with write_input_layer, or, for a file above the inline cap, gives the user the request_input_upload link instead.
The agent moves the bytes: first upload the GeoJSON yourself, with the same agent key, to GeoNode's upload endpoint at the site origin:
curl -sS -H 'Authorization: Bearer hk_...' -F "base_file=@/path/rainfall.geojson" https://<site>/api/v2/uploads/upload/→ JSON with execution_id. Then call this tool with it. The tool polls
GET /api/v2/resource-service/execution-status/<execution_id> (bounded by
timeout_seconds; statuses ready → running → finished | failed), reads the
new dataset's pk, and PATCHes it onto the project's DEFAULT row of that
kind ('Boundary 01' … 'MeshRegion 01' — the six rows the terrain import
seeds ~30 s after get_terrain reports ready; if the list is still empty
the tool says so: run finalize_terrain_upload / wait for get_terrain first).
kind culvert (Hydraulic Structures; one two-point line per culvert,
Inlet first, then Outlet): no culvert row is seeded by the terrain import,
so a project with none answers no_default_row: write the culverts with
write_input_layer, which makes the row. Hydrata converts every attached
layer into the project's grid and the kind's table shape (single
geometries, the_geom, the kind's own columns); attribute names are matched
as they are, nothing is renamed for you (see write_input_layer).
The culvert engine conveys flow through each culvert in a run (GPU
lanes and localhost; the multi-core CPU lanes refuse a culvert scenario).
outcome is exactly one of: attached (row_id, gn_layer, dataset_pk and
dataset_alternate — the WFS typename — of the CONVERTED layer the row now
uses, source_dataset_pk — the dataset you uploaded — and every row id seen);
timed_out (still importing: call
again with the same arguments, except pass retry_execution_id as
execution_id when the result carries one); upload_failed (the
execution record, incl. its log, is returned verbatim — fix the file and
upload again); no_default_row; no_dataset (finished but no resource
was recorded). The PATCH is refused with a 400 if the dataset is not
owned by you.
Every layer attached here is marked as written by your agent key and is UNREVIEWED until the user reviews it in their browser (the build refuses UNREVIEWED_INPUTS until then). INFLOWS: never invent an inflow location — no coordinates you made up, guessed or "placed plausibly". Import the location from the study's own files, or give the user the ui_url to draw it in the map; say in say_to_user that the inflow is unreviewed and where they check or draw it.
Refused, with no request made: kind breakline — no REST create path
exists for it at HEAD (TASK-3040 AC6), so attaching one would only
pretend. Also refused without a request: an execution_id that is not the
UUID the upload returned.
One GeoJSON per kind: all of a kind's features travel in that one file. A
rainfall polygon names its gauge in its data property — create that
gauge with create_time_series under the exact same name.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | Which input the uploaded layer is: boundary, friction, inflow, rainfall, building, mesh_region or culvert ('structure' is a deprecated alias of building). breakline is refused (see below). | |
| project_id | Yes | The project ID | |
| execution_id | Yes | `execution_id` returned by your multipart POST to <origin>/api/v2/uploads/upload/ | |
| timeout_seconds | No | How long this call keeps polling the upload before it returns `timed_out` (default 180, ceiling 200 — claude.ai cuts a tool call at 240 s). 0 = one status read, no waiting. | |
| poll_interval_seconds | No | Seconds between polls (default 5) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the annotations: it discloses the full upload→poll→PATCH sequence, the status transitions, the 400 refusal when the dataset isn't owned by the caller, the UNREVIEWED_INPUTS build gate, refused inputs (breakline, non-UUID execution_id) with no request made, and the one-GeoJSON-per-kind constraint. The annotations (destructive false, idempotent false) are consistent with a row-PATCH that is retryable only via retry_execution_id.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the verb and the target kinds, and most paragraphs earn their place (alternatives, prerequisites, outcome codes). It is long, and one passage — the culvert engine's GPU/CPU lane behaviour — describes simulation behaviour rather than invocation of this tool, which is tangential for a 5-parameter call.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-step tool with an output schema, an agent gets everything needed to call it correctly: upload endpoint with curl example, polling bounds, all outcome values, failure remediation, ownership constraint, and the review workflow afterwards. Nothing material is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description earns more by clarifying that execution_id must be the exact UUID the upload returned, documenting the outcome/timed_out retry path via retry_execution_id, and stating the kind semantics including the deprecated 'structure' alias and the breakline refusal. Timeout ceiling rationale lives in the schema, not the description, so it isn't double-counted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — attach an uploaded GeoJSON as one of seven enumerated project input kinds — and immediately distinguishes itself from write_input_layer and request_input_upload by client capability. An agent can pick this tool without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use gate (client with a shell and agent key), explicit when-not (no-shell connector → write_input_layer or request_input_upload), and named prerequisites: the terrain import seeds the six default rows ~30 s after get_terrain is ready, otherwise run finalize_terrain_upload. The culvert case gets its own routing rule (write_input_layer, since no row is seeded).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
build_scenarioBuild a scenario's mesh and packageAInspect
Build a scenario's package (mesh + inputs) after showing what it will cost, and poll until built.
Needs a launch-level agent key (a build can start AWS Batch); a read or draft key gets 403 AGENT_LEVEL_INSUFFICIENT — the user creates a launch key on the site's Agent keys page (/agents/).
Order of operations, so the number is shown before anything is spent:
GET the scenario detail. A record with no
boundary/computed_statuskeys is a non-member's read of a public project → refused: a build needs the EDITOR role.Re-call checks on
latest_run(a re-POST is NOT deduplicated afterbuilt/complete— it would dispatch a duplicate build): no run → proceed; runcreated/building→ resume polling, no POST; runbuilt/queued/computing/processing/completewithlatest_run_is_validnot false → return that state, no POST unless rebuild=true; runerror/cancelled, orlatest_run_is_validfalse (the scenario was edited since the build) → proceed.Spend gates, each a refusal with
outcome: "refused"and no POST: the scenario has no boundary or its boundary row has no features (the server would admit the build and fail it in make_package); the estimate is None (resolution is 0/unset); the estimate is above 100,000 triangles and confirm is not true — the refusal states the number; re-call with confirm=true to proceed. An estimate of 0 over a boundary WITH features is buildable and is reported, not refused.POST /projects//scenarios//build/. Every 4xx comes back verbatim as a normal result with
http_status: 422 MESH_TOO_LARGE (error_code,estimate,ceiling,detail— the server's hard ceiling; coarsenresolutionor shrink the boundary; no run was created), 409 COMPUTE_TARGET_UNAVAILABLE, 400/403/404. 409 UNREVIEWED_INPUTS (inputs you wrote that the user has not reviewed) answersoutcomeunreviewed_inputswith theunreviewed_inputslist and aui_urlto the scenario's review screen: give the user the link, poll get_scenario until itsunreviewed_inputsis empty, then build again. A 409 WITHOUT an error_code is the dedup body ({status, run_id, detail}: a build is already in flight) — the tool resumes polling that run.On 202 poll the detail's
computed_status(created → building → built | error), bounded by timeout_seconds.
Returns a COMPACT state, never the whole detail: outcome (built, error,
cancelled, complete/queued/computing/processing for a run past the build,
timed_out, or refused), computed_status, mesh_triangle_count_estimate,
posted, the POST's build body + http_status when one was made, and
the latest run's run_id, run_status, error_message, user_message,
mesh_triangle_count. timed_out is normal (make_package re-downloads
the terrain from S3 every build; minutes): call again with the same
arguments — step 2 resumes polling the same run, it never POSTs twice —
or cancel_run(run_id) if the run is stuck in created with no worker.
error is terminal: error_message says why (fix the inputs, then call
again — an errored latest run is rebuilt).
Units: resolution — on the SCENARIO and on every MeshRegion FEATURE — is
a LENGTH in metres; ANUGA maximum_triangle_area = resolution²/2 (FloatField
default 100, not nullable; 0 makes the estimate None), and the estimate
prices both the same way (TASK-3186). The smallest value becomes the raster
cell size. A MeshRegion feature must carry resolution_units = m (features
drawn in the map are marked automatically); an unmarked one makes the build
answer 422 MESH_REGION_UNITS_UNMARKED, naming the conversion an operator runs.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | Required (true) when the estimate is above 100,000 triangles — the tool refuses first and tells you the number. Default false. | |
| rebuild | No | true to dispatch a NEW build of a scenario whose latest run is already built/complete and still valid (default false: the tool returns that state instead of duplicating the build). | |
| project_id | Yes | The project ID | |
| scenario_id | Yes | The scenario ID from create_scenario | |
| timeout_seconds | No | How long this call keeps polling before it returns `timed_out` (default 180, ceiling 200 — claude.ai cuts a tool call at 240 s). 0 = one status read, no waiting. | |
| poll_interval_seconds | No | Seconds between polls (default 5) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say non-read-only, non-idempotent, non-destructive; the description goes far beyond by disclosing the launch-key requirement and the 403 AGENT_LEVEL_INSUFFICIENT path, that a re-POST after built/complete is not deduplicated and would dispatch a duplicate build, and that 4xx bodies come back verbatim with http_status. It also explains that timed_out is normal and recoverable and that the server re-downloads terrain from S3 each build, which an agent cannot get from the flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is long, but it is front-loaded with the one-sentence purpose and then organized as numbered steps that mirror the actual call sequence, so an agent can scan to the branch it is in. A few lines are denser than needed (the units paragraph, the repeated assurance that it never POSTs twice), which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a non-idempotent, spend-incurring, long-polling build tool with an output schema, this covers everything an agent needs: auth level, the exact pre-flight checks, every refusal branch, the meaning of each 4xx code, timeout recovery, and what 'error' means for retries. The return shape is defined by the output schema, so the compact-state summary is a bonus rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all six parameters are already documented, and the description correctly avoids restating them. It still adds value beyond the schema by explaining the causal chain behind confirm (refusal states the number, above 100,000 triangles, re-call with confirm=true) and by tying resolution semantics to the estimate, though a few of those details sit closer to domain data than to parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names the specific verb and resource (build a scenario's package = mesh + inputs) plus the two behavioral traits that define it: cost is shown first, and the call polls until built. That distinguishes it cleanly from siblings like create_scenario, start_simulation, and get_run_status without the reader opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It spells out the ordering explicitly: check the scenario detail, re-check latest_run, pass three spend gates, only then POST. It names concrete alternatives in the moment they matter — resume polling instead of re-POSTing, cancel_run for a stuck 'created' run, rebuild=true to force a new build — rather than leaving the agent to infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cancel_runCancel a runADestructiveIdempotentInspect
Cancel an in-flight simulation run.
Needs a launch-level agent key; a read or draft key gets 403 AGENT_LEVEL_INSUFFICIENT.
Works on runs in built, queued, or computing status. Cleans up compute resources (terminates EC2 instance, Celery task, or Batch job).
Returns 409 if the run is already in a terminal state (complete, cancelled, or error).
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | The run ID to cancel |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses the required key scope with the exact error code (launch-level agent key, else 403 AGENT_LEVEL_INSUFFICIENT), what side effects occur (compute teardown of EC2/Celery/Batch resources), and the terminal-state conflict behavior (409). Annotations only say destructive=true and idempotent=true; the description supplies the operational consequences and failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short lines, each front-loaded with a distinct fact: auth requirement, valid states, side effects, and failure code. No restatement of the title or name and nothing decorative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-param destructive mutation, it covers permissions, preconditions, side effects, and error responses, and an output schema already handles return values. Nothing an agent needs to invoke it safely and predict failure is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter (run_id) and the schema already documents it at 100% coverage. The description adds no format, sourcing, or lookup guidance for run_id beyond the schema, so it sits at the baseline for high-coverage schemas.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Cancel an in-flight simulation run') and scopes it narrowly with 'in-flight', implicitly separating it from get_run, get_run_status, list_runs, and retry_run. An agent can tell immediately this is the termination path, not a status or retry path.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit eligibility ('built, queued, or computing status') and an explicit when-not ('409 if the run is already in a terminal state'). It stops short of naming a sibling alternative (e.g., retry_run for failed runs or get_run_status to check state first), so it is clear context without full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_observation_layerCreate a flood observation layerAInspect
Create a flood observation layer in a project and wait for its map layer.
A flood observation layer holds real flood evidence (Flood marks, Timed
levels, Gauge records, Dry points) that every historic run is compared
with (Compare with observations). It is project-level: it is never a scenario input.
POSTs /projects//flood-observations/, then polls the layer until its
GeoServer layer exists (ready), usually a few seconds; until then
add_observations refuses. On timed_out, call list_observations later.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | Layer title, e.g. 'August 1998 survey' | |
| project_id | Yes | The project ID | |
| datum_offset_m | No | Metres ADDED to every stage on the layer to bring it onto the terrain datum. Required for vertical_datum=local; null means 0 otherwise | |
| vertical_datum | No | The datum the layer's stages are on: terrain (default, 'Same as terrain'), local ('Local datum (constant offset)', needs datum_offset_m), or the vertical datum the levels were surveyed on: an EPSG vertical CRS (e.g. 'EPSG:5703') or the datum's own name (at most 32 characters). Ask the user; never assume one from the country | terrain |
| timeout_seconds | No | How long to wait for the map layer (clamped to 200) | |
| poll_interval_seconds | No | Seconds between layer polls |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description carries substantial context the annotations do not: the underlying POST endpoint, the fact that the call blocks and polls until a GeoServer layer reaches `ready` (seconds), that add_observations is refused during that window, and that `timed_out` is a non-fatal outcome handled later via list_observations. This is exactly the async/readiness detail an agent needs before invoking.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with what the tool produces, then the domain meaning, then the operational behavior. Dense but purposeful. The `ready`/`timed_out` outcome names are compact and useful rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need no prose. For a blocking create with a 200-second clamp, the description covers creation, readiness polling, refusal of dependent calls, and timeout recovery — everything needed to call it correctly and interpret the wait.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already explains vertical_datum, datum_offset_m, timeout_seconds and poll_interval_seconds. The description references waiting and timeouts implicitly but adds no parameter-level meaning beyond what the schema states, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a flood observation layer in a project') and immediately defines the domain object (real flood evidence: Flood marks, Timed levels, Gauge records, Dry points) plus its distinguishing property: project-level, never a scenario input. An agent can separate this from create_scenario or create_time_series without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The sequencing is explicit: creation must complete before add_observations will accept data, and a `timed_out` result should be followed by list_observations rather than a retry. It stops short of enumerating when an agent should NOT create a layer (e.g. reusing an existing one via list_observations), but the practical routing guidance is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_projectCreate a projectAInspect
Create a new ANUGA project. Returns the project record including its id, base_map and ui_url.
The caller's own account becomes the owner. projection is the projected
CRS every scenario in the project is meshed and run in — pick the UTM zone
covering the site. The project's map is created alongside it; ui_url
opens it — give it to the user. A project you create is unpublished
(is_published: false): only its owner and members can see it until the
user presses Publish in its Sharing panel in the browser — you cannot
publish it. Next step for a new project: presign_terrain_upload.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Project name | |
| projection | Yes | Working CRS as an EPSG string, normally the UTM zone of the site, e.g. 'EPSG:32756' (WGS 84 / UTM 56S) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (which only say it's a non-destructive, non-idempotent write), the description discloses ownership semantics (caller's account becomes owner), visibility (unpublished, only owner/members can see), and a hard constraint the agent cannot work around ('you cannot publish it'). That is exactly the kind of non-obvious behavior the schema and annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with purpose and return values, then layers in the projection rule, visibility constraint, and next step. Slightly dense, but each sentence carries distinct, actionable information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still summarizes the returned fields and their use (ui_url for the user), and it covers the unpublished-state caveat and the follow-up call. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning for `projection`: it is the CRS every scenario in the project is meshed and run in, and should be the UTM zone covering the site. `name` is left to the schema, which is acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource (create an ANUGA project) and the second names exactly what comes back (id, base_map, ui_url). This is clearly distinguishable from siblings like create_scenario or list_projects.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives strong operational context: pick the UTM zone covering the site, hand the ui_url to the user, and the explicit next step is presign_terrain_upload. It lacks an explicit 'do not use this when...' clause or a contrasting alternative, so it falls just short of the top band.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_scenarioCreate a draft scenarioAInspect
Create a DRAFT scenario (no build, no run) and report its mesh-triangle estimate.
POSTs /projects//scenarios/ with the write fields, then GETs the
scenario detail — the create response carries NO estimate; the detail's
mesh_triangle_count_estimate (+ _breakdown) does. Returns a compact
record (the same fields get_scenario answers with): id, name, the FK ids
as stored, resolution, duration, computed_status (created = no run
yet), the estimate and its breakdown, the price (compute_cost_estimate
in USD, vcpu_hours_estimate), inflow_anchor_mismatch, and
http_status. Next step: build_scenario (which asks for
confirm=true above 100,000 triangles). Nothing is meshed or queued here.
Units: resolution — on the SCENARIO and on every MeshRegion FEATURE — is
a LENGTH in metres; ANUGA maximum_triangle_area = resolution²/2 (FloatField
default 100, not nullable; 0 makes the estimate None), and the estimate
prices both the same way (TASK-3186). The smallest value becomes the raster
cell size. A MeshRegion feature must carry resolution_units = m (features
drawn in the map are marked automatically); an unmarked one makes the build
answer 422 MESH_REGION_UNITS_UNMARKED, naming the conversion an operator runs.
The server does NOT validate that the FK ids belong to project_id —
pass the row ids attach_input_layer / get_terrain returned for THIS
project. Every FK is nullable at create time, and the build fails later
on a scenario with no terrain, or with neither an inflow nor a rainfall.
A boundary whose row has no features (the default 'Boundary 01' before
attach_input_layer) is accepted here and refused by build_scenario. The
estimate is None when resolution is 0; an estimate of 0 with a real
boundary is a very coarse mesh, not an error.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Scenario name | |
| inflow | No | Inflow row id (optional; the build needs an inflow OR a rainfall) | |
| culvert | No | Culvert row id (optional; attach_input_layer kind=culvert → row_id). The build refuses a culvert missing its shape, size or invert levels. | |
| terrain | No | Terrain id (get_terrain → terrain.id); the build fails without one | |
| boundary | No | Boundary row id (attach_input_layer kind=boundary → row_id) | |
| building | No | Building row id (optional) | |
| duration | Yes | Simulation duration in seconds (e.g. 43200 = 12 h) | |
| friction | No | Friction row id (optional) | |
| rainfall | No | Rainfall row id (optional; the build needs an inflow OR a rainfall) | |
| structure | No | Deprecated alias of `building` (TASK-3586); ignored when `building` is given. | |
| project_id | Yes | The project ID | |
| resolution | Yes | Mesh resolution as a LENGTH in metres (ANUGA maximum_triangle_area = resolution²/2). Coarser (larger) = fewer triangles: on a ~13 km² boundary 36-40 m gives ~16-20k triangles, 10 m ~255k, 1 m ~25M (refused by the API). | |
| description | No | Free-text description (optional) | |
| mesh_region | No | MeshRegion row id (optional): finer meshing inside its polygons, each feature's `resolution` a LENGTH in metres (see the units note). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, idempotentHint=false), it discloses substantial non-obvious behavior: the create response carries no estimate and a follow-up GET supplies it, the server does NOT validate FK ids belong to this project_id, FKs are nullable but the build fails later without terrain/inflow/rainfall, and an empty boundary row is accepted here but refused by build_scenario.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and next-step routing are front-loaded, and each paragraph targets a distinct risk (return semantics, units, FK validation, failure modes). It is dense and long for a 14-parameter tool, but most sentences carry actionable information; minor consolidation of the units paragraph is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter mutation tool with an output schema present, the description covers the full decision surface: what it does, what it deliberately does not do, what the response contains, downstream prerequisites, and the FK/units pitfalls. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the schema does the heavy lifting, but the description adds real meaning: resolution is a length in metres (ANUGA max_triangle_area = resolution²/2, applies to scenario and every MeshRegion feature), reset-to-0 yields a None estimate, and the FK ownership caveat. It largely reinforces rather than fully extends the schema, hence 4 rather than 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: 'Create a DRAFT scenario (no build, no run) and report its mesh-triangle estimate.' The parenthetical immediately separates it from build_scenario and start_simulation, which an agent can distinguish without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the next step (build_scenario, with confirm=true above 100,000 triangles) and states what does not happen here ('Nothing is meshed or queued'). It also routes boundary/terrain/rainfall requirements to build-time behavior, giving clear when/when-not guidance against siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_terrain_from_sourceFetch terrain from a Hydrata sourceAInspect
Have Hydrata fetch a terrain from one of its own sources, then wait for the import (like get_terrain).
Use a key from list_terrain_sources. Hydrata fetches, reprojects and publishes the
DEM and seeds the project's default input rows; the DEM's datum is stamped by the source.
The result is get_terrain's envelope (outcome ready | error | timed_out, terrain,
polls) plus terrain_source: the source's key, name, resolution_m, licence,
credit and vertical_datum. timed_out is normal for a large area: keep calling
get_terrain(project_id, terrain_id). A refusal (the box is over the source's size cap,
the source has no data there, an unknown source) comes back as outcome: refused
with the reason in say_to_user and nothing is created.
| Name | Required | Description | Default |
|---|---|---|---|
| bbox | Yes | The site as [min_lon, min_lat, max_lon, max_lat] in WGS84 degrees | |
| title | No | Terrain title (default: the source name and box) | |
| source | Yes | A source `key` from list_terrain_sources, e.g. `ga_lidar_5m` or `copernicus_glo30` | |
| project_id | Yes | The project ID (the key needs Contributor rights; a launch-level key since the import can start AWS Batch) | |
| timeout_seconds | No | How long this call keeps polling the import before it returns `timed_out` (default 180, ceiling 200). 0 = start it and return at once; then call get_terrain. | |
| poll_interval_seconds | No | Seconds between polls (default 5) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint=false, destructiveHint=false, idempotentHint=false) by disclosing side effects: Hydrata fetches, reprojects, publishes the DEM and seeds the project's default input rows, with datum stamped by the source. It also explains that `timed_out` is normal for large areas and that a refusal creates nothing and puts the reason in `say_to_user`.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action, then the prerequisites, then the return shape and failure path — a sensible order with little filler. The return-envelope sentence partially restates what the existing output schema already provides, which costs some tightness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write operation with an output schema, it covers the things an agent still needs: contributor/launch-level key rights, that the import can start AWS Batch, the timeout-as-polling contract, and the refused outcome path. Nothing material is missing for correct invocation or follow-up.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already defines bbox, source, timeout_seconds and poll_interval_seconds. The description still adds meaning: the `key`-from-list_terrain_sources convention and the operational interpretation of timeout as 'returns timed_out, then poll get_terrain', which the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Have Hydrata fetch a terrain from one of its own sources, then wait for the import'. It is clearly distinct from get_terrain (polling/reading an existing import) and from presign_terrain_upload/finalize_terrain_upload (user-supplied DEM), because it emphasizes the source catalog path.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete routing: use a `key` from list_terrain_sources, and when the call returns `timed_out`, keep calling get_terrain(project_id, terrain_id). It also enumerates when the tool won't proceed (bbox over the source size cap, no source data, unknown source). It stops short of explicitly contrasting with the upload flow (presign/finalize), leaving one sibling choice to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_time_seriesCreate a time seriesAInspect
Create a time series (rain gauge, hydrograph, tide/stage) in a project.
POSTs /projects//time-series/ with series_type and units as
top-level fields. series_type is checked against the four choices and
data against the {"rowData": [{timestamp, value}, ...]} shape before any
request is made — the API answers 500 (not 400) to a malformed row.
Returns a compact record — id, name, series_type, units, timezone,
row_count, http_status — not the echoed rows; fetch the full row with the
REST API (GET /projects//time-series//) if you need to round-trip it.
A rainfall polygon references its gauge by the series NAME, so create the
gauges with the exact names the rainfall GeoJSON's features carry.
The units must match the series_type (see units), and a hydrograph or
hyetograph must END at 0 unless hold_last_value is true. The result
carries Hydrata's own summary of the series (peak, volume or depth,
first and last stamp, trailing value): repeat those numbers to the user
(say_to_user does) rather than computing your own.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | The rows: {"rowData": [{"timestamp": "1998-08-17T00:00:00", "value": 1.5}, ...]}. Timestamps ISO 8601 (a trailing Z is tolerated), values numeric. Validated here before anything is sent. | |
| name | Yes | Series name, kept VERBATIM — a rainfall polygon binds to its gauge by this exact name (its `data` property), so use the name the GeoJSON features carry | |
| units | No | Units of the values. REQUIRED for hyetograph ('mm/hr' or 'mm/h'), hydrograph ('m3/s', 'm^3/s' or 'cumec') and stage ('m'): the engine reads those units whatever the label says, so a mismatch is refused before anything is sent. Free for generic. | |
| method | No | One short phrase saying how you got these numbers (e.g. 'read off the council hydrograph PDF', 'scaled the 1% AEP peak'). Shown to the person who reviews the inputs. | |
| source | No | Where the data came from, e.g. a gauge id or agency (optional) | |
| timezone | No | IANA timezone of the timestamps (default 'UTC'), e.g. 'Australia/Sydney' | UTC |
| project_id | Yes | The project ID | |
| description | No | Free-text description (optional) | |
| series_type | No | One of hyetograph (rainfall depth/intensity — the default), hydrograph (flow, read by the Hydrographs panel and inflow boundaries), stage (water level, e.g. a tide) or generic. Sent as a top-level field. | hyetograph |
| location_name | No | Human-readable location of the gauge (optional) | |
| hold_last_value | No | Set true ONLY when the last value is meant to be held after the series ends. A hydrograph or hyetograph whose last value is not 0 is refused (TRAILING_VALUE_HELD) unless this is true: end the series with a 0 row instead, unless holding is really intended. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, idempotentHint=false) it discloses that validation happens client-side before any request, that the API answers 500 rather than 400 to a malformed row, and that the response is a compact record rather than the echoed rows. It also explains the TRAILING_VALUE_HELD refusal path, which is exactly the kind of failure mode an agent needs warned about.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and then ordered by what an agent must know (validation, return shape, naming/units constraints). Dense but every paragraph carries actionable content; the only mild redundancy is describing the returned fields when an output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter, nested-object mutation tool with no enum coverage on series_type, the description supplies the missing choice set, the units-per-type rules, the validation timing and the error behavior. Return values are described even though an output schema exists, leaving no operational gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter semantics the schema alone does not: series_type is checked against four choices, units must be consistent with series_type, and `name` is bound verbatim because rainfall polygons reference gauges by name. The hold_last_value/trailing-zero interaction is also spelled out.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a time series') and enumerates the concrete domain objects it covers (rain gauge, hydrograph, tide/stage), plus where it lives ('in a project'). It does not explicitly contrast with the sibling update_time_series or delete_time_series, so the create-vs-modify boundary is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real usage conditions: units must match series_type, hydrograph/hyetograph must end at 0 unless hold_last_value is true, and gauge names must match the rainfall GeoJSON feature names. It also routes the agent elsewhere for round-tripping ('fetch the full row with the REST API'). It stops short of stating when to use update_time_series instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_observationDelete one flood observationADestructiveIdempotentInspect
Delete one flood observation and its photos (cannot be undone).
DELETEs /projects//flood-observations//observations//; a missing fid is an error (404), not a silent success.
| Name | Required | Description | Default |
|---|---|---|---|
| fid | Yes | The observation's fid | |
| layer_id | Yes | The flood observation layer id | |
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds the non-obvious cascade that associated photos are also destroyed, plus the exact error semantics (404 on a missing fid rather than a silent success). It stops short of mentioning permission requirements or any partial-failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the destructive effect and irreversibility are front-loaded, then the endpoint and error contract follow. No filler and nothing repeated from annotations or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and annotations cover the safety profile. The description closes the remaining gaps (cascade, irreversibility, 404 behavior) for a 3-parameter destructive tool; only auth/permission context is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all three parameters are documented and the baseline is 3. The description adds value by spelling out the resource path template, showing how project_id, layer_id, and fid map into the URL hierarchy and confirming fid identifies a single observation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb (delete) and resource (one flood observation), plus the cascading scope of deleting its photos. It is clearly distinguishable from siblings like update_observation, list_observations, and set_observation_exclusion without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage through the destructive verb and the 'cannot be undone' warning, but it never states when to choose deletion over an alternative such as hiding the observation via set_observation_exclusion. No prerequisites or exclusions are given, so the routing guidance is only implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_time_seriesDelete a time seriesADestructiveIdempotentInspect
Delete a time series (cannot be undone). Needs the Manager role on the project.
A series still used by a feature of an inflow, rainfall or boundary layer is refused (409) and the refusal names the layer and the feature that use it: detach it there (or point that feature at another series), then call again. A series that no feature uses is deleted.
| Name | Required | Description | Default |
|---|---|---|---|
| series_id | Yes | The time series id | |
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint and idempotentHint, and the description adds context the annotations cannot carry: the operation is irreversible, requires the Manager role, and returns a 409 whose message names the blocking layer and feature. That is exactly the authorization and failure-mode detail an agent needs before a destructive call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the destructive nature and the permission requirement, then the refusal workflow. The closing sentence 'A series that no feature uses is deleted' is largely redundant with the preceding 409 explanation, a small amount of waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive two-parameter tool with an output schema and full annotation coverage, the description covers the safety profile, permissions, error semantics and remediation. Nothing an agent needs to invoke it safely and correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for both required parameters (series_id, project_id), so the schema already carries the parameter semantics. The description adds nothing about parameter meaning or format, which is acceptable at full coverage but leaves the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete a time series'), immediately qualified with irreversibility. The resource (time series) is unambiguous against siblings such as delete_observation or update_time_series, so an agent can pick it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit precondition (Manager role) and a concrete failure path: if the series is used by an inflow/rainfall/boundary layer, detach or repoint it and retry. It does not name the specific sibling tools (attach_input_layer / write_input_layer / update_time_series) that accomplish the remediation, so routing still takes one inference step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_input_kindsDescribe the input layer formatsARead-onlyIdempotentInspect
Say what each input layer kind looks like: geometry, properties, allowed values, a minimal example.
Read this BEFORE you build GeoJSON for write_input_layer or an upload. Per kind it
returns the geometry (LineString or Polygon), every property the layer reads with its
type, whether it is required and its allowed values or min/max, the
required_one_of groups (an inflow needs data_constant or data_timeseries_id), notes
in plain words and a minimal example FeatureCollection. It is generated by Hydrata from
the same definitions the build reads, so it is never out of date: do not read source code
or guess column names.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | One kind to describe (boundary, friction, inflow, rainfall, building, mesh_region or culvert); empty describes all seven |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered structurally. The description adds genuine value by disclosing provenance ('generated by Hydrata from the same definitions the build reads, so it is never out of date') and the per-kind return contents. It does not add much beyond that provenance note, so a 3 is appropriate with annotations already carrying the operational traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded: the one-line purpose comes first, then the usage directive, then the return detail. Mostly tight, though 'Per kind it returns' partially restates the opening sentence and the field list is dense; a small trim would make it ideal.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still orients the agent on what comes back (geometry types, property types, required flags, allowed/min-max, required_one_of groups, notes, example). Combined with the provenance guarantee, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema's `kind` description already enumerates the seven values and the empty-string behavior. The description reiterates the per-kind return shape but adds no new meaning about the parameter itself, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Say what each input layer kind looks like') and enumerates the exact payload: geometry, properties, allowed values, minimal example. It is clearly a read-only reference/spec tool, distinguishable from the write siblings (write_input_layer, request_input_upload) it feeds.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Read this BEFORE you build GeoJSON for write_input_layer or an upload', naming the downstream tools, and adds a negative instruction ('do not read source code or guess column names'). Both the when and the alternative paths are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
finalize_terrain_uploadRegister an uploaded terrainAInspect
Step 2 of a terrain import: register the PUT GeoTIFF as a Terrain and start the import.
Needs a launch-level agent key (the import can start AWS Batch); a read or draft key gets 403 AGENT_LEVEL_INSUFFICIENT — the user creates a launch key on the site's Agent keys page (/agents/).
Call this only after the presigned PUT returned 200. Creates the Terrain row
(status creating) and queues the import chain — reproject to UTM, publish
the layer + hillshade, style — which also seeds the project's six default
boundary, friction, inflow, rainfall, building and mesh-region rows.
Returns 202 with the terrain record; keep its id for get_terrain. A 400 UPLOAD_NOT_FOUND
means no object is at staging_key: the PUT did not land (check its status
code and Content-Type) — do not retry finalize until it has.
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | Terrain title (default: the filename without .tif) | |
| process_id | No | `process_id` returned by presign_terrain_upload (pass it so the upload's progress record is reused; the API tolerates its absence) | |
| project_id | Yes | The project ID | |
| staging_key | Yes | `staging_key` returned by presign_terrain_upload | |
| vertical_datum_declared | No | TASK-4061: the datum the user SAYS the heights are on: `ahd` (Australian Height Datum), `orthometric_egm2008` or `ellipsoid`. Pass it only when the user told you; if they did not, ask them, do not guess. Stored as the terrain's declared datum, which beats Hydrata's own inference. Omit when unknown. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read-only, non-idempotent and non-destructive. The description does correctly reinforce the non-idempotent trait by warning against retrying finalize, but most of its length is spent on auth requirements, side effects and error codes rather than on behaviors the annotations leave undisclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The step number and precondition are front-loaded, which is good, but the description runs long and stacks auth details, side effects, response codes and error remediation into dense paragraphs. The parenthetical about checking the PUT's status code and Content-Type is useful but sits inside a block of otherwise ancillary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter mutation that chains into a multi-stage import, it covers preconditions, side effects, auth, the 202 response and the one documented error branch, which is more than adequate alongside the existing output schema. It stops short of naming the alternative path (create_terrain_from_source) for importing terrain from a source rather than an upload.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the schema already defines every parameter, yet the description adds real meaning: staging_key is tied to a concrete failure mode (UPLOAD_NOT_FOUND when no object exists at that key) and the sequencing constraint on when finalize is safe. This makes the schema fields actionable rather than merely documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a specific verb and resource ('register the PUT GeoTIFF as a Terrain and start the import') and places it as 'Step 2 of a terrain import', which cleanly separates it from presign_terrain_upload (step 1) and create_terrain_from_source. An agent can identify this tool and its role in the pipeline without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit precondition ('Call this only after the presigned PUT returned 200') and an explicit prohibition ('do not retry finalize until it has [landed]'), plus the exact failure branch (400 UPLOAD_NOT_FOUND means the PUT did not land). The 'Step 2' framing routes the agent to the preceding sibling in the sequence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_observation_comparisonCompare a run with flood observationsARead-onlyIdempotentInspect
Compare a run with the project's flood observations: how well does it match them?
Returns headline (the figures to tell the user, e.g. "47 observations · 31
within ±0.30 m (66%) · bias -0.12 m · RMSE 0.35 m · 1 excluded"),
headline_numbers (the same as numbers), tolerance_m (used) and
default_tolerance_m (the project's saved one), statistics
(the API's summary: n, within, within_pct, bias_m, rmse_m, weighted_rmse_m, mae_m, max_abs_m,
excluded, not_scored by reason, gauges), gauges (Gauge records: peak error,
timing error, NSE), datum_checks (warn the user only when warning is true:
both datums known and different; not_recorded = the terrain has no
recorded datum, stated in note, not a warning)
and one row per observation: observed_m / modelled_m / residual_m (modelled -
observed, + = model high), within, scored / not_scored_reason, match
(outside_run_window = not this flood), excluded + exclusion {reason, by, at}.
sampling counts how the modelled values were read: centroid (the peak
of the mesh triangle the observation sits in), nearest_node_fallback (an
older run without that peak: the nearest mesh node's value, tell the user)
and nearest_node (just outside the mesh); each row's sample.method says
which.
There is no pass or fail: report the figures. A run that is not historic has
none (has_comparison false) — do not retry it.
| Name | Required | Description | Default |
|---|---|---|---|
| fid | No | With layer_id: the observation's fid (list_observations) | |
| run_id | Yes | The run ID (a historic run; others are not compared with observations) | |
| layer_id | No | With fid: narrow the rows to ONE flood observation and add its history | |
| tolerance | No | Metres within which a residual counts as within (default: the project's saved tolerance, 0.3 unless an Editor changed it; presets 0.15, 0.3, 0.4; above 0 and at most 5). Not stored: it only changes this answer | |
| include_series | No | Keep each Gauge record's modelled stage series (every saved frame); default false |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower, yet the description adds genuine behavioral context: the no-pass/fail reporting stance, the warning semantics of datum_checks, the meaning of sampling fallbacks, and the non-retry rule for non-historic runs. Much of the remainder enumerates return fields that the output schema already carries, so it is not maximally efficient, but the caveats are real value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded well, but the bulk is a dense, backtick-heavy enumeration of every returned field (headline_numbers, statistics sub-fields, per-row columns), much of which overlaps the output schema. Every sentence is accurate, but the volume exceeds what the agent needs given a structured output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex comparison tool with an output schema present, the description covers the applicability constraint (historic runs), the scoring model, edge cases (excluded/not_scored, datum warnings, mesh fallbacks) and the reporting posture. An agent has enough to invoke it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters are already documented in the schema (including tolerance presets and include_series). The description adds only marginal semantics (tolerance as 'used' vs saved default), leaving the baseline of 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Compare a run with the project's flood observations') and even frames the user-facing question it answers ('how well does it match them?'). It is clearly distinguishable from siblings like list_observations or get_run, which merely list data rather than scoring a comparison.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real routing context: 'There is no pass or fail: report the figures' and 'A run that is not historic has none (has_comparison false) — do not retry it,' which tells the agent when the tool is applicable and how to behave on an inapplicable input. It stops short of naming an alternative tool or the set_comparison_tolerance sibling, so it is clear context without explicit alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_projectGet a project and its map linkARead-onlyIdempotentInspect
Get one ANUGA project: id, name, projection, visibility, your role, its base map — and the link to it.
Returns the project record (id, name, projection (EPSG code),
simple_view_config, visibility, owner_username, my_role,
base_map) plus ui_url: the link that opens the project's map, for the
user (<site>/catalogue/#/map/<base_map>; null while a new project's map
is still being created). Scenarios are NOT listed here — use get_scenario
with a scenario id.
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so the safety profile is covered. The description adds real behavioral value beyond that: the exact return shape and the non-obvious edge case that ui_url is null while a new project's map is still being created.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the one-sentence summary of what is returned, then structured detail on fields and the ui_url pattern. Slightly dense, and the field list partly restates what the output schema already exposes, but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description need not spell out return values, yet the added field list, ui_url URL pattern, and null-map edge case make it self-sufficient. Only the lack of sibling differentiation (list_projects) keeps it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is a single required project_id documented in the schema, so the schema carries the parameter burden. The description does not add syntax, format, or constraints for project_id, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Get one ANUGA project') and enumerates exactly which fields belong to the project record versus what does not (scenarios). It clearly distinguishes itself from siblings like list_projects and get_scenario.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly excludes a scope ('Scenarios are NOT listed here — use get_scenario with a scenario id'), which is a genuine when-not plus named alternative. It does not, however, contrast against list_projects or state when fetching a single project is preferable, so it falls short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_runGet a run's full recordARead-onlyIdempotentInspect
Get full details of a simulation run including timing and results.
Returns the complete run record: status, progress, timing (start/end timestamps, duration), compute details (backend, instance type, cost), mesh info, error messages, and result log. Use get_run_status for lightweight polling; use this for final results.
The presigned s3_*_url download links are ELIDED — each is a 6-hour
capability and no tool relays one. The results stay viewable through the
gn_layer_* entries (published WMS layers on the project's map).
sww reports the run's full time series (the raw ANUGA output): state
(available, not_kept, archived or restoring), size_bytes, and a ui_url
to the Results panel where the person downloads it (or requests a restore
of an archived one and is emailed when it is ready). The download link
itself is never returned.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | The run ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnly/idempotent annotations by disclosing that presigned s3_*_url links are elided because they are 6-hour capabilities no tool relays, and by explaining that results remain viewable via gn_layer_* WMS entries. The `sww` block adds state semantics (available/not_kept/archived/restoring), size, and the ui_url download/restore path — exactly the non-obvious behavior an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and sibling routing, then structured paragraphs for downloads and `sww`. The `sww` passage is dense but earns its space by preventing a failed download attempt; slight over-length keeps it off a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an output schema existing, the description supplies the interpretive context the schema cannot: why URLs are absent, what the alternative result-access path is, and what each `sww.state` value implies. Nothing an agent needs to call it correctly or interpret the response is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter (run_id) with 100% schema coverage, so the schema already fully documents it; the description adds no extra constraint or format detail on run_id. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
First sentence names a specific verb and resource ('Get full details of a simulation run') and enumerates the payload: status, progress, timing, compute details, mesh info, errors, result log. It is immediately distinguishable from get_run_status, which is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'Use get_run_status for lightweight polling; use this for final results.' That is a clear when-to-use/when-to-use-the-alternative statement with the selecting condition (polling vs. final results).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_run_statusPoll a run's statusARead-onlyIdempotentInspect
Lightweight status check for a simulation run (fast, <50ms).
Use this for polling instead of get_run. Returns only: id, status,
phase, progress_pct (0-100), eta_seconds, error_message, and
compute_backend.
phase is never empty: it is status, except preparing_inputs while a
computing run has no progress yet (it is downloading its input package
and building the domain — minutes on a big model; this is NOT a stall).
Poll every 5-10 seconds. Terminal states: complete, error, cancelled.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | The run ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description still adds real behavioral context beyond them: sub-50ms latency, the exact projected return fields, phase-vs-status divergence, and the misleading non-stall state. That is genuine disclosure an agent cannot derive from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the fast polling purpose, then the return payload, then the phase nuance, then the cadence. Every sentence carries distinct operational information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still names the fields an agent will see, and it supplies the polling cadence and terminal states needed to drive a poll loop. Nothing required to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single run_id parameter is already fully described in the schema (100% coverage), so the schema does the work. The description adds no syntax or constraint detail for run_id beyond implying it identifies the run. Baseline 3 is correct for a one-param tool with complete schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource and scope: 'Lightweight status check for a simulation run (fast, <50ms).' It also names the sibling it replaces ('instead of get_run'), so an agent can distinguish it from get_run without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing rule ('Use this for polling instead of get_run') plus operational cadence ('Poll every 5-10 seconds') and terminal-state list (complete, error, cancelled) that tells the agent when to stop. The 'preparing_inputs ... is NOT a stall' note preempts a specific misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_scenarioGet a scenario's state, inputs and priceARead-onlyIdempotentInspect
Get a scenario's COMPACT state: its computed_status, inputs, estimate and price.
Returns a compact record, never the raw ~50 KB detail: scenario_id,
computed_status, mesh_triangle_count_estimate and its _breakdown,
latest_run_is_valid, the latest run's run_id, run_status,
error_message, user_message, status_detail and mesh_triangle_count
— plus what the scenario IS and what it will cost: name, description,
project, resolution, duration, the input row ids (terrain,
boundary, friction, inflow, rainfall, building, mesh_region, culvert),
compute_cost_estimate (USD), vcpu_hours_estimate, and
inflow_anchor_mismatch (null unless an inflow series starts after the
model does: the model gets zero flow from that series over the lead-in
gap before its first sample), and
hydrology_check (when Hydrata sends it: for each inflow and rainfall
feature, the series that drives it, its peak and volume, and structured
warnings — repeat those numbers to the user, never your own), and
unbound_series with a say_to_user warning when the project holds a
rainfall or flow series that no inflow or rainfall feature uses (the model
ignores it: tell the user and ask which input it belongs to).
The computed_status field (there is NO status key on a scenario) is
derived from the latest run and will be one of: created, building, built,
queued, computing, processing, complete, error, or cancelled — created
also means no run exists yet. A scenario must be built before it can be
run. latest_run_is_valid is false after any edit since the last build.
unreviewed_inputs lists the inputs written by an agent key that the user
has not reviewed at their current content (kind, layer_id, title,
feature_count, the grant that wrote it, authored_method (the agent's own account of
how it made the input, when it gave one), reopened when an edit undid an
earlier input review): while it is not empty, build and run are refused
UNREVIEWED_INPUTS. Only the user reviews, in the browser — poll this tool
every 30-60 s after giving them the review link.
A non-member reading a public project's scenario gets a reduced record:
the fields the server withholds (the input ids, the price,
inflow_anchor_mismatch) are ABSENT here rather than reported as null —
"withheld" is not "no terrain, no cost" — while the run-state keys,
computed_status among them, read null.
No presigned S3 URL is returned by any read tool (each is a 6-hour
capability): results stay viewable through a run's gn_layer_* WMS
entries — use get_run for the full run record.
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project ID | |
| scenario_id | Yes | The scenario ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds what readOnlyHint/idempotentHint convey: it enumerates computed_status values, explains latest_run_is_valid semantics, discloses the reduced record for non-members (fields ABSENT rather than null, run-state keys null), and states no read tool returns a presigned S3 URL. These are exactly the behaviors an agent cannot infer from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the compact-state framing, and every clause carried content (status enum, withholding, review gating, anchor mismatch). It is still a very long, clause-heavy block — several sentences run past 60 words, which costs some scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description supplies the interpretation the schema cannot: null vs absent under reduced access, what computed_status values imply, and how to relay hydrology_check and unbound_series to the user. Nothing needed to call or interpret it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters are simple ids documented in the schema; the description adds nothing about project_id/scenario_id. Baseline 3 applies when the schema already does the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope ("Get a scenario's COMPACT state") and immediately contrasts it with the raw ~50 KB detail, which together with the explicit pointer to get_run distinguishes it from the sibling tools get_run, list_runs and get_run_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete operating guidance: poll every 30–60 s after handing over the review link, build/run are refused while unreviewed_inputs is non-empty, and "use get_run for the full run record" names the alternative and the condition that selects it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_terrainWait for a terrain importARead-onlyIdempotentInspect
Poll a terrain's import until it is ready (or error), bounded by timeout_seconds.
Returns outcome — exactly one of ready, error, timed_out, not_found
(the project has no terrain yet; an unknown terrain_id is an API 404 error
instead) — plus the last status seen (creating → styling → ready | error)
and phase (that status, or not_found; never empty),
polls, elapsed_seconds and the full terrain record (its gn_layer is
the published elevation dataset pk once ready). An import takes minutes to
tens of minutes (the SAME 32 MB 1 m DEM measured 4.5 min once and 26 min
once — the worker's S3 download speed dominates), so timed_out is normal
and NOT a failure: keep calling with the same arguments while status is
still creating/styling; several calls in a row is expected. error is
terminal — the import failed and no default input rows were seeded; upload
a corrected GeoTIFF as a new terrain.
ready is written by the import task; the project's default input rows
(Boundary 01, Friction 01, Inflow 01, Rainfall 01, Building 01,
MeshRegion 01, one GeoNode layer each) are seeded by the NEXT task in the
chain and appear over the following ~30 s. Poll the input-layer list until
it is non-empty before attaching your own layer to a default row.
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project ID | |
| terrain_id | No | The terrain ID from finalize_terrain_upload. Omit to follow the project's newest terrain. | |
| timeout_seconds | No | How long this call keeps polling before it returns `timed_out` (default 180, ceiling 200 — claude.ai cuts a tool call at 240 s). 0 = one status read, no waiting. | |
| poll_interval_seconds | No | Seconds between polls (default 5) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds the readOnly/idempotent annotations: it enumerates the exact `outcome` values, distinguishes `not_found` (project has no terrain) from an unknown terrain_id (API 404), and discloses realistic durations (4.5–26 min) so the agent can calibrate polling behavior. It also warns that `ready` precedes default input-row seeding by ~30 s.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and outcome enum, then state-machine and failure semantics. Dense but well ordered; the 32 MB DEM timing anecdote and the enumerated default input rows are slightly verbose but serve a real calibration purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description covers the terminal states, the non-obvious `not_found` case, the seeding lag, and retry semantics — everything an agent needs to poll correctly without guessing. Nothing material is missing for a read-only polling tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schemas already document project_id, terrain_id (omit → newest terrain), timeout_seconds ceiling and 0 = single read, and poll_interval. The description reinforces semantics (timeout bounding, same-arguments retry) but adds little the schema does not already say, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb+resource+termination condition: 'Poll a terrain's import until it is `ready` (or `error`), bounded by timeout_seconds.' It is clearly distinct from finalize_terrain_upload (which it implicitly follows) and from generic status tools like get_run_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent that `timed_out` is normal and NOT a failure, to keep calling with the same arguments while status is creating/styling, and that `error` is terminal requiring a re-upload. It also gives the follow-up ritual: poll the input-layer list until non-empty before attaching a layer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_inputsList a project's input layersARead-onlyIdempotentInspect
List every input layer row of a project, per kind, with whether it has features.
For each of boundary, friction, inflow, rainfall, building, mesh_region and culvert:
the rows (row_id, title, gn_layer — the dataset pk — and
dataset_alternate, the workspace:name WFS typename), authored_method
(the one-line account an agent gave of how it made the layer; null when
nobody said) and has_features.
has_features is the API's own answer for every kind. It is null only when
a row's record does not carry it: treat null as unknown, not as empty. A row
with no gn_layer has no layer yet (has_features false). Use the row ids with
create_scenario; this is the listing primitive — no need to probe files.
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the description's real value is the semantics it adds: null in has_features means unknown rather than empty, and a row without gn_layer means no layer yet. That is genuinely non-obvious behavior not recoverable from annotations or schema. It omits any statement about result size or pagination, keeping it below 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded summary sentence followed by a structured per-field breakdown; the parenthetical glosses for gn_layer and dataset_alternate earn their space. Slightly dense, with the one-line-per-kind framing doing most of the work, but there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape needn't be spelled out — yet the description covers the interpretive edge cases (null vs. empty, missing gn_layer) and the intended downstream use with create_scenario. Nothing an agent needs to select and call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema coverage, so the schema already defines project_id. The description adds nothing about the parameter itself (e.g. what happens with an unknown or empty project), so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List every input layer row of a project') plus the exact scope: per kind, with has_features. The enumeration of kinds (boundary, friction, inflow, rainfall, building, mesh_region, culvert) makes it clearly distinct from list_projects, describe_input_kinds and list_terrain_sources without needing the schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use the row ids with create_scenario; this is the listing primitive — no need to probe files', giving both a downstream consumer and a negative instruction that steers the agent away from an alternative approach. It stops short of naming a sibling tool (e.g. describe_input_kinds) as the alternative, so it is not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_observationsList flood observation layers or observationsARead-onlyIdempotentInspect
List a project's flood observation layers, or one layer's observations.
Without layer_id: every layer (layer_id, title, dataset_alternate, vertical_datum,
datum_offset_m, has_features). With layer_id: {layer, count, results} where each
observation carries its fid (the key for update_observation / delete_observation),
subtype + subtype_label, stage/depth, sigma, bound, the observed window in UTC,
datum status (an unknown datum is not scored), photo_count and problems
(fields drawn in the map that fail validation, reported, never fixed).
| Name | Required | Description | Default |
|---|---|---|---|
| layer_id | No | A flood observation layer id; omit to list the project's layers instead | |
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe read-only, idempotent profile. The description adds behavioral context the annotations cannot: an 'unknown' datum is not scored, and 'problems' are validation failures that are reported but never fixed. These are non-obvious semantic traits beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the mode split before the field inventory. The second sentence is dense with a nested parenthetical, but each listed field and clarification earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return fields need not be enumerated, yet the description's semantic annotations (datum scoring rule, never-fixed problems, fid as the mutation key) add genuinely useful context. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description goes further by tying each layer_id state to a distinct result shape and by flagging that the returned `fid` is the key required by update_observation/delete_observation, giving the parameter operational meaning beyond its schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource and immediately splits the two modes (project's layers vs. one layer's observations) governed by layer_id. It also names the downstream siblings (update_observation / delete_observation) whose key is the returned fid, so an agent can distinguish this from those tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly explains the two invocation modes and which parameter selects each ('Without layer_id: ... With layer_id: ...'), giving an agent enough to choose correctly. It stops short of explicit when-not-to-use guidance or naming the create/add observation siblings as alternatives, so it lands just below the top.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_projectsList projectsARead-onlyIdempotentInspect
List ANUGA simulation projects accessible to the authenticated user.
Returns a paginated list of projects with their names, projections, and base map references.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (default 1) | |
| page_size | No | Results per page, max 100 (default 100) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, covering the safety profile. The description usefully adds that results are paginated and scoped to the authenticated user, but discloses nothing about ordering, total counts, or filtering behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences with the scope front-loaded. The second sentence listing returned fields is largely redundant given the tool has an output schema, so it doesn't fully earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a simple paginated list: annotations carry the safety profile, the schema covers both parameters at 100%, and an output schema handles return values. The only gap is the absence of routing guidance versus get_project.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both page and page_size are fully documented in the schema. The description adds no parameter-level meaning beyond that, making the baseline 3 correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb (List) and resource (ANUGA simulation projects) with an explicit scope: 'accessible to the authenticated user.' This cleanly distinguishes it from the singular get_project sibling without needing to name it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the plural 'List' versus the singular get_project. The description never states when to prefer this over get_project for a single lookup, nor any prerequisites or exclusions, so an agent must infer the routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_runsList a project's runsARead-onlyIdempotentInspect
List all simulation runs across all scenarios in a project.
Returns a paginated list of runs. Optionally filter by status
to find active, completed, or failed runs. Each row's presigned
s3_*_url download links are elided (6-hour capabilities).
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (default 1) | |
| page_size | No | Results per page, max 100 (default 100) | |
| project_id | Yes | The project ID | |
| status_filter | No | Filter by status: created, building, built, queued, computing, processing, complete, error, cancelled. Omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description adds real behavioral context beyond them: pagination behavior and the notable fact that presigned s3_*_url download links are elided with a 6-hour capability lifetime. That return-shape caveat is something the agent could not infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action in the first sentence, then adds only three short supporting sentences; no filler. Minor cost is that pagination and status filtering are split across separate short sentences that could compress slightly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be enumerated, and annotations carry the safety profile, so the description is nearly sufficient. The one extra detail it does provide, elided presigned URLs, meaningfully closes the remaining gap between what the schema shows and what a caller actually receives.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with every parameter including the full status_filter value list documented inline, so the schema does the heavy lifting. The description only gestures at status filtering and pagination, adding no syntax or format detail beyond the schema, which is the correct baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with precise scope: 'List all simulation runs across all scenarios in a project.' An agent can immediately distinguish this bulk-list operation from the singular get_run, get_run_status, and the unrelated list_projects/list_inputs siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for use (list a project's runs, optionally narrowed by status) but names no alternative tool or exclusion condition, e.g. it never says to prefer get_run when a single run ID is already known.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_terrain_sourcesList the terrain Hydrata can fetch for a siteARead-onlyIdempotentInspect
List the terrain Hydrata can fetch for a site, finest resolution first.
Ask this BEFORE fetching or uploading your own DEM. Each source row has key,
name, resolution_m, coverage_pct (share of your box it has data for),
cap (state ok | too_large, the area and the maximum, and a plain message
when too large), vertical_datum, credit and licence. Only sources with some
coverage appear: Copernicus GLO-30 (30 m, worldwide) always, and finer regional
LiDAR such as Geoscience Australia 5 m where it has data. Pick one whose cap.state
is ok and pass its key to create_terrain_from_source. Tell the user which source
you chose, its resolution, licence and datum (say_to_user says it for you).
| Name | Required | Description | Default |
|---|---|---|---|
| bbox | Yes | The site as [min_lon, min_lat, max_lon, max_lat] in WGS84 degrees, e.g. [149.105, -35.285, 149.135, -35.255] for Sullivans Creek, Canberra. | |
| project_id | Yes | The project ID (the key needs Contributor rights on it) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, yet the description adds genuine behavior: results are ordered finest-first, only sources with non-zero coverage are returned, Copernicus GLO-30 always appears, and oversized requests are surfaced via cap.state and a plain message. The row-field enumeration overlaps with the output schema, which is the only reason this isn't a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then the ordering constraint, then the workflow instruction — good structure with no filler. The middle enumeration of row fields ('key', 'name', 'resolution_m', ...) is long and partly duplicates the output schema, costing a point.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value detail is optional; the description still supplies what the agent needs to act (which field to pick, what 'coverage_pct' means, how to handle 'too_large'). The only loose end is the mention of `say_to_user`, which is not among the listed sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented there, so the description adds little parameter detail. It only obliquely ties 'your box' to bbox via coverage_pct; no added semantics for project_id or the bbox format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List the terrain sources') plus an ordering guarantee ('finest resolution first'). It is clearly separable from sibling tools that upload terrain (presign_terrain_upload, finalize_terrain_upload) or consume a source key (create_terrain_from_source).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit sequencing guidance: 'Ask this BEFORE fetching or uploading your own DEM' names the alternative path (uploading a DEM) and its preconditions. It also names the downstream tool (create_terrain_from_source) and the selection rule ('Pick one whose cap.state is ok'), leaving no inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_time_seriesList a project's time seriesARead-onlyIdempotentInspect
List a project's time series (rain gauges, hydrographs, tides) — never their rows.
Each series: id, name (a rainfall polygon binds to its gauge by this
exact name), series_type, units, timezone, authored_method (how an
agent made it; null when nobody said), row_count,
first_timestamp and last_timestamp. The data rows themselves are
dropped (a project's list is megabytes); fetch one series with the REST API
(GET /projects//time-series//) if you need its values.
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive; the description goes beyond them by disclosing that row data is dropped and the reason (a project's list is megabytes), which is exactly the behavioral context annotations can't express. It omits pagination/ordering behavior, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the verb, scope, and the row exclusion before the field list; no filler sentences. The field enumeration partly duplicates the existing output schema, which costs it a point, though the semantic notes attached to fields keep it earning its space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with an output schema, the definition is essentially complete — what it returns, what it omits, and where to go for values. Only missing element is ordering/pagination expectations for a potentially large list.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single project_id parameter, so baseline is 3. The description's 'a project's time series' reinforces scoping but adds no format, ID-source, or validation detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List a project's time series') and immediately bounds scope with '— never their rows', heading off the most likely misuse. The parenthetical examples (rain gauges, hydrographs, tides) make the resource concrete, and it is clearly separable from create/update/delete_time_series siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when not to expect values and names an alternative path ('fetch one series with the REST API (GET /projects/<id>/time-series/<id>/)'). It does not distinguish itself from nearby siblings such as get_project or list_inputs, so the routing advice is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
presign_terrain_uploadGet a terrain upload URLAInspect
Step 1 of a terrain import: get a presigned S3 PUT URL for a GeoTIFF DEM.
Only for a client that has a shell and an agent key AND a DEM no platform source covers. A connector agent with no shell (claude.ai) uses list_terrain_sources then create_terrain_from_source instead, or asks the user to upload their own DEM in the map.
The import needs a launch-level agent key: a draft key can presign, but finalize_terrain_upload (and the multipart fallback below) answer a read or draft key 403 AGENT_LEVEL_INSUFFICIENT — check the key before moving bytes.
The agent moves the bytes itself — no tool accepts file contents. After this
call, PUT the file straight to upload_url, sending the SAME Content-Type
you passed here (it is part of the signature; a mismatch is a 403
SignatureDoesNotMatch before it is anything else):
curl -sS -X PUT -H "Content-Type: image/tiff" --upload-file /path/dem.tif "$UPLOAD_URL"then call finalize_terrain_upload with the returned staging_key and
process_id. Nothing exists in Hydrata until finalize; the URL expires after
expires_in seconds (3600).
Platform guidance: keep the terrain extent within 5° across and 40,000 km²
(200 × 200 km). The API enforces that cap on its bbox-fetch path; an
uploaded GeoTIFF is only rejected above 5 GiB, but a larger DEM will not
mesh or run well. The GeoTIFF must carry a CRS; the import reprojects it to
the site's UTM zone and builds a hillshade. Fallback when a presigned PUT is
impossible: multipart-POST the file with the same agent key to
/api/v2/anuga/projects//terrain/upload/ (form field file, optional
title), which creates the terrain in one step — then get_terrain.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | File size in bytes (`stat -c %s <file>`). The API rejects > 5 GiB up front. Omit if unknown. | |
| filename | Yes | Base name of the GeoTIFF, e.g. 'dem.tif' (a name only — never contents) | |
| project_id | Yes | The project ID | |
| content_type | No | MIME type the PUT will send (default 'image/tiff'). It is SIGNED into the URL, so the PUT must send exactly this Content-Type header. | image/tiff |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are thin (readOnlyHint=false, destructiveHint=false), so the description carries real weight and delivers: nothing exists in Hydrata until finalize, the URL expires after 3600s, the Content-Type is signed and a mismatch yields 403 SignatureDoesNotMatch, and draft keys get 403 AGENT_LEVEL_INSUFFICIENT on finalize. It also discloses size cap (5 GiB) and CRS/reprojection behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose and the routing decision, then sequences prerequisites, the curl example, and the fallback — a logical flow. It is long, and the platform extent guidance (5°/40,000 km²) and multipart fallback run past the immediate call, but each remains actionable context rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-step upload handshake with an output schema already covering return values, the description supplies everything an agent needs to call correctly: prerequisites, exact PUT semantics, the follow-up call with staging_key and process_id, and the escalation path when the key is insufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning beyond the schema — that content_type is SIGNED into the URL and must be echoed verbatim on the PUT, and that size must be a byte count with a 5 GiB rejection threshold. It does not add much on project_id or filename that the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('get a presigned S3 PUT URL for a GeoTIFF DEM') and situates it as step 1 of a multi-step import that continues in finalize_terrain_upload. It explicitly names the sibling alternatives (list_terrain_sources, create_terrain_from_source) so an agent can distinguish it without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use ('a client that has a shell and an agent key AND a DEM no platform source covers') and when-not ('a connector agent with no shell (claude.ai) uses list_terrain_sources then create_terrain_from_source instead'). It also names a fallback path (multipart POST) for cases where presigned PUT is impossible, and states the key-level prerequisite.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
request_input_uploadGet a browser upload link for a big input layerARead-onlyIdempotentInspect
Get the link where the PERSON uploads a big input layer in their browser.
For a layer too big to send with write_input_layer (over about 150 KB):
building footprints, land-use friction. You cannot move file bytes, so give
the person ui_url. It opens the project's upload page for this kind; they
drop a GeoJSON, a zipped shapefile or a GeoPackage (up to 100 MB), Hydrata
converts it into the project's grid and attaches it to the kind's layer,
replacing what it held. Nothing is created until they drop a file.
A file the person drops is their own input: it is marked 'uploaded by the
user' and needs no review step. Afterwards call list_inputs: the layer is
there with that authored_method. A file of the wrong kind (polygons on an
inflow) is refused on the page with a plain message. The person needs Editor
access on the project.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | Which input the file is for: boundary, friction, inflow, rainfall, building, mesh_region or culvert ('structure' is a deprecated alias of building). | |
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint/idempotent/non-destructive, and the description explains why: nothing is created until the person drops a file. It adds behavior beyond the annotations — accepted formats, 100 MB cap, conversion into the project grid, replacement of existing layer content, 'uploaded by user' authored_method, no review step, and wrong-kind rejection at the page.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core instruction (get the link, give the person ui_url) is front-loaded and followed by consequences and follow-up steps in a logical order. Slightly long, with the 'building footprints, land-use friction' examples and 'you cannot move file bytes' restating the size rationale, but every sentence carries usable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Two required parameters, an output schema, and full annotation coverage — and the description still supplies the operational picture (what the human does, size/format limits, permission requirement, post-call verification via list_inputs). Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the enum-free kind field is already documented, but the description adds meaning: kind selects which layer is replaced, and a file of the wrong kind (polygons on an inflow) is refused. project_id gains only the Editor-access context, which is marginal but useful.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (get the browser upload link for a big input layer) and immediately scopes it against the sibling write_input_layer by size threshold. An agent can tell exactly what this returns and when it is the right tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: use this for layers too big to send with write_input_layer (over about 150 KB), because the agent cannot move file bytes. It also names the follow-up step (call list_inputs) and the prerequisite (Editor access), leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retry_runRetry a failed runAInspect
Retry a failed simulation run.
Needs a launch-level agent key (a retry rebuilds the package and can start AWS Batch); a read or draft key gets 403 AGENT_LEVEL_INSUFFICIENT.
Starts a fresh package build of the run's scenario as a NEW run, which
becomes the scenario's latest run. The errored run keeps its status and
error as history, and the response describes that old run; the new run's
ID is get_scenario's run_id. Only valid when status is 'error'. Returns
409 for any other state.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | The run ID to retry |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, the description discloses important side effects: a new package build is triggered, AWS Batch may be started, a new run becomes the scenario's latest run, and the old errored run is preserved as history. It also flags a non-obvious response quirk: the response describes the old run while the new run ID must be read from get_scenario's run_id. This is exactly the kind of context annotations cannot provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core action, then immediately covers authorization, side effects, response semantics, and state validation. Each sentence carries useful information, and the surprising response behavior is called out clearly without excess.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description adds necessary operational context: auth requirements, valid state, side effects on scenario history, and how to obtain the new run ID. Nothing an agent needs in order to invoke this tool correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is only one parameter, and schema coverage is 100%, so the schema already explains run_id as 'The run ID to retry.' The description reinforces that only errored runs are valid targets, but it adds little parameter-level syntax or format beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Retry a failed simulation run.' It goes further to distinguish the operation from a plain re-run by stating it starts a fresh package build as a NEW run while preserving the errored run as history. This clearly separates it from siblings like start_simulation and get_run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states explicit preconditions: a launch-level agent key is required, and a read or draft key returns 403 AGENT_LEVEL_INSUFFICIENT. It also says the tool is only valid when status is 'error' and returns 409 otherwise, which is exactly the when-to-use guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_comparison_toleranceSave a project's default comparison toleranceAIdempotentInspect
Save a project's default tolerance for comparing runs with flood observations.
Needs Editor (or above). Every later get_observation_comparison (and the map's
Compare with observations tab) uses it unless a tolerance is passed. Only
save it when the user asks to change the project's default; to show the
figures at another tolerance, pass tolerance to get_observation_comparison.
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project ID | |
| tolerance_m | Yes | The project's default tolerance in metres (above 0 and at most 5; presets 0.15, 0.3, 0.4) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-destructive, idempotent write, but the description adds genuinely new behavioral context: the Editor-or-above permission requirement and the persistent downstream effect on every later get_observation_comparison call and the map's Compare with observations tab. It doesn't discuss overwrite semantics or validation failure behavior, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action, then prerequisites, then the routing rule. Every sentence earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description covers purpose, permissions, persistence effect, and alternative routing. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both parameters (project_id, tolerance_m) fully documented including the metres range and presets, so the schema carries the load. The description adds no parameter-level detail beyond what the schema provides, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (save/set) and resource (project's default comparison tolerance for comparing runs with flood observations), and explicitly distinguishes it from get_observation_comparison, which reads figures rather than persisting a default. An agent can tell exactly what this does without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when ('only save it when the user asks to change the project's default') and when-not, plus the alternative ('to show the figures at another tolerance, pass `tolerance` to get_observation_comparison'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_observation_exclusionExclude or include a flood observation in a run's comparisonAIdempotentInspect
Exclude a flood observation from ONE run's comparison with observations, or include it again.
Needs Editor (or above) on the project. The exclusion is logged with the user
and reason (nothing is overwritten) and keyed on (run, layer, fid), so it
survives a recompute. The figures change at once: headline_after is the
run's headline with the change applied. To exclude, the user must give the
reason: if they have not, ASK them; do not make one up.
| Name | Required | Description | Default |
|---|---|---|---|
| fid | Yes | The observation's fid | |
| reason | No | WHY the engineer excludes it, in their words (required to exclude; never invent one — ask the user). Optional when including it again | |
| run_id | Yes | The run ID (a historic run) | |
| excluded | No | true to exclude (default), false to include it again | |
| layer_id | Yes | The flood observation layer id |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=false, idempotentHint=true, and the description adds real substance beyond them: the exclusion is logged with user and reason, nothing is overwritten, it is keyed on (run, layer, fid) so it survives a recompute, and figures update immediately via headline_after. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then permissions, durability, and the reason requirement in a logical order. Every sentence carries information, though the reason rule is restated in both description and schema, which is slightly redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a stateful toggle tool with an output schema, the description covers permissions, idempotency/durability semantics, and the immediate-figure-change behavior (headline_after). Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all five parameters including the reason-required-to-exclude rule. The description reinforces that rule but adds little syntax or format detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Exclude a flood observation from ONE run's comparison... or include it again'), clearly a toggle keyed to a single run. This distinguishes it from siblings like get_observation_comparison and set_comparison_tolerance without opening their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear operational context: Editor (or above) permission is required, and it must be keyed to one run. It also instructs the agent to ASK the user for a reason rather than invent one, which is strong guidance. It lacks explicit when-not-to-use vs siblings, so 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_simulationStart a simulation run (spends compute)AInspect
Start a flood simulation run for a built scenario.
Needs a launch-level agent key (a run spends compute); a read or draft key gets 403 AGENT_LEVEL_INSUFFICIENT — the user creates a launch key on the site's Agent keys page (/agents/).
The scenario must be in 'built' status. Returns 202 with the new run. The run transitions through: built → queued → computing → processing → complete.
After starting, poll get_run_status to track progress. Returns 409
if the scenario is not in the correct state. The returned run record has
its presigned s3_*_url links elided (6-hour capabilities).
INPUT REVIEW (Hydrata enforces it): while an input you wrote is not reviewed by
the user, the run is not started - outcome unreviewed_inputs,
error_code UNREVIEWED_INPUTS, a ui_url to the scenario's review screen.
A run built from inputs other than the ones reviewed now answers
outcome run_invalidated (RUN_INVALIDATED): build_scenario with
rebuild=true, then start it again.
SPEND CONSENT (Hydrata enforces it; you cannot): a run whose quote does not
fit your agent key's monthly spend limit (default $0), or that Hydrata
cannot price, is NOT started. The result is then a normal (non-error)
answer with outcome consent_required, error_code CONSENT_REQUIRED,
quoted_cost_usd and consent_url: give the user the link and the price
(say_to_user). Only they can approve, in their browser. Then do NOT call
start_simulation again for this run: poll get_run_status(run_id) — the run
leaves built once they press the button. (With consent_timeout_seconds > 0
this call polls the run itself and answers outcome consented, with the
run, if they approve within that time.)
| Name | Required | Description | Default |
|---|---|---|---|
| scenario_id | Yes | The scenario ID to run | |
| poll_interval_seconds | No | Seconds between consent polls (default 5) | |
| consent_timeout_seconds | No | When the run needs the person's consent (CONSENT_REQUIRED), how long this call keeps polling the run for their click before it returns (ceiling 200). Default 0: return the consent link at once, so you can give it to them — they cannot press a button they have not been shown. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the annotations: names the required key level and the 403 AGENT_LEVEL_INSUFFICIENT failure, the 202 response, the built→queued→computing→processing→complete lifecycle, the 409 state error, and that presigned s3_*_url links are elided (6-hour capabilities). It also discloses two enforced gates (input review, spend consent) with their outcome/error codes and the fact that the 2023 non-idempotent call must not be repeated — consistent with idempotentHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, prerequisite and the post-start polling instruction; the two enforcement sections are labelled in caps so they are scannable. It is long (~350 words) and a few clauses about error codes could be tightened, but nearly every sentence carries operational information an agent would otherwise get wrong.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a non-idempotent, compute-spending, gated mutation, the description covers auth, preconditions, response timing, lifecycle, all meaningful failure outcomes and the required recovery path. With an output schema present it correctly avoids re-documenting the run record while still flagging the elided presigned links.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema does not: with consent_timeout_seconds > 0 the call polls internally and answers outcome 'consented', tying the parameter to a distinct response shape. scenario_id itself is only echoed ('must be in built status'), which the schema already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Start a flood simulation run for a built scenario') with the exact prerequisite state, and the final sentences distinguish it from the siblings an agent might confuse it with (build_scenario for rebuilds, get_run_status for polling). An agent can identify the operation and its boundary conditions without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: poll get_run_status after starting, rebuild with build_scenario(rebuild=true) when a run is invalidated, and — critically — do NOT call start_simulation again after a CONSENT_REQUIRED result, poll instead. That is a real when-not-to-call rule with a named alternative, not just implied usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_capabilityTell the Hydrata team about a capability that is missingARead-onlyInspect
Tell the Hydrata team about something the person asked for that NO existing tool can do.
Use it only when you have checked the other tools and none can do what the person asked
(never to report a bug, and never instead of a tool that can do it). Describe the need, not a
workaround; send no personal data, keys or file contents. It changes none of the person's data.
The reply tells you what to say: relay say_to_user to the person as it is. Limit: 20 a day
per person.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | What they were trying to achieve with it (optional) | |
| what | Yes | What the person asked for that no tool can do, in one or two plain sentences |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations it discloses a concrete rate limit (20 per day per person), a data-handling constraint (no personal data, keys or file contents), and a follow-up contract (relay `say_to_user` verbatim). The statement that it changes none of the person's data is consistent with readOnlyHint=true and destructiveHint=false rather than a restatement of them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Usage constraints are front-loaded and each sentence carries a distinct rule (precondition, exclusions, content rules, effect, reply handling, quota). Slightly dense with stacked parentheticals, and 'changes none of the person's data' partly overlaps the readOnly annotation, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, yet the description still tells the agent what to do with the reply (`say_to_user`). For a 2-parameter escalation tool, nothing needed to call it correctly or handle its result is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both fields are already documented, but the description still adds guidance the schema lacks: describe the need rather than a workaround, and never include personal data, keys or file contents. The required `what` field gets one/two-plain-sentences style guidance from the schema rather than the description, which keeps this just under a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource — reporting a missing capability to the Hydrata team — and the 'NO existing tool can do' framing immediately separates it from every CRUD/simulation sibling in the list. An agent can identify this as the escalation/feedback channel without inspecting the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit precondition ('only when you have checked the other tools and none can do what the person asked') plus two explicit exclusions: never for bugs, and never as a substitute for a tool that already can do it. That is a complete when/when-not rule set with no inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_observationEdit one flood observationAIdempotentInspect
Edit one flood observation (PATCH; only the fields given change).
The API checks the stored observation merged with changes and refuses
(400, every bad field named) rather than store a half-valid one. Photos are
not fields: attach a link with add_observation_photo_link.
| Name | Required | Description | Default |
|---|---|---|---|
| fid | Yes | The observation's fid (from list_observations / add_observations) | |
| changes | Yes | Only the fields to change, in the add_observations write shape (e.g. {"stage_m": 2.5} or a new geometry); validated by the API against the stored observation (a flood_mark or dry_point must keep a date window or a flood_name) | |
| layer_id | Yes | The flood observation layer id | |
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only carry the safety profile (readOnly=false, idempotent=true, destructive=false, openWorld=false); the description adds genuinely new behavior: PATCH merge semantics, atomic validation against the stored observation, the 400 failure mode with all bad fields named, and the explicit exclusion of photos. This tells an agent what happens on failure and why no half-valid state is stored.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and mutation mode are front-loaded in the first clause, followed by the two details an agent actually needs (validation failure behavior, photo routing). Slightly prose-heavy wrapping but every sentence carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter mutation tool with an output schema and full annotation coverage, the description supplies the missing pieces: idempotent partial-update semantics, validation/refusal behavior, and where photo attachments belong. Nothing needed to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description reinforces the meaning of 'changes' as a merge patch (only supplied fields change, merged with the stored record) and explicitly scopes photos out of the field set, which is not stated in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Edit one flood observation') and immediately qualifies it as PATCH-style partial mutation, which cleanly separates it from add_observations, delete_observation, and add_observation_photo_link in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the operative rule (only fields given change) and routes photos to add_observation_photo_link, which is real alternative-selection guidance. It stops short of stating when a partial edit is preferred over delete+re-add, so it is clear context without explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_time_seriesCorrect a time seriesAIdempotentInspect
Correct a time series you created (PATCH; only the fields you pass change).
Use it to fix a series instead of leaving a wrong one behind. The same
rules as create_time_series apply to new rows (units match the type, a
hydrograph or hyetograph ends at 0 unless hold_last_value, at least 2
rows, no negative rain or flow, not all zero) and Hydrata refuses with the
reason in plain words. A series already used by a built scenario changes the
scenario: it needs a rebuild and the user reviews it again. Returns a compact
record, not the rows.
| Name | Required | Description | Default |
|---|---|---|---|
| data | No | Replacement rows: {"rowData": [{"timestamp": "<ISO 8601>", "value": <number>}, ...]}. Validated here before anything is sent; Hydrata refuses fewer than 2 rows, negative rain or flow values and an all-zero rain or flow series. | |
| name | No | New name (a rainfall polygon binds to its gauge by this exact name) | |
| units | No | New units (must match the series_type, as in create_time_series) | |
| method | No | One short phrase saying how you got the new numbers. Replaces the earlier account. | |
| series_id | Yes | The time series id (from list_time_series or create_time_series) | |
| project_id | Yes | The project ID | |
| description | No | New description | |
| series_type | No | New series_type: hyetograph, hydrograph, stage or generic | |
| hold_last_value | No | Set true only when the last value is meant to be held |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations: discloses that only passed fields change, that Hydrata rejects requests with plain-language reasons, and — critically — that correcting a series already used by a built scenario forces a rebuild and user re-review. That downstream consequence is exactly the kind of side effect annotations cannot express. It also notes the return is a compact record rather than rows.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the verb and the PATCH contract in the first clause, then layers validation rules, then the scenario consequence in order of increasing risk. No sentence is padding; the density is appropriate for a nine-parameter mutation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the operation semantics, validation behavior, failure modes, and the cross-tool side effect on built scenarios, which is the main risk an agent needs to know before calling. An output schema exists, and the description still usefully clarifies the return shape is a compact record rather than the rows.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3 and the schema already documents every parameter including the rowData shape and validation limits. The description adds the conditional rule that a hydrograph or hyetograph must end at 0 unless hold_last_value, but that constraint already appears in the parameter docs, so it is mostly reinforcing rather than new.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Correct a time series you created') and immediately distinguishes the operation as a PATCH with partial-update semantics. An agent can tell it apart from create_time_series and delete_time_series without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use it to fix a series instead of leaving a wrong one behind' gives a clear trigger condition, and the explicit cross-reference to create_time_series rules tells the agent what validation contract applies. It does not, however, state when to prefer delete_time_series plus recreate over a correction, so the alternative path is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
write_input_layerWrite a project input layer from GeoJSONAInspect
Write a project input layer (boundary, friction, inflow, rainfall, building, mesh_region or culvert) from GeoJSON you send in this call.
No file, no key, no upload: the features go in features. Hydrata
converts them into the project's grid and puts them in the project's
default layer of that kind, replacing what it held (the old layer is kept,
unlinked). Unlike attach_input_layer there is nothing to poll.
Every feature must be the kind's geometry (lines for boundary, inflow and culvert; polygons for friction, rainfall, building and mesh_region); a feature of another geometry refuses the whole write and nothing changes. A culvert is one two-point line per culvert, Inlet first, then Outlet; its attributes are the culvert fields (name, shape, width_m, ... see the culvert guidance), nothing is renamed for you.
Limit: about 150 KB of GeoJSON (a few thousand vertices). A bigger layer is refused before anything is sent: ask the person to upload it in their browser with a request_input_upload link instead.
The layer is marked as written by your agent key and is UNREVIEWED until the user reviews it in their browser. INFLOWS: never invent an inflow location; take it from the study's files or give the user the ui_url to draw it.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | Which input this is: boundary, friction, inflow, rainfall, building, mesh_region or culvert ('structure' is a deprecated alias of building). | |
| method | No | One short phrase saying how you made these features (e.g. 'traced from the council PDF', 'digitised from the survey CSV'). Shown to the person who reviews the layer. | |
| features | Yes | A GeoJSON FeatureCollection with every feature of this kind. Coordinates are read as EPSG:4326 (lon/lat) unless the collection declares a `crs` member; Hydrata converts them into the project's grid. Multi* geometries are split into single ones. | |
| project_id | Yes | The project ID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: says the existing default layer is replaced but kept and unlinked, that a geometry mismatch refuses the entire write atomically, the ~150 KB pre-flight limit, that the layer is attributed to the agent key and is UNREVIEWED until browser review. These are precisely the side-effect and state details the hints (destructive=false, idempotent=false) cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The payload, the replace behavior and the size limit are front-loaded, with the safety-critical inflow warning last. Dense but a couple of clauses ('No file, no key, no upload') restate the same idea the preceding sentence already made.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no prose. For a write tool with a nested GeoJSON payload, the description covers validation failure modes, size ceiling, coordinate assumption, review state and the escalation path — everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns more by adding per-kind geometry constraints (lines for boundary/inflow/culvert, polygons for friction/rainfall/building/mesh_region) and culvert structure (one two-point line, Inlet then Outlet) that the schema's FeatureCollection description does not state. The `method` parameter is only covered in the schema, not the prose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb (write) and resource (project input layer) and enumerates the seven kinds it accepts. It is immediately distinguishable from siblings attach_input_layer and request_input_upload, which are named in the text.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes away from attach_input_layer ('nothing to poll') and instructs the agent to use request_input_upload plus a browser upload when the payload exceeds ~150 KB. Also gives an exclusion for inflows ('never invent an inflow location'), which is a when-not rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
15 tool updates
v0.2.0- Changed
attach_input_layer2 fields changed- changed
Input schema / properties / timeout_seconds / defaultPrevious value: -240New value: +180 - changed
Input schema / properties / timeout_seconds / descriptionPrevious value: -"How long this call keeps polling the upload before it returns `timed_out` (default 240, ceiling 280 — the prod /mcp/ proxy cuts a call at 300 s). 0 = one status read, no waiting."New value: +"How long this call keeps polling the upload before it returns `timed_out` (default 180, ceiling 200 — claude.ai cuts a tool call at 240 s). 0 = one status read, no waiting."
- Changed
build_scenario2 fields changed- changed
Input schema / properties / timeout_seconds / defaultPrevious value: -240New value: +180 - changed
Input schema / properties / timeout_seconds / descriptionPrevious value: -"How long this call keeps polling before it returns `timed_out` (default 240, ceiling 280 — the prod /mcp/ proxy cuts a call at 300 s). 0 = one status read, no waiting."New value: +"How long this call keeps polling before it returns `timed_out` (default 180, ceiling 200 — claude.ai cuts a tool call at 240 s). 0 = one status read, no waiting."
- Changed
create_observation_layer1 field changed- changed
Input schema / properties / timeout_seconds / descriptionPrevious value: -"How long to wait for the map layer (clamped to 280)"New value: +"How long to wait for the map layer (clamped to 200)"
- Added
create_terrain_from_source - Changed
create_time_series1 field changed- added
Input schema / properties / methodAdded value: +{ + "default": "", + "description": "One short phrase saying how you got these numbers (e.g. 'read off the council hydrograph PDF', 'scaled the 1% AEP peak'). Shown to the person who reviews the inputs.", + "type": "string" +}
- Added
delete_time_series - Added
describe_input_kinds - Changed
finalize_terrain_upload1 field changed- added
Input schema / properties / vertical_datum_declaredAdded value: +{ + "default": "", + "description": "TASK-4061: the datum the user SAYS the heights are on: `ahd` (Australian Height Datum), `orthometric_egm2008` or `ellipsoid`. Pass it only when the user told you; if they did not, ask them, do not guess. Stored as the terrain's declared datum, which beats Hydrata's own inference. Omit when unknown.", + "type": "string" +}
- Changed
get_terrain2 fields changed- changed
Input schema / properties / timeout_seconds / defaultPrevious value: -240New value: +180 - changed
Input schema / properties / timeout_seconds / descriptionPrevious value: -"How long this call keeps polling before it returns `timed_out` (default 240, ceiling 280 — the prod /mcp/ proxy cuts a call at 300 s). 0 = one status read, no waiting."New value: +"How long this call keeps polling before it returns `timed_out` (default 180, ceiling 200 — claude.ai cuts a tool call at 240 s). 0 = one status read, no waiting."
- Added
list_terrain_sources - Added
request_input_upload - Changed
start_simulation2 fields changed- removed
Input schema / properties / compute_backendRemoved value: -{ - "default": "local", - "description": "Compute backend: 'local' (Celery), 'ec2' (dedicated instance), or 'batch' (AWS Batch spot, cheapest). Default: 'local'", - "type": "string" -} - changed
Input schema / properties / consent_timeout_seconds / descriptionPrevious value: -"When the run needs the person's consent (CONSENT_REQUIRED), how long this call keeps polling the run for their click before it returns (ceiling 280). Default 0: return the consent link at once, so you can give it to them — they cannot press a button they have not been shown."New value: +"When the run needs the person's consent (CONSENT_REQUIRED), how long this call keeps polling the run for their click before it returns (ceiling 200). Default 0: return the consent link at once, so you can give it to them — they cannot press a button they have not been shown."
- Added
suggest_capability - Added
update_time_series - Added
write_input_layer
28 tool updates
v0.2.1- First observed
add_observation_photo_link - First observed
add_observations - First observed
attach_input_layer - First observed
build_scenario - First observed
cancel_run - First observed
create_observation_layer - First observed
create_project - First observed
create_scenario - First observed
create_time_series - First observed
delete_observation - First observed
finalize_terrain_upload - First observed
get_observation_comparison - First observed
get_project - First observed
get_run - First observed
get_run_status - First observed
get_scenario - First observed
get_terrain - First observed
list_inputs - First observed
list_observations - First observed
list_projects - First observed
list_runs - First observed
list_time_series - First observed
presign_terrain_upload - First observed
retry_run - First observed
set_comparison_tolerance - First observed
set_observation_exclusion - First observed
start_simulation - First observed
update_observation
TDQS
Scored across 36 tools
Most tools target a distinct resource+action (runs vs scenarios vs observations vs time series), and the descriptions give explicit decision guidance. The main overlap is the trio write_input_layer / attach_input_layer / request_input_upload, which all create input layers but are differentiated by client capability and file size. get_run vs get_run_status vs list_runs are clearly delineated by weight and purpose.
Names are uniformly snake_case and follow a verb_noun pattern (create_project, list_runs, update_observation, delete_time_series). Even the less common ones like presign_terrain_upload and set_comparison_tolerance fit the verb-first convention. No mixing of camelCase or inconsistent verb styles.
36 tools is heavy and above the comfortable 3-15 range, requiring the agent to hold a large mental map. However, the ANUGA domain genuinely spans many sub-resources (projects, terrain, inputs, scenarios, runs, observations, comparisons), and each tool appears to serve a real need rather than being redundant. It sits at the borderline of warranted but unwieldy.
The surface covers CRUD across nearly every domain entity: projects, scenarios, runs, time series, observations, terrain imports, and input layers, plus comparison and tolerance tools. Minor gaps exist — no delete_project, delete_scenario, or delete_run — but these are non-essential and agents can work around them. Overall a very thorough lifecycle representation.
Maintenance
Related MCP Connectors
Run AI models, create deployments, and manage predictions via cloud API
Create, deploy and inspect Eurobase projects and Functions in the European cloud.
Flood MCP — wraps Open-Meteo Flood API (free, no auth)
Manage Pipefork API projects, drafts, connections, secrets, and deployments through MCP.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables querying HEC-RAS project information, geometry elements, plan results, and compute messages through natural language, allowing interaction with hydraulic modeling projects.34 PyPI16MIT

SWATGenX MCP Serverofficial
AlicenseNot gradedqualityCmaintenanceEnables search and retrieval of calibrated SWAT+ watershed models, national groundwater lithology and PFAS inventories, plus API-key-secured ordering and downloading of custom watershed models.1MIT- AlicenseNot gradedqualityCmaintenanceEnables Claude to drive HEC-RAS headless — inspecting projects, validating and executing 1D steady, 1D unsteady and 2D plans, and reading hydraulic results from HDF5 files. It also supports limited model modification, such as setting steady discharges, all without the Windows desktop application or a programmatic API.MIT
- AlicenseAqualityCmaintenanceEnables headless control of DHI MIKE Zero, including launching and batch-running simulations, monitoring job progress and logs, and reading/plotting simulation results from DFS and RES1D files.15MIT