MapSmith
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| describe_datasetA | Inspect a dataset, vector or raster, before analysing it. Vector: CRS, geometry types, schema, extent, feature count. A MULTI-LAYER container (e.g. a GeoPackage holding several layers) is described per layer — name, feature count, geometry type, CRS — because operations refuse containers with no chosen layer: extract the layer you mean first (run_sql: SELECT * FROM ST_Read(path, layer='name') with an output_path). Raster (.tif): CRS, grid size, resolution, bands with dtype, nodata and masked statistics (nodata cells counted separately). Call this first on any dataset you have not inspected yet — most silent GIS errors start with wrong assumptions about CRS, units, nodata or which layer you are on. Raster inspection requires the [raster] extra. |
| buffer_layerA | Buffer all features by a distance in meters. Geographic-CRS inputs are reprojected to an estimated UTM zone for the metric
operation and back; the decision is recorded in the provenance manifest.
A |
| clip_layerA | Clip a layer to the area of a mask layer. CRS are aligned automatically. A |
| overlay_layersA | Set-theoretic overlay of two layers: intersection (default), union, identity, symmetric_difference or difference. The overlay layer is reprojected to the input CRS when they differ; the
decision is recorded in the provenance manifest. Overlay pieces of lower
dimension than the inputs (shared edges, corner contacts) are dropped, and
the manifest says so. Inputs without a CRS are refused; an empty result
comes back with a |
| dissolve_layerA | Merge features into one geometry per value of aggfunc — first (default), last, sum, mean, median, min, max or count — is
applied to the other columns and RECORDED in the manifest: a sum reported
where a mean was meant is a plausible wrong number nobody can see. Features
with a null |
| nearest_joinA | Attach each feature's nearest neighbour from another layer, with the distance IN METERS in a named column. Geographic-CRS inputs are measured in an estimated UTM zone (decision
recorded in the manifest) and returned in the input CRS — a nearest
distance in degrees is the classic silent error of this operation, and it
cannot happen here. max_distance_meters drops pairs farther than that; an
emptied result comes back with a |
| explode_layerA | Split multi-part geometries into one feature per part (attributes copied). The output feature count is verified against the number of parts counted before the engine ran, so a lost part fails loudly instead of shipping. Inputs without a CRS are refused. |
| measure_areaA | Area per feature in SQUARE METRES, written to a named column, with the total in the result. method='geodesic' (default) measures ground area on the ellipsoid the layer's CRS names: no map plane, so no projection distortion. method= 'planar' measures in the layer's own CRS and converts with its declared linear unit — a layer in US survey feet is not assumed to be in metres — and is refused on a geographic CRS, where an area would be in square degrees. Two things this tool does that a bare area call cannot: invalid geometry is
repaired BEFORE measuring (the planar area of a self-intersecting ring is
the signed shoelace, a number matching no region, returned without
complaint) and every repair is recorded; and a planar measurement is
compared against the ground area, so a plane that is not equal-area here
comes back with a |
| merge_layersA | Append two or more layers into one (schema union, attributes aligned by name). Layers are reprojected to the FIRST layer's CRS when they differ; the decision is recorded in the provenance manifest. Columns present in only some inputs are null-filled in the others and the manifest names them — data that looks measured and is actually absent is a silent error. The output feature count is verified against the sum of the input counts. Inputs without a CRS are refused. This is an append, not a geometric union: use dissolve_layer to merge geometries afterwards. |
| simplify_layerA | Simplify geometries (Douglas-Peucker, topology preserved) with the drift measured: the manifest records total area and length before and after. Geographic-CRS inputs are simplified in an estimated UTM zone (decision recorded) and returned in the input CRS — a tolerance in degrees is a different distance at every latitude. On projected CRS the tolerance is interpreted in the CRS units. The feature count is verified unchanged; vertex counts before/after are in the result. Inputs without a CRS are refused. |
| centroid_layerA | One point per feature: the geometric centroid, computed in a metric CRS. Geographic-CRS inputs are measured in an estimated UTM zone (decision recorded in the manifest) and returned in the input CRS — a planar centroid of degree coordinates lands in the wrong place, quietly. The output is verified: same feature count, Point geometry, input CRS. Note the manifest's caveat: the centroid of a concave or multi-part feature can fall outside it. Inputs without a CRS are refused. |
| convert_formatA | Convert a vector dataset between formats; the target is chosen by the output extension (.parquet, .gpkg, .geojson). The output is re-read and verified: same feature count, same CRS. Two conversions are refused with the reason: shapefile (field names truncated to 10 characters, silently) and GeoJSON for non-WGS84 layers (RFC 7946 is WGS84 by definition — reproject first). Invalid geometry carried through is repaired deterministically and reported in a 'repairs' key. |
| reproject_layerA | Reproject a layer to a target CRS, e.g. 'EPSG:32632' or a WKT string. Inputs without a CRS are refused. Geometry passes through unchanged, so an
invalid input yields an invalid output: mechanically broken geometry is
repaired deterministically and reported in a |
| spatial_joinA | Join by spatial predicate (intersects/within/contains). engine='auto' routes to the fastest available engine for the inputs:
SedonaDB (heavy joins, 10-180x) > DuckDB (GeoParquet fast path) > GeoPandas.
A |
| run_sqlA | Run spatial SQL (DuckDB dialect, ST_* functions, read_parquet/ST_Read for files). Without output_path: returns up to 50 preview rows. With output_path (.parquet): materializes the full result as GeoParquet with a provenance manifest. |
| zonal_statisticsA | Statistics of a raster within each vector zone (exact fractional pixel coverage). stats: subset of count/sum/mean/median/min/max/stdev/variance/majority/minority/
variety (default: count, mean, min, max). Zones are aligned to the raster CRS
automatically; the decision is recorded in the provenance manifest.
Zones without a CRS are refused; |
| hillshadeA | Shaded relief from a DEM: GeoTIFF in, GeoTIFF out (values scaled 0-32767). azimuth = sun direction in degrees (default 315, NW); altitude = sun angle above the horizon (default 30). DEMs without a CRS are rejected. Requires the [whitebox] extra. |
| slopeA | Slope gradient from a DEM: GeoTIFF in, GeoTIFF out. units: degrees (default), percent or radians. DEMs in a geographic CRS are refused — degree cells with meter elevations give plausible but wrong values everywhere; reproject to a projected CRS first. The CRS decision is recorded in the provenance manifest. Requires the [whitebox] extra. |
| aspectA | Aspect from a DEM: downslope azimuth in degrees, 0 = north. GeoTIFF in/out. FLAT CELLS ARE -1, not nodata — mask them before averaging aspect over an area, or the average is plausibly wrong. DEMs in a geographic CRS are refused (see slope): reproject to a projected CRS first. Requires the [whitebox] extra. |
| flow_accumulationA | D8 flow accumulation from a DEM (GeoTIFF in/out). Depressions are filled first. out_type: 'cells' (upslope cell count, includes the cell itself) or 'sca' (specific catchment area). log_transform=True for visualization-friendly values. Requires the [whitebox] extra. |
| watershedA | Watershed of each pour point: DEM + points in, basin raster out (GeoTIFF). Basins get 1-based IDs following the pour-point feature order; cells not draining to any point stay nodata. Points are aligned to the DEM CRS automatically (decision recorded). Requires the [whitebox] extra. |
| validate_planA | Statically validate a multi-step geoprocessing plan BEFORE running anything. Write the plan as steps in execution order; each step has a unique id, an operation name from list_operations, and its arguments. Use "$step_id" as an argument value to consume the output dataset of an earlier step. Checks: operations exist and are installed, arguments complete and well-typed, references resolve backwards (mis-ordered steps are rejected), input files exist, outputs don't collide, and CRS flow is simulated end-to-end from the real input files. Returns machine-actionable errors/warnings/notes plus the simulated output CRS per step. Nothing is executed and nothing is written. Example plan: {"goal": "wells at risk", "steps": [ {"id": "buf", "operation": "buffer_layer", "arguments": {"input_path": "wells.gpkg", "distance_meters": 300, "output_path": "buf.parquet"}}, {"id": "cut", "operation": "clip_layer", "arguments": {"input_path": "$buf", "mask_path": "zone.gpkg", "output_path": "risk.parquet"}}]} |
| execute_planA | Validate, then execute a geoprocessing plan step by step. The plan is re-validated first (an invalid plan runs nothing). Steps run in order; "$step_id" references resolve to the outputs of earlier steps. Every step writes its own provenance manifest, and a plan-level manifest (.plan.json, with the plan sha256 and per-step outcomes) ties them together. Execution stops at the first failing step; outputs already produced stay on disk with their manifests. Same plan format as validate_plan — validate first, then execute. A |
| get_provenanceA | Return the full lineage manifest of a MapSmith output dataset. |
| preview_mapA | Show datasets on the interactive in-chat map panel (MCP Apps). Pass the paths of one or more MapSmith outputs or source datasets (vector or GeoTIFF). Layers are previewed in EPSG:4326 with simplified geometry and capped feature counts sized to fit client limits; each layer card shows its provenance summary and verification status. Read-only: the datasets of record stay on disk. On clients without MCP Apps support the same payload is returned as structured data. |
| list_operationsA | Find the operation you need. Say what you have and what you want — it matters more than the words you search with. Ranking alone does not scale, and this is measured rather than assumed. Over 118 requests written by other models against this catalog, searching by words alone finds the right operation in the top 3 a quarter of the time. Declaring what you already know does not make the ranking better — it makes the ranking unnecessary, because few enough operations survive that you get all of them: That last column is not an accuracy figure. It is what happens when nothing is dropped: the right operation was in the answer for all 118 requests, by construction rather than by ranking. So fill these in whenever you know them, and you usually do:
If the answer comes back as a single entry with A If the answer comes back with If the answer comes back with
|
| run_operationA | Run ANY catalog operation by name, including the ones with no tool of their own — which is most of them, and increasingly so. The tools above are the handful an agent reaches for constantly. The catalog holds every operation MapSmith can perform, and it grows faster than the tool list on purpose: tool-selection accuracy degrades past a few dozen exposed tools, while capability count has no such ceiling. Discover with list_operations (use detail=true to get parameters and worked examples), then call it here. Arguments are validated against the catalog BEFORE anything runs — unknown operation, missing or misnamed argument, wrong type, path outside the workspace — and the errors come back with stable codes, so a failed call tells the planner what to fix instead of what went wrong. Execution goes through the same path as execute_plan, so an operation cannot behave one way here and another way in a plan. |
| server_infoA | MapSmith version, licensing, and available engines. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| map-panel | Interactive in-chat map panel (MCP Apps): renders preview_map results |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/mapsmith-ai/mapsmith'
If you have feedback or need assistance with the MCP directory API, please join our Discord server