mcp-geoes
This server lets an AI agent discover, inspect, query, and visualize Spanish geological and cartographic data (IGME/IGN) through MCP tools, including composing multi-source maps with legends.
List services: enumerate available catalog services (ArcGIS) from a source.
Describe services and layers: get metadata such as layers, extents, CRS, formats, field schemas, and capabilities.
Query layer attributes: run SQL-style
wherefilters, select fields, order results, paginate withoffset, and optionally filter by bounding box, returning GeoJSON.Identify at a point: retrieve attributes at a given lon/lat for one or more layers.
Export a single-source map: render a source as an image for a bounding box.
Get legends: obtain structured or image-based legends for a source or layer.
Compose multi-source maps: align several sources into one map image with a combined legend, with options for title, size, and legend placement.
Provides access to Spanish geological data published by IGME through ArcGIS REST services, enabling queries for geological units, lithologies, faults, and other geology attributes.
Provides access to Spanish base mapping and orthophotos published by the Instituto Geográfico Nacional through OGC WMS and WMTS services, enabling map composition and imagery overlays.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-geoes ¿Hay fallas cuaternarias cerca de este punto? Enséñame un mapa sobre la ortofoto."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
IGN-IGME-MCP
Ask an AI agent about Spanish geology and get an answer with a map.
This is an MCP server that puts the public cartography of Spain — the IGME's geology and the IGN's base mapping and orthophotos — behind a single set of tools an agent can use, and composes them into one image when a question needs both.
One question, two publishers, one answer:
"¿Hay fallas cuaternarias cerca de este punto? Enséñame un mapa sobre la ortofoto."
The faults come from the IGME over ArcGIS REST, the orthophoto from the IGN over OGC WMS, and they arrive as a single aligned image with a legend saying which is which.
Read-only, always. Every operation is a GET; there is no editing path anywhere in the codebase.
Why it exists
Spain publishes an enormous amount of high-quality geospatial data for free — and almost none of it is reachable from an AI assistant. Three problems stand in the way, and this project is the answer to each:
The data lives behind two incompatible protocol families. The IGME runs ArcGIS Server; the IGN publishes OGC WMS and WMTS. An agent should not have to know, so the tools are the same for both — and a source that cannot do something says so and names the alternative, instead of returning an empty result that reads like "there is nothing there".
Real questions cross publishers. "Are there active faults nearby, and what does the ground look like?" is one question and two organisations. Splitting it across two servers pushes the join into the agent, which is where scale confusion and misattribution creep in.
A map without provenance is a liability. A geological contact read from a 1:1,000,000 synthesis and one from a 1:50,000 sheet are not interchangeable, and an agent that cannot tell them apart will use the first to answer about a parcel. Every answer here carries its service, publisher and nominal scale.
New to WMS, WMTS or ArcGIS REST? → docs/theory.md
Related MCP server: groundstation
What it can do
Find a place | turn "Suances" into a map envelope — a municipality's real boundary, not a guessed square |
Say what exists | enumerate every source, from both publishers, before assuming one |
Answer at a point | which geological unit, which lithology, which flight date — with the scale it was read at |
Query by attributes | SQL-style filtering with transparent paging, where the source supports it |
Draw maps | one source framed on a place, or several stacked and aligned to the pixel with a combined legend |
Describe itself | what each source publishes, what it can do, and what its fields mean |
Refuse usefully | when a source cannot answer, it says why and what can |
See it in use → docs/examples.md
Quick start
Requires Python ≥ 3.11 and uv.
git clone <this repository> && cd IGN-IGME-MCP
uv sync --all-extras
uv run pytest # the whole suite, offline
uv run mcp-geoes --list-profiles
uv run mcp-geoes --profile general --validateThen connect a client. The configuration files ship with the repository, with all five profiles already declared — open it and start the server you want:
Client | File |
VS Code | |
Claude Code | |
Claude Desktop |
Anything else that speaks MCP runs the same command:
uv run mcp-geoes --profile geologiaWiring, hosted transport and multi-profile caveats →
examples/mcp_clients.md
Then ask it "¿qué cartografía tienes de Suances?" or "¿qué unidad geológica hay ahí?".
Five profiles, one process each — the tool list an agent sees is what keeps its choices accurate. The split is by domain, never by publisher: real questions cross the IGME and the IGN in the same sentence.
Profile | For | Tools |
| "what do you have for this place?" — both publishers, short answer | 19 |
| the IGN as subject: orthophoto, MTN sheets, historical series, relief | 25 |
| the IGME's geology, with the IGN's cartography to read it against | 27 |
| active faults, seismicity, ground movements, neotectonics | 21 |
| hydrogeology and permeability over the IGN's hydrography | 21 |
Counts include the thirteen generic tools, which always register.
What each profile declares, which one to pick, and how to write another →
docs/profiles.md
Prefer to see it work before wiring up a client?
uv run python scripts/demo_tools.py --out working/ # the tools, live
uv run python scripts/demo_compose.py --out working/ # a composed map
uv run python scripts/demo_discovery.py --place Suances --out working/Full instructions, container and hosting → docs/deployment.md
How it fits together
AI agent ──MCP──▶ mcp_geoes ──▶ domain profile (YAML, Spanish)
│
├──▶ arcgis_client ──▶ IGME (ArcGIS REST)
├──▶ ogc_client ──▶ IGN (WMS · WMTS)
└──▶ map_compose ──▶ one image, one legendThree ideas carry the design:
Capabilities are declared, never assumed. Each source states what it can answer. Asking for anything else raises an error naming the alternative — never a plausible empty result.
Questions start from places, not coordinates. resolve_place turns a name
into an envelope, and every map tool takes place= instead of bbox=.
Composition happens in EPSG:3857. Layers from different publishers can only be stacked if all were rendered for the same envelope in the same projection. Tool signatures still speak lon/lat; the conversion is done for you.
Profiles add knowledge, never code. A YAML file names its sources across both publishers, their semantics, its closed vocabularies and its convenience tools. A new domain — hydrogeology, geological risk, mining — is a new file.
Why each of those, and what was rejected → docs/architecture.md
· Requirements and their tests → docs/specs.md
Documentation
Document | For |
the GIS concepts, if you are new to them, with pointers to the standards | |
what you must write when you publish — the IGN's and IGME's attribution terms | |
what a profile declares, the five shipped ones, and how to add one | |
what you can ask, what comes back, and what it refuses | |
the design decisions and why they were taken | |
numbered requirements, acceptance criteria, milestones | |
build, test, run, containerise, host, and keep it current | |
client configuration, copy-paste |
Each package also has its own README: geo_core,
geo_http, arcgis_client,
ogc_client, map_compose,
mcp_geoes.
Layout
IGN-IGME-MCP/
├── packages/
│ ├── geo_core/ # backend contract, model, geometry, logging
│ ├── geo_http/ # shared transport: retries, cache, timing
│ ├── arcgis_client/ # ArcGIS Server REST → IGME
│ ├── ogc_client/ # OGC WMS, WMTS and WFS → IGN, regional SDIs
│ ├── map_compose/ # composition engine and combined legend
│ └── mcp_geoes/ # the MCP server and the profile loader
├── profiles/ # domain profiles (YAML + prompt), in Spanish
├── docs/ # theory · profiles · examples · architecture · specs · deployment
├── scripts/ # demos, live validation, catalog audit
├── docker/ # container healthcheck
└── tests/Troubleshooting
Three log levels on one axis, because troubleshooting a chain of agent → server → two origins means asking three questions in order:
Level | Answers | Emits |
| what did the agent ask for, and did it work? | one line per tool call: tool, backend, duration, status |
| what did we ask the origins? | one line per upstream request: URL, status, bytes, cache, duration |
| what exactly went over the wire? | full URL, every parameter, truncated payload |
Every record carries a call_id that propagates from the tool call down to the
HTTP request, so one grep reconstructs a whole interaction. Pass the agent's
own trace id as trace_id and the two timelines join.
uv run mcp-geoes --profile geologia --log-level TRACE --log-format jsonLogs go to stderr: under the stdio transport, stdout carries the MCP protocol itself.
Language
The code, its comments and its documentation are in English, because layers
0–2 are reusable well beyond Spain. The domain profiles are in Spanish —
tool names, field semantics, prompts, vocabularies — because the data is Spanish
(UNIDAD, LITOLOGIA, "Triásico"), users ask in Spanish, and a translation step
between question, tool and data is exactly where models introduce mapping
errors.
Licence and attribution
The software is MIT.
The data is not. It belongs to the Instituto Geológico y Minero de España (IGME, CSIC) and the Instituto Geográfico Nacional (IGN), who publish it freely on the condition that you cite the source. That condition travels with the data: when you put one of these maps in a report, a site or a product, the obligation to attribute is yours.
This server gives you everything you need to meet it — publisher, nominal scale, edition date and the official product page ride along with every answer — but it cannot meet it for you, because it does not know where your result ends up.
The IGN requires the literal form PNOA 2023 CC-BY 4.0 scne.es, prefixed with
"Obra derivada de" if you modified anything — and composing counts. The IGME
requires Origen de los datos: © Instituto Geológico y Minero de España (IGME).
Read docs/licensing.md before you publish anything.
It has both formulas, what counts as a derived work, and a checklist.
This project is not affiliated with, endorsed by, or maintained by either institute.
Available Tools
8 toolscompose_mapA
Compose one map from several sources, aligned, with a combined legend. Name a composition the profile declares, or list sources bottom-first. legend_mode is panel, below, separate or none — use 'separate' for rich geological keys. The bbox is lon/lat; projection, pixel grid and legend filtering are handled for you.
Inputs: bbox (required), title, width, height, +3 more.
describe_layerA
Describe a layer: fields with their types and coded-value domains, geometry type and record count. WMS sources publish no field schema and say so.
Inputs: source (required), layer_id (required). Returns: object
describe_serviceB
Service metadata: layers with their ids, extent, CRS, formats, limits, and the capabilities this source actually supports.
Inputs: source (required). Returns: object
export_mapA
Render one source for a bbox [minlon,minlat,maxlon,maxlat] in WGS84 degrees and return it as an image. For several sources on one map use compose_map.
Inputs: bbox (required), source (required), width, height, +1 more.
get_legendC
Legend of a source: structured entries (ArcGIS) or an image (WMS).
Inputs: source (required), layer_id. Returns: object
identify_at_pointC
What is at a point: attributes at the given lon/lat (WGS84) for one or more layers of a source.
Inputs: lat (required), lon (required), source (required), layers, +1 more. Returns: object
list_servicesC
List the services published by a source that has a catalog (ArcGIS).
Inputs: source (required), folder. Returns: object
query_layerA
Query layer attributes and return GeoJSON in WGS84. Supports a SQL where, field selection, ordering and a bbox [minlon,minlat,maxlon,maxlat]. If exceededTransferLimit is true, repeat with offset. Only sources that declare the 'query' capability.
Inputs: source (required), layer_id (required), bbox, limit, +5 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Each tool targets a distinct operation: listing services, describing services or layers, getting legends, querying attributes, identifying by point, and rendering maps. The overlap between query_layer and identify_at_point is minimal and well-differentiated by interaction style.
All tool names follow a clear verb_noun snake_case pattern (list_services, describe_layer, get_legend, export_map). Even identify_at_point fits the pattern with a prepositional phrase, and no mixed conventions appear.
Eight tools is well-scoped for a geospatial service client, covering discovery, metadata, query, legend retrieval, and map rendering without redundancy or bloat.
The tool surface covers the full geospatial workflow: catalog browsing, metadata inspection, query, point identification, legend access, single-source export, and multi-source composition. No obvious dead ends or missing core operations.
Maintenance
Related MCP Connectors
Italian cadastre for AI agents: 85M parcels, geocoding, OMI values, risk layers.
GIS tools for AI agents: 65 free tools + 8 paid (hazard/site-scouting/GeoJSON export)
Verifiable Earth ground truth for AI agents: water, hazard, ground stability, resource, with proof.
Geodata for any place, inside your agent: map data, terrain, routes, satellite images, GIS files.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with QGIS, supporting project management, layer inspection, spatial queries, styling, and map export in both headless and desktop modes.-
- AlicenseAqualityBmaintenanceEnables AI agents to query Earth observation data, satellite imagery, active fires, and weather via natural language, returning interactive maps and briefs.12MIT

MapSmithofficial
AlicenseAqualityBmaintenanceEnables AI agents to perform professional-grade geoprocessing tasks such as buffers, overlays, reprojections, and terrain analysis with deterministic tools and verifiable provenance.29428 PyPI2AGPL 3.0- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to perform geospatial analysis, spatial data processing, vector and raster operations, coordinate transformations, spatial statistics, mapping, and access to climate, satellite, and other geospatial data through MCP-compatible clients.MIT