Skip to content

Map data

Markdown

Buffer, merge, clip or simplify features

One GIS operation on a set of features: buffer, union, dissolve, intersection, difference, clip or simplify, returned as a file.

RESTPOST https://mcp.terra-lab.ai/v1/tools/process_geometry
MCP toolprocess_geometry on https://mcp.terra-lab.ai/mcp
GroupMap data

Request

curl -X POST https://mcp.terra-lab.ai/v1/tools/process_geometry \
  -H "Authorization: Bearer $TERRALAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"operation":"buffer","geojson":{"type":"LineString","coordinates":[[6.12,45.9],[6.13,45.905]]},"radius_m":200}'
import os
import requests

response = requests.post(
    "https://mcp.terra-lab.ai/v1/tools/process_geometry",
    headers={"Authorization": f"Bearer {os.environ['TERRALAB_API_KEY']}"},
    json={
        "operation": "buffer",
        "geojson": {
            "type": "LineString",
            "coordinates": [[6.12, 45.9], [6.13, 45.905]],
        },
        "radius_m": 200,
    },
    timeout=120,
)
response.raise_for_status()
print(response.json()["structuredContent"])
const response = await fetch('https://mcp.terra-lab.ai/v1/tools/process_geometry', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TERRALAB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "operation": "buffer",
    "geojson": {
      "type": "LineString",
      "coordinates": [
        [
          6.12,
          45.9
        ],
        [
          6.13,
          45.905
        ]
      ]
    },
    "radius_m": 200
  }),
});
const data = await response.json();
console.log(data.structuredContent);

Other valid request bodies:

{"operation":"clip","url":"https://mcp.terra-lab.ai/dl/geojson/TOKEN/buildings.geojson","area":{"place":"Annecy","radius_m":150}}

Parameters

A JSON object in the request body; in an MCP client, the arguments of the tool call.

NameTypeRequiredDescription
operationstringYesThe operation to apply. One of "buffer", "union", "intersection", "difference", "clip", "simplify", "centroid", "area_length".
fileobjectNoA file uploaded in the conversation (GeoJSON, KML, KMZ, GPX, zipped Shapefile, CSV or WKT).
file.download_urlstringYes
file.file_idstringYes
file.file_namestringNo
file.mime_typestringNo
urlstringNoA public http(s) link to the features, or a TerraLab download link from an earlier answer.
geojsonobjectNoThe features as a GeoJSON FeatureCollection, Feature or geometry in WGS 84 (longitude, latitude).
with_fileobjectNoFor intersection, difference and clip: the second layer, uploaded in the conversation.
with_file.download_urlstringYes
with_file.file_idstringYes
with_file.file_namestringNo
with_file.mime_typestringNo
with_urlstringNoFor intersection, difference and clip: a link to the second layer, or a TerraLab download link.
with_geojsonobjectNoFor intersection, difference and clip: the second layer as GeoJSON in WGS 84. Only its polygons count.
areaobjectNoFor clip: the area to keep, as a bbox or a place with a radius (its bounding box is used). The place the user asks about, not the user's own location.
area.bboxarray of numberNo[west, south, east, north] in decimal degrees (WGS 84). Exactly 4 items.
area.placestring or objectNoA place name or address, or a point.
area.radius_mnumberNoRadius around the place in metres. From 1 to 100000.
radius_mnumberNoFor buffer: the distance in metres (convert km or miles first). From 0.1 to 100000.
tolerance_mnumberNoFor simplify: the largest allowed shift of the outline in metres. From 0.01 to 100000.
dissolve_fieldstringNoFor union: dissolve into one feature per value of this field instead of one feature.
formatsarray of stringNoDownload formats. All five by default.
titlestringNoName for the map and the output files.

Response

structuredContent holds the result, content the same result as text for a model, and isError is true when the tool refused the request or failed; then structuredContent.code, message and hint say what to change.

{
  "structuredContent": {
    "sources": [{ "name": "...", "licence": "...", "url": "..." }],
    "downloads": [{ "label": "...", "format": "...", "url": "...", "name": "..." }]
  },
  "content": [{ "type": "text", "text": "..." }],
  "isError": false
}

Every result lists its sources with their licence. File results come as downloads: each link builds its file when opened.

Errors

A missing key answers 401, an empty balance 402, too many calls 429. A call that fails or finds nothing is not counted. See Errors and rate limits.

Description for agents

The text the server gives an agent to decide when to call this tool:

Use this when the user wants to apply one GIS operation to a set of features (an uploaded file, a link, inline GeoJSON, or a download link from another TerraLab answer) and get the result as a file: buffer every feature by radius_m, union (dissolve all features into one, or one per value of dissolve_field), intersection or difference with a second layer, clip to a second layer or to an area (place, place with radius_m, or bbox), simplify by tolerance_m, centroid of each feature, or area_length (adds area_m2, perimeter_m and length_m to each feature, geodesic). Overlays run in WGS 84 degrees; buffer, simplify and centroid in a local equidistant projection. Up to 20,000 features and 100,000 vertices (10,000 for buffer). Returns the feature count, geometry types, total area or length, a map and GeoJSON, KML, Shapefile zip, GeoPackage and CSV downloads. Not for one distance or the area of a shape drawn in the chat: that is measure. Not for reading or converting a file without changing its geometry: that is open_gis_file. Not for styling layers, print layouts or chaining steps on the layers of a QGIS project the user has open: TerraLab AI Agent in QGIS does that. Never use the user's current location unless they type it. Download links build their file when opened; no file is saved. Never pass these links to open_gis_file: list every format the user needs in formats, in this one call. TerraLab reads the file or link to answer and keeps no copy.

Updated 2026-10-27