Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,071Paid calls: 1,558Letters: 14Defects: 1,336counted 2 min ago
teppi

Server definition

Hash
sha256:28cbf7680884cc0f3d6612c34d7fea24493941cd21dc4b5f1c09d4133445d3b5
What it is
What a remote MCP server returned when asked what it offers: 17 tools

The blob, as servednamed by its sha256

{ "instructions": "Hydrata is a geospatial hydraulic modeling platform. Use these tools to manage ANUGA flood simulation projects, scenarios, and runs. A typical workflow is: list_projects → get_scenario → start_simulation → poll get_run_status until complete → get_run for results. To author a project from your own files: create_project → presign_terrain_upload → PUT the GeoTIFF yourself (curl --upload-file) → finalize_terrain_upload → get_terrain (polls until ready) → for each input GeoJSON (boundary, friction, inflow, rainfall, structure, mesh_region): multipart-POST it yourself to <origin>/api/v2/uploads/upload/ with the same credential, then attach_input_layer with the execution_id → create_time_series for each rain gauge / hydrograph → create_scenario (reports the mesh-triangle estimate from the detail) → build_scenario (polls computed_status to built; asks for confirm=true above 100,000 triangles; returns the API's 422 MESH_TOO_LARGE body verbatim) → start_simulation. No tool accepts file contents; the agent moves the bytes.", "tools": [ { "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 <user>:<password> -F \"base_file=@/path/rainfall.geojson\" https://<site>/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/<execution_id> (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 <origin>/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" }, "name": "attach_input_layer", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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/<id>/scenarios/<pk>/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" }, "name": "build_scenario", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "cancel_run", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "create_project", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "Create a DRAFT scenario (no build, no run) and report its mesh-triangle estimate.\n\nPOSTs /projects/<id>/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" }, "name": "create_scenario", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "Create a time series (rain gauge, hydrograph, tide/stage) in a project.\n\nPOSTs /projects/<id>/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/<id>/time-series/<id>/) 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" }, "name": "create_time_series", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "finalize_terrain_upload", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "get_project", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "get_run", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "Lightweight status check for a simulation run (fast, <50ms).\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" }, "name": "get_run_status", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "get_scenario", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "get_terrain", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "list_projects", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "list_runs", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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/<id>/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 <file>`). The API rejects > 5 GiB up front. Omit if unknown." } }, "required": [ "project_id", "filename" ], "type": "object" }, "name": "presign_terrain_upload", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "retry_run", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "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" }, "name": "start_simulation", "outputSchema": { "properties": { "result": { "type": "string" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:28cbf7680884cc0f3d6612c34d7fea24493941cd21dc4b5f1c09d4133445d3b5 | sha256sum