Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

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

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
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 warnings key in the result flags a suspicious-but-valid outcome with a hint — e.g. a negative distance that eroded every geometry away.

clip_layerA

Clip a layer to the area of a mask layer. CRS are aligned automatically.

A warnings key in the result means the analysis ran but something is worth your attention (typically an empty result, or inputs whose extents do not overlap); each entry carries a hint. Inputs without a CRS are refused.

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 warnings entry, never as a silent success.

dissolve_layerA

Merge features into one geometry per value of by (or one feature in all).

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 by key are dropped by the grouping and the manifest counts them. The output feature count is verified against the number of distinct keys, so a wrong grouping fails loudly instead of shipping.

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 warnings entry, never silently.

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 warnings entry carrying the ratio — Web Mercator at 42° reports 1.80× the land it covers.

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 repairs key — read it, the geometry type may have changed.

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 warnings key in the result flags an empty join or inputs whose extents do not overlap, each with a hint. Inputs without a CRS are refused.

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; warnings and repairs keys in the result flag a suspicious outcome or geometry MapSmith had to repair. Requires the [raster] extra.

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 step_warnings key in the response means the plan ran but some step produced a suspicious result (an empty output, non-overlapping inputs): read it before treating a completed plan as a correct one.

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:

facets you declare              candidates left   ranked@3   in the answer
(none)                                       51        25%             25%
input_kind                                   33        29%             43%
input_kind + produces                        21        48%            100%

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:

  • input_kind — what you are holding: 'vector' (points, lines, polygons), 'raster' (a grid, a GeoTIFF), 'dataset' (either), 'plan', or 'none'.

  • produces — what you want back: 'dataset:vector', 'dataset:raster', 'answer' (a number, nothing written), 'description' (what something IS, rather than a computation over it), 'plan_result'.

  • category — the family, when you know it: vector, raster, terrain, hydrology, inspection, sql, network, planning, provenance, visualization, bridge. Unlike the others this one only ORDERS the results — a wrong guess about our families costs you positions, never the answer, so guessing is safe.

  • projected — pass False if your data is in a geographic CRS (degrees), and every operation that would refuse it disappears from the results.

  • dataset_inputs — how many datasets you are holding for this step: 1 if you have one layer, 2 if the operation combines two. This is the facet that makes a large catalog usable: on the current one it takes the surviving set from a median of 34 to 9, because "clip these parcels with that boundary" and "simplify these parcels" are different questions and you already know which one you have.

query is then plain words for what you are trying to do, and it breaks the tie inside what is left. Describe the PROBLEM rather than the operation: "the coastline has too many vertices and the browser dies" works as well as the name of the tool, and better when you do not know the name.

If the answer comes back as a single entry with status: "choose", that is the normal case and it is asking you to pick. It carries every operation that survived, in relevance order, each with the sentence saying what it is NOT for. The order is a hint and nothing else: our ranking puts the right operation in the top three 48% of the time, while a model reading the same candidates and choosing gets its first pick right 69% — and 70% is where the two model labellers who wrote the ground truth agree with EACH OTHER, so there is often no single right answer to rank toward. You have context no ranking has: which file is open, what ran a minute ago, what the person actually asked for. Use it. And if two candidates would both be defensible, ask them — that is a better move than picking one silently, and it is what a GIS analyst would do.

A order_is_weak field means the two rankers shared nothing in their top three, which usually means the request does not match this catalog well: read the candidates instead of trusting the order, and say so if none of them fits.

If the answer comes back with status: "unsure", the two ranking engines agreed on nothing and the set was too large to hand over — usually the request was not understood rather than impossible. It carries both engines' guesses and a question; answering the question with the facets above is the fastest way through.

If the answer comes back with status: "none_apply", nothing you declared can be true at once — no ranking ran. It lists each declaration and how many operations would come back without it, smallest first, so the one that is excluding everything is the first line. The common case is produces: several operations compute the number you want and write it into a column instead of returning it, so they declare dataset:vector. If nothing in relax helps, MapSmith probably does not do this — say so rather than running a neighbour.

detail=True adds parameters and worked example calls: use it on the exact operation name before calling an unfamiliar tool. An empty query lists everything that survives the facets, planned operations included.

engine selects the ranker and every result says which one ran: 'auto' (the default) prefers embeddings and falls back to BM25 where the model cannot load; 'lexical' is BM25 alone, deterministic and network-free; 'vector' forces embeddings. The default changed on measurement, not preference, and the facets above matter far more than this choice.

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

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription
map-panelInteractive in-chat map panel (MCP Apps): renders preview_map results

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/mapsmith-ai/mapsmith'

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