mcp server
georescue
Audit-first GIS data-quality checks and logged, reviewable repairs for parcel datasets, with deed/COGO verification and an MCP server for AI agents.
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
{
"mcpServers": {
"georescue": {
"command": "uvx",
"args": [
"georescue"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 28, 2026Status: early prototype, work in progress.
Test demo — not authoritative. Not a survey, title opinion, or legal determination; for testing and demonstration only. Results are automated, experimental data quality test results computed from public data. Verdicts are proposals, not findings; placements of deed descriptions are best-fit, not measured in the field. Consult a licensed surveyor and mapper or an attorney and the official records. GeoRescue is not affiliated with the City of Jacksonville, the Duval County Clerk of Courts or the Duval County Property Appraiser. See TERMS.md. Questions, corrections or removal requests: open an issue at https://github.com/knightchrism/georescue/issues
What it does
- Inspects parcel layers (SHP / GPKG / GeoJSON) for invalid or empty geometry, duplicate IDs and geometries, CRS problems, out-of-bounds features, overlaps, slivers, gaps and attribute-rule violations (YAML rules, Pydantic-validated).
- Proposes repairs on a copy — the source file is never modified; every proposed change is written to
changelog.csvwith before/after, reason and whether it was applied (an audit trail for review). - Checks overlaps against the record: appraiser legal descriptions, deed OCR, metes-and-bounds / COGO traverses and closure, compared back to the GIS fabric (
verify/). - Publishes a static dashboard with per-case evidence pages, owner names redacted by default.
- Talks to agents through an MCP server backed by a redacted DuckDB results store.
Architecture
flowchart LR
A[Parcel layer<br/>SHP · GPKG · GeoJSON · ArcGIS REST] --> B[inspect<br/>checks.py + YAML rules]
B --> C[repair on a copy<br/>repair.py]
C --> D[(out/<br/>corrected.gpkg · changelog.csv<br/>issues.csv · diff.csv · report.html)]
B --> V[verify/<br/>PAO legal desc · deed OCR · COGO · PLSS]
D --> P[publish<br/>redact owners]
V --> P
P --> S[Static site<br/>GitHub Pages]
D --> L[load-db<br/>redacted DuckDB]
L --> M[georescue-mcp<br/>read-only tools · logs/mcp.log]
M --> AG[AI agent<br/>Claude · Cursor · ...]
Quickstart
git clone https://github.com/knightchrism/georescue.git && cd georescue
uv sync --extra verify
PYTHONPATH=. uv run --extra verify pytest -q # test suite
uv run georescue inspect data.gpkg -c configs/columbia_fl.yaml
uv run georescue repair data.gpkg -c configs/columbia_fl.yaml -o out/
On Windows, clone to a local folder such as C:\dev\georescue (keep projects out of OneDrive-synced folders).
AI / agent angle
georescue-mcpexposes inspection, repair-to-a-new-folder, guarded read-only SQL, governed metrics and case lookups to any MCP client (details below).scripts/mcp_demo.pyrecords real agent sessions;agent_demo/drives a visualization loop and saves before/after snapshots.- Agents get the redacted store only — never owner names, never write access to source data.
Tech stack
Python 3.13 · uv · GeoPandas · Shapely · pyogrio · PyProj · DuckDB · Pydantic · Typer · Jinja2 · Streamlit + Folium · MCP Python SDK · MapLibre GL JS · GitHub Actions + Pages
Core (V1)
GIS data-quality & repair for parcel datasets. Load (SHP/GPKG/GeoJSON) → inspect → classify issues → propose repairs on a copy (every change logged) → export corrected.gpkg, changelog.csv, issues.csv, diff.csv, summary.json, report.html.
Checks
missing/empty/invalid geometry · duplicate IDs · duplicate geometries · required attributes & types (YAML rules, Pydantic-validated) · CRS missing/unexpected · out-of-bounds · overlaps · slivers · small gaps · original-vs-corrected diff.
Repairs (all logged: feature_id, check, action, before, after, reason, post_valid, applied)
make_valid (polygonal parts kept) · numeric text→number coercion · assign CRS if missing · optional: drop empty geoms, drop exact duplicates, trim overlaps below an area. Everything else is flag_only. The source file is never modified.
Usage
uv sync
uv run georescue inspect data.gpkg -c configs/columbia_fl.yaml
uv run georescue repair data.gpkg -c configs/columbia_fl.yaml -o out/
uv run georescue report data.gpkg -c configs/columbia_fl.yaml -o out/
uv run streamlit run app.py # demo UI (docs/demo.png)
uv run georescue-mcp # MCP stdio server: inspect_dataset, repair_dataset
PYTHONPATH=. uv run --extra verify pytest -q
Real data: uv run python scripts/fetch_columbia.py (Columbia County FL LCParcels FeatureServer).
Known gaps
Gap detection uses holes in the unioned fabric (misses gaps open to the outside edge); overlap trimming is greedy (higher row loses); DuckDB batch mode not implemented; no map of issue geometries in the UI (points only); type rules don't parse unit-suffixed text (e.g. "3 Ac").
Automated vs. manual steps
| Step | Status |
|---|---|
| Inspect, classify, repair, change log, QA report | Automated (georescue CLI / MCP) |
| RustGIS visualization loop | Automated (agent_demo/run_demo.py) |
| Appraiser legal descriptions, PLSS corner tie (BLM CadNSDI) | Automated (verify/) |
| Fetching recorded deed images (myfloridacounty.com ORI) | Manual today: portal sits behind a human-verification check |
| Deed OCR, metes-and-bounds + curve parsing, COGO traverse, closure and GIS comparison | Automated (verify/run_deeds.py) |
| Final boundary position within ~3 ft | Needs a licensed surveyor |
Deed PDFs, page images, and raw county data are excluded from the repo.
Credits
See THIRD_PARTY_NOTICES.md for open-source licenses and data sources, and Data sources below. Brand font: Exo 2 (SIL Open Font License, brand/fonts/OFL.txt).
Live demo
Static dashboard (GitHub Pages): https://knightchrism.github.io/georescue/
- KPIs per check, filterable issues table, Leaflet map of flagged parcels only (small GeoJSON, not the 584 MB county layer), per-overlap case files (verdict, confidence, ORB refs, deed closure/acreage, overlay PNGs) and run history.
- Basemap: OpenStreetMap tiles. The COJ Duval orthoimagery has no published licence, so imagery-backed figures are not published; case pages use the plain (no-imagery) overlay PNGs.
PYTHONPATH=. uv run --extra verify georescue run --config configs/duval_fl.yaml # -> out/runs/<ts>/, out/latest/
PYTHONPATH=. uv run --extra verify georescue publish # -> site/
python -m http.server -d site 8765 # preview locally
Automation: .github/workflows/pipeline.yml (weekly cron + manual dispatch) runs the pipeline on a bbox extract
(configs/duval_fl_ci.yaml), fetching parcels at runtime, and deploys site/ to Pages.
To enable: push the repo to GitHub, then Settings → Pages → Source: GitHub Actions, and allow Actions under Settings → Actions.
Only invalid-geometry repair is ever auto-applied; every other fix is a proposal recorded in changelog.csv.
Data sources
GeoRescue does not own the data below and is not affiliated with, or endorsed by, any of these sources. Their records are maintained for their own purposes (for example, assessment) and, as the Property Appraiser states for its data, are not intended for legal use such as conveyances or boundary determinations.
- City of Jacksonville GIS — parcels (CityBiz/Parcels service): https://maps.coj.net/coj/rest/services/CityBiz/Parcels/MapServer/0 · home/disclaimer: https://maps.coj.net/
- Duval County Property Appraiser: https://paopropertysearch.coj.net/Basic/Search.aspx (disclaimer shown on the search site)
- Duval County Clerk of Courts — Official Records: https://or.duvalclerk.com · disclaimer: https://www.duvalclerk.com/disclaimer
Owner and person names are removed from the public site (georescue publish redacts by default; --no-redact-owners is for private local builds only).
Ask GeoRescue (MCP server)
georescue load-db loads the latest run into a redacted DuckDB results store, out/georescue.duckdb. It holds the tables issues, cases, verdicts, deed_traverses, runs and glossary, and it never contains owner names. georescue run refreshes it automatically. The MCP server (uv run --extra verify georescue-mcp, stdio) exposes these tools:
inspect_dataset, repair_dataset (writes a repaired copy into a new folder only), list_tables, describe_table, run_query (single SELECT/WITH, guard + row cap + 10 s timeout), list_metrics/get_metric (governed metrics in semantic/metrics.yml), get_case, find_issues, explain_issue and compare_runs. All calls are logged to logs/mcp.log.
scripts/mcp_demo.py drives the server over stdio through realistic questions and records the real calls and outputs to examples/agent_sessions.{json,md}. The site's Ask GeoRescue page renders those sessions. Each answer is filled in by a fixed template from the tool outputs. The page also has Claude Desktop / Cursor config snippets for running it yourself. These are recorded sessions and test results, not authoritative.
The server structure, SQL guard, metrics layer, logging and demo are adapted from the author's own census-pipeline (MIT). GeoRescue keeps its existing MCP SDK (mcp>=2.3, MCPServer).
Glossary
The site's glossary (generated by georescue publish from src/georescue/glossary.py and the config thresholds) explains every issue type the checks emit — what it means, why it matters, how it is detected, what (if anything) is done automatically — plus terms like verdict, confidence, deed traverse/COGO, misclosure, POB, ORB, IoU and PAO. All results are proposed test results, not authoritative.
Terms
See TERMS.md. Questions, corrections or removal requests: open an issue at https://github.com/knightchrism/georescue/issues
License
Code: MIT, see LICENSE. Third-party software and data keep their own licenses and terms (THIRD_PARTY_NOTICES.md).