Skip to main content
Glama
geolens-mcp

geolens-mcp

Official

English · Español · Français · Deutsch · 简体中文

Latest release CI status License: Apache-2.0 OpenSSF Scorecard OpenSSF Best Practices

GeoLens is for teams whose spatial data is spread across file shares, PostGIS databases, web services and STAC catalogs. It puts that data in one searchable catalog, records where each dataset came from and checks whether the source is still current. Teams build and share maps in the browser, and QGIS, scripts and AI agents read the same data through OGC API and STAC. It runs on your own servers with Docker Compose, sends no telemetry and is licensed under Apache 2.0.

The demo needs no install or account; sign in with Google, GitHub or Microsoft to use the map builder. Demo data may be wiped at any time.

A closer look

Related MCP server: FastAPI Database MCP Server

How it fits together

flowchart LR
    subgraph IN ["Bring data in"]
      F["Files<br/>GeoPackage · Shapefile · GeoParquet<br/>GeoTIFF · COPC · 3D Tiles"]
      DB["Existing PostGIS tables"]
      SVC["Services<br/>ArcGIS · WFS · OGC API Features"]
      ST["Remote STAC assets"]
    end
    subgraph GL ["GeoLens"]
      CAT["Catalog<br/>search · metadata · provenance"]
      MB["Map builder<br/>styles · 3D · analysis · stories · dashboards · sharing"]
      STD["Open APIs<br/>OGC API · STAC · DCAT · tiles"]
    end
    subgraph OUT ["Use it anywhere"]
      WEB["Browsers and embeds"]
      GIS["QGIS · ArcGIS · CesiumJS"]
      CODE["curl · Python · TypeScript · DuckDB"]
      AG["AI agents via MCP"]
    end
    F & DB & SVC & ST --> CAT
    CAT --> MB --> WEB
    CAT --> STD --> GIS & CODE & AG

One catalog for scattered data

  • Upload Shapefile, GeoPackage, GeoJSON, GeoParquet, FlatGeobuf, KML/KMZ, zipped File Geodatabase, CSV, Excel or GeoTIFF (converted to Cloud-Optimized GeoTIFF). 3D Tiles and COPC point clouds are hosted for CesiumJS, QGIS and Potree.

  • Serve tables already in GeoLens's PostGIS database in place, import WFS, ArcGIS and OGC API Features layers and refresh them on demand, or reference remote STAC assets without copying them.

  • Draw new datasets in the browser.

  • Find data with fuzzy search, or by meaning once an embedding provider is configured. Filter by type, place and time, group datasets into collections, edit metadata and restore a dataset's previous version after a replacement.

Know where every dataset came from

Each dataset records where it came from: an uploaded file, a database table, a service, a STAC item or a drawing in the browser. Imported datasets also record when they were last refreshed, and with an update cadence GeoLens marks them fresh, due or overdue. For services and STAC sources, GeoLens also checks that the source still answers, and for services it flags upstream schema changes before they reach your maps. If a service disappears, the imported copy keeps working.

Build and share maps

  • Point, symbol, heatmap, cluster, line, arrow, fill, 3D extrusion, raster and hillshade layers, with data-driven styles, labels, icons, patterns, filters and popups. Terrain comes from your own elevation models.

  • Buffer, centroid, clip, dissolve, spatial join, select by location, measure and intersect. Most operations preview on the map, and each result is saved as a new dataset, from the builder or the CLI.

  • Story maps walk readers through a map scene by scene, with Markdown text, images, buttons and separators. Dashboards put indicators, charts, filters and Markdown notes beside a map. A Map data panel shows the rows behind each layer, as a table or a list.

  • Public maps and published stories show their title and image when pasted into Slack, Teams or social posts, and maps embed in other sites with private tokens.

  • The interface is in English, Spanish, French, German and Simplified Chinese.

Use the data from anywhere

Vector datasets are OGC API Features collections, the catalog is OGC API Records and STAC, and every layer has a tile URL. You can try this against the demo without an account (the second command needs jq):

# Search the catalog (OGC API Records)
curl "https://demo.getgeolens.com/api/collections/datasets/items?q=volcanic%20eruptions"

# Read the top match with a CQL2 filter (OGC API Features): eruptions of VEI 6 or larger
ID=$(curl -s "https://demo.getgeolens.com/api/collections/datasets/items?q=volcanic%20eruptions&limit=1" | jq -r '.features[0].id')
curl -G "https://demo.getgeolens.com/api/collections/$ID/items" \
  --data-urlencode "filter=vei >= 6" -d limit=3

QGIS adds the same API as an OGC API Features connection, as the QGIS guide shows. The GeoLens plugin for QGIS adds catalog search, private datasets and edits that sync back to GeoLens.

Standard

Where

Use it with

OGC API Features, with CQL2 filtering and queryables

/api/collections/{id}/items

QGIS, ArcGIS, GDAL/OGR and other OGC API clients

OGC API Records

/api/collections/datasets/items

Catalog search from other portals and tools

STAC API 1.0

/api/stac/

STAC clients such as pystac-client and STAC Browser

DCAT 3, DCAT-US 3.0 and GeoDCAT-AP as JSON-LD

/api/datasets/dcat/, /api/datasets/dcat-us/3.0/, /api/datasets/geodcat-ap/

Harvesting into national and EU open-data portals

Vector tiles and COG raster tiles

a tile URL on every layer

MapLibre, OpenLayers, Leaflet

3D Tiles and COPC

each 3D dataset's page

CesiumJS, QGIS, Potree

Data exports as GeoJSON, Shapefile, GeoPackage, CSV, FlatGeobuf, GeoParquet, PMTiles or Cloud-Optimized GeoTIFF.

The geolens CLI publishes files and applies catalog manifests, Python and TypeScript SDKs cover the API, and a read-only MCP server lets AI agents search the catalog. The API reference and SDK guides document them, and the examples gallery has runnable code for MapLibre, Leaflet, OpenLayers, the ArcGIS Maps SDK, QGIS and DuckDB.

Optional AI

GeoLens can answer questions about a dataset, edit maps from plain-language requests, draft metadata and search in natural language. It works with any OpenAI-compatible endpoint, including a local server such as Ollama, and with Claude through Anthropic, Microsoft Foundry, Amazon Bedrock or Google Vertex AI. AI stays off until an administrator configures a provider, and every workflow works without it.

Install

You need Git, curl and Docker with the Compose plugin. The Install Guide lists the versions, memory and ports it expects.

curl -fsSL https://getgeolens.com/install.sh | sh    # clone, generate secrets, start the stack
cd geolens
grep '^GEOLENS_ADMIN_PASSWORD=' .env                  # the generated admin password

Open http://localhost:8080 and sign in as admin with that password. Each release includes a SHA256SUMS file for checking install.sh before you run it. To build from source instead, clone the repository and run bash scripts/install.sh; the first build takes 5-10 minutes.

For production, read the cloud deployment guide, which also lists what an external database needs. Docker Compose is the supported path, and geolens-deployments has a community-maintained Helm chart and Terraform recipes for AWS ECS Fargate and Azure Container Apps.

The bundled database is backed up daily, and the backup guide covers off-site copies and restores. UPGRADING.md covers upgrades and rollback, RUNBOOK.md covers operations, and the Configuration Reference lists every setting.

Your first dataset

With the CLI installed, publish the sample file from the install directory:

geolens login http://localhost:8080/api               # your admin username and password
geolens publish examples/manifests/first-catalog/city-parks.geojson --name "City Parks"

geolens publish prints the new dataset's URL. To manage a whole catalog, describe the sources in a geolens.yaml manifest and run geolens apply; examples/manifests/ has templates.

To load the demo's maps and datasets, export GEOLENS_ADMIN_PASSWORD from .env and run python scripts/seed-showcase.py --username admin. The script needs Python 3.10+ and httpx and downloads public data from about a dozen sources; scripts/README.md has the sizes and options.

Privacy and access

  • GeoLens sends no telemetry. Apart from the default basemap tiles and the remote services or STAC sources your users register, it makes outbound calls only for features an administrator turns on. EGRESS.md lists them and explains how to run air-gapped.

  • Your data stays readable without GeoLens. Vector datasets are ordinary PostGIS tables in a data schema, rasters are Cloud-Optimized GeoTIFFs in your own storage (local disk, S3/MinIO or Azure Blob), and the catalog exports through OGC API, STAC and DCAT.

  • Sign-in uses local accounts or OAuth 2.0/OIDC (Google, Microsoft, GitHub or a generic provider), with roles, per-dataset permissions, per-user API keys and an audit log. Self-registration is off by default.

  • Features released in this repository stay free. EDITIONS.md describes the optional paid support and add-ons.

Known limitations

  • The supported install, Docker Compose, runs on one host. For high availability, run several replicas of the API, worker, frontend and Titiler against a managed PostgreSQL with automatic failover, shared object storage and one Valkey or Redis cache. With Azure Blob or local storage, API and worker replicas also need a shared staging volume, since only S3 keeps uploads in the bucket. Local storage keeps every file on that volume, so Titiler replicas mount it too. geolens-deployments has a community-maintained Helm chart, Terraform recipes for AWS and Azure, and guides for AWS, Azure, Google Cloud and DigitalOcean. GeoLens itself doesn't cluster the database or read from replicas.

  • One organization per deployment.

  • Terrain rendering assumes elevation in meters; other vertical units render exaggerated.

  • GeoLens's own REST API can change between minor releases (the standards endpoints follow their specifications). The CHANGELOG lists contract changes. When a change breaks callers, the old form keeps working for the later of the next minor release and 90 days, and the CHANGELOG records its removal date. That covers REST routes and fields, the map and dashboard JSON clients write, and CLI commands and flags; the SDKs follow the API, and MCP tool names and arguments aren't covered.

Contributing

Bug reports, fixes, translations and docs are welcome. CONTRIBUTING covers setup and tests, and ARCHITECTURE maps the code. The QGIS plugin, examples and deployments repositories take issues and pull requests too. Ask questions in GitHub Discussions, report bugs in Issues, and report security problems privately as described in SECURITY.md. The roadmap shows what's planned.

Built on

GeoLens is built on these open source projects. Thanks to everyone who maintains them.

  • PostgreSQL and PostGIS hold the catalog and every vector dataset, and pgvector stores the embeddings behind search by meaning.

  • GDAL reads the files and services GeoLens imports and writes the formats it exports, and PROJ handles coordinate transformations.

  • TiTiler serves raster tiles from Cloud Optimized GeoTIFFs.

  • FastAPI serves the API, and Procrastinate runs background jobs with PostgreSQL as the queue.

  • MapLibre GL JS draws the maps, deck.gl and loaders.gl render 3D Tiles and point clouds, and Terra Draw handles drawing and editing.

  • The web app is written in React.

These names belong to their owners, and listing them doesn't mean they endorse GeoLens; see TRADEMARKS.md.

License

GeoLens is licensed under the Apache License 2.0. The GeoLens name, logo and brand assets are not covered by this license; see TRADEMARKS.md. Sample-data attribution is in THIRD_PARTY_DATA.md. The web app serves the license notices for the code it bundles at /third-party-licenses.txt, and the backend image's copyleft notices are in backend/licenses.

Project policies: editions · support · governance · maintainers · security · release process · egress &amp; air-gap

Available Tools

9 tools
aggregateA

Compute an exact aggregate over a dataset's rows: counts, summaries and breakdowns without writing SQL. Use query for anything else.

request is the JSON body of the aggregate route, chosen by op. Every op takes an optional CQL2-JSON filter and an optional bbox [west, south, east, north] in WGS 84. Unknown keys are refused.

  • {"op": "count"}

  • {"op": "stats", "column", "stats": [count|sum|avg|min|max, ...]}

  • {"op": "value_counts", "column", "limit"} (limit 1-50, default 10)

  • {"op": "histogram", "column", "bins"} (bins 1-50, default 10)

  • {"op": "group_by", "group_column", "stat", "column"} or "stats": [{"stat", "column"}], plus optional date_bucket (day|week|month|year), sort_by, sort and limit (1-50)

  • {"op": "rows", "columns": [up to 20], "sort_column", "sort", "limit", "cursor"} lists features a page at a time (limit 1-100, default 25), each with its gid and bbox, never a geometry; pass the previous page's next_cursor as cursor under the same sort.

Returns {op, result, approximate, cached}. Refusals keep the route's HTTP status and a code in the error detail:

  • 422 too_wide: the bbox view holds over 500,000 rows. Narrow the bbox or drop it.

  • 422 invalid_column, invalid_cursor, invalid_filter, no_geometry, query_timeout, query_data_error, result_too_large: fix the request and retry.

  • 429 query_busy (two aggregates already running for you) or query_at_capacity: retry after 200-400 ms with jitter.

  • 503 query_unavailable: retry after the Retry-After delay. Datasets you can't read answer 404. The route allows 10 requests a second.

Args: dataset_id: Dataset id with a feature table (not a raster). request: The aggregate body described above.

Inputs: request (required), dataset_id (required).

get_dataset_schemaA

Get a dataset's schema and source trust metadata.

Returns columns (name/type/role), geometry type, CRS/SRID, feature count, spatial extent, and the safe source_origin. source_health is healthy, missing, inaccessible, or unknown: inaccessible means GeoLens could not determine whether the source still exists, while unknown means it was never probed or cannot be probed. source_health_detail is a fixed GeoLens reason code, not provider text. last_checked_at records the latest probe attempt; last_refreshed_at records only the latest successful committed refresh. source_freshness is advisory; overdue means two declared update intervals elapsed without a successful refresh. Raw provider URLs, origin pointers, and credentials are excluded. Call this before writing spatial questions so you know both the available columns and whether the source may be stale.

Args: dataset_id: Dataset id (e.g. from search_datasets).

Inputs: dataset_id (required).

get_featuresA

Get GeoJSON features for a dataset (bounded).

Returns an OGC-API FeatureCollection. Raster datasets have no features and will error. Results are capped by limit; page with offset. Only the arguments listed below are supported; anything else is rejected.

Args: dataset_id: Dataset id. limit: Max features (1-200, default 10). offset: Feature offset for paging. bbox: Optional bounding box filter "minx,miny,maxx,maxy" (WGS84).

Inputs: dataset_id (required), bbox, limit, offset.

get_mapA

Get a summary of one saved map: name, description, visibility, view state (center, zoom, bearing, pitch), basemap, terrain configuration and layer list.

Each layer has id, dataset_id, dataset_name, dataset_table_name, dataset_geometry_type, display_name, visible, layer_type and filter. Styling, popups, labels, column info and sample values are not included. dashboard_widget_count is the number of dashboard widgets (0 for none).

Args: map_id: Map id (e.g. from list_maps).

Inputs: map_id (required).

get_storyA

Get one story's published version: title, summary, visibility and the document with its chapters. Each chapter has a title, blocks and a scene (map_id, camera, layer_visibility); a chapter on a map you can't read comes back without its scene and with scene_hidden true. Never returns the draft. document is null until the story is published, and a story you can't read answers 404.

Args: story_id: Story id (e.g. from list_stories).

Inputs: story_id (required).

list_mapsA

List saved maps (read-only metadata: id, name, visibility, layer count).

Args: search: Optional text filter on map name/description. limit: Max results (1-200, default 50). offset: Result offset for paging.

Inputs: limit, offset, search.

list_storiesA

List published stories you can read (read-only metadata: id, title, summary, visibility, chapter count). Drafts are never listed.

Args: search: Optional text filter on story title/summary. limit: Max results (1-200, default 50). offset: Result offset for paging. total and paging reflect the server's answer.

Inputs: limit, offset, search.

queryA

Run one read-only SQL SELECT against accessible datasets.

Executes through the server's hardened SQL sandbox: a single SELECT over data.* tables, an allowlisted function set (aggregates, math, string, date, JSON), and a strict server-side budget (a 5 s statement timeout, a repetition cap on self-joins, and row_limit rows, at most 1000). For counts, statistics, histograms and group-by summaries prefer aggregate, which needs no SQL. Returns {columns, rows, row_count, truncated} with rows as lists in column order. Geometry columns come back as hex EWKB; select ST_AsText(geom) or ST_AsGeoJSON(geom) for readable geometry. ST_AsGeoJSON(geom, 6) rounds coordinates to six decimals, which suits display but can make a small polygon invalid.

PostGIS functions allowed: ST_Area, ST_AsGeoJSON, ST_AsText, ST_Buffer, ST_Centroid, ST_Collect, ST_Contains, ST_Distance, ST_DWithin, ST_GeometryType, ST_GeomFromGeoJSON, ST_GeomFromText, ST_Intersects, ST_IsValid, ST_Length, ST_MakeEnvelope, ST_MakePoint, ST_NPoints, ST_Point, ST_SetSRID, ST_Transform, ST_Union, ST_Within, ST_X, ST_Y. ST_Collect and ST_Union take two geometries (no aggregate form). The && bounding-box operator works, as do ::geography / ::geometry and geography(geom).

Requires credentials with AI-chat permission — anonymous configurations cannot use this tool. Workflow: search_datasets to find a dataset, then get_dataset_schema for its table_name and columns, then reference it as data.<table_name> in the SQL and list the same table_name in restrict_tables. Every table the query touches must be listed there; the scope can only narrow what your credentials already see. Writes, other schemas, and unlisted functions are rejected with a short reason that names the refused function.

Args: sql: A single SELECT statement over data.* tables. restrict_tables: Table names (no data. prefix) the query may touch. Required and non-empty. row_limit: Max rows to return (1-1000, default 100).

Inputs: sql (required), restrict_tables (required), row_limit.

search_datasetsA

Search the GeoLens catalog for datasets by free text.

Matches title, description, and keywords (semantic ranking is used automatically when the instance has it enabled). Returns a compact FeatureCollection (numberMatched, numberReturned, features) where each feature is a trimmed dataset record: id, bbox, and properties title, description (cut at 300 characters), record_type, geometry_type, feature_count, crs, keywords and updated. Use the feature id as the dataset_id for the other tools; get_dataset_schema has the full detail. Each feature's properties also include source_origin (upload, postgis, service, stac, created, or null) and source_freshness (fresh, due, overdue, or unknown). Freshness is advisory: due means one declared update interval has elapsed, while overdue means two have elapsed; neither proves that the content is wrong.

Search does not make a detail request per result. When the catalog summary has no health/check/refresh value, source_health, source_health_detail, last_checked_at, and last_refreshed_at are null. Call get_dataset_schema for populated trust metadata. Raw provider URLs and credentials are never included in these source-state fields.

Args: query: Search text. limit: Max results (1-200, default 10). offset: Result offset for paging.

Inputs: query (required), limit, offset.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 9 tools

    Disambiguation4/5

    Most tools are clearly distinct: stories, maps, dataset discovery/schema, feature retrieval, SQL query, and structured aggregate are separate operations. The main overlap is between `query` and `aggregate`, but the descriptions explicitly distinguish SQL use from no-SQL summaries, and `get_features` is also adjacent to data retrieval but still clearly bounded.

    Naming Consistency4/5

    Seven of nine tools follow a predictable verb_noun pattern (list_stories, get_story, get_dataset_schema, get_features, get_map, list_maps, search_datasets). `query` and `aggregate` are bare operation names rather than verb_noun, which is a minor but noticeable deviation.

    Tool Count5/5

    Nine tools is well-scoped for a read-oriented geospatial/story/map server. Each tool covers a distinct area: discovery, schema inspection, feature access, SQL, aggregates, maps, and stories.

    Completeness4/5

    The surface covers the core read-only workflows well: discovering datasets, inspecting schemas, querying/aggregating data, fetching features, and reading maps/stories. Minor gaps exist around direct dataset detail or dashboard retrieval, but agents can largely work around them through search, schema, and story/map metadata.

    Maintenance

    ActivityActive
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Provides read-only access to PostgreSQL databases with schema inspection, query execution in multiple formats (JSON, CSV, Markdown), and query history tracking with built-in security features.
      -
    • F
      license
      Not graded
      quality
      F
      maintenance
      Provides read-only SQL query access to Postgres and DuckDB databases via MCP tools, with extensive security hardening for public endpoints.
      1
      -
    • F
      license
      B
      quality
      D
      maintenance
      Provides read-only query tools over OpenStreetMap data in PostGIS, enabling natural language queries for features, categories, and spatial analysis.
      7
      -
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables browsing Global Forest Watch's catalogue and running read-only SQL queries against dataset versions, covering tree cover loss, deforestation alerts, fire alerts, carbon flux, and more.
      121 npm
      MIT