Map data
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.
| REST | POST https://mcp.terra-lab.ai/v1/tools/process_geometry |
| MCP tool | process_geometry on https://mcp.terra-lab.ai/mcp |
| Group | Map 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.
| Name | Type | Required | Description |
|---|---|---|---|
operation | string | Yes | The operation to apply. One of "buffer", "union", "intersection", "difference", "clip", "simplify", "centroid", "area_length". |
file | object | No | A file uploaded in the conversation (GeoJSON, KML, KMZ, GPX, zipped Shapefile, CSV or WKT). |
file.download_url | string | Yes | |
file.file_id | string | Yes | |
file.file_name | string | No | |
file.mime_type | string | No | |
url | string | No | A public http(s) link to the features, or a TerraLab download link from an earlier answer. |
geojson | object | No | The features as a GeoJSON FeatureCollection, Feature or geometry in WGS 84 (longitude, latitude). |
with_file | object | No | For intersection, difference and clip: the second layer, uploaded in the conversation. |
with_file.download_url | string | Yes | |
with_file.file_id | string | Yes | |
with_file.file_name | string | No | |
with_file.mime_type | string | No | |
with_url | string | No | For intersection, difference and clip: a link to the second layer, or a TerraLab download link. |
with_geojson | object | No | For intersection, difference and clip: the second layer as GeoJSON in WGS 84. Only its polygons count. |
area | object | No | For 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.bbox | array of number | No | [west, south, east, north] in decimal degrees (WGS 84). Exactly 4 items. |
area.place | string or object | No | A place name or address, or a point. |
area.radius_m | number | No | Radius around the place in metres. From 1 to 100000. |
radius_m | number | No | For buffer: the distance in metres (convert km or miles first). From 0.1 to 100000. |
tolerance_m | number | No | For simplify: the largest allowed shift of the outline in metres. From 0.01 to 100000. |
dissolve_field | string | No | For union: dissolve into one feature per value of this field instead of one feature. |
formats | array of string | No | Download formats. All five by default. |
title | string | No | Name 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