| Name | gdal-mcp JSON |
| Version |
1.0.0
JSON |
| download |
| home_page | None |
| Summary | FastMCP server for Python-native GDAL ops (Rasterio/PyProj/pyogrio|Fiona/Shapely) |
| upload_time | 2025-10-25 01:22:08 |
| maintainer | None |
| docs_url | None |
| author | GDAL MCP Team |
| requires_python | >=3.11 |
| license | MIT License
Copyright (c) 2025 Jordan T Godau
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. |
| keywords |
gis
qgis
fastmcp
gdal
geomatics
geospatial
mcp
raster
remote sensing
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# GDAL MCP
**The first geospatial AI substrate with epistemic reasoning**
> *"Before reprojecting to EPSG:3857, why is this CRS appropriate for your analysis? What spatial properties must be preserved? What distortion tradeoffs are acceptable?"*
GDAL MCP doesn't just execute geospatial operationsโit **thinks through them**. Built on FastMCP with a reflection middleware that requires AI agents to justify methodological decisions before execution.
**๐ v1.0.0 Released (2025-10-24)** โ First MCP server with built-in epistemic governance
**๐ง Reflection System** โ Pre-execution reasoning for CRS, resampling, hydrology, and aggregation
[](https://github.com/Wayfinder-Foundry/gdal-mcp/actions/workflows/ci.yml)
[](LICENSE)
[](https://www.python.org/downloads/)
[](https://github.com/jlowin/fastmcp)
[](https://pepy.tech/projects/gdal-mcp)
## ๐ง Why Reflection Matters
**Geospatial operations have consequences.** Choosing the wrong resampling method can introduce false elevation data. Selecting an inappropriate CRS can distort area calculations by 40%. Aggregating without understanding data distribution can hide critical outliers.
**Traditional approach:**
```
User: "Reproject this DEM to Web Mercator"
AI: *immediately executes gdal.Warp()*
```
**GDAL MCP with reflection:**
```
User: "Reproject this DEM to Web Mercator for a web map"
AI: *triggered to justify CRS choice*
"Before reprojecting to EPSG:3857:
- Intent: Preserve angular relationships for web tile rendering
- Alternatives considered: EPSG:4326 (rejected: not conformal)
- Tradeoffs: Distance/area distortion at high latitudes acceptable for visualization
- Confidence: High"
*stores justification, proceeds with operation*
```
The AI doesn't just follow instructionsโit **understands the methodology**.
## ๐ฏ Real-World Examples
### Example 1: DEM Reprojection with Methodological Reasoning
**Scenario:** You need to reproject a 30m elevation model from WGS84 to UTM for slope analysis.
**User prompt:**
```
Reproject my DEM from test/data/elevation.tif to UTM Zone 10N.
I need accurate slope calculations.
```
**What happens:**
1. **AI inspects the source:** `raster_info` reveals EPSG:4326, 30m resolution
2. **Reflection triggered (CRS):**
- Why UTM Zone 10N (EPSG:32610)?
- Intent: Preserve distance accuracy for slope/aspect calculations
- Alternative: Web Mercator (EPSG:3857) โ rejected, non-conformal distortion
- Tradeoff: Limited to ~6ยฐ longitude zone, acceptable for local analysis
3. **Reflection triggered (Resampling):**
- Why cubic convolution?
- Intent: Smooth gradients while preserving elevation values
- Alternative: Nearest neighbor โ rejected, creates blocky artifacts in slope
- Alternative: Bilinear โ rejected, cubic provides superior smoothness for derivatives
4. **Execution:** Reprojection proceeds with cached justifications
5. **Result:** Properly reprojected DEM with documented methodology
**Cache behavior:** Next time you reproject *any* DEM to UTM with cubic, no re-justification needed.
### Example 2: Multi-Resolution COG Creation
**User prompt:**
```
Create a Cloud-Optimized GeoTIFF from this 10GB Landsat scene.
Optimize for web serving with multiple zoom levels.
```
**What happens:**
1. **AI plans the operation:** Convert with compression + overviews
2. **Smart defaults applied:**
- Driver: COG (Cloud-Optimized GeoTIFF)
- Compression: DEFLATE (lossless, good ratio)
- Tiling: 256ร256 blocks (web-optimized)
- Overviews: [2, 4, 8, 16] (zoom levels)
3. **Execution with real-time feedback:**
```
Building overviews [2, 4, 8, 16]...
Output: 1.2GB (88% reduction)
Validation: โ COG structure valid
```
### Example 3: Cache Intelligence
**First request:**
```
Reproject this imagery to EPSG:3857 using cubic resampling for a web map.
```
โ Triggers both CRS and resampling justifications (~30 seconds)
**Second request (same session):**
```
Now reproject this other tile to EPSG:3857 with cubic for the same map.
```
โ Cache hit! Both justifications reused (instant)
**Third request (different parameter):**
```
Actually, use bilinear instead to reduce processing time.
```
โ CRS justification cached, only resampling re-justified
## โก Key Features
### ๐ง Reflection System (v1.0.0)
**The core innovation:** FastMCP middleware that intercepts tool calls and enforces epistemic discipline.
- **Pre-execution reasoning prompts** for operations with methodological implications
- **Structured justifications** (intent โ alternatives โ choice โ tradeoffs โ confidence)
- **Persistent cache** (`.preflight/justifications/{domain}/`) with SHA256-based lookup
- **Domain-specific reasoning:** CRS/datum, resampling, hydrology conditioning, aggregation
- **Automatic cache hits:** Same parameters = instant execution (no re-justification)
**Reflection domains:**
- `crs_datum` โ Coordinate system selection and datum transformations
- `resampling` โ Interpolation method choice for raster operations
- `hydrology` โ Flow direction, watershed delineation, DEM conditioning *(planned)*
- `aggregation` โ Zonal statistics, temporal composites, data fusion *(planned)*
**How it works:**
1. User requests operation with methodological choices (e.g., "reproject to UTM")
2. Middleware intercepts `raster_reproject` call, checks cache
3. If no justification exists โ triggers `justify_crs_selection` prompt
4. AI provides structured reasoning โ stored with hash key
5. Operation proceeds with validated methodology
6. Future requests with same parameters skip justification (cache hit)
**See:** [test/REFLECTION_TESTING.md](test/REFLECTION_TESTING.md) for comprehensive testing guide with 7 scenarios
### ๐ก๏ธ Production Quality
- **Type-safe:** Full mypy strict mode, Pydantic models with JSON schemas
- **Tested:** 72 passing tests including reflection system integration
- **Secure:** PathValidationMiddleware for workspace isolation (no directory traversal)
- **Fast:** Python-native (Rasterio/GDAL bindings, no CLI shelling)
- **Observable:** Real-time feedback during long operations via FastMCP Context API
### Resources & Discovery
- **๐งญ Workspace Catalog**: `catalog://workspace/{all|raster|vector}/{subpath}` for autonomous planning
- **๐ Metadata Intelligence**: `metadata://{file}/format` for driver/format details
- **๐ Reference Library**: CRS, resampling, compression, glossary knowledge (`reference://crs/common/{coverage}`)
### Infrastructure
- **FastMCP 2.0**: Native configuration, middleware, Context API
- **CI/CD Pipeline**: GitHub Actions with quality gates, test matrix, PyPI publishing
- **ADR-Documented**: 26 architecture decisions guiding development
## ๐ฆ Installation
### Method 1: uvx (Recommended)
```bash
# Run directly without installation
uvx --from gdal-mcp gdal --transport stdio
```
### Method 2: Docker
```bash
# Build and run
docker build -t gdal-mcp .
docker run -i gdal --transport stdio
```
### Method 3: Local Development
```bash
# 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](docs/QUICKSTART.md) for detailed setup instructions.
### Method 4: Dev Container (For Contributors)
Use VS Code with the provided devcontainer for a pre-configured development environment:
```bash
# Open in VS Code and select "Reopen in Container"
# Everything is set up automatically!
```
See [CONTRIBUTING.md](CONTRIBUTING.md) and [`.devcontainer/README.md`](.devcontainer/README.md) for details.
---
See [QUICKSTART.md](QUICKSTART.md) for detailed setup instructions.
## ๐ง Available Tools
### Raster Tools
#### `raster_info`
Inspect raster metadata without reading pixel data.
**Use cases:** Understand projection, resolution, extent before processing
**Input:** `uri` (path to raster)
**Output:** Driver, CRS, bounds, transform, dimensions, data type, nodata value, overview levels
**Example conversation:**
```
User: "What's the CRS and resolution of elevation.tif?"
AI: *calls raster_info*
"The DEM is in EPSG:4326 (WGS84) with 0.000277ยฐ resolution (~30m at equator).
It covers bounds: [-122.5, 37.5, -122.0, 38.0]"
```
#### `raster_convert`
Format conversion with compression and multi-resolution overviews.
**Use cases:** Create Cloud-Optimized GeoTIFFs, reduce file size, build pyramids for fast rendering
**Key options:**
- `driver`: GTiff, COG, PNG, JPEG (COG = Cloud-Optimized GeoTIFF)
- `compression`: deflate, lzw, zstd, jpeg (case-insensitive)
- `tiled`: 256ร256 blocks for efficient partial reads
- `overviews`: [2, 4, 8, 16] for multi-resolution display
**Example conversation:**
```
User: "Optimize this 5GB satellite image for web serving"
AI: "Converting to COG with DEFLATE compression and overviews..."
*calls raster_convert with driver=COG, compression=deflate, overviews=[2,4,8,16]*
"Done! Reduced to 1.2GB (76% savings). Ready for cloud storage with efficient range requests."
```
#### `raster_reproject` โก *Reflection-enabled*
Reproject to new coordinate system with methodological justification.
**๐ง Triggers reflection for:**
- **CRS selection** โ Why this projection? What properties must be preserved?
- **Resampling method** โ How to interpolate? What artifacts are acceptable?
**Use cases:** Transform to analysis-appropriate CRS, align multiple datasets, prepare for web mapping
**Required parameters:**
- `dst_crs`: Target projection (e.g., "EPSG:32610" for UTM Zone 10N)
- `resampling`: Interpolation method
- `nearest` โ Categorical data (land cover, classified imagery)
- `bilinear` โ Fast, good for continuous data
- `cubic` โ Smoothest, best for DEMs and visualization
- `lanczos` โ Highest quality, slower
**Optional parameters:**
- `resolution`: Target pixel size [x, y] in destination units
- `bounds`: Crop to area of interest [left, bottom, right, top]
**Example conversation:**
```
User: "Reproject this land cover map to UTM for area calculations"
AI: *raster_info shows categorical data*
*reflection: Why UTM? โ accurate area/distance in local zone*
*reflection: Why nearest? โ preserves exact class values, no new categories*
"Reprojecting to EPSG:32610 with nearest-neighbor to preserve classification..."
*executes with justified methodology*
```
#### `raster_stats`
Compute statistical summaries and histograms.
**Use cases:** Understand data distribution, find outliers, validate processing results
**Output:** min, max, mean, std, median, percentiles, histogram (optional)
**Example conversation:**
```
User: "Check the elevation range in this DEM"
AI: *calls raster_stats*
"Elevation ranges from 145m to 2,847m with mean 892m.
Distribution shows two peaks (bimodal) - likely valley and ridge areas."
```
### Vector Tools
#### `vector_info`
Inspect vector dataset metadata (Shapefile, GeoJSON, GeoPackage, etc.).
**Output:** Driver, CRS, geometry types, feature count, field schema, bounds
**Example conversation:**
```
User: "What's in this shapefile?"
AI: *calls vector_info*
"It's a polygon layer with 1,247 parcels in EPSG:2227 (California State Plane).
Fields: parcel_id (string), area_sqft (float), zoning (string), assessed_value (int)"
```
### Reflection Tools
#### `store_justification`
Explicitly cache epistemic justifications (used internally by reflection system).
**Purpose:** Allows AI to store methodological reasoning for future operations
**When called:** Automatically after reflection prompts, or manually for custom workflows
**Cache structure:** `.preflight/justifications/{domain}/sha256:{hash}.json`
## ๐งช Testing
Run the comprehensive test suite:
```bash
# 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**: โ
72 tests passing (includes reflection system, prompts, and full integration suite)
Test fixtures create tiny synthetic datasets (10ร10 rasters, 3-feature vectors) for fast validation.
## ๐ Connecting to Claude Desktop
See [QUICKSTART.md](docs/QUICKSTART.md) for full instructions. Quick version:
1. Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"gdal-mcp": {
"command": "uvx",
"args": ["--from", "gdal", "gdal", "--transport", "stdio"],
"env": {
"GDAL_CACHEMAX": "512"
}
}
}
}
```
2. Restart Claude Desktop
3. 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/](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
**Getting Started:**
- [QUICKSTART.md](docs/QUICKSTART.md) โ Installation and Claude Desktop setup
- [REFLECTION_TESTING.md](test/REFLECTION_TESTING.md) โ Testing the reflection system
**Development:**
- [CONTRIBUTING.md](docs/CONTRIBUTING.md) โ Development guide and standards
- [docs/design/](docs/design/) โ Architecture and design documentation
- [docs/ADR/](docs/ADR/) โ 26 Architecture Decision Records
**Key ADRs:**
- [ADR-0026](docs/ADR/0026-prompting-and-epistemic-governance.md) โ Reflection system design
- [ADR-0011](docs/ADR/0011-explicit-resampling-required.md) โ Why resampling must be explicit
- [ADR-0017](docs/ADR/0017-python-native-over-cli.md) โ Python bindings over CLI shelling
- [ADR-0022](docs/ADR/0022-path-validation-middleware.md) โ Workspace isolation security
## ๐ค Contributing
We welcome contributions! See [CONTRIBUTING.md](docs/CONTRIBUTING.md) for:
- Development setup
- Code style guide (Ruff + mypy)
- Testing requirements (pytest + fixtures)
- ADR process
## ๐ License
MIT License - see [LICENSE](LICENSE) for details.
## ๐ Acknowledgments
- Built with [FastMCP](https://github.com/jlowin/fastmcp)
- Powered by [Rasterio](https://github.com/rasterio/rasterio) and [GDAL](https://gdal.org)
- Inspired by the [Model Context Protocol](https://modelcontextprotocol.io)
## ๐บ๏ธ Roadmap
### โ
v1.0.0 โ Epistemic Foundation (Released 2025-10-24)
**Reflection middleware:**
- Pre-execution reasoning for CRS selection and resampling methods
- Persistent justification cache with SHA256-based lookup
- Structured justifications (intent, alternatives, choice, tradeoffs, confidence)
- Integration with `raster_reproject` tool
**Production infrastructure:**
- Full type safety (mypy strict mode)
- 72 passing tests with reflection system coverage
- PathValidationMiddleware for workspace security
- FastMCP 2.0 with native middleware support
### ๐ง v1.1.0 โ Extended Reflection Domains (Q1 2025)
**New reflection triggers:**
- Hydrology conditioning (DEM preprocessing, flow accumulation parameters)
- Aggregation strategies (zonal statistics, temporal composites, resampling for aggregation)
- Format selection (when to use COG vs JPEG vs PNG, compression tradeoffs)
**Workflow composition:**
- Multi-step analysis discovery ("analyze watershed from this DEM")
- Chain justifications (reproject โ condition โ flow direction โ watershed)
- Provenance tracking across operations
### ๐ฎ v2.0.0 โ Analysis Primitives (Q2 2025)
**Vector analysis:**
- Spatial joins and overlays with geometric reasoning
- Buffer/clip operations with distance unit justification
- Attribute queries with SQL generation
**Raster analysis:**
- Classification with threshold justification
- Raster calculator with band math validation
- Zonal statistics with aggregation reflection
- Contour generation with interval selection
**Semantic capabilities:**
- Urban area detection from imagery
- Terrain analysis workflows (slope โ aspect โ hillshade)
- Water body classification with spectral reasoning
See [docs/ROADMAP.md](docs/ROADMAP.md) for detailed milestones and technical planning.
---
## ๐ Learn More
- **[Quick Start Guide](docs/QUICKSTART.md)** โ Setup and first operations
- **[Reflection Testing Guide](test/REFLECTION_TESTING.md)** โ 7 scenarios testing cache behavior
- **[Architecture Decisions](docs/ADR/)** โ 26 ADRs documenting design choices
- **[Contributing Guide](docs/CONTRIBUTING.md)** โ Development setup and standards
---
**Status:** v1.0.0 Production Release ๐
*The first geospatial MCP server that doesn't just execute operationsโit reasons about them.*
**Core innovation:** Epistemic governance through reflection middleware. AI agents must justify methodological choices (CRS, resampling, aggregation) before execution. Justifications are cached for workflow efficiency while maintaining scientific rigor.
**Vision:** Enable discovery of novel geospatial analysis workflows through tool composition with domain understanding, not just prescribed procedures.
Built with โค๏ธ for the geospatial AI community.
Raw data
{
"_id": null,
"home_page": null,
"name": "gdal-mcp",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "GIS, QGIS, fastmcp, gdal, geomatics, geospatial, mcp, raster, remote sensing",
"author": "GDAL MCP Team",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/38/4f/a5d1e1ee5c839372201b80bc0527a073a4985b03db282c0c7bea044cfcf4/gdal_mcp-1.0.0.tar.gz",
"platform": null,
"description": "# GDAL MCP\n\n**The first geospatial AI substrate with epistemic reasoning**\n\n> *\"Before reprojecting to EPSG:3857, why is this CRS appropriate for your analysis? What spatial properties must be preserved? What distortion tradeoffs are acceptable?\"*\n\nGDAL MCP doesn't just execute geospatial operations\u2014it **thinks through them**. Built on FastMCP with a reflection middleware that requires AI agents to justify methodological decisions before execution.\n\n**\ud83c\udf89 v1.0.0 Released (2025-10-24)** \u2014 First MCP server with built-in epistemic governance \n**\ud83e\udde0 Reflection System** \u2014 Pre-execution reasoning for CRS, resampling, hydrology, and aggregation\n\n[](https://github.com/Wayfinder-Foundry/gdal-mcp/actions/workflows/ci.yml)\n[](LICENSE)\n[](https://www.python.org/downloads/)\n[](https://github.com/jlowin/fastmcp)\n[](https://pepy.tech/projects/gdal-mcp)\n\n## \ud83e\udde0 Why Reflection Matters\n\n**Geospatial operations have consequences.** Choosing the wrong resampling method can introduce false elevation data. Selecting an inappropriate CRS can distort area calculations by 40%. Aggregating without understanding data distribution can hide critical outliers.\n\n**Traditional approach:**\n```\nUser: \"Reproject this DEM to Web Mercator\"\nAI: *immediately executes gdal.Warp()*\n```\n\n**GDAL MCP with reflection:**\n```\nUser: \"Reproject this DEM to Web Mercator for a web map\"\nAI: *triggered to justify CRS choice*\n \"Before reprojecting to EPSG:3857:\n - Intent: Preserve angular relationships for web tile rendering\n - Alternatives considered: EPSG:4326 (rejected: not conformal)\n - Tradeoffs: Distance/area distortion at high latitudes acceptable for visualization\n - Confidence: High\"\n*stores justification, proceeds with operation*\n```\n\nThe AI doesn't just follow instructions\u2014it **understands the methodology**.\n\n## \ud83c\udfaf Real-World Examples\n\n### Example 1: DEM Reprojection with Methodological Reasoning\n\n**Scenario:** You need to reproject a 30m elevation model from WGS84 to UTM for slope analysis.\n\n**User prompt:**\n```\nReproject my DEM from test/data/elevation.tif to UTM Zone 10N. \nI need accurate slope calculations.\n```\n\n**What happens:**\n\n1. **AI inspects the source:** `raster_info` reveals EPSG:4326, 30m resolution\n2. **Reflection triggered (CRS):**\n - Why UTM Zone 10N (EPSG:32610)?\n - Intent: Preserve distance accuracy for slope/aspect calculations\n - Alternative: Web Mercator (EPSG:3857) \u2014 rejected, non-conformal distortion\n - Tradeoff: Limited to ~6\u00b0 longitude zone, acceptable for local analysis\n3. **Reflection triggered (Resampling):**\n - Why cubic convolution?\n - Intent: Smooth gradients while preserving elevation values\n - Alternative: Nearest neighbor \u2014 rejected, creates blocky artifacts in slope\n - Alternative: Bilinear \u2014 rejected, cubic provides superior smoothness for derivatives\n4. **Execution:** Reprojection proceeds with cached justifications\n5. **Result:** Properly reprojected DEM with documented methodology\n\n**Cache behavior:** Next time you reproject *any* DEM to UTM with cubic, no re-justification needed.\n\n### Example 2: Multi-Resolution COG Creation\n\n**User prompt:**\n```\nCreate a Cloud-Optimized GeoTIFF from this 10GB Landsat scene.\nOptimize for web serving with multiple zoom levels.\n```\n\n**What happens:**\n\n1. **AI plans the operation:** Convert with compression + overviews\n2. **Smart defaults applied:**\n - Driver: COG (Cloud-Optimized GeoTIFF)\n - Compression: DEFLATE (lossless, good ratio)\n - Tiling: 256\u00d7256 blocks (web-optimized)\n - Overviews: [2, 4, 8, 16] (zoom levels)\n3. **Execution with real-time feedback:**\n ```\n Building overviews [2, 4, 8, 16]...\n Output: 1.2GB (88% reduction)\n Validation: \u2713 COG structure valid\n ```\n\n### Example 3: Cache Intelligence\n\n**First request:**\n```\nReproject this imagery to EPSG:3857 using cubic resampling for a web map.\n```\n\u2192 Triggers both CRS and resampling justifications (~30 seconds)\n\n**Second request (same session):**\n```\nNow reproject this other tile to EPSG:3857 with cubic for the same map.\n```\n\u2192 Cache hit! Both justifications reused (instant)\n\n**Third request (different parameter):**\n```\nActually, use bilinear instead to reduce processing time.\n```\n\u2192 CRS justification cached, only resampling re-justified\n\n## \u26a1 Key Features\n\n### \ud83e\udde0 Reflection System (v1.0.0)\n\n**The core innovation:** FastMCP middleware that intercepts tool calls and enforces epistemic discipline.\n\n- **Pre-execution reasoning prompts** for operations with methodological implications\n- **Structured justifications** (intent \u2192 alternatives \u2192 choice \u2192 tradeoffs \u2192 confidence)\n- **Persistent cache** (`.preflight/justifications/{domain}/`) with SHA256-based lookup\n- **Domain-specific reasoning:** CRS/datum, resampling, hydrology conditioning, aggregation\n- **Automatic cache hits:** Same parameters = instant execution (no re-justification)\n\n**Reflection domains:**\n- `crs_datum` \u2014 Coordinate system selection and datum transformations\n- `resampling` \u2014 Interpolation method choice for raster operations \n- `hydrology` \u2014 Flow direction, watershed delineation, DEM conditioning *(planned)*\n- `aggregation` \u2014 Zonal statistics, temporal composites, data fusion *(planned)*\n\n**How it works:**\n1. User requests operation with methodological choices (e.g., \"reproject to UTM\")\n2. Middleware intercepts `raster_reproject` call, checks cache\n3. If no justification exists \u2192 triggers `justify_crs_selection` prompt\n4. AI provides structured reasoning \u2192 stored with hash key\n5. Operation proceeds with validated methodology\n6. Future requests with same parameters skip justification (cache hit)\n\n**See:** [test/REFLECTION_TESTING.md](test/REFLECTION_TESTING.md) for comprehensive testing guide with 7 scenarios\n\n### \ud83d\udee1\ufe0f Production Quality\n\n- **Type-safe:** Full mypy strict mode, Pydantic models with JSON schemas\n- **Tested:** 72 passing tests including reflection system integration\n- **Secure:** PathValidationMiddleware for workspace isolation (no directory traversal)\n- **Fast:** Python-native (Rasterio/GDAL bindings, no CLI shelling)\n- **Observable:** Real-time feedback during long operations via FastMCP Context API\n\n### Resources & Discovery\n- **\ud83e\udded Workspace Catalog**: `catalog://workspace/{all|raster|vector}/{subpath}` for autonomous planning\n- **\ud83d\udd0d Metadata Intelligence**: `metadata://{file}/format` for driver/format details\n- **\ud83d\udcda Reference Library**: CRS, resampling, compression, glossary knowledge (`reference://crs/common/{coverage}`)\n\n### Infrastructure\n- **FastMCP 2.0**: Native configuration, middleware, Context API\n- **CI/CD Pipeline**: GitHub Actions with quality gates, test matrix, PyPI publishing\n- **ADR-Documented**: 26 architecture decisions guiding development\n\n## \ud83d\udce6 Installation\n\n### Method 1: uvx (Recommended)\n\n```bash\n# Run directly without installation\nuvx --from gdal-mcp gdal --transport stdio\n```\n\n### Method 2: Docker\n\n```bash\n# Build and run\ndocker build -t gdal-mcp .\ndocker run -i gdal --transport stdio\n```\n\n### Method 3: Local Development\n\n```bash\n# Clone and install\ngit clone https://github.com/JordanGunn/gdal-mcp.git\ncd gdal-mcp\nuv sync\nuv run gdal --transport stdio\n```\n\nSee [QUICKSTART.md](docs/QUICKSTART.md) for detailed setup instructions.\n### Method 4: Dev Container (For Contributors)\n\nUse VS Code with the provided devcontainer for a pre-configured development environment:\n\n```bash\n# Open in VS Code and select \"Reopen in Container\"\n# Everything is set up automatically!\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) and [`.devcontainer/README.md`](.devcontainer/README.md) for details.\n\n---\n\nSee [QUICKSTART.md](QUICKSTART.md) for detailed setup instructions.\n\n## \ud83d\udd27 Available Tools\n\n### Raster Tools\n\n#### `raster_info`\nInspect raster metadata without reading pixel data.\n\n**Use cases:** Understand projection, resolution, extent before processing\n\n**Input:** `uri` (path to raster)\n\n**Output:** Driver, CRS, bounds, transform, dimensions, data type, nodata value, overview levels\n\n**Example conversation:**\n```\nUser: \"What's the CRS and resolution of elevation.tif?\"\nAI: *calls raster_info*\n \"The DEM is in EPSG:4326 (WGS84) with 0.000277\u00b0 resolution (~30m at equator).\n It covers bounds: [-122.5, 37.5, -122.0, 38.0]\"\n```\n\n#### `raster_convert`\nFormat conversion with compression and multi-resolution overviews.\n\n**Use cases:** Create Cloud-Optimized GeoTIFFs, reduce file size, build pyramids for fast rendering\n\n**Key options:**\n- `driver`: GTiff, COG, PNG, JPEG (COG = Cloud-Optimized GeoTIFF)\n- `compression`: deflate, lzw, zstd, jpeg (case-insensitive)\n- `tiled`: 256\u00d7256 blocks for efficient partial reads\n- `overviews`: [2, 4, 8, 16] for multi-resolution display\n\n**Example conversation:**\n```\nUser: \"Optimize this 5GB satellite image for web serving\"\nAI: \"Converting to COG with DEFLATE compression and overviews...\"\n *calls raster_convert with driver=COG, compression=deflate, overviews=[2,4,8,16]*\n \"Done! Reduced to 1.2GB (76% savings). Ready for cloud storage with efficient range requests.\"\n```\n\n#### `raster_reproject` \u26a1 *Reflection-enabled*\nReproject to new coordinate system with methodological justification.\n\n**\ud83e\udde0 Triggers reflection for:**\n- **CRS selection** \u2014 Why this projection? What properties must be preserved?\n- **Resampling method** \u2014 How to interpolate? What artifacts are acceptable?\n\n**Use cases:** Transform to analysis-appropriate CRS, align multiple datasets, prepare for web mapping\n\n**Required parameters:**\n- `dst_crs`: Target projection (e.g., \"EPSG:32610\" for UTM Zone 10N)\n- `resampling`: Interpolation method\n - `nearest` \u2014 Categorical data (land cover, classified imagery)\n - `bilinear` \u2014 Fast, good for continuous data\n - `cubic` \u2014 Smoothest, best for DEMs and visualization\n - `lanczos` \u2014 Highest quality, slower\n\n**Optional parameters:**\n- `resolution`: Target pixel size [x, y] in destination units\n- `bounds`: Crop to area of interest [left, bottom, right, top]\n\n**Example conversation:**\n```\nUser: \"Reproject this land cover map to UTM for area calculations\"\nAI: *raster_info shows categorical data*\n *reflection: Why UTM? \u2192 accurate area/distance in local zone*\n *reflection: Why nearest? \u2192 preserves exact class values, no new categories*\n \"Reprojecting to EPSG:32610 with nearest-neighbor to preserve classification...\"\n *executes with justified methodology*\n```\n\n#### `raster_stats`\nCompute statistical summaries and histograms.\n\n**Use cases:** Understand data distribution, find outliers, validate processing results\n\n**Output:** min, max, mean, std, median, percentiles, histogram (optional)\n\n**Example conversation:**\n```\nUser: \"Check the elevation range in this DEM\"\nAI: *calls raster_stats*\n \"Elevation ranges from 145m to 2,847m with mean 892m.\n Distribution shows two peaks (bimodal) - likely valley and ridge areas.\"\n```\n\n### Vector Tools\n\n#### `vector_info`\nInspect vector dataset metadata (Shapefile, GeoJSON, GeoPackage, etc.).\n\n**Output:** Driver, CRS, geometry types, feature count, field schema, bounds\n\n**Example conversation:**\n```\nUser: \"What's in this shapefile?\"\nAI: *calls vector_info*\n \"It's a polygon layer with 1,247 parcels in EPSG:2227 (California State Plane).\n Fields: parcel_id (string), area_sqft (float), zoning (string), assessed_value (int)\"\n```\n\n### Reflection Tools\n\n#### `store_justification`\nExplicitly cache epistemic justifications (used internally by reflection system).\n\n**Purpose:** Allows AI to store methodological reasoning for future operations\n\n**When called:** Automatically after reflection prompts, or manually for custom workflows\n\n**Cache structure:** `.preflight/justifications/{domain}/sha256:{hash}.json`\n\n## \ud83e\uddea Testing\n\nRun the comprehensive test suite:\n\n```bash\n# All tests with pytest\nuv run pytest test/ -v\n\n# With coverage\nuv run pytest test/ --cov=src --cov-report=term-missing\n\n# Specific test file\nuv run pytest test/test_raster_tools.py -v\n```\n\n**Current Status**: \u2705 72 tests passing (includes reflection system, prompts, and full integration suite)\n\nTest fixtures create tiny synthetic datasets (10\u00d710 rasters, 3-feature vectors) for fast validation.\n\n## \ud83d\udd0c Connecting to Claude Desktop\n\nSee [QUICKSTART.md](docs/QUICKSTART.md) for full instructions. Quick version:\n\n1. Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):\n\n```json\n{\n \"mcpServers\": {\n \"gdal-mcp\": {\n \"command\": \"uvx\",\n \"args\": [\"--from\", \"gdal\", \"gdal\", \"--transport\", \"stdio\"],\n \"env\": {\n \"GDAL_CACHEMAX\": \"512\"\n }\n }\n }\n}\n```\n\n2. Restart Claude Desktop\n3. Test with: \"Use raster_info to inspect /path/to/raster.tif\"\n\n## \ud83c\udfd7\ufe0f Architecture\n\n**Python-Native Stack** (ADR-0017):\n- **Rasterio** - Raster I/O and manipulation\n- **PyProj** - CRS operations and transformations\n- **pyogrio** - High-performance vector I/O (fiona fallback)\n- **Shapely** - Geometry operations\n- **NumPy** - Array operations and statistics\n- **Pydantic** - Type-safe models with JSON schema\n\n**Design Principles** (see [docs/design/](docs/design/)):\n- ADR-0007: Structured outputs with Pydantic\n- ADR-0011: Explicit resampling methods\n- ADR-0012: Large outputs via ResourceRef\n- ADR-0013: Per-request config isolation\n- ADR-0017: Python-native over CLI shelling\n\n## \ud83d\udcda Documentation\n\n**Getting Started:**\n- [QUICKSTART.md](docs/QUICKSTART.md) \u2014 Installation and Claude Desktop setup\n- [REFLECTION_TESTING.md](test/REFLECTION_TESTING.md) \u2014 Testing the reflection system\n\n**Development:**\n- [CONTRIBUTING.md](docs/CONTRIBUTING.md) \u2014 Development guide and standards\n- [docs/design/](docs/design/) \u2014 Architecture and design documentation\n- [docs/ADR/](docs/ADR/) \u2014 26 Architecture Decision Records\n\n**Key ADRs:**\n- [ADR-0026](docs/ADR/0026-prompting-and-epistemic-governance.md) \u2014 Reflection system design\n- [ADR-0011](docs/ADR/0011-explicit-resampling-required.md) \u2014 Why resampling must be explicit\n- [ADR-0017](docs/ADR/0017-python-native-over-cli.md) \u2014 Python bindings over CLI shelling\n- [ADR-0022](docs/ADR/0022-path-validation-middleware.md) \u2014 Workspace isolation security\n\n## \ud83e\udd1d Contributing\n\nWe welcome contributions! See [CONTRIBUTING.md](docs/CONTRIBUTING.md) for:\n- Development setup\n- Code style guide (Ruff + mypy)\n- Testing requirements (pytest + fixtures)\n- ADR process\n\n## \ud83d\udcdd License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## \ud83d\ude4f Acknowledgments\n\n- Built with [FastMCP](https://github.com/jlowin/fastmcp)\n- Powered by [Rasterio](https://github.com/rasterio/rasterio) and [GDAL](https://gdal.org)\n- Inspired by the [Model Context Protocol](https://modelcontextprotocol.io)\n\n## \ud83d\uddfa\ufe0f Roadmap\n\n### \u2705 v1.0.0 \u2014 Epistemic Foundation (Released 2025-10-24)\n\n**Reflection middleware:**\n- Pre-execution reasoning for CRS selection and resampling methods\n- Persistent justification cache with SHA256-based lookup\n- Structured justifications (intent, alternatives, choice, tradeoffs, confidence)\n- Integration with `raster_reproject` tool\n\n**Production infrastructure:**\n- Full type safety (mypy strict mode)\n- 72 passing tests with reflection system coverage\n- PathValidationMiddleware for workspace security\n- FastMCP 2.0 with native middleware support\n\n### \ud83d\udea7 v1.1.0 \u2014 Extended Reflection Domains (Q1 2025)\n\n**New reflection triggers:**\n- Hydrology conditioning (DEM preprocessing, flow accumulation parameters)\n- Aggregation strategies (zonal statistics, temporal composites, resampling for aggregation)\n- Format selection (when to use COG vs JPEG vs PNG, compression tradeoffs)\n\n**Workflow composition:**\n- Multi-step analysis discovery (\"analyze watershed from this DEM\")\n- Chain justifications (reproject \u2192 condition \u2192 flow direction \u2192 watershed)\n- Provenance tracking across operations\n\n### \ud83d\udd2e v2.0.0 \u2014 Analysis Primitives (Q2 2025)\n\n**Vector analysis:**\n- Spatial joins and overlays with geometric reasoning\n- Buffer/clip operations with distance unit justification\n- Attribute queries with SQL generation\n\n**Raster analysis:**\n- Classification with threshold justification\n- Raster calculator with band math validation\n- Zonal statistics with aggregation reflection\n- Contour generation with interval selection\n\n**Semantic capabilities:**\n- Urban area detection from imagery\n- Terrain analysis workflows (slope \u2192 aspect \u2192 hillshade)\n- Water body classification with spectral reasoning\n\nSee [docs/ROADMAP.md](docs/ROADMAP.md) for detailed milestones and technical planning.\n\n---\n\n## \ud83c\udf93 Learn More\n\n- **[Quick Start Guide](docs/QUICKSTART.md)** \u2014 Setup and first operations\n- **[Reflection Testing Guide](test/REFLECTION_TESTING.md)** \u2014 7 scenarios testing cache behavior\n- **[Architecture Decisions](docs/ADR/)** \u2014 26 ADRs documenting design choices\n- **[Contributing Guide](docs/CONTRIBUTING.md)** \u2014 Development setup and standards\n\n---\n\n**Status:** v1.0.0 Production Release \ud83d\ude80\n\n*The first geospatial MCP server that doesn't just execute operations\u2014it reasons about them.*\n\n**Core innovation:** Epistemic governance through reflection middleware. AI agents must justify methodological choices (CRS, resampling, aggregation) before execution. Justifications are cached for workflow efficiency while maintaining scientific rigor.\n\n**Vision:** Enable discovery of novel geospatial analysis workflows through tool composition with domain understanding, not just prescribed procedures.\n\nBuilt with \u2764\ufe0f for the geospatial AI community.\n",
"bugtrack_url": null,
"license": "MIT License\n \n Copyright (c) 2025 Jordan T Godau\n \n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.",
"summary": "FastMCP server for Python-native GDAL ops (Rasterio/PyProj/pyogrio|Fiona/Shapely)",
"version": "1.0.0",
"project_urls": {
"Documentation": "https://github.com/Wayfinder-Foundry/gdal-mcp",
"Homepage": "https://github.com/Wayfinder-Foundry/gdal-mcp"
},
"split_keywords": [
"gis",
" qgis",
" fastmcp",
" gdal",
" geomatics",
" geospatial",
" mcp",
" raster",
" remote sensing"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "49ac4e76a1241fa88282011906adcec1285e8dbe4498b6e7973baaf851176fc3",
"md5": "71ebe7e4fdd4a8560f552cc7107992aa",
"sha256": "22b83aed465e9630633d94b7aab675c1dce1796228805bbc62b9211e2af5e64d"
},
"downloads": -1,
"filename": "gdal_mcp-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "71ebe7e4fdd4a8560f552cc7107992aa",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 92326,
"upload_time": "2025-10-25T01:22:07",
"upload_time_iso_8601": "2025-10-25T01:22:07.642252Z",
"url": "https://files.pythonhosted.org/packages/49/ac/4e76a1241fa88282011906adcec1285e8dbe4498b6e7973baaf851176fc3/gdal_mcp-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "384fa5d1e1ee5c839372201b80bc0527a073a4985b03db282c0c7bea044cfcf4",
"md5": "47fc5aac43ebad89840bb79fe5a4cd1e",
"sha256": "c384b6f1ec52cafc324753c4401da32b583bc499047090bc31dfdeba85c942fa"
},
"downloads": -1,
"filename": "gdal_mcp-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "47fc5aac43ebad89840bb79fe5a4cd1e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 388571,
"upload_time": "2025-10-25T01:22:08",
"upload_time_iso_8601": "2025-10-25T01:22:08.928069Z",
"url": "https://files.pythonhosted.org/packages/38/4f/a5d1e1ee5c839372201b80bc0527a073a4985b03db282c0c7bea044cfcf4/gdal_mcp-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-25 01:22:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Wayfinder-Foundry",
"github_project": "gdal-mcp",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "gdal-mcp"
}