{
  "data": {
    "tool": {
      "category": "infrastructure",
      "endpoint": "https://hydrata.com/mcp/",
      "jsonUrl": "https://www.anchorterminal.com/api/v1/tools/hydrata-mcp-server.json",
      "kind": "mcp",
      "listed": "indexed",
      "liveUrl": "https://www.anchorterminal.com/api/v1/live/hydrata-mcp-server.json",
      "markdownUrl": "https://www.anchorterminal.com/tools/hydrata-mcp-server.md",
      "mcpTools": {
        "check": {
          "checker": "anchor-check/1.0",
          "totalTokens": 6814,
          "counts": {
            "error": 0,
            "note": 0,
            "warn": 19
          },
          "findings": [
            {
              "rule": "TC07",
              "severity": "warn",
              "tool": "build_scenario",
              "message": "the description is about 812 tokens",
              "fix": "Keep the description to what a model needs to choose and call the tool; move the manual to a resource or the docs."
            },
            {
              "rule": "TC13",
              "severity": "warn",
              "tool": "create_time_series",
              "message": "data (object with no properties)",
              "fix": "Declare the properties (or additionalProperties with a schema) and the array's items."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "attach_input_layer",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "build_scenario",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "cancel_run",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "create_project",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "create_scenario",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "create_time_series",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "finalize_terrain_upload",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "get_project",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "get_run",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "get_run_status",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "get_scenario",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "get_terrain",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"get\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "list_projects",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "list_runs",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Its name starts with \"list\"; if it only reads, set readOnlyHint: true so harnesses can run it without asking."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "presign_terrain_upload",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "retry_run",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            },
            {
              "rule": "TC16",
              "severity": "warn",
              "tool": "start_simulation",
              "message": "no readOnlyHint or destructiveHint",
              "fix": "Set readOnlyHint: true if it only reads; otherwise set destructiveHint and idempotentHint."
            }
          ]
        },
        "checkedAt": "2026-10-04T22:23:04Z",
        "count": 17,
        "schemaTokens": 6814,
        "status": "ok",
        "tools": [
          {
            "name": "list_projects",
            "title": "List Projects",
            "description": "List ANUGA simulation projects accessible to the authenticated user.\n\nReturns a paginated list of projects with their names, projections,\nand base map references.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "page": {
                  "default": 1,
                  "description": "Page number (default 1)",
                  "type": "integer"
                },
                "page_size": {
                  "default": 100,
                  "description": "Results per page, max 100 (default 100)",
                  "type": "integer"
                }
              },
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "get_project",
            "title": "Get Project",
            "description": "Get details of a specific ANUGA project including its scenarios.\n\nReturns the project name, projection (EPSG code), base map ID,\nand configuration.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                }
              },
              "required": [
                "project_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "get_scenario",
            "title": "Get Scenario",
            "description": "Get scenario details including its `computed_status` and latest run.\n\nThe `computed_status` field (there is NO `status` key on a scenario) is\nderived from the latest run and will be one of: created, building, built,\nqueued, computing, processing, complete, error, or cancelled — `created`\nalso means no run exists yet. A scenario must be `built` before it can be\nrun. The detail also carries `mesh_triangle_count_estimate` (+ its\n`_breakdown`) and `latest_run_is_valid` (false after any edit since the\nlast build). A non-member reading a public project's scenario gets a\nreduced record with no `computed_status`.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "scenario_id": {
                  "description": "The scenario ID",
                  "type": "integer"
                }
              },
              "required": [
                "project_id",
                "scenario_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "start_simulation",
            "title": "Start Simulation",
            "description": "Start a flood simulation run for a built scenario.\n\nThe scenario must be in 'built' status. Returns 202 with the new run.\nThe run transitions through: built → queued → computing → processing → complete.\n\nAfter starting, poll get_run_status to track progress. Returns 409\nif the scenario is not in the correct state.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "compute_backend": {
                  "default": "local",
                  "description": "Compute backend: 'local' (Celery), 'ec2' (dedicated instance), or 'batch' (AWS Batch spot, cheapest). Default: 'local'",
                  "type": "string"
                },
                "scenario_id": {
                  "description": "The scenario ID to run",
                  "type": "integer"
                }
              },
              "required": [
                "scenario_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "get_run_status",
            "title": "Get Run Status",
            "description": "Lightweight status check for a simulation run (fast, \u003c50ms).\n\nUse this for polling instead of get_run. Returns only: id, status,\nprogress_pct (0-100), eta_seconds, error_message, and compute_backend.\n\nPoll every 5-10 seconds. Terminal states: complete, error, cancelled.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "run_id": {
                  "description": "The run ID",
                  "type": "integer"
                }
              },
              "required": [
                "run_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "get_run",
            "title": "Get Run",
            "description": "Get full details of a simulation run including timing and results.\n\nReturns the complete run record: status, progress, timing (start/end\ntimestamps, duration), compute details (backend, instance type, cost),\nmesh info, error messages, and result log. Use get_run_status for\nlightweight polling; use this for final results.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "run_id": {
                  "description": "The run ID",
                  "type": "integer"
                }
              },
              "required": [
                "run_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "cancel_run",
            "title": "Cancel Run",
            "description": "Cancel an in-flight simulation run.\n\nWorks on runs in built, queued, or computing status. Cleans up\ncompute resources (terminates EC2 instance, Celery task, or Batch job).\n\nReturns 409 if the run is already in a terminal state\n(complete, cancelled, or error).",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "run_id": {
                  "description": "The run ID to cancel",
                  "type": "integer"
                }
              },
              "required": [
                "run_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "retry_run",
            "title": "Retry Run",
            "description": "Retry a failed simulation run.\n\nResets an errored run back to 'created' status and triggers a new\npackage build. The same run ID is reused. Only valid when\nstatus is 'error'. Returns 409 for any other state.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "run_id": {
                  "description": "The run ID to retry",
                  "type": "integer"
                }
              },
              "required": [
                "run_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "list_runs",
            "title": "List Runs",
            "description": "List all simulation runs across all scenarios in a project.\n\nReturns a paginated list of runs. Optionally filter by status\nto find active, completed, or failed runs.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "page": {
                  "default": 1,
                  "description": "Page number (default 1)",
                  "type": "integer"
                },
                "page_size": {
                  "default": 100,
                  "description": "Results per page, max 100 (default 100)",
                  "type": "integer"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "status_filter": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "Filter by status: created, building, built, queued, computing, processing, complete, error, cancelled. Omit for all."
                }
              },
              "required": [
                "project_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "create_project",
            "title": "Create Project",
            "description": "Create a new ANUGA project. Returns the project record including its id.\n\nThe caller's own account becomes the owner. `projection` is the projected\nCRS every scenario in the project is meshed and run in — pick the UTM zone\ncovering the site. Next step for a new project: presign_terrain_upload.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "name": {
                  "description": "Project name",
                  "type": "string"
                },
                "projection": {
                  "description": "Working CRS as an EPSG string, normally the UTM zone of the site, e.g. 'EPSG:32756' (WGS 84 / UTM 56S)",
                  "type": "string"
                }
              },
              "required": [
                "name",
                "projection"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "presign_terrain_upload",
            "title": "Presign Terrain Upload",
            "description": "Step 1 of a terrain import: get a presigned S3 PUT URL for a GeoTIFF DEM.\n\nThe agent moves the bytes itself — no tool accepts file contents. After this\ncall, PUT the file straight to `upload_url`, sending the SAME Content-Type\nyou passed here (it is part of the signature; a mismatch is a 403\nSignatureDoesNotMatch before it is anything else):\n\n    curl -sS -X PUT -H \"Content-Type: image/tiff\" --upload-file /path/dem.tif \"$UPLOAD_URL\"\n\nthen call finalize_terrain_upload with the returned staging_key and\nprocess_id. Nothing exists in Hydrata until finalize; the URL expires after\n`expires_in` seconds (3600).\n\nPlatform guidance: keep the terrain extent within 5° across and 40,000 km²\n(200 × 200 km). The API enforces that cap on its bbox-fetch path; an\nuploaded GeoTIFF is only rejected above 5 GiB, but a larger DEM will not\nmesh or run well. The GeoTIFF must carry a CRS; the import reprojects it to\nthe site's UTM zone and builds a hillshade. Fallback when a presigned PUT is\nimpossible: multipart-POST the file with the same credential to\n/api/v2/anuga/projects/\u003cid\u003e/terrain/upload/ (form field `file`, optional\n`title`), which creates the terrain in one step — then get_terrain.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "content_type": {
                  "default": "image/tiff",
                  "description": "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.",
                  "type": "string"
                },
                "filename": {
                  "description": "Base name of the GeoTIFF, e.g. 'dem.tif' (a name only — never contents)",
                  "type": "string"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "size": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "File size in bytes (`stat -c %s \u003cfile\u003e`). The API rejects \u003e 5 GiB up front. Omit if unknown."
                }
              },
              "required": [
                "project_id",
                "filename"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "finalize_terrain_upload",
            "title": "Finalize Terrain Upload",
            "description": "Step 2 of a terrain import: register the PUT GeoTIFF as a Terrain and start the import.\n\nCall this only after the presigned PUT returned 200. Creates the Terrain row\n(status `creating`) and queues the import chain — reproject to UTM, publish\nthe layer + hillshade, style — which also seeds the project's six default\nboundary, friction, inflow, rainfall, structure and mesh-region rows.\nReturns 202 with the terrain record; keep its `id` for get_terrain. A 400 UPLOAD_NOT_FOUND\nmeans no object is at `staging_key`: the PUT did not land (check its status\ncode and Content-Type) — do not retry finalize until it has.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "process_id": {
                  "default": "",
                  "description": "`process_id` returned by presign_terrain_upload (pass it so the upload's progress record is reused; the API tolerates its absence)",
                  "type": "string"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "staging_key": {
                  "description": "`staging_key` returned by presign_terrain_upload",
                  "type": "string"
                },
                "title": {
                  "default": "",
                  "description": "Terrain title (default: the filename without .tif)",
                  "type": "string"
                }
              },
              "required": [
                "project_id",
                "staging_key"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "get_terrain",
            "title": "Get Terrain",
            "description": "Poll a terrain's import until it is `ready` (or `error`), bounded by timeout_seconds.\n\nReturns `outcome` — exactly one of `ready`, `error`, `timed_out`, `not_found`\n(the project has no terrain yet; an unknown terrain_id is an API 404 error\ninstead) — plus the last `status` seen (creating → styling → ready | error),\n`polls`, `elapsed_seconds` and the full `terrain` record (its `gn_layer` is\nthe published elevation dataset pk once ready). An import takes minutes to\ntens of minutes (the SAME 32 MB 1 m DEM measured 4.5 min once and 26 min\nonce — the worker's S3 download speed dominates), so `timed_out` is normal\nand NOT a failure: keep calling with the same arguments while `status` is\nstill `creating`/`styling`; several calls in a row is expected. `error` is\nterminal — the import failed and no default input rows were seeded; upload\na corrected GeoTIFF as a new terrain.\n\n`ready` is written by the import task; the project's default input rows\n(Boundary 01, Friction 01, Inflow 01, Rainfall 01, Structure 01,\nMeshRegion 01, one GeoNode layer each) are seeded by the NEXT task in the\nchain and appear over the following ~30 s. Poll the input-layer list until\nit is non-empty before attaching your own layer to a default row.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "poll_interval_seconds": {
                  "default": 5,
                  "description": "Seconds between polls (default 5)",
                  "type": "number"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "terrain_id": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "The terrain ID from finalize_terrain_upload. Omit to follow the project's newest terrain."
                },
                "timeout_seconds": {
                  "default": 240,
                  "description": "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.",
                  "type": "integer"
                }
              },
              "required": [
                "project_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "create_time_series",
            "title": "Create Time Series",
            "description": "Create a time series (rain gauge, hydrograph, tide/stage) in a project.\n\nPOSTs /projects/\u003cid\u003e/time-series/ with `series_type` and `units` as\ntop-level fields. `series_type` is checked against the four choices and\n`data` against the {\"rowData\": [{timestamp, value}, ...]} shape before any\nrequest is made — the API answers 500 (not 400) to a malformed row.\nReturns a compact record — id, name, series_type, units, timezone,\nrow_count, http_status — not the echoed rows; fetch the full row with the\nREST API (GET /projects/\u003cid\u003e/time-series/\u003cid\u003e/) if you need to round-trip it.\nA rainfall polygon references its gauge by the series NAME, so create the\ngauges with the exact names the rainfall GeoJSON's features carry.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "data": {
                  "additionalProperties": true,
                  "description": "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.",
                  "type": "object"
                },
                "description": {
                  "default": "",
                  "description": "Free-text description (optional)",
                  "type": "string"
                },
                "location_name": {
                  "default": "",
                  "description": "Human-readable location of the gauge (optional)",
                  "type": "string"
                },
                "name": {
                  "description": "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",
                  "type": "string"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "series_type": {
                  "default": "hyetograph",
                  "description": "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.",
                  "type": "string"
                },
                "source": {
                  "default": "",
                  "description": "Where the data came from, e.g. a gauge id or agency (optional)",
                  "type": "string"
                },
                "timezone": {
                  "default": "UTC",
                  "description": "IANA timezone of the timestamps (default 'UTC'), e.g. 'Australia/Sydney'",
                  "type": "string"
                },
                "units": {
                  "default": "",
                  "description": "Display label for the values, e.g. 'mm/hr', 'm^3/s', 'm' (optional)",
                  "type": "string"
                }
              },
              "required": [
                "project_id",
                "name",
                "data"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "attach_input_layer",
            "title": "Attach Input Layer",
            "description": "Attach a GeoJSON you uploaded to GeoNode as the project's boundary, friction, inflow, rainfall, structure or mesh_region layer.\n\nThe agent moves the bytes: first upload the GeoJSON yourself, with the\nsame credential, to GeoNode's upload endpoint at the site origin:\n\n    curl -sS -u \u003cuser\u003e:\u003cpassword\u003e -F \"base_file=@/path/rainfall.geojson\" https://\u003csite\u003e/api/v2/uploads/upload/\n\n→ JSON with `execution_id`. Then call this tool with it. The tool polls\nGET /api/v2/resource-service/execution-status/\u003cexecution_id\u003e (bounded by\ntimeout_seconds; statuses ready → running → finished | failed), reads the\nnew dataset's pk, and PATCHes it onto the project's DEFAULT row of that\nkind ('Boundary 01' … 'MeshRegion 01' — the six rows the terrain import\nseeds ~30 s after get_terrain reports ready; if the list is still empty\nthe tool says so: run finalize_terrain_upload / wait for get_terrain first).\n\n`outcome` is exactly one of: `attached` (row_id, gn_layer, dataset_pk,\ndataset_alternate — the WFS typename — and every row id seen);\n`timed_out` (the import is still running: call again with the same\narguments); `upload_failed` (the execution record, incl. its log, is\nreturned verbatim — fix the file and upload again); `no_default_row`;\n`no_dataset` (finished but no resource was recorded). The PATCH is\nrefused with a 400 if the dataset is not owned by you.\n\nRefused, with no request made: kind `breakline` and kind `culvert` — no\nREST create path exists for either at HEAD (TASK-3040 AC6), and culvert\nflow is not conveyed by run_anuga, so attaching one would only pretend.\nAlso refused without a request: an execution_id that is not the UUID the\nupload returned.\nOne GeoJSON per kind: all of a kind's features travel in that one file. A\nrainfall polygon names its gauge in its `data` property — create that\ngauge with create_time_series under the exact same name.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "execution_id": {
                  "description": "`execution_id` returned by your multipart POST to \u003corigin\u003e/api/v2/uploads/upload/",
                  "type": "string"
                },
                "kind": {
                  "description": "Which input the uploaded layer is: boundary, friction, inflow, rainfall, structure or mesh_region. breakline and culvert are refused (see below).",
                  "type": "string"
                },
                "poll_interval_seconds": {
                  "default": 5,
                  "description": "Seconds between polls (default 5)",
                  "type": "number"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "timeout_seconds": {
                  "default": 240,
                  "description": "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.",
                  "type": "integer"
                }
              },
              "required": [
                "project_id",
                "kind",
                "execution_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "create_scenario",
            "title": "Create Scenario",
            "description": "Create a DRAFT scenario (no build, no run) and report its mesh-triangle estimate.\n\nPOSTs /projects/\u003cid\u003e/scenarios/ with the write fields, then GETs the\nscenario detail — the create response carries NO estimate; the detail's\n`mesh_triangle_count_estimate` (+ `_breakdown`) does. Returns a compact\nrecord: id, name, the FK ids as stored, resolution, duration,\n`computed_status` (`created` = no run yet), the estimate and its\nbreakdown, and http_status. Next step: build_scenario (which asks for\nconfirm=true above 100,000 triangles). Nothing is meshed or queued here.\n\nUnits: `resolution` on the SCENARIO is a LENGTH in metres — ANUGA\nmaximum_triangle_area = resolution²/2 (run_utils.py:227/:290; FloatField\ndefault 100, not nullable; 0 makes the estimate None) and the same value\nbecomes the raster cell size; a MeshRegion FEATURE's `resolution` is\nconsumed by the mesher as an AREA (max_triangle_area, m²) while the\nestimate prices it as a length, so attached regions mesh ~15x more than\nestimated (Towradgi 100/36/8 m² regions: estimate ~18k, mesh ~283k); the\nsmallest MeshRegion value becomes the raster cell size.\n\nThe server does NOT validate that the FK ids belong to `project_id` —\npass the row ids attach_input_layer / get_terrain returned for THIS\nproject. Every FK is nullable at create time, and the build fails later\non a scenario with no terrain, or with neither an inflow nor a rainfall.\nA `boundary` whose row has no features (the default 'Boundary 01' before\nattach_input_layer) is accepted here and refused by build_scenario. The\nestimate is None when resolution is 0; an estimate of 0 with a real\nboundary is a very coarse mesh, not an error.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "boundary": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "Boundary row id (attach_input_layer kind=boundary → row_id)"
                },
                "description": {
                  "default": "",
                  "description": "Free-text description (optional)",
                  "type": "string"
                },
                "duration": {
                  "description": "Simulation duration in seconds (e.g. 43200 = 12 h)",
                  "type": "integer"
                },
                "friction": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "Friction row id (optional)"
                },
                "inflow": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "Inflow row id (optional; the build needs an inflow OR a rainfall)"
                },
                "mesh_region": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "MeshRegion row id (optional). Leave UNSET unless you want the regions' finer meshing — see the units note: they mesh ~15x more than estimated."
                },
                "name": {
                  "description": "Scenario name",
                  "type": "string"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "rainfall": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "Rainfall row id (optional; the build needs an inflow OR a rainfall)"
                },
                "resolution": {
                  "description": "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).",
                  "type": "number"
                },
                "structure": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "Structure row id (optional)"
                },
                "terrain": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "default": null,
                  "description": "Terrain id (get_terrain → terrain.id); the build fails without one"
                }
              },
              "required": [
                "project_id",
                "name",
                "resolution",
                "duration"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          },
          {
            "name": "build_scenario",
            "title": "Build Scenario",
            "description": "Build a scenario's package (mesh + inputs) after showing what it will cost, and poll until built.\n\nOrder of operations, so the number is shown before anything is spent:\n\n1. GET the scenario detail. A record with no `boundary`/`computed_status`\n   keys is a non-member's read of a public project → refused: a build\n   needs the EDITOR role.\n2. Re-call checks on `latest_run` (a re-POST is NOT deduplicated after\n   `built`/`complete` — it would dispatch a duplicate build): no run →\n   proceed; run `created`/`building` → resume polling, no POST; run\n   `built`/`queued`/`computing`/`processing`/`complete` with\n   `latest_run_is_valid` not false → return that state, no POST unless\n   rebuild=true; run `error`/`cancelled`, or `latest_run_is_valid` false\n   (the scenario was edited since the build) → proceed.\n3. Spend gates, each a refusal with `outcome: \"refused\"` and no POST: the\n   scenario has no boundary or its boundary row has no features (the\n   server would admit the build and fail it in make_package); the\n   estimate is None (resolution is 0/unset); the estimate is above\n   100,000 triangles and confirm is not true — the refusal states the\n   number; re-call with confirm=true to proceed. An estimate of 0 over a\n   boundary WITH features is buildable and is reported, not refused.\n4. POST /projects/\u003cid\u003e/scenarios/\u003cpk\u003e/build/. Every 4xx comes back\n   verbatim as a normal result with `http_status`: 422 MESH_TOO_LARGE\n   (`error_code`, `estimate`, `ceiling`, `detail` — the server's hard\n   ceiling; coarsen `resolution` or shrink the boundary; no run was\n   created), 409 COMPUTE_TARGET_UNAVAILABLE, 400/403/404. A 409 WITHOUT\n   an error_code is the dedup body ({status, run_id, detail}: a build is\n   already in flight) — the tool resumes polling that run.\n5. On 202 poll the detail's `computed_status` (created → building →\n   built | error), bounded by timeout_seconds.\n\nReturns a COMPACT state, never the whole detail: `outcome` (built, error,\ncancelled, complete/queued/computing/processing for a run past the build,\ntimed_out, or refused), `computed_status`, `mesh_triangle_count_estimate`,\n`posted`, the POST's `build` body + `http_status` when one was made, and\nthe latest run's `run_id`, `run_status`, `error_message`, `user_message`,\n`mesh_triangle_count`. `timed_out` is normal (make_package re-downloads\nthe terrain from S3 every build; minutes): call again with the same\narguments — step 2 resumes polling the same run, it never POSTs twice —\nor cancel_run(run_id) if the run is stuck in `created` with no worker.\n`error` is terminal: `error_message` says why (fix the inputs, then call\nagain — an errored latest run is rebuilt).\n\nUnits: `resolution` on the SCENARIO is a LENGTH in metres — ANUGA\nmaximum_triangle_area = resolution²/2 (run_utils.py:227/:290; FloatField\ndefault 100, not nullable; 0 makes the estimate None) and the same value\nbecomes the raster cell size; a MeshRegion FEATURE's `resolution` is\nconsumed by the mesher as an AREA (max_triangle_area, m²) while the\nestimate prices it as a length, so attached regions mesh ~15x more than\nestimated (Towradgi 100/36/8 m² regions: estimate ~18k, mesh ~283k); the\nsmallest MeshRegion value becomes the raster cell size.",
            "inputSchema": {
              "additionalProperties": false,
              "properties": {
                "confirm": {
                  "default": false,
                  "description": "Required (true) when the estimate is above 100,000 triangles — the tool refuses first and tells you the number. Default false.",
                  "type": "boolean"
                },
                "poll_interval_seconds": {
                  "default": 5,
                  "description": "Seconds between polls (default 5)",
                  "type": "number"
                },
                "project_id": {
                  "description": "The project ID",
                  "type": "integer"
                },
                "rebuild": {
                  "default": false,
                  "description": "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).",
                  "type": "boolean"
                },
                "scenario_id": {
                  "description": "The scenario ID from create_scenario",
                  "type": "integer"
                },
                "timeout_seconds": {
                  "default": 240,
                  "description": "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.",
                  "type": "integer"
                }
              },
              "required": [
                "project_id",
                "scenario_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "result": {
                  "type": "string"
                }
              },
              "required": [
                "result"
              ],
              "type": "object",
              "x-fastmcp-wrap-result": true
            }
          }
        ]
      },
      "name": "Hydrata - ANUGA Flood Simulation",
      "note": "Indexed from the official MCP registry: facts and our own checks, not reviewed, so no score, grade or rank.",
      "packages": null,
      "pageJsonUrl": "https://www.anchorterminal.com/tools/hydrata-mcp-server.json",
      "popularity": {
        "githubStars": 1
      },
      "registryName": "com.hydrata/hydrata-mcp-server",
      "remotes": [
        {
          "type": "streamable-http",
          "url": "https://hydrata.com/mcp/"
        }
      ],
      "repository": "https://github.com/Hydrata/hydrata-mcp-server",
      "reviewed": false,
      "slug": "hydrata-mcp-server",
      "source": "the official MCP registry",
      "sourceUrl": "https://registry.modelcontextprotocol.io/v0.1/servers?search=com.hydrata/hydrata-mcp-server",
      "summary": "Run ANUGA flood simulations, track progress, and retrieve results on Hydrata Cloud.",
      "updatedAt": "2026-09-21T12:22:59Z",
      "url": "https://www.anchorterminal.com/tools/hydrata-mcp-server",
      "vendor": "hydrata.com",
      "vendorUrl": "https://hydrata.com",
      "version": "0.2.0",
      "websiteUrl": "",
      "where": "hosted",
      "why": [
        "vendor"
      ]
    }
  },
  "kind": "anchor.page",
  "links": {
    "api": "https://www.anchorterminal.com/api/v1/index.json",
    "html": "https://www.anchorterminal.com/tools/hydrata-mcp-server",
    "json": "https://www.anchorterminal.com/tools/hydrata-mcp-server.json",
    "llms": "https://www.anchorterminal.com/llms.txt",
    "markdown": "https://www.anchorterminal.com/tools/hydrata-mcp-server.md",
    "slim": "https://www.anchorterminal.com/tools/hydrata-mcp-server.min.md"
  },
  "markdown": "# Hydrata - ANUGA Flood Simulation\n\n\u003e Indexed, not reviewed: facts from the official MCP registry and our own checks. No score, grade or rank, and not in the rankings until the panel reviews it. How the index works: https://www.anchorterminal.com/indexed/\n\n- Kind: MCP server, by hydrata.com (https://hydrata.com)\n- Category: Cloud \u0026 infrastructure (https://www.anchorterminal.com/categories/infrastructure.md)\n- Listed because: It's published in the registry under hydrata.com, a namespace the registry only gives to whoever proves they control that domain.\n- What the official MCP registry says: Run ANUGA flood simulations, track progress, and retrieve results on Hydrata Cloud.\n\n## Facts\n\n- MCP registry: `com.hydrata/hydrata-mcp-server` 0.2.0\n- Endpoint: https://hydrata.com/mcp/ (streamable HTTP)\n- Source: https://github.com/Hydrata/hydrata-mcp-server\n- GitHub stars: 1\n- Registry entry updated: 2026-09-21\n\n## Tools\n\n- Tools it lists (17, about 6,814 tokens of context, `tools/list` without credentials over MCP 2026-07-28, checked 2026-10-04 22:23 UTC):\n  - `list_projects`: List ANUGA simulation projects accessible to the authenticated user. Returns a paginated list of projects with their names, projections, and base map…\n  - `get_project`: Get details of a specific ANUGA project including its scenarios. Returns the project name, projection (EPSG code), base map ID, and configuration.\n  - `get_scenario`: Get scenario details including its `computed_status` and latest run. The `computed_status` field (there is NO `status` key on a scenario) is derived from the…\n  - `start_simulation`: Start a flood simulation run for a built scenario. The scenario must be in 'built' status. Returns 202 with the new run. The run transitions through: built →…\n  - `get_run_status`: Lightweight status check for a simulation run (fast, \u003c50ms). Use this for polling instead of get_run. Returns only: id, status, progress_pct (0-100),…\n  - `get_run`: Get full details of a simulation run including timing and results. Returns the complete run record: status, progress, timing (start/end timestamps, duration),…\n  - `cancel_run`: Cancel an in-flight simulation run. Works on runs in built, queued, or computing status. Cleans up compute resources (terminates EC2 instance, Celery task, or…\n  - `retry_run`: Retry a failed simulation run. Resets an errored run back to 'created' status and triggers a new package build. The same run ID is reused. Only valid when…\n  - `list_runs`: 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…\n  - `create_project`: Create a new ANUGA project. Returns the project record including its id. The caller's own account becomes the owner. `projection` is the projected CRS every…\n  - `presign_terrain_upload`: Step 1 of a terrain import: get a presigned S3 PUT URL for a GeoTIFF DEM. The agent moves the bytes itself — no tool accepts file contents. After this call,…\n  - `finalize_terrain_upload`: Step 2 of a terrain import: register the PUT GeoTIFF as a Terrain and start the import. Call this only after the presigned PUT returned 200. Creates the…\n  - `get_terrain`: Poll a terrain's import until it is `ready` (or `error`), bounded by timeout_seconds. Returns `outcome` — exactly one of `ready`, `error`, `timed_out`,…\n  - `create_time_series`: Create a time series (rain gauge, hydrograph, tide/stage) in a project. POSTs /projects/\u003cid\u003e/time-series/ with `series_type` and `units` as top-level fields.…\n  - `attach_input_layer`: Attach a GeoJSON you uploaded to GeoNode as the project's boundary, friction, inflow, rainfall, structure or mesh_region layer. The agent moves the bytes:…\n  - `create_scenario`: Create a DRAFT scenario (no build, no run) and report its mesh-triangle estimate. POSTs /projects/\u003cid\u003e/scenarios/ with the write fields, then GETs the scenario…\n  - `build_scenario`: Build a scenario's package (mesh + inputs) after showing what it will cost, and poll until built. Order of operations, so the number is shown before anything…\n- How its tools read to an agent (0 errors, 19 warnings, 0 notes, about 6,814 tokens; rules at https://www.anchorterminal.com/check.md; not part of the score):\n  - warn TC07 build_scenario: the description is about 812 tokens\n  - warn TC13 create_time_series: data (object with no properties)\n  - warn TC16 attach_input_layer: no readOnlyHint or destructiveHint\n  - warn TC16 build_scenario: no readOnlyHint or destructiveHint\n  - warn TC16 cancel_run: no readOnlyHint or destructiveHint\n  - warn TC16 create_project: no readOnlyHint or destructiveHint\n  - warn TC16 create_scenario: no readOnlyHint or destructiveHint\n  - warn TC16 create_time_series: no readOnlyHint or destructiveHint\n  - warn TC16 finalize_terrain_upload: no readOnlyHint or destructiveHint\n  - warn TC16 get_project: no readOnlyHint or destructiveHint\n  - warn TC16 get_run: no readOnlyHint or destructiveHint\n  - warn TC16 get_run_status: no readOnlyHint or destructiveHint\n  - warn TC16 get_scenario: no readOnlyHint or destructiveHint\n  - warn TC16 get_terrain: no readOnlyHint or destructiveHint\n  - warn TC16 list_projects: no readOnlyHint or destructiveHint\n  - warn TC16 list_runs: no readOnlyHint or destructiveHint\n  - warn TC16 presign_terrain_upload: no readOnlyHint or destructiveHint\n  - warn TC16 retry_run: no readOnlyHint or destructiveHint\n  - warn TC16 start_simulation: no readOnlyHint or destructiveHint\n\n- JSON: https://www.anchorterminal.com/api/v1/tools/hydrata-mcp-server.json\n- Being indexed says nothing about quality, and nobody can pay for it. Ask for a review: https://www.anchorterminal.com/builders/#claiming\n",
  "meta": {
    "attribution": "Anchor Terminal (https://www.anchorterminal.com)",
    "docs": "https://www.anchorterminal.com/docs/",
    "generatedAt": "2026-10-05",
    "license": "CC-BY-4.0",
    "method": "https://www.anchorterminal.com/benchmark/",
    "methodology": "0.3",
    "openapi": "https://www.anchorterminal.com/openapi.json",
    "preview": false,
    "run": "2026-10-01",
    "runLabel": "October 2026 research run"
  },
  "page": {
    "breadcrumbs": [
      {
        "name": "Home",
        "url": "https://www.anchorterminal.com/"
      },
      {
        "name": "Terminal",
        "url": "https://www.anchorterminal.com/tools/"
      },
      {
        "name": "Indexed",
        "url": "https://www.anchorterminal.com/indexed/"
      },
      {
        "name": "Hydrata - ANUGA Flood Simulation",
        "url": ""
      }
    ],
    "description": "Hydrata - ANUGA Flood Simulation, an MCP server by hydrata.com, listed from the official MCP registry. Indexed, not reviewed: facts and our own checks, no score or ranking. Run ANUGA flood simulations, track progress, and retrieve results on Hydrata Cloud.",
    "facts": [
      "not reviewed",
      "not ranked",
      "facts only"
    ],
    "h1": "Hydrata - ANUGA Flood Simulation",
    "image": "https://www.anchorterminal.com/assets/og/indexed.png",
    "path": "/tools/hydrata-mcp-server",
    "published": "",
    "section": "indexed",
    "title": "Hydrata - ANUGA Flood Simulation | Anchor Terminal",
    "toc": null,
    "updated": "2026-10-05",
    "url": "https://www.anchorterminal.com/tools/hydrata-mcp-server"
  },
  "tokens": {
    "markdown": 1600,
    "slim": 1530
  },
  "version": 1
}
