EO — Tool Reference
Earth observation via Sentinel Hub: satellite scene search, rendered imagery (true color, NDVI, NDWI), and AOI statistics from Sentinel-2. Works with a free Copernicus Data Space account
Your AI assistant discovers and invokes these tools through the
MCP Server's meta tools —
it calls execute_tool with the tool name and arguments below.
# get_statistics read
Compute NDVI/NDWI time-series statistics (mean, min, max) over an AOI without downloading imagery.
Full description
Compute a spectral-index time series over an AOI (Statistical API). Returns per-interval mean/min/max/std-dev of NDVI or NDWI, as JSON — ideal for questions like "when was this field greenest last year" or "how did the reservoir's water extent evolve". Daily intervals return one entry per satellite pass (gaps are normal); monthly intervals are cheaper and smoother. Intervals start at time_from and step by the interval length; a trailing partial interval is included, shortened to end at time_to (so March 1 - June 30 monthly yields four intervals, the last covering June 1-30). Works with Sentinel-2 (10 m, data from 2015-06), and with a Planet account also landsat-ot-l2 (30 m) and byoc-<id> PlanetScope collections (~3 m).
| Parameter | Type | Required | Description |
|---|---|---|---|
aoi | object | null | No | GeoJSON Polygon/MultiPolygon geometry (WGS84). Accepts the geo toolkit's `geojson` output. Provide either aoi or bbox. |
bbox | array<number> | null | No | [west, south, east, north] WGS84 degrees. Alternative to aoi. |
index | "ndvi" | "ndwi" | Yes | Spectral index: ndvi (vegetation greenness, -1..1) or ndwi (water presence, -1..1). |
collection | string | No | Collection id: sentinel-2-l2a (default) or sentinel-2-l1c; with a Planet account also landsat-ot-l2, or byoc-<id> for a PlanetScope subscription collection. Default: "sentinel-2-l2a" |
time_from | string | Yes | Start date (YYYY-MM-DD) or ISO datetime. |
time_to | string | Yes | End date (YYYY-MM-DD) or ISO datetime. |
interval | "P1D" | "P1M" | No | Aggregation interval: P1D (daily) or P1M (monthly, default). Default: "P1M" |
max_cloud_cover | number | null | No | Skip scenes above this cloud cover percent when aggregating. |
Parameter schema (JSON)
{
"description": "Parameters for get_statistics.",
"properties": {
"aoi": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"description": "GeoJSON Polygon/MultiPolygon geometry (WGS84). Accepts the geo toolkit's `geojson` output. Provide either aoi or bbox.",
"title": "Aoi"
},
"bbox": {
"anyOf": [
{
"items": {
"type": "number"
},
"maxItems": 4,
"minItems": 4,
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "[west, south, east, north] WGS84 degrees. Alternative to aoi.",
"title": "Bbox"
},
"index": {
"description": "Spectral index: ndvi (vegetation greenness, -1..1) or ndwi (water presence, -1..1).",
"enum": [
"ndvi",
"ndwi"
],
"title": "Index",
"type": "string"
},
"collection": {
"default": "sentinel-2-l2a",
"description": "Collection id: sentinel-2-l2a (default) or sentinel-2-l1c; with a Planet account also landsat-ot-l2, or byoc-<id> for a PlanetScope subscription collection.",
"title": "Collection",
"type": "string"
},
"time_from": {
"description": "Start date (YYYY-MM-DD) or ISO datetime.",
"title": "Time From",
"type": "string"
},
"time_to": {
"description": "End date (YYYY-MM-DD) or ISO datetime.",
"title": "Time To",
"type": "string"
},
"interval": {
"default": "P1M",
"description": "Aggregation interval: P1D (daily) or P1M (monthly, default).",
"enum": [
"P1D",
"P1M"
],
"title": "Interval",
"type": "string"
},
"max_cloud_cover": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Skip scenes above this cloud cover percent when aggregating.",
"title": "Max Cloud Cover"
}
},
"required": [
"index",
"time_from",
"time_to"
],
"title": "GetStatisticsParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"$defs": {
"IntervalStats": {
"description": "Index statistics for one time interval.",
"properties": {
"interval_from": {
"description": "Interval start (UTC).",
"title": "Interval From",
"type": "string"
},
"interval_to": {
"description": "Interval end (UTC).",
"title": "Interval To",
"type": "string"
},
"mean": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Mean index value over the AOI.",
"title": "Mean"
},
"min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Minimum index value.",
"title": "Min"
},
"max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Maximum index value.",
"title": "Max"
},
"st_dev": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Standard deviation.",
"title": "St Dev"
},
"sample_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Pixels sampled.",
"title": "Sample Count"
},
"no_data_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Pixels with no data.",
"title": "No Data Count"
}
},
"required": [
"interval_from",
"interval_to"
],
"title": "IntervalStats",
"type": "object"
}
},
"description": "Result of get_statistics.",
"properties": {
"success": {
"description": "Whether the operation succeeded",
"title": "Success",
"type": "boolean"
},
"index": {
"description": "Spectral index computed.",
"title": "Index",
"type": "string"
},
"collection": {
"description": "Collection used.",
"title": "Collection",
"type": "string"
},
"interval": {
"description": "Aggregation interval used.",
"title": "Interval",
"type": "string"
},
"intervals": {
"description": "Per-interval statistics, chronological.",
"items": {
"$ref": "#/$defs/IntervalStats"
},
"title": "Intervals",
"type": "array"
},
"empty_intervals_skipped": {
"default": 0,
"description": "Intervals with no usable data (fully cloudy/masked), omitted.",
"title": "Empty Intervals Skipped",
"type": "integer"
},
"processing_units_spent": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Processing units this call consumed, when reported.",
"title": "Processing Units Spent"
},
"note": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Extra guidance, when relevant.",
"title": "Note"
}
},
"required": [
"success",
"index",
"collection",
"interval"
],
"title": "GetStatisticsResult",
"type": "object"
} # render_image write
Render a satellite image (true color, false color, NDVI, or NDWI) of an AOI and return a displayable URL.
Full description
Render satellite imagery of an AOI to a PNG and return a presigned URL. Mosaics scenes from the time window (filtered by cloud cover where the collection supports it, prioritized by mosaicking_order), renders the chosen visualization, and uploads the PNG to temporary storage. Embed the returned image_url in a markdown image tag to show it. Default is Sentinel-2 at 10 m pixels: choose field-scale or larger AOIs (parks, farms, lakes), not building-scale. With a Planet account, landsat-ot-l2 (30 m) and byoc-<id> PlanetScope collections (~3 m, resolves buildings) are also renderable. Use search_catalog first to pick a window containing a clear scene.
| Parameter | Type | Required | Description |
|---|---|---|---|
aoi | object | null | No | GeoJSON Polygon/MultiPolygon geometry (WGS84). Accepts the geo toolkit's `geojson` output; pixels outside it render transparent. Provide either aoi or bbox. |
bbox | array<number> | null | No | [west, south, east, north] WGS84 degrees. Alternative to aoi. |
visualization | "true_color" | "false_color" | "ndvi" | "ndwi" | No | Rendering: true_color (natural), false_color (vegetation in red), ndvi (greenness ramp), ndwi (water ramp). Default: "true_color" |
collection | string | No | Collection id: sentinel-2-l2a (default, 10 m) or sentinel-2-l1c; with a Planet account also landsat-ot-l2 (30 m), or byoc-<id> for a PlanetScope subscription collection (~3 m, sharpest). Default: "sentinel-2-l2a" |
time_from | string | Yes | Start date (YYYY-MM-DD) or ISO datetime. |
time_to | string | Yes | End date (YYYY-MM-DD) or ISO datetime. |
max_cloud_cover | number | No | Only mosaic scenes at or below this cloud cover percent. Prefer 10-30; a value of 0 requires perfectly cloud-free scenes and usually produces an empty image. Default: 30 |
mosaicking_order | "mostRecent" | "leastCC" | "leastRecent" | No | Scene priority when several match: leastCC (least cloudy, default), mostRecent, or leastRecent. Default: "leastCC" |
width | integer | No | Output width in pixels (64-1536); height follows the AOI aspect ratio. Width beyond the AOI's native pixel count at the collection's resolution (10 m Sentinel-2, 30 m Landsat, ~3 m PlanetScope) adds no detail; the server caps excessive values. Default: 512 |
Parameter schema (JSON)
{
"description": "Parameters for render_image.",
"properties": {
"aoi": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"description": "GeoJSON Polygon/MultiPolygon geometry (WGS84). Accepts the geo toolkit's `geojson` output; pixels outside it render transparent. Provide either aoi or bbox.",
"title": "Aoi"
},
"bbox": {
"anyOf": [
{
"items": {
"type": "number"
},
"maxItems": 4,
"minItems": 4,
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "[west, south, east, north] WGS84 degrees. Alternative to aoi.",
"title": "Bbox"
},
"visualization": {
"default": "true_color",
"description": "Rendering: true_color (natural), false_color (vegetation in red), ndvi (greenness ramp), ndwi (water ramp).",
"enum": [
"true_color",
"false_color",
"ndvi",
"ndwi"
],
"title": "Visualization",
"type": "string"
},
"collection": {
"default": "sentinel-2-l2a",
"description": "Collection id: sentinel-2-l2a (default, 10 m) or sentinel-2-l1c; with a Planet account also landsat-ot-l2 (30 m), or byoc-<id> for a PlanetScope subscription collection (~3 m, sharpest).",
"title": "Collection",
"type": "string"
},
"time_from": {
"description": "Start date (YYYY-MM-DD) or ISO datetime.",
"title": "Time From",
"type": "string"
},
"time_to": {
"description": "End date (YYYY-MM-DD) or ISO datetime.",
"title": "Time To",
"type": "string"
},
"max_cloud_cover": {
"default": 30,
"description": "Only mosaic scenes at or below this cloud cover percent. Prefer 10-30; a value of 0 requires perfectly cloud-free scenes and usually produces an empty image.",
"maximum": 100,
"minimum": 0,
"title": "Max Cloud Cover",
"type": "number"
},
"mosaicking_order": {
"default": "leastCC",
"description": "Scene priority when several match: leastCC (least cloudy, default), mostRecent, or leastRecent.",
"enum": [
"mostRecent",
"leastCC",
"leastRecent"
],
"title": "Mosaicking Order",
"type": "string"
},
"width": {
"default": 512,
"description": "Output width in pixels (64-1536); height follows the AOI aspect ratio. Width beyond the AOI's native pixel count at the collection's resolution (10 m Sentinel-2, 30 m Landsat, ~3 m PlanetScope) adds no detail; the server caps excessive values.",
"maximum": 1536,
"minimum": 64,
"title": "Width",
"type": "integer"
}
},
"required": [
"time_from",
"time_to"
],
"title": "RenderImageParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of render_image.",
"properties": {
"success": {
"description": "Whether the operation succeeded",
"title": "Success",
"type": "boolean"
},
"image_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Short PNG URL — embed as a markdown image or share as a link. Valid for about a day, then the image is deleted.",
"title": "Image Url"
},
"expires_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "ISO-8601 UTC time after which the image is deleted.",
"title": "Expires At"
},
"width": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Rendered width in pixels.",
"title": "Width"
},
"height": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Rendered height in pixels.",
"title": "Height"
},
"visualization": {
"description": "Visualization that was rendered.",
"title": "Visualization",
"type": "string"
},
"collection": {
"description": "Collection used.",
"title": "Collection",
"type": "string"
},
"time_from": {
"description": "Start of the mosaicking window.",
"title": "Time From",
"type": "string"
},
"time_to": {
"description": "End of the mosaicking window.",
"title": "Time To",
"type": "string"
},
"processing_units_spent": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Processing units this call consumed, when reported.",
"title": "Processing Units Spent"
},
"note": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Extra guidance, when relevant.",
"title": "Note"
}
},
"required": [
"success",
"visualization",
"collection",
"time_from",
"time_to"
],
"title": "RenderImageResult",
"type": "object"
} # search_catalog read
Search the Sentinel Hub catalog for satellite scenes over an area: acquisition times, cloud cover, and footprints.
Full description
Search satellite scenes (STAC catalog) over an AOI or bbox. Returns scene ids, acquisition times, cloud cover, and footprints for the requested collection and time range. Use it to find good (e.g. least cloudy) dates before calling render_image, or to check data availability before get_statistics. Free CDSE accounts cover the Sentinel missions; Landsat/MODIS/commercial collections need Planet credentials with the endpoint field set to 'planet'.
| Parameter | Type | Required | Description |
|---|---|---|---|
aoi | object | null | No | GeoJSON Polygon/MultiPolygon geometry (WGS84 lon/lat) to search over. Accepts the `geojson`/`merged_geojson` output of the geo toolkit. Provide either aoi or bbox, not both. |
bbox | array<number> | null | No | [west, south, east, north] in WGS84 degrees. Alternative to aoi. |
collection | string | No | Data collection id, e.g. sentinel-2-l2a (default), sentinel-2-l1c, sentinel-1-grd. Planet-endpoint accounts can also use e.g. landsat-ot-l2, or byoc-<id> for a PlanetScope subscription collection. Default: "sentinel-2-l2a" |
time_from | string | Yes | Start date (YYYY-MM-DD) or ISO datetime. |
time_to | string | Yes | End date (YYYY-MM-DD) or ISO datetime. |
max_cloud_cover | number | null | No | Maximum scene cloud cover percent (optical collections only). |
limit | integer | No | Maximum number of scenes to return (1-50). Default: 10 |
Parameter schema (JSON)
{
"description": "Parameters for search_catalog.",
"properties": {
"aoi": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"description": "GeoJSON Polygon/MultiPolygon geometry (WGS84 lon/lat) to search over. Accepts the `geojson`/`merged_geojson` output of the geo toolkit. Provide either aoi or bbox, not both.",
"title": "Aoi"
},
"bbox": {
"anyOf": [
{
"items": {
"type": "number"
},
"maxItems": 4,
"minItems": 4,
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "[west, south, east, north] in WGS84 degrees. Alternative to aoi.",
"title": "Bbox"
},
"collection": {
"default": "sentinel-2-l2a",
"description": "Data collection id, e.g. sentinel-2-l2a (default), sentinel-2-l1c, sentinel-1-grd. Planet-endpoint accounts can also use e.g. landsat-ot-l2, or byoc-<id> for a PlanetScope subscription collection.",
"title": "Collection",
"type": "string"
},
"time_from": {
"description": "Start date (YYYY-MM-DD) or ISO datetime.",
"title": "Time From",
"type": "string"
},
"time_to": {
"description": "End date (YYYY-MM-DD) or ISO datetime.",
"title": "Time To",
"type": "string"
},
"max_cloud_cover": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Maximum scene cloud cover percent (optical collections only).",
"title": "Max Cloud Cover"
},
"limit": {
"default": 10,
"description": "Maximum number of scenes to return (1-50).",
"maximum": 50,
"minimum": 1,
"title": "Limit",
"type": "integer"
}
},
"required": [
"time_from",
"time_to"
],
"title": "SearchCatalogParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"$defs": {
"SceneInfo": {
"description": "One catalog scene.",
"properties": {
"id": {
"description": "Scene/item id (usable for traceability).",
"title": "Id",
"type": "string"
},
"datetime": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Acquisition time (UTC).",
"title": "Datetime"
},
"cloud_cover": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Scene cloud cover percent, when the collection reports it.",
"title": "Cloud Cover"
},
"bbox": {
"anyOf": [
{
"items": {
"type": "number"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "Scene footprint bbox [west, south, east, north].",
"title": "Bbox"
},
"thumbnail_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Low-res quicklook URL, when the collection provides one.",
"title": "Thumbnail Url"
}
},
"required": [
"id"
],
"title": "SceneInfo",
"type": "object"
}
},
"description": "Result of search_catalog.",
"properties": {
"success": {
"description": "Whether the operation succeeded",
"title": "Success",
"type": "boolean"
},
"collection": {
"description": "Collection that was searched.",
"title": "Collection",
"type": "string"
},
"scene_count": {
"description": "Number of scenes returned.",
"title": "Scene Count",
"type": "integer"
},
"scenes": {
"description": "Matching scenes.",
"items": {
"$ref": "#/$defs/SceneInfo"
},
"title": "Scenes",
"type": "array"
},
"truncated": {
"default": false,
"description": "True when more scenes matched than `limit` returned.",
"title": "Truncated",
"type": "boolean"
},
"note": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Extra guidance, when relevant.",
"title": "Note"
}
},
"required": [
"success",
"collection",
"scene_count"
],
"title": "SearchCatalogResult",
"type": "object"
}