FastMCP server for Python-native GDAL ops (Rasterio/PyProj/pyogrio|Fiona/Shapely)
Project description
GDAL MCP
Democratizing geospatial analysis through conversational AI
GDAL MCP is a production-ready MCP server that exposes powerful geospatial operations through natural language interaction. Built with empathy for domain experts who need GDAL's capabilities without the CLI complexity.
🎉 Milestone (2025-09-30): First successful live tool invocation - GDAL operations are now conversational! 🚀 Update (2025-10-10): Phase 2A resource suite shipped (metadata/catalog/reference) – unlocking autonomous geospatial reasoning workflows.
🌟 Vision
Bridging the gap between geospatial domain experts and powerful tools.
Instead of requiring analysts to master:
- Command-line interfaces
- Python programming
- System configuration
- GDAL syntax
Users can now ask in natural language:
- "Show me the metadata for this raster"
- "Convert this to Cloud-Optimized GeoTIFF with compression"
- "Reproject this DEM to Web Mercator using cubic resampling"
The AI agent uses GDAL MCP under the hood - properly, safely, with production-quality code.
🚀 Features
- ✅ Production-Ready: First live tool invocation successful (2025-09-30)
- 🧭 Resource Discovery (0.2.0):
catalog://workspace/{all|raster|vector}/{subpath}resources expose the active workspace so agents can plan without manual file listings. - 🔍 Metadata Intelligence (0.2.0):
metadata://{file}/formatsurfaces driver/format details alongside existing raster/vector metadata. - 📚 Reference Library (0.2.0): CRS, resampling, compression, and glossary resources provide curated knowledge for agents (
reference://crs/common/{coverage}, etc.). - Python-Native Stack: Rasterio, PyProj, pyogrio, Shapely (no GDAL CLI dependency)
- 5 Core Tools:
raster_info,raster_convert,raster_reproject,raster_stats,vector_info - Type-Safe: Pydantic models with auto-generated JSON schemas
- Workspace Security: PathValidationMiddleware for secure file access (ADR-0022)
- Context Support: Real-time LLM feedback during long operations (ADR-0020)
- FastMCP 2.0: Native configuration, middleware, Context API
- CI/CD Pipeline: GitHub Actions with quality gates, test matrix, PyPI publishing
- Comprehensive Tests: 23/23 tests passing across Python 3.11-3.12
- ADR-Documented: 25 architecture decisions guiding development
📦 Installation
Method 1: uvx (Recommended)
# Run directly without installation
uvx --from gdal-mcp gdal --transport stdio
Method 2: Docker
# Build and run
docker build -t gdal-mcp .
docker run -i gdal --transport stdio
Method 3: Local Development
# Clone and install
git clone https://github.com/JordanGunn/gdal-mcp.git
cd gdal-mcp
uv sync
uv run gdal --transport stdio
See QUICKSTART.md for detailed setup instructions.
🔧 Available Tools
Raster Tools
raster_info
Inspect raster metadata using Rasterio.
Input: uri (str), optional band (int)
Output: RasterInfo with:
- Driver, CRS, bounds, transform
- Width, height, band count, dtype
- NoData value, overview levels, tags
Example: Get metadata for a GeoTIFF
{
"uri": "/data/example.tif",
"band": 1
}
raster_convert
Convert raster formats with compression, tiling, and overviews.
Input: uri (str), output (str), optional options (ConversionOptions)
Options:
driver: Output format (GTiff, COG, PNG, JPEG, etc.)compression: lzw, deflate, zstd, jpeg, packbits, nonetiled: Create tiled output (default: True)blockxsize/blockysize: Tile dimensions (default: 256×256)overviews: List of overview levels (e.g., [2, 4, 8, 16])overview_resampling: nearest, bilinear, cubic, average, mode
Example: Convert to Cloud-Optimized GeoTIFF with compression
{
"uri": "/data/input.tif",
"output": "/data/output_cog.tif",
"options": {
"driver": "COG",
"compression": "deflate",
"overviews": [2, 4, 8, 16]
}
}
raster_reproject
Reproject raster to new CRS with explicit resampling method (ADR-0011 requirement).
Input: uri (str), output (str), params (ReprojectionParams)
Required Params:
dst_crs: Target CRS (e.g., "EPSG:3857", "EPSG:4326")resampling: Resampling method (nearest, bilinear, cubic, lanczos, etc.)
Optional Params:
src_crs: Override source CRS if missing/incorrectresolution: Target pixel size as (x, y) tuplewidth/height: Explicit output dimensionsbounds: Crop to extent (left, bottom, right, top)
Example: Reproject DEM to Web Mercator with cubic resampling
{
"uri": "/data/dem.tif",
"output": "/data/dem_webmercator.tif",
"params": {
"dst_crs": "EPSG:3857",
"resampling": "cubic"
}
}
raster_stats
Compute comprehensive statistics for raster bands.
Input: uri (str), optional params (RasterStatsParams)
Optional Params:
bands: List of band indices (None = all bands)include_histogram: Generate histogram (default: False)histogram_bins: Number of bins (default: 256)percentiles: Compute specific percentiles (e.g., [25, 50, 75])sample_size: Sample random pixels for large rasters
Output: RasterStatsResult with per-band statistics:
- min, max, mean, std, median
- percentile_25, percentile_75
- valid_count, nodata_count
- Optional histogram bins
Example: Compute statistics with histogram for band 1
{
"uri": "/data/landsat.tif",
"params": {
"bands": [1],
"include_histogram": true,
"percentiles": [10, 25, 50, 75, 90]
}
}
Vector Tools
vector_info
Inspect vector dataset metadata using pyogrio (with fiona fallback).
Input: uri (str)
Output: VectorInfo with:
- Driver (e.g., "ESRI Shapefile", "GeoJSON", "GPKG")
- CRS, layer count, geometry types
- Feature count, field schema
- Spatial bounds
Example: Get metadata for Shapefile
{
"uri": "/data/parcels.shp"
}
🧪 Testing
Run the comprehensive test suite:
# All tests with pytest
uv run pytest test/ -v
# With coverage
uv run pytest test/ --cov=src --cov-report=term-missing
# Specific test file
uv run pytest test/test_raster_tools.py -v
Current Status: ✅ 58 tests passing (catalog, metadata, reference, band metadata suites)
Test fixtures create tiny synthetic datasets (10×10 rasters, 3-feature vectors) for fast validation.
🔌 Connecting to Claude Desktop
See QUICKSTART.md for full instructions. Quick version:
- Add to your Claude Desktop config (
~/Library/Application Support/Claude/claude_desktop_config.jsonon macOS):
{
"mcpServers": {
"gdal-mcp": {
"command": "uvx",
"args": ["--from", "gdal", "gdal", "--transport", "stdio"],
"env": {
"GDAL_CACHEMAX": "512"
}
}
}
}
- Restart Claude Desktop
- Test with: "Use raster_info to inspect /path/to/raster.tif"
🏗️ Architecture
Python-Native Stack (ADR-0017):
- Rasterio - Raster I/O and manipulation
- PyProj - CRS operations and transformations
- pyogrio - High-performance vector I/O (fiona fallback)
- Shapely - Geometry operations
- NumPy - Array operations and statistics
- Pydantic - Type-safe models with JSON schema
Design Principles (see docs/design/):
- ADR-0007: Structured outputs with Pydantic
- ADR-0011: Explicit resampling methods
- ADR-0012: Large outputs via ResourceRef
- ADR-0013: Per-request config isolation
- ADR-0017: Python-native over CLI shelling
📚 Documentation
- QUICKSTART.md - Setup and usage guide
- CONTRIBUTING.md - Development guide
- docs/design/ - Architecture and design docs
- docs/ADR/ - Architecture Decision Records
🤝 Contributing
We welcome contributions! See CONTRIBUTING.md for:
- Development setup
- Code style guide (Ruff + mypy)
- Testing requirements (pytest + fixtures)
- ADR process
📝 License
MIT License - see LICENSE for details.
🙏 Acknowledgments
- Built with FastMCP
- Powered by Rasterio and GDAL
- Inspired by the Model Context Protocol
🔮 Roadmap
MVP Complete ✅:
- ✅ Raster tools (info, convert, reproject, stats)
- ✅ Vector info tool
- ✅ Comprehensive tests (23/23)
- ✅ Docker deployment
- ✅ MCP client integration
0.2.0 Achievements:
- Phase 2A resources (ADR-0023) delivered: catalog discovery, metadata format inspection, knowledge/reference APIs.
- Shared reference utilities enable smarter agent planning (resampling heuristics, CRS guidance, compression catalog, glossary).
- Styleguide and ADR additions (0023–0025) guide future contributions.
Next Steps:
- Phase 2C context/history resources (session state, provenance).
- Phase 2D domain references expansion (terrain analysis guides, advanced format primers).
- Expanded spatial analysis tools and workflows powered by new reference knowledge.
Status: MVP Ready for Public Release 🚀
Built with ❤️ for the geospatial AI community.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gdal_mcp-0.2.1.tar.gz.
File metadata
- Download URL: gdal_mcp-0.2.1.tar.gz
- Upload date:
- Size: 245.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3cfe5f5d053baedd139238b24d68efd252d93668244a2f1fe1dfc22018f339eb
|
|
| MD5 |
b6b07037889a694b8c6b0f92284f1c4e
|
|
| BLAKE2b-256 |
08a873443b900e28dc04def9b61f25a4ce2be77fb4adaa727d51bf83785c433f
|
Provenance
The following attestation bundles were made for gdal_mcp-0.2.1.tar.gz:
Publisher:
publish.yml on Wayfinder-Foundry/gdal-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gdal_mcp-0.2.1.tar.gz -
Subject digest:
3cfe5f5d053baedd139238b24d68efd252d93668244a2f1fe1dfc22018f339eb - Sigstore transparency entry: 601059996
- Sigstore integration time:
-
Permalink:
Wayfinder-Foundry/gdal-mcp@6c28fd02d86b464e4185898bdebb5695f67dcc59 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/Wayfinder-Foundry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6c28fd02d86b464e4185898bdebb5695f67dcc59 -
Trigger Event:
release
-
Statement type:
File details
Details for the file gdal_mcp-0.2.1-py3-none-any.whl.
File metadata
- Download URL: gdal_mcp-0.2.1-py3-none-any.whl
- Upload date:
- Size: 70.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18cea1e0afe04819c1f9b2b555b8c17835744bab807c0661501f7b1af2dcce18
|
|
| MD5 |
d413e99831a0ea6db8c34bd76504c08a
|
|
| BLAKE2b-256 |
45fd21d5f85070a68d118fdf52ed7334861eccb13e33818c8826856dc653d36d
|
Provenance
The following attestation bundles were made for gdal_mcp-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on Wayfinder-Foundry/gdal-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gdal_mcp-0.2.1-py3-none-any.whl -
Subject digest:
18cea1e0afe04819c1f9b2b555b8c17835744bab807c0661501f7b1af2dcce18 - Sigstore transparency entry: 601059997
- Sigstore integration time:
-
Permalink:
Wayfinder-Foundry/gdal-mcp@6c28fd02d86b464e4185898bdebb5695f67dcc59 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/Wayfinder-Foundry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6c28fd02d86b464e4185898bdebb5695f67dcc59 -
Trigger Event:
release
-
Statement type: