Skip to main content
Glama
GSA-TTS

mcp-server-gis-helper

Official
by GSA-TTS

mcp-server-gis-helper

An MCP server that lets a user draw GIS geometry on an interactive map and returns clean, validated GeoJSON — ready to hand off to other GIS MCP servers such as FEMA NFHL flood screening or USGS National Map hydrography.

It solves the "how do I generate a complex shape and pass it to the geometry-based tools?" problem: instead of hand-typing coordinates, the user sketches a polygon, line, or point on a Leaflet map and gets back a compact GeoJSON string.

This server does not query flood/waterway services itself. It only produces and validates geometry; the agent passes that geometry to the downstream tools.

Tools

Tool

Purpose

gis_open_map

Interactive entry point. Returns a Prefab MCP App with a link to a browser drawing map and a "Load drawn geometry" button. Optional lat/lon/zoom center the map.

gis_get_drawn_geometry

Retrieves the shape the user drew and saved on the map for a given session_id. Returns a compact GeoJSON string.

gis_validate_geometry

Validates/normalizes an arbitrary GeoJSON string you already have (no map needed). Closes polygon rings, checks WGS84 ranges, unwraps Feature/FeatureCollection.

All geometry is WGS84 decimal degrees in GeoJSON [lon, lat] order. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, plus the BoundingBox shorthand ({"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}) — exactly what the FEMA/USGS tools accept.

Related MCP server: Eddie MCP Server

How it works (the map bridge)

Prefab's Embed renders a sandboxed iframe whose content cannot write back into Prefab state, so the drawing map cannot live purely inside the MCP app. Instead a small companion HTTP "map bridge" (Starlette) serves the Leaflet + Leaflet.draw page:

  1. gis_open_map creates a draw session and returns a Prefab app with a link to <public_url>/map?session=<id>.

  2. The user opens that link in a browser, draws one shape, and clicks Save. The page POSTs the GeoJSON to <public_url>/session/<id>/geometry, where it's validated and stored in an in-memory session store.

  3. gis_get_drawn_geometry reads the stored geometry out of the shared store and returns it as a compact GeoJSON string.

  4. The agent passes that string to nfhl_screen_flood_zone, hydro_find_waterways, etc.

Transports (mirrors the sibling GIS servers)

  • stdio (local MCP clients like Claude Desktop/Code): MCP runs over stdio and the map bridge is started on a localhost daemon thread (default 127.0.0.1:8765).

  • HTTP (deployed / containerized): when PORT (or DATABRICKS_APP_PORT) is set, MCP is served at /mcp and the bridge routes (/map, /session/{id}/geometry, /health) are mounted onto the same port.

Configuration (all optional)

Env var

Default

Purpose

GIS_HELPER_MAP_HOST

127.0.0.1

Bridge bind host (stdio mode)

GIS_HELPER_MAP_PORT

8765

Bridge port (stdio mode)

GIS_HELPER_PUBLIC_URL

http://<host>:<port>

Origin the browser uses to reach the bridge (set behind a proxy/container)

GIS_HELPER_TILE_URL

OpenStreetMap

Leaflet basemap tile URL template

GIS_HELPER_TILE_ATTRIBUTION

OSM

Tile attribution string

PORT / DATABRICKS_APP_PORT

If set, selects HTTP transport for MCP

Copy .env.example to .env for local overrides.

Running

uv sync

# stdio (local MCP client)
uv run python main.py

# HTTP (deployed)
PORT=8080 uv run python main.py

Example workflow

User:  I want to screen a project area for FEMA flood zones.
Agent: (calls gis_open_map centered on the site)
User:  (draws a polygon on the map, clicks Save, clicks "Load drawn geometry")
Agent: (gis_get_drawn_geometry -> geometry string)
Agent: (passes geometry to nfhl_screen_flood_zone)

If the user already has coordinates, skip the map and use gis_validate_geometry to clean them up before querying downstream.

Project layout

src/gis_helper_mcp/
├── app.py            # FastMCP init, instructions, transport, bridge startup
├── models.py         # dataclasses (DrawSession, GeometrySummary) + constants
├── utils.py          # GeoJSON validation/normalization, summaries, session store, config
├── bridge.py         # Starlette map-bridge routes + runners
├── static/
│   └── map.html      # Leaflet + Leaflet.draw drawing page (CDN assets)
└── tools/
    ├── __init__.py           # register_tools(mcp)
    ├── open_map.py           # gis_open_map (Prefab app)
    ├── get_drawn_geometry.py # gis_get_drawn_geometry
    └── validate_geometry.py  # gis_validate_geometry

Available Tools

3 tools
gis_get_drawn_geometryGet Geometry Drawn on the MapA
Read-onlyIdempotent

Retrieve the geometry a user drew and saved on the interactive map.

Call this after gis_open_map once the user has drawn a shape and clicked "Save" on the map page. Geometry stored by the map is already validated and normalized (WGS84, closed rings). The returned "geometry" string can be passed directly to nfhl_screen_flood_zone, hydro_find_waterways, and other geometry-accepting GIS tools.

Use when: "I drew a shape, get it", or wired to the "Load drawn geometry" button inside the gis_open_map app.

session_id handling:

  • If you know the exact id from the latest gis_open_map result, pass it.

  • If you don't have it (e.g. a later turn), OMIT session_id entirely and the most recently saved geometry is returned. Never pass a placeholder like "default" — that will fail.

Returns when a shape has been saved: { "ready": true, "session_id": str, # the resolved session id "geometry": str, # compact GeoJSON string, ready to paste downstream "summary": { geo_type, crs_epsg, vertex_count, part_count, bbox, ... } }

Returns when nothing has been saved yet: { "ready": false, "message": "No geometry saved yet ..." }

Error responses:

  • {"ready": false, "error": "Unknown or expired session ..."} — bad session_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
session_idNoThe draw session id returned by gis_open_map. Optional: if omitted (or if you don't have the exact id), the most recently drawn-and-saved geometry is returned. Prefer passing the exact session_id from the most recent gis_open_map result when you have it. Do NOT invent a value like 'default' — leave it unset instead.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint, idempotentHint), the description discloses valuable behaviors: geometry is 'validated and normalized (WGS84, closed rings)', return structures for both success and failure cases are shown, and error responses are documented. It also explains session_id fallback behavior and warns against placeholder values, providing comprehensive transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with clear sections (purpose, use case, session_id handling, return values, errors). Every sentence adds practical value, and examples are provided without unnecessary fluff. The structure front-loads the core purpose and then logically details the usage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is fully complete for this tool: it explains when to call it, how to handle the optional parameter, what the return values look like (with examples), and what error responses may occur. Even though an output schema exists, the description adds clarity with concrete examples, making it self-sufficient for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already describes the session_id parameter in detail, including its optionality, fallback behavior, and the warning not to invent values. The description's session_id handling section essentially repeats this information without adding new meaning. Since schema coverage is 100%, the baseline is 3, and the description does not elevate it further.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Retrieve the geometry a user drew and saved on the interactive map.' It uses a specific verb ('Retrieve') and resource ('geometry'), and distinguishes it from sibling tools like gis_open_map (opens map) and gis_validate_geometry (validates geometry). This provides immediate clarity on what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage context: 'Call this after gis_open_map once the user has drawn a shape and clicked "Save" on the map page.' It also provides example use cases ('I drew a shape, get it') and mentions it integrates with the 'Load drawn geometry' button. However, it does not explicitly mention when not to use this tool or contrast it with alternatives, so it falls slightly short of a perfect score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gis_open_mapOpen Interactive Map to Draw GeometryA
Read-only

Open an interactive map so the user can draw GIS geometry, then capture it.

Returns a Prefab app with (1) a link that opens a Leaflet drawing page in the browser and (2) a "Load drawn geometry" button. Workflow:

  1. Call this tool (optionally center it with lat/lon/zoom).

  2. The user clicks "Open drawing map", draws a polygon/line/point, clicks Save.

  3. The user clicks "Load drawn geometry" (or you call gis_get_drawn_geometry with the session_id) to retrieve a compact GeoJSON string.

  4. Pass that GeoJSON to nfhl_screen_flood_zone, hydro_find_waterways, etc.

Use when: "let me draw a shape / area on a map", "I want to sketch a polygon". Don't use when: the user already has coordinates (use gis_validate_geometry).

The returned app also surfaces the session_id in text so the agent can call gis_get_drawn_geometry directly if the user prefers not to click the button.

ParametersJSON Schema
NameRequiredDescriptionDefault
latNoOptional initial map center latitude (WGS84 decimal degrees).
lonNoOptional initial map center longitude (WGS84 decimal degrees).
zoomNoOptional initial map zoom level (0 = world, 19 = building).

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral context: the returned Prefab app, the user-driven draw/save/load sequence, session_id surfacing, and how the GeoJSON output feeds downstream tools. It does not contradict the annotations, though it doesn't explicitly remark on non-idempotency beyond implying a new session.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is multi-paragraph but well-structured with a numbered workflow and clear sections. Each part earns its place, though a few phrases (e.g., 'then capture it') are slightly redundant with the later workflow steps.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description fully explains the return (a Prefab app with link and button), the interactive workflow, session_id usage, downstream GeoJSON consumers, and the option to call gis_get_drawn_geometry directly. It accounts for both user-driven and agent-driven retrieval paths.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% coverage with rich descriptions for lat, lon, and zoom. The description only briefly mentions 'optionally center it with lat/lon/zoom', adding little beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Open an interactive map so the user can draw GIS geometry, then capture it' with a clear verb and resource. It distinguishes from siblings by explicitly pointing to gis_validate_geometry for users who already have coordinates and referencing gis_get_drawn_geometry for retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit 'Use when' and 'Don't use when' guidance, naming gis_validate_geometry as the alternative and outlining the workflow involving gis_get_drawn_geometry. This leaves no ambiguity about when to invoke this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gis_validate_geometryValidate & Normalize GeoJSON GeometryA
Read-onlyIdempotent

Validate and normalize a GeoJSON geometry string for use with GIS servers.

Checks that the geometry is a supported type with valid WGS84 [lon, lat] coordinates, unwraps Feature/FeatureCollection wrappers, and closes any unclosed polygon rings. Returns a compact, single-line GeoJSON string that can be passed directly to the FEMA NFHL (nfhl_screen_flood_zone) or USGS National Map (hydro_find_waterways, etc.) tools.

Use when: you already have coordinates/GeoJSON and want to confirm it's valid and correctly formatted before querying another GIS server. Don't use when: you want to draw a shape interactively (use gis_open_map).

Returns on success: { "valid": true, "geometry": str, # compact GeoJSON string, ready to paste downstream "summary": { # geo_type, crs_epsg, vertex_count, part_count, ... # bbox [minLon,minLat,maxLon,maxLat], approx area/length } }

Error responses:

  • {"valid": false, "error": "..."} — invalid JSON, unsupported type, out-of-range coordinate (e.g. swapped lat/lon), or malformed BoundingBox.

ParametersJSON Schema
NameRequiredDescriptionDefault
geometryYesGeoJSON geometry as a JSON string. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon. Also accepts a BoundingBox shorthand: {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}. A GeoJSON Feature or single-feature FeatureCollection is also accepted and unwrapped to a bare geometry. All coordinates must be WGS84 decimal degrees in [lon, lat] order.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds substantial behavioral context: it unwraps Feature/FeatureCollection wrappers, closes unclosed polygon rings, checks WGS84 coordinate validity, returns a compact single-line GeoJSON string, and documents error scenarios. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: a leading summary, usage guidance, success return format, and error responses. It is moderately long but every sentence serves a purpose—no fluff or repetition. Front-loaded with the core purpose and quickly readable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (normalization, validation, coordinate system, wrappers, downstream compatibility), the description covers everything needed: what is validated, what transformations occur, the exact return shape (with a summary sub-object), and possible error messages. It is complete even without relying on the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description covers the only parameter (geometry) fully at 100% coverage, including supported types, BoundingBox shorthand, accepted wrappers, and coordinate order. The description adds behavioral normalization details (e.g., closing rings) but that falls under transparency rather than parameter semantics. With high schema coverage, a baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a specific verb+resource: 'Validate and normalize a GeoJSON geometry string for use with GIS servers.' It clearly distinguishes itself from siblings by stating when to use it (before querying another GIS server) and when not to (interactive drawing, use gis_open_map). This is a precise, non-tautological purpose statement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit 'Use when' and 'Don't use when' guidance, naming the alternative tool (gis_open_map) for interactive drawing. It also lists downstream GIS tools that consume the output, making the usage context very clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.7/5.0
Disambiguation5/5

Each tool has a distinct role in the workflow: gis_open_map initiates an interactive drawing session, gis_get_drawn_geometry retrieves the result, and gis_validate_geometry validates an existing GeoJSON string. There is no overlap in purpose, and the 'Use when' conditions clearly separate them.

Naming Consistency5/5

All tool names follow a consistent 'gis_' prefix followed by a verb_noun pattern: open_map, get_drawn_geometry, validate_geometry. The naming is uniform, snake_case, and each verb clearly indicates the action.

Tool Count5/5

Three tools is well-scoped for a GIS helper that focuses on geometry capture and validation. The count falls within the ideal 3-15 range, and each tool is necessary for the core workflow without redundancy.

Completeness5/5

The toolset covers the entire lifecycle of preparing user-drawn geometry for downstream GIS servers: open a map to draw, retrieve the drawn geometry, and validate/normalize it. There are no obvious gaps; session handling is gracefully managed by omitting the session ID, and the output is directly usable.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Browser-based geometry processing server that enables AI agents to create geometry, run analysis and operators, inspect results, and take screenshots via MCP.
    84
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Free remote MCP server for GIS/ArcGIS Online automation — coordinate/EPSG conversion, GeoJSON validation and geometry operations, ArcGIS FeatureServer inspection (feature count/query, schema, health check), and Shapefile/KML/GPX/WKT format conversion. Works with public ArcGIS layers without a token;
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/GSA-TTS/mcp-server-gis-helper'

If you have feedback or need assistance with the MCP directory API, please join our Discord server