Atlas / MCP servers / mapsmith-ai / MapSmith

MapSmithBLOCK

mcp/mapsmith-ai/mapsmith

Professional-grade GIS geoprocessing over MCP, with a verifiable provenance manifest on every output

Verdict
BLOCK
Grade
D
Trust score
63 /100
Exposed tools
28 22r · 6w · 0d
Transport
stdio · streamable-http
License
AGPL-3.0
Stars
2
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://doi.org/10.5281/zenodo.22213091)

[](https://github.com/mapsmith-ai/MapSmith/actions/workflows/ci.yml) [](https://pypi.org/project/mapsmith/) [](https://github.com/mapsmith-ai/MapSmith/pkgs/container/mapsmith) [](https://modelcontextprotocol.io) [](LICENSE)

Ask a question about your data. Get an analysis — and the record that proves it.

Most GIS servers hand an agent a tool to run. MapSmith takes the question, works out the analysis — usually several operations, in an order that has to be right — validates the plan before a single file is touched, runs it, and leaves a record of every step — which bytes went in, with which parameters and CRS decisions, and which checks ran — that somebody else can read afterwards and rerun to confirm.

Try it

Point any MCP client at MapSmith (one JSON block) and ask, in your own words:

Which parcels lie within 1.5 km of the river and sit at 120 m or lower? Give me the mean elevation and the ground area of each.

That is five operations, two coordinate systems and forty-eight checks. What actually happens is below — the plan, the step that gets rejected for reading something a later step produces, the CRS decision behind every metric step, and an answer you can work out on paper before MapSmith sees the files. That rejection is structural, and so is every other one: a plan that is well formed and answers the wrong question runs instead, which is [measured and written down further down this page](#pla

Read from source at commit 6dfd3ce07595OBSERVED · 2026-10-08
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control.

claude-code (pypi)
claude mcp add mapsmith -- uvx mapsmith==0.8.0
claude-code (oci)
claude mcp add mapsmith:0.8.0 -- docker run -i --rm ghcr.io/mapsmith-ai/mapsmith:0.8.0:None
03

Exposed tools (28)

22 read · 6 write · 0 destructive.

ToolRiskDescription
aspectreadAspect from a DEM: downslope azimuth in degrees, 0 = north. GeoTIFF in/out.
buffer_layerreadBuffer all features by a distance in meters.
centroid_layerreadOne point per feature: the geometric centroid, computed in a metric CRS.
clip_layerreadClip a layer to the area of a mask layer. CRS are aligned automatically.
convert_formatreadConvert a vector dataset between formats; the target is chosen by the
describe_datasetreadInspect a dataset, vector or raster, before analysing it.
dissolve_layerwriteMerge features into one geometry per value of `by` (or one feature in all).
execute_planwriteValidate, then execute a geoprocessing plan step by step.
explode_layerreadSplit multi-part geometries into one feature per part (attributes copied).
flow_accumulationreadD8 flow accumulation from a DEM (GeoTIFF in/out). Depressions are filled first.
get_provenancereadReturn the manifest of the ONE operation that wrote this dataset.
hillshadereadShaded relief from a DEM: GeoTIFF in, GeoTIFF out (values scaled 0-32767).
list_operationsreadFind the operation you need. **Say what you have and what you want** — it matters more than the words you search with.
measure_areareadArea per feature in SQUARE METRES, written to a named column, with the
merge_layerswriteAppend two or more layers into one (schema union, attributes aligned by name).
nearest_joinreadAttach each feature
overlay_layerswriteSet-theoretic overlay of two layers: intersection (default), union,
preview_mapreadShow datasets on the interactive in-chat map panel (MCP Apps).
reproject_layerreadReproject a layer to a target CRS, e.g.
run_operationwriteRun ANY catalog operation by name, including the ones with no tool of
run_sqlwriteRun spatial SQL (DuckDB dialect, ST_* functions, read_parquet/ST_Read for files).
server_inforeadMapSmith version, licensing, and available engines.
simplify_layerreadSimplify geometries (Douglas-Peucker, topology preserved) with the drift
slopereadSlope gradient from a DEM: GeoTIFF in, GeoTIFF out.
spatial_joinreadJoin by spatial predicate (intersects/within/contains).
validate_planreadStatically validate a multi-step geoprocessing plan BEFORE running anything.
watershedreadWatershed of each pour point: DEM + points in, basin raster out (GeoTIFF).
zonal_statisticsreadStatistics of a raster within each vector zone (exact fractional pixel coverage).
04

Trust audit

BLOCKgrade D · trust 63/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
declared (1 observation(s))
Shell
declared (1 observation(s))
Dependencies
pinned
Secrets in source
found

Findings (20)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/mapsmith/engines/raster.py:1198
computed = eval(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHHard-coded secrets · secret.db_uri · CWE-798, CWE-321
docker-compose.yml:18
DATABASE_URL: postgresql://mapsmith:mapsmith@postgres:5432/mapsmith
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
src/mapsmith/server.py:46
origins = ["http://127.0.0.1:*", "http://localhost:*", "http://[::1]:*"]
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
CHANGELOG.md:2009
model or the user. The sharp case: refusing `ATTACH 'postgres://user:pw@...'`
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
tests/test_sql_credentials.py:38
"ATTACH 'postgres://user:shh@host/db' AS pg",
LOWInventory / provenance · inv.binary · CWE-1104
examples/fixtures/monte_baldo_dem.tif
monte_baldo_dem.tif
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.binary · CWE-1104
examples/fixtures/monte_baldo_s2.tif
monte_baldo_s2.tif
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.binary · CWE-1104
examples/fixtures/mount_st_helens_dem.tif
mount_st_helens_dem.tif
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.hidden_file · CWE-1104
.zenodo.json
.zenodo.json
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
tests/test_band_math.py:117
for bad in ("__import__(chr(111))", "b1 + x", "open(f)", "b1 % 2", "b1; b2"):
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/test_duckdb_sandbox.py:250
url = f"http://127.0.0.1:{server.server_address[1]}/remote.geojson"
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/test_gdal_policy.py:136
vrt = _write_vrt(tmp_path, f"/vsicurl/http://127.0.0.1:{server.port}/x.geojson")
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/test_gdal_policy.py:147
vrt = _write_vrt(tmp_path, f"/vsicurl/http://127.0.0.1:{server.port}/x.geojson")
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/test_gdal_policy.py:167
vrt = _write_vrt(tmp_path, f"http://127.0.0.1:{server.port}/x.geojson")
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
tests/test_preview.py:172
png = base64.b64decode(result["png_data_uri"].split(",", 1)[1])
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
CHANGELOG.md:1242
Both matchers now read one definition of what a credential name looks
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
README.md:1024
DuckDB's `aws` extension and read this machine's real cloud credentials back through a tool
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
SECURITY.md:196
DuckDB's `aws` extension and read the host's real cloud credentials back through
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
site/index.template.html:710
<div><h3>Never fetches code on a model's word</h3><p>A statement that says <code>INSTALL</code> or <code>LOAD</code> is refused in both modes since 0.4.0 — an <code>INSTALL</code> is an HTTPS fetch of
Why it matters. asks the agent to read credentials
INFOInventory / provenance · inv.oversize · CWE-1104
docs/images/map-panel.png
docs/images/map-panel.png
Why it matters. 1187953 bytes not read

Gates applied: no_behavioural_pass.

Audited 2026-10-08 · audit v0.4.1 · source sha 6dfd3ce07595full audit observations/trust-audit/mcp-server/mapsmith-ai__mapsmith.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-086dfd3ce07595BLOCKD63first audit
06

Questions

What is the MapSmith MCP server?

Professional-grade GIS geoprocessing over MCP, with a verifiable provenance manifest on every output

What tools does MapSmith expose?

28 in total: 22 read-only, 6 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.

Is MapSmith safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (63/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on.

What credentials does MapSmith need?

No credential environment variables were found in its source, so it appears to need none.

How does MapSmith run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on PyPI as mapsmith.

How current is this page?

The grade is for one exact copy of the source (6dfd3ce07595), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement