AI geology pipeline: a scanned geologic map moves through five steps, register, process, georeference, query and overlay, onto real terrain where earthquakes and faults are found, and ends in an answer linked to its map, georef and bundle
Five steps, each handing the next an ID

Key Takeaways

  • Stratigraphic Amenity is Eigenform’s open-source (MIT) GitHub repo for georeferencing scanned geologic maps, built as an MCP server so an AI geology agent can run it. It fits the map from ground control points (scale and offset with two, affine with three or more), takes the CRS as an EPSG code or UTM text, and reports residual and leave-one-out holdout error.
  • It does more than the fit. Before it, a detector finds the legend and main map on the sheet; after it, the georeferenced bounds drive earthquake and fault lookups, drawn back onto the scan as an overlay.
  • Five tools run in order (register, process, georeference, query, overlay), and each hands the next an ID, so an answer traces back to one georeference revision and one set of records.
  • There is no OCR: control points come from you or a separate OCR or vision model, in full-resolution source pixels. A wrong fit raises no error, and every later lookup then searches the wrong area.

TL;DR

Looking for a GitHub repo to georeference scanned geologic maps? Stratigraphic Amenity fits your ground control points, then queries and plots what is recorded inside the georeferenced area. Run its tools in order and keep the IDs each step returns, because they show which map, fit and records an answer rests on.

What Is the AI Geology Map Pipeline?

The AI geology map pipeline is the open-source georeferencing workflow in Stratigraphic Amenity: register a scanned geologic map, detect its legend and main map, georeference it from ground control points, then query and plot knowledge records inside the georeferenced bounds. Each step stores its result under the map’s ID or a new geomap:// handle for the next step.

Stratigraphic Amenity runs as an MCP server, so an agent calls each step as a tool. It supplies evidence, not answers: map coordinates come from the user or a separate OCR or vision model, and the agent writes the reply from what the server stored.

One server runs the whole sequence when it has the mcp, geo, assets and detectors extras. However, semantic search over geological notes requires a newer Torch than the detector, so it runs in a second server process.

How Do You Run an AI Geology Pipeline on a Scanned Geologic Map?

A full run uses six tools, plus two install tools when the server is not ready. Each call reads what an earlier one stored, so each step must come after the one it reads from.

Check readiness, then install what is missing

First, call geomap_list_capabilities, which changes nothing. Here the capability check looks at map_processing, georeferencing, knowledge_query and the two default area providers, earthquake_history and active_faults.

When map processing is not ready, the agent asks the user, then calls geomap_prepare_detectors to install the map-detection model, about 200 MiB of downloads. It installs only the runtime and weights; missing Python packages need the operator.

geomap_prepare_knowledge installs the geological knowledge base, which carries the earthquake catalogue and the GEM fault file as well as the rock notes. Skip it and a map query still succeeds but reports “found 0 record(s) across 0 provider(s)”, and only the warnings explain why.

Register the map

geomap_register_map takes a path inside an allowed root and returns map_id, map_uri and source_uri, the handles you get when loading a scanned geologic map. Every later map tool takes the map_id, never the path.

Registration keys on the file’s resolved path, not its contents. For example, export a better scan over the old file and you get the old map ID back, with the old boxes and georeference. Give a new scan a new name.

Detect the map parts

geomap_process_image detects the legend and main map and stores the boxes against the map. Two outputs travel on: the main_map box, the default pixel extent for georeferencing, and the lonlat_corner_crop, the main map’s four corners stitched into one picture, where grid coordinates usually sit.

Legend labels come back null because this build has no OCR, so nothing reaches the rock-type lookups. If the detector cannot be made ready, skip this step and pass pixel_extent to georeferencing yourself, or it fails with invalid_bounds.

Read the coordinates, then georeference

Between these steps the server does nothing. The user, or a separate OCR or vision model that reads the corner crop or source image through resources/read, supplies the coordinate system and ideally four or more control points. Finding the UTM zone and EPSG code of a scanned map is often the harder half.

Control point pixels must be in the full-resolution source frame, like the main_map box. A position measured on the stitched corner crop, or on a preview shrunk to at most 1,536 pixels, is not a source pixel. The tool cannot tell, so it raises no error.

Then geomap_georeference with map_id, crs and gcps fits the georeference. It writes revision geomap://maps/<id>/georef/<n>.json, returns it as georef_uri and points the georef.json alias at it. Check residual_m, holdout_error and the warnings now, because the next step trusts the alias.

Query the map’s area

geomap_query_map with only a map_id takes its bounds from that alias, as when you ask questions about a registered map. Even so, name the providers you rely on:

json
{
  "map_id": "<map_id>",
  "include": ["earthquake_history", "active_faults"],
  "max_records_by_provider": {"earthquake_history": 20}
}

If every named provider fails, so does the call, with missing_knowledge_asset when the knowledge base is absent, instead of returning zero records. Also, a question reaches only the semantic providers you include.

Draw the bundle on the map

geomap_render_knowledge_overlay takes the same map_id plus the bundle_uri:

json
{"map_id": "<map_id>", "bundle_uri": "geomap://bundles/<bundle_id>.json"}

It plots the knowledge results onto the map as an SVG and, with OpenCV from the detectors extra, as a PNG of the records on the scan. Finally, the agent reads only the URIs it needs and writes the reply.

What Each Step Hands to the Next

StepNeedsHands on
Registerpath inside an allowed rootmap_id, map_uri, source_uri
Processmap_idmain_map box, crops as geomap://artifacts/<id>.<ext>, unlabeled legend entries
Georeferencemap_id, crs, 2 or more gcpsgeoref_uri for revision <n>, the moved georef.json alias, bounds
Querymap_id with a stored georeference (else georef_required)bundle_uri (geomap://bundles/<id>.json), counts, warnings
Overlaymap_id, bundle_urigeomap://overlays/<id>.svg and .png, out_of_bounds

Text-only hosts still pass these on, because every result’s text ends with an “Evidence digest” block repeating the IDs the call produced, its trace_id and each warning. On a failure, the agent branches on error.code and keeps the trace_id.

Where the Provenance in an AI Geology Answer Comes From

Provenance is the record of where evidence came from and how it was obtained. Here it sits in stored files, which the answer should cite.

Claim in the answerWhere its evidence sits
The map covers this areaGeoreference revision: bounds, fit_method, residual_m, holdout_error, warnings
N earthquakes are recorded hereBundle item: record_count, truncated, provenance.source_id
The records come from USGS, public domainItem provenance: license, citation, attribution, source_version
No faults were foundBundle warnings and trace.providers, which show whether the provider ran
They sit here on the sheetOverlay URIs and out_of_bounds

Without a synced mirror, an earthquake item reports coverage_status: "legacy-local-asset" and a version like 1@sha256:<12 hex characters>, a hash of the installed file. A synced mirror adds source_url, retrieved_at and a manifest hash.

The trace also records cache_hit, which shows whether records came from this call or an earlier identical request. In short, keep provider_versions, each item’s provenance and the bundle trace with any claim built on them.

One link must be kept by hand. The bundle stores the box it searched but not which georeference revision supplied it, so record the georef_uri beside the bundle_uri.

What AI Geology Agents Should Watch For Between Steps

Most mistakes in a full run raise no error. Each step succeeds, and the mistake travels.

  • Georeferencing again after a query. The overlay draws with the current alias but hides records using the box stored in the bundle. After a new revision, query again, then render the new bundle.
  • A bundle drawn on the wrong map. Nothing checks that a bundle came from the map_id you render with. In our test, a bundle from one map rendered on another with no warning about the mismatch.
  • A box smaller than the sheet. Explicit bounds win over stored ones, but the SVG still stretches the whole main-map panel behind the smaller box, so the background no longer lines up. The PNG stays aligned.
  • Stray earthquakes. The earthquake search reaches 0.05° past the box, about 5.5 km north to south and less east to west. As a result, the overlay can hide a real quake just outside the sheet and blame the coordinate system.

FAQs

Do I have to run every step of an AI geology pipeline?

No. Processing is optional: without a ready detector, pass pixel_extent to georeferencing yourself. Georeferencing alone needs no knowledge providers. When the area is already known, you can look up earthquakes, faults and minerals for a bounding box without a map. Only the overlay needs both a georeference and a bundle.

Which IDs should an AI geology agent keep from a run?

Keep the map_uri, the georef_uri revision that the georeferencing call returned (not the moving georef.json alias), the bundle_uri of the query the answer uses, and the overlay URIs. Add each call’s trace_id. Together they show which map, which fit and which records an answer rests on.

Why did my map query return zero records?

Three causes are common: the knowledge base is not installed, the provider you need is off by default, or that source has no records for the area. The warnings name the first two, and naming providers in include turns a missing knowledge base into an error. An empty result is never proof of geological absence.

No. They are opaque handles to files on one server, and they stop working if its cache folder moves or is deleted. To share the evidence, read the bundle, the georeference revision and the overlay through resources/read. Then pass those files on with the answer.

Try It With Geocluster

Stratigraphic Amenity is one of the Geocluster tools, MCP servers that let AI agents work with geology data and maps.

Once a person or an OCR model supplies the legend labels, an agent can turn each legend label into a rock type and age to add the map’s own units to the answer.