OpenLandMap MCP Server
Provides access to the OpenLandMap STAC catalog, offering over 100 global environmental datasets including soil, climate, and vegetation data. It enables AI agents to discover, search, and retrieve Cloud-Optimized GeoTIFFs for global geospatial analysis.
Ask AI about OpenLandMap MCP Server
Powered by Claude Β· Grounded in docs
I know everything about OpenLandMap MCP Server. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
OpenLandMap MCP Server
MCP Server for the OpenLandMap STAC catalog β full access to global geospatial environmental data for AI agents.
Overview
OpenLandMap provides 104+ collections of global environmental data as Cloud-Optimized GeoTIFFs (COG), covering:
| Theme | Examples |
|---|---|
| Soil | Organic carbon, pH, texture, bulk density, water content |
| Vegetation | EVI, FAPAR, forest cover, plant functional types |
| Land Cover | Land cover, land use, cropland, pasture, urban areas |
| Climate | Land surface temperature (LST), precipitation, bioclim |
| Terrain | DEM, slope, aspect, curvature, geomorphometry |
| Water | Water occurrence, snow cover |
| Atmosphere | NO2, water vapor, aerosol optical depth |
| Population | Population density, human footprint, wilderness |
Installation
cd openlandmap-mcp
# Install with uv
uv pip install -e .
# Or run directly (uv resolves dependencies automatically)
uv run openlandmap-mcp
Configuration
Prerequisites: uv must be installed and available in
PATH.
Claude Code
Add to .claude/settings.json (project-level) or ~/.claude/settings.json (global):
{
"mcpServers": {
"openlandmap": {
"command": "uv",
"args": ["run", "--directory", "/path/to/openlandmap-mcp", "openlandmap-mcp"]
}
}
}
Claude Desktop
Add to your claude_desktop_config.json:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
{
"mcpServers": {
"openlandmap": {
"command": "uv",
"args": ["run", "--directory", "/path/to/openlandmap-mcp", "openlandmap-mcp"]
}
}
}
Gemini CLI
Add to ~/.gemini/settings.json (global) or .gemini/settings.json (project-level):
| OS | Global path |
|---|---|
| Linux / macOS | ~/.gemini/settings.json |
| Windows | %USERPROFILE%\.gemini\settings.json |
{
"mcpServers": {
"openlandmap": {
"command": "uv",
"args": ["run", "--directory", "/path/to/openlandmap-mcp", "openlandmap-mcp"],
"timeout": 60000
}
}
}
After configuration, verify with the /mcp command inside Gemini CLI to list connected servers and available tools.
ChatGPT Desktop
ChatGPT supports MCP servers exclusively via remote HTTP/SSE transport β local stdio processes are not supported. You need to expose the server over HTTP first.
Step 1 β Start the server with SSE transport:
uv run openlandmap-mcp --transport sse --port 8811
Step 2 β Expose locally (for development) or deploy publicly:
For local development, use a tunnel like ngrok:
ngrok http 8811
# Example output: https://abc123.ngrok.app
For production, deploy behind a reverse proxy with a public HTTPS URL.
Step 3 β Register in ChatGPT Desktop:
- Open Settings β Apps & Connectors β Advanced Settings
- Enable Developer Mode
- Go to Settings β Connectors β Create
- Fill in:
- Name:
OpenLandMap - Connector URL:
https://abc123.ngrok.app/mcp(or your public URL) - Authentication: None (or configure as needed)
- Name:
Note: ChatGPT does not support local config files for MCP. All registration is done through the UI. The server must be reachable over HTTPS.
Cursor / VS Code
Add to .cursor/mcp.json (Cursor) or .vscode/mcp.json (VS Code):
{
"mcpServers": {
"openlandmap": {
"command": "uv",
"args": ["run", "--directory", "/path/to/openlandmap-mcp", "openlandmap-mcp"]
}
}
}
Compatibility Matrix
| Client | Transport | Config file | Local stdio |
|---|---|---|---|
| Claude Code | stdio | .claude/settings.json | Yes |
| Claude Desktop | stdio | claude_desktop_config.json | Yes |
| Gemini CLI | stdio | ~/.gemini/settings.json | Yes |
| ChatGPT Desktop | HTTP/SSE | UI only (no file) | No |
| Cursor | stdio | .cursor/mcp.json | Yes |
| VS Code | stdio | .vscode/mcp.json | Yes |
Capabilities
1. Catalog Discovery
Browse and search the entire OpenLandMap catalog.
catalog_info()
Returns root catalog metadata: ID, description, STAC version, total collection count.
"What data is available on OpenLandMap?"
list_collections(theme?, keyword?, limit?)
List collections with optional filters by theme alias or keyword search across titles, descriptions, and keywords.
"List all soil collections"
β list_collections(theme="soil")
"Find collections related to organic carbon"
β list_collections(keyword="organic carbon")
"Show the first 5 vegetation datasets"
β list_collections(theme="vegetation", limit=5)
Available theme aliases: soil, vegetation, land_cover, climate, terrain, water, atmosphere, population
get_collection_schema(collection_id)
Returns the full schema of a collection: asset type definitions (MIME types, roles), STAC extensions used, spatial/temporal extent, contact info, style URLs (SLD/QML), and related links.
"Show me everything about the organic carbon collection"
β get_collection_schema("organic.carbon_usda.6a1c")
discover_data_for_topic(topic)
Natural language search across all collection titles, descriptions, and keywords. Returns results ranked by relevance score.
"Find data about deforestation in the Amazon"
β discover_data_for_topic("Amazon deforestation forest loss")
"What datasets exist for air quality analysis?"
β discover_data_for_topic("air quality NO2 aerosol")
2. Collection Operations
Analyze, compare, and explore collections in depth.
compare_collections(collection_ids)
Side-by-side comparison of 2β10 collections: temporal coverage, resolution, units, keywords, and theme.
"Compare soil organic carbon and pH datasets"
β compare_collections(["organic.carbon_usda.6a1c", "ph.h2o_usda.4c1a2a"])
get_collection_temporal_stats(collection_id)
Temporal statistics: earliest/latest dates, item count, year-by-year distribution, and median update interval.
"How often is the EVI dataset updated?"
β get_collection_temporal_stats("evi_mod13q1.tmwm.inpaint")
find_related_collections(collection_id)
Finds collections sharing the same theme or native category. Useful for discovering complementary datasets.
"What other datasets are related to land surface temperature?"
β find_related_collections("lst_mod11a2.daytime")
get_soil_collections()
Shortcut returning all soil-related collections (bulk density, organic carbon, pH, sand/clay/silt, texture, water content, taxonomy).
"List all available soil datasets"
β get_soil_collections()
get_vegetation_collections()
Shortcut returning all vegetation-related collections (EVI, FAPAR, forest cover, plant functional types).
"What vegetation indices are available?"
β get_vegetation_collections()
get_land_cover_collections()
Shortcut returning all land cover/land use collections (classification, cropland, pasture, urban, change detection).
"Show me land cover datasets"
β get_land_cover_collections()
3. Item Search & Access
Search and retrieve individual temporal snapshots within collections.
search_items(collection_id, bbox?, datetime_range?, limit?, offset?)
Search items with spatial (bounding box) and temporal (ISO 8601 interval) filters. Supports pagination.
"Find organic carbon data for the Cerrado region"
β search_items("organic.carbon_usda.6a1c", bbox=[-60.47, -24.68, -41.28, -2.33])
"Get EVI data from 2015 to 2020"
β search_items("evi_mod13q1.tmwm.inpaint", datetime_range="2015-01-01/2020-12-31", limit=10)
"Show all items in the land cover collection"
β search_items("land.cover_esacci.lc.l4", limit=50)
get_item_detail(collection_id, item_id)
Full item details: geometry (GeoJSON), bounding box, temporal range, all assets with resolved URLs, MIME types, file sizes, and checksums.
"Show full details for the 2018 organic carbon item"
β get_item_detail("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231")
list_items_temporal(collection_id)
Lists all items sorted chronologically. Shows the complete temporal coverage and update pattern of a dataset.
"What time periods are available for EVI?"
β list_items_temporal("evi_mod13q1.tmwm.inpaint")
find_items_by_point(lon, lat, collection_ids?)
Given a WGS84 coordinate, finds all items covering that point across one or more collections.
"What data is available for BrasΓlia?"
β find_items_by_point(-47.9, -15.8)
"Find soil data at this location"
β find_items_by_point(-47.9, -15.8, ["organic.carbon_usda.6a1c", "ph.h2o_usda.4c1a2a"])
4. Asset Access & Download
Resolve URLs and generate download instructions for data files.
get_asset_url(collection_id, item_id, asset_key)
Resolves the full S3 URL for a specific asset. Returns MIME type, roles, COG status, file size, checksum, and S3 bucket/key.
"Get the URL for the 0cm depth organic carbon layer"
β get_asset_url("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231", "organic.carbon_usda.6a1c_m_250m_b0cm")
list_assets_for_item(collection_id, item_id)
Lists all assets (data layers, thumbnails, style files) with complete metadata for each.
"What files are available in this item?"
β list_assets_for_item("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231")
get_all_data_assets(collection_id, item_id)
Filters to only data assets (role="data"), excluding thumbnails, QML, and SLD files. Returns direct COG URLs.
"Give me only the data layers, not the styles"
β get_all_data_assets("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231")
get_asset_download_info(collection_id, item_id, asset_key)
Returns the direct URL plus ready-to-use commands and code snippets:
- curl command for download
- wget command for download
- Python snippet using
rasterio(streaming, no download needed) - R snippet using
terra(streaming, no download needed)
"How do I access the soil carbon data programmatically?"
β get_asset_download_info("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231", "organic.carbon_usda.6a1c_m_250m_b0cm")
get_visualization_assets(collection_id, item_id)
Returns visualization-related assets: thumbnails (PNG), QGIS layer styles (QML), and WMS style descriptors (SLD).
"Get the QGIS style file for this layer"
β get_visualization_assets("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231")
5. Spatial Queries
Work with geographic regions and spatial coverage.
get_bbox_for_region(region_name)
Returns the WGS84 bounding box [west, south, east, north] for a named region. Supports ~50 regions:
- Countries:
brazil,usa,china,india,australia,germany,france,japan,mexico,argentina,colombia,south_africa,kenya,indonesia, etc. - Brazilian states:
goias,mato_grosso,para,minas_gerais,sao_paulo,bahia,amazonas,tocantins,maranhao,rondonia,acre,roraima,amapa, etc. - Brazilian biomes:
cerrado,amazon,amazonia_legal,caatinga,pantanal,mata_atlantica,pampa - Continents/regions:
south_america,north_america,europe,africa,asia,southeast_asia,oceania,middle_east,global
"What's the bounding box for the Cerrado biome?"
β get_bbox_for_region("cerrado")
# Returns: {"region": "cerrado", "bbox": [-60.47, -24.68, -41.28, -2.33]}
"Get the bbox for GoiΓ‘s state"
β get_bbox_for_region("goias")
find_collections_for_bbox(bbox, theme?)
Finds all collections whose spatial extent intersects the given bounding box. Optionally filters by theme.
"What soil data covers the Cerrado?"
β find_collections_for_bbox([-60.47, -24.68, -41.28, -2.33], theme="soil")
"Find all datasets available for Southeast Asia"
β find_collections_for_bbox([92.0, -11.0, 141.0, 28.0])
get_collection_spatial_coverage(collection_id)
Returns full spatial coverage: bounding box, GeoJSON polygon of the extent, ground sample distance (resolution in meters), and CRS.
"What is the spatial resolution of the elevation model?"
β get_collection_spatial_coverage("dtm.bareearth_ensemble")
6. Analysis & Code Generation
Discover data by topic, analyze temporal coverage, and generate ready-to-use code.
get_data_timeline(collection_ids)
Generates a structured timeline showing data availability across 1β10 collections. Useful for planning multi-temporal analyses.
"Show me when soil and vegetation data overlap"
β get_data_timeline(["organic.carbon_usda.6a1c", "evi_mod13q1.tmwm.inpaint"])
find_overlapping_datasets(collection_id, start_year, end_year)
Finds all other collections with temporal overlap in the given period. Useful for multi-variable correlation studies.
"What datasets overlap with land cover data between 2010 and 2020?"
β find_overlapping_datasets("land.cover_esacci.lc.l4", 2010, 2020)
get_stac_item_as_geojson(collection_id, item_id)
Returns the item as a pure GeoJSON Feature, ready for use in any GIS tool, web map, or geospatial pipeline.
"Export this item as GeoJSON"
β get_stac_item_as_geojson("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231")
build_python_snippet(collection_id, item_id, asset_key, operation)
Generates a ready-to-run Python code snippet using rasterio and matplotlib.
Operations: open, info, plot, clip_bbox, stats, export_csv
"Generate Python code to plot organic carbon data"
β build_python_snippet("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231", "organic.carbon_usda.6a1c_m_250m_b0cm", "plot")
"Generate code to compute statistics"
β build_python_snippet(..., operation="stats")
"Generate code to clip to a bounding box"
β build_python_snippet(..., operation="clip_bbox")
build_r_snippet(collection_id, item_id, asset_key, operation)
Generates a ready-to-run R code snippet using terra and sf.
Operations: open, info, plot, clip_bbox, stats, export_csv
"Generate R code to open and plot this raster"
β build_r_snippet("organic.carbon_usda.6a1c", "organic.carbon_usda.6a1c_19500101_20171231", "organic.carbon_usda.6a1c_m_250m_b0cm", "plot")
MCP Resources
Static data accessible via URI patterns:
| URI | Description |
|---|---|
stac://openlandmap/catalog | Root catalog metadata (ID, version, collection count) |
stac://openlandmap/themes | Index of all collections organized by thematic category |
stac://openlandmap/guide | Usage guide with quick-start instructions |
stac://openlandmap/collection/{id} | Full metadata for a specific collection |
stac://openlandmap/collection/{id}/item/{item_id} | Full item details including all assets |
MCP Prompts
Pre-built workflow templates for common analysis patterns:
| Prompt | Description | Parameters |
|---|---|---|
explore_collection | Step-by-step exploration of a collection (schema, temporal coverage, assets, related data) | collection_id |
find_data_for_analysis | Guided workflow to find data for a specific analysis (region + topic + period) | topic, region, period |
download_workflow | Complete data access workflow with URLs, commands, and code snippets | collection_id, item_id |
Usage Examples
"What data is available on OpenLandMap?"
"List all soil datasets"
"Find collections about organic carbon"
"Show the temporal coverage of evi_mod13q1.tmwm.inpaint"
"Find vegetation data for the Cerrado between 2015 and 2020"
"Generate a Python snippet to access EVI data"
"Compare soil collections: organic.carbon vs ph.h2o"
"What is the spatial resolution of the elevation dataset?"
"Find datasets that overlap temporally with land cover between 2010-2020"
"Generate R code to plot soil organic carbon"
"What data is available at coordinates -47.9, -15.8?"
"Export this STAC item as GeoJSON for use in QGIS"
"How do I download the bulk density dataset with curl?"
"Show me the QGIS style file for the pH collection"
Architecture
- Static catalog: Data is served from S3 (Wasabi) as static STAC JSONs β no server-side search API
- In-memory cache: Configurable TTL per resource type (1h catalog, 30min collections, 10min items)
- Lazy loading: Collections fetched on demand with concurrent batch fetch (semaphore-limited) when global filtering is needed
- No native dependencies: Pure Python and pre-built wheels only (no GDAL/GEOS compilation required)
- Retry with backoff: Automatic retry (3 attempts, exponential delays 1s/2s/4s) for all HTTP requests
- Thundering herd protection: Per-key async locks prevent duplicate fetches for the same resource
License
OpenLandMap data is distributed under CC-BY-SA-4.0.
