carbon-geo-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@carbon-geo-mcprun declared vs calculated area check with 1% tolerance on project.gpkg"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
carbon-geo-mcp

An MCP server that lets an AI assistant run the GIS checks a carbon project auditor runs, on real files, instead of guessing numbers.
Ask a chatbot "how many hectares does this project have?" and it will answer with confidence without opening a single file. With this server connected, the assistant calls real geoprocessing (GeoPandas, Shapely, PyProj, Rasterio), gets the answer back as data and explains it, always saying which CRS it used and what was missing.
Question
Can an AI assistant be trusted with the routine spatial checks of a REDD+, ARR or IFM validation or verification (areas, overlaps, plots, forest loss) if it is given proper tools and the same rules an auditor follows?
Related MCP server: GIS MCP Server
Tools
Tool | What it checks | Typical audit question |
| CRS (and whether it is in degrees), geometry problems, fields, bounds | "Is this shapefile usable as delivered?" |
| Hectares per stratum in an equal-area CRS, dissolving overlaps, reporting overlap within and between strata | "How large is each stratum really?" |
| Declared vs. calculated hectares, with a tolerance | "Do the areas in the PD match the shapefile?" |
| Overlap between two polygon layers, in ha and %, with the largest pairs | "Does the project overlap a protected area or another project?" |
| Plots outside the strata, wrong declared stratum, overlapping strata, plots near the edge, duplicated coordinates | "Are the inventory plots where the report says they are?" |
| Loss per year from a local Hansen-style | "How much forest was lost inside the project in the monitoring period?" |
| Filled and missing values per attribute | "Which fields of the plot database are incomplete?" |
Design rules
These come from audit practice and from the most common failure of GIS agents: a calculation that "succeeds" in the wrong CRS.
CRS first. Nothing is measured in degrees. Areas use a local Lambert Azimuthal Equal Area projection centred on the data (equal-area anywhere on Earth); distances use the local UTM zone. A geographic CRS passed by the user is refused. Every result names the CRS used.
No double counting. Polygons are dissolved before measuring, and overlaps are reported, not hidden.
Say what is missing. Every result includes missing, empty, invalid and repaired geometries.
forest_loss_in_areareports how much of the area the raster actually covers.Zero is an answer, errors are errors. "No overlap" comes back as
0 ha, and a missing file or field comes back as an explicit tool error the assistant must report.Read-only and local. The server runs over stdio, never writes files and can be restricted to specific folders with
CARBON_GEO_MCP_ROOTS.
Results on the synthetic example
The sample data in data/sample is fictional: an 8,000 ha project placed in the Paraguayan Chaco, delivered in EPSG:4326 (degrees), with problems planted on purpose. The tools find all of them:
Check | Result |
Overlap between strata |
|
Declared vs. calculated |
|
Protected area | 150 ha of the project (1.9 %) inside the fictional reserve |
Plots | 2 plots outside the strata (300 m and 800 m), 1 plot in the wrong stratum, 1 plot 20 m from the boundary, 1 pair of duplicated coordinates |
Forest loss 2015-2024 | 289 ha inside the project (3.6 %), 100 % raster coverage |
One detail worth noting: the strata were drawn in UTM 20S as exactly 8,000 ha, but the equal-area measurement gives 8,004 ha. The 0.05 % difference is the UTM scale factor, which is exactly why declared areas should state the CRS they were computed in.
Install
Requires Python 3.10 or later.
pip install git+https://github.com/albertolozada/carbon-geo-mcp.gitOr run it without installing, with uv:
uvx --from git+https://github.com/albertolozada/carbon-geo-mcp.git carbon-geo-mcpGuía detallada en español: docs/USAGE_es.md (instalación en Windows, Claude Desktop, Claude Code CLI, MCP Inspector y problemas frecuentes).
Connect it to an AI assistant
The same configuration works in Claude Desktop (claude_desktop_config.json), Cursor (.cursor/mcp.json) and other MCP hosts. On Windows:
{
"mcpServers": {
"carbon-geo-mcp": {
"command": "uvx",
"args": ["--from", "git+https://github.com/albertolozada/carbon-geo-mcp.git", "carbon-geo-mcp"],
"env": { "CARBON_GEO_MCP_ROOTS": "D:\\GIS\\projects" }
}
}
}On macOS or Linux use a path such as /home/you/gis/projects. Several folders can be listed, separated by ; on Windows and : elsewhere. Restart the host completely after editing the configuration.
Example prompts
Check the layers in D:\GIS\projects\demo: run layer_info on each one and tell me
which are in a geographic CRS and whether any geometry is invalid.
The PD declares 8,000 ha in total, 4,800 ha of dense_forest and 2,800 ha of
open_forest. Compare it with project_strata.gpkg (field "stratum") using a 1 %
tolerance and explain any difference.
Using plots.gpkg and project_strata.gpkg, list plots outside the strata, plots
whose declared stratum is wrong and plots closer than 50 m to the boundary.
How much forest was lost inside the project between 2015 and 2024 according to
lossyear_sample.tif? Say which CRS and pixel-area method were used.Reproduce it
In your browser: click the "Open in Colab" badge. The notebook installs the server, calls every tool through a real MCP client, and then confirms the key numbers with an independent GeoPandas script (the agent explores, the script confirms).
On your computer:
git clone https://github.com/albertolozada/carbon-geo-mcp.git
cd carbon-geo-mcp
pip install -e ".[dev]"
python scripts/make_sample_data.py # regenerates data/sample
pytest # 14 tests with known answersLimitations
Forest loss uses pixels whose centre falls inside the area, the usual convention; small or narrow areas can differ slightly from an area-weighted count.
forest_loss_in_areareads a local raster. Download the Hansen GFClossyeartile for your area first (seedata/README.md).The server returns short summaries, not geometries, but those summaries do reach the AI model you connect. Check your confidentiality obligations before using it on client data.
Version 0.1: the tools cover the checks I use most often and are not a substitute for the auditor's judgement.
Repository structure
├── src/carbon_geo_mcp/ the server (server.py) and the checks (geo.py)
├── tests/ tests with known answers, run on every push
├── data/sample/ synthetic, fictional sample data
├── notebooks/ demo notebook (Colab-ready)
├── scripts/ sample data and preview map generators
└── outputs/maps/ figures used in this READMEAuthor
Alberto Lozada Silva, forestry engineer and carbon project auditor. Portfolio: albertolozada.github.io · LinkedIn
Servidor MCP que permite a un asistente de IA ejecutar, sobre archivos reales, los controles SIG que hace un auditor de proyectos de carbono: áreas por estrato en un CRS de igual área, comparación de áreas declaradas y calculadas, solapamientos, ubicación de parcelas de monitoreo, pérdida de bosque por año y completitud de atributos. Cada resultado indica el CRS utilizado y qué datos faltaban. El servidor es local y de solo lectura, y puede limitarse a carpetas concretas. Los datos de ejemplo son ficticios.
Instalación y uso paso a paso: docs/USAGE_es.md.
Licence
Code under the MIT License. Sample data is synthetic and free to reuse.
Available Tools
7 toolsarea_by_stratumARead-onlyIdempotent
Area in hectares of a polygon layer, in total and per stratum, measured in an equal-area CRS. Overlapping polygons are dissolved so ground is never counted twice, and the overlap inside each stratum and between strata is reported.
Args: path: Polygon layer (project area, strata, eligible area...). stratum_field: Attribute holding the stratum or class (optional). layer: Layer name inside a multi-layer file (optional). crs: Projected CRS to measure in, e.g. "EPSG:32720". If omitted, a local Lambert Azimuthal Equal Area projection centred on the data is used.
| Name | Required | Description | Default |
|---|---|---|---|
| crs | No | ||
| path | Yes | ||
| layer | No | ||
| stratum_field | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
While annotations cover safety, the description adds critical operational context, such as the guarantee that 'ground is never counted twice' due to dissolving overlaps. This explains the specific nature of the calculation process beyond simple execution hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured, dedicating the first sentence to the primary value proposition. It uses the second sentence to explain the core processing behavior without unnecessary jargon.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of GIS area calculations and CRS handling, the definition is highly complete regarding how the tool handles overlap and measurement. This context is crucial for an AI agent to select this over simpler area calculation tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Since schema coverage is 0%, the description must carry the weight of semantics. It clarifies that 'path' is a polygon layer and explains the critical default behavior of the 'crs' parameter (local Lambert Azimuthal Equal Area projection).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the specific resource (a polygon layer) and the result (Area in hectares), specifying that the calculation includes reporting per stratum. It distinguishes itself by detailing the use of an equal-area CRS and the process of dissolving overlapping polygons.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description focuses entirely on the technical mechanics of the tool rather than providing guidance on when to use it versus alternatives. It does not compare the tool's functionality to siblings like 'check_overlap' or 'layer_info.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_overlapARead-onlyIdempotent
Overlap between two polygon layers (e.g. project area vs. protected areas, other registered projects, leakage belt or reference region): hectares, percentage of each layer and the largest overlapping feature pairs. Reports 0 ha explicitly.
Args: path_a: First polygon layer (usually the project area). path_b: Second polygon layer. id_field_a: Attribute used to name features of layer A (optional). id_field_b: Attribute used to name features of layer B (optional). layer_a: Layer name inside a multi-layer file A (optional). layer_b: Layer name inside a multi-layer file B (optional). crs: Projected CRS to measure in (optional, equal-area by default). max_pairs: Maximum number of overlapping pairs to list (default 20).
| Name | Required | Description | Default |
|---|---|---|---|
| crs | No | ||
| path_a | Yes | ||
| path_b | Yes | ||
| layer_a | No | ||
| layer_b | No | ||
| max_pairs | No | ||
| id_field_a | No | ||
| id_field_b | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive, closed-world behavior, so the description's burden is small; it still adds real value by disclosing that 0 ha is reported explicitly, that results are measured in a projected equal-area CRS by default, and that pair listing is capped. It does not cover failure behavior (e.g. non-overlapping extents, unprojectable data).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence front-loads the purpose and outputs, and the Args block is scannable with one line per parameter; nothing is padding. Minor redundancy in restating schema defaults (20, null) inside the Args lines.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an eight-parameter spatial tool with zero schema descriptions, the definition supplies purpose, use-case examples, all parameter meanings, and default projection behavior, while the output schema covers return values. Remaining gaps are secondary details like CRS format expectations and behavior on degenerate or empty geometries.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description carries the full burden and does so through an Args block covering all eight parameters, including non-obvious semantics such as id_field_a naming features of layer A, layer_a selecting a layer inside a multi-layer file, and crs defaulting to an equal-area projection. It stops short of specifying accepted CRS syntax or what the max_pairs cutoff does to reported totals.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific computation on a specific resource pair ('Overlap between two polygon layers') and enumerates the outputs (hectares, percentage of each layer, largest overlapping feature pairs). It is unambiguous and clearly distinct from siblings like area_by_stratum or compare_declared_area, but it never explicitly differentiates itself from them, leaving that inference to the agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The parenthetical examples ('project area vs. protected areas, other registered projects, leakage belt or reference region') convey the intended contexts, which is genuinely useful, but they are examples of layer types rather than explicit use/when-not-use guidance. No alternative tool is named and no prerequisite or exclusion is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_declared_areaARead-onlyIdempotent
Compare areas declared in a project document (PD, monitoring report) with the areas calculated from the layer, and flag differences above a tolerance.
Args: path: Polygon layer with the project area or strata. declared_ha: Declared hectares, keyed by stratum value and/or "total", e.g. {"total": 8000, "dense_forest": 5200}. stratum_field: Attribute holding the stratum (needed for per-stratum keys). tolerance_pct: Accepted absolute difference in percent (default 1.0). layer: Layer name inside a multi-layer file (optional). crs: Projected CRS to measure in (optional, equal-area by default).
| Name | Required | Description | Default |
|---|---|---|---|
| crs | No | ||
| path | Yes | ||
| layer | No | ||
| declared_ha | Yes | ||
| stratum_field | No | ||
| tolerance_pct | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered. The description adds genuine behavioral context beyond that: the tolerance threshold concept, the default of 1.0, and the equal-area default CRS used for measurement. It doesn't say what a 'flag' looks like in the response, but the output schema carries that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose sentence is front-loaded and the remaining content is a tight Args block with no filler. The docstring formatting is slightly mechanical, but every line carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter tool with a nested object argument and an output schema, this covers nearly everything needed to invoke it correctly, including the CRS/measurement concern. The main gap is that it doesn't say whether tolerance violations cause an error or are simply reported, though the output schema likely answers that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the full burden, and it does: it explains path, the declared_ha keying convention with a concrete example ({"total": 8000, "dense_forest": 5200}), when stratum_field is required, what layer means for multi-layer files, and the meaning/default of crs and tolerance_pct. This is meaning an agent cannot get from the bare schema titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: compare areas declared in a project document (PD, monitoring report) against areas calculated from the layer, and flag differences above a tolerance. That is far more than a restatement of the name. It does not explicitly distinguish itself from siblings such as area_by_stratum, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The context of use is implied by 'declared in a project document' versus 'calculated from the layer', which tells an agent this is a QA/validation step. However, there is no explicit when-to-use, no prerequisites (e.g. run area_by_stratum first), and no named alternatives or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
data_completenessARead-onlyIdempotent
Completeness of the attributes of a layer: filled and missing values per field (blank text counts as missing) and number of distinct values.
Args: path: Vector layer to inspect. fields: Fields to check (optional, all fields by default). layer: Layer name inside a multi-layer file (optional).
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| layer | No | ||
| fields | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds one genuinely useful behavioral rule beyond that: blank text counts as missing. However it says nothing about how nulls vs empty strings vs whitespace are treated further, or what happens for a nonexistent field name. Given the read-only annotations cover the risky dimensions, a 3 is fair.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first sentence with the key rule (blank text equals missing) in parentheses, followed by a compact Args list. The Args list partially duplicates schema titles, but with 0% schema description coverage that duplication is earning its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the return shape does not need explaining, and the description already states what the result measures (filled, missing, distinct counts). For a 3-parameter read-only inspection tool this is close to complete; only edge-case behavior for invalid paths or fields is unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameters, and it does explain all three: path is the vector layer to inspect, fields is an optional subset defaulting to all fields, and layer selects a layer inside a multi-layer file. It does not specify accepted path formats or what error surfaces for an invalid field name, which keeps it below a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the specific measurement (filled/missing values per field plus distinct-value counts) and its scope (attributes of a vector layer), which clearly separates it from siblings like layer_info or area_by_stratum. It is not a bare restatement of the name 'data_completeness' because it enumerates exactly what is counted.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the purpose (a data-quality check on a layer's attributes) but there is no explicit when-to-use or when-not-to-use guidance, and no pointer to the sibling tools such as layer_info that also describe a layer. An agent can infer the context but must decide on its own.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
forest_loss_in_areaARead-onlyIdempotent
Forest loss per year inside an area of interest from a local "lossyear" raster (e.g. a Hansen Global Forest Change tile, where 1 = 2001 ... 24 = 2024). Pixel areas are geodesic for rasters in degrees. Also reports how much of the area the raster actually covers, so a partial tile is never read as "no loss".
Args: aoi_path: Polygon layer with the area of interest (project area, leakage belt...). lossyear_raster: Path to the GeoTIFF with loss years. aoi_layer: Layer name inside a multi-layer AOI file (optional). start_year: First year to include, e.g. 2015 (optional). end_year: Last year to include, e.g. 2024 (optional). base_year: Year added to the raster value (2000 for Hansen GFC).
| Name | Required | Description | Default |
|---|---|---|---|
| aoi_path | Yes | ||
| end_year | No | ||
| aoi_layer | No | ||
| base_year | No | ||
| start_year | No | ||
| lossyear_raster | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, so the description is not burdened with the safety profile. It instead adds substantive traits the annotations cannot convey: geodesic pixel areas for degree-based rasters and the coverage fraction that prevents a partial tile from being misread as 'no loss'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the key caveat are front-loaded before the Args block, and every line is doing work given the empty schema descriptions. The Args enumeration duplicates parameter names from the schema, but that duplication is justified at 0% coverage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description still flags the coverage-reporting output as the key safeguard. For a two-required-parameter geospatial tool it covers the essential semantics, missing only edge-case handling for out-of-range years or mismatched CRS.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameter burden, and it does: each of the six parameters gets meaning, including the non-obvious base_year offset (2000 for Hansen GFC) and the optional aoi_layer for multi-layer files. It stops short of specifying path format or how start_year/end_year interact with base_year.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
First sentence states a specific verb and resource: forest loss per year inside an AOI computed from a local lossyear raster, with the raster encoding spelled out (1 = 2001 ... 24 = 2024). This is clearly distinct from siblings like area_by_stratum or data_completeness, which do not operate on a loss-year raster.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the use case (project area, leakage belt) but never explicitly says when to pick this over data_completeness or compare_declared_area, nor does it state preconditions such as raster/AOI CRS compatibility. Usage is inferable rather than instructed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
layer_infoARead-onlyIdempotent
Describe a vector layer before any analysis: CRS (and whether it is in degrees), feature count, missing/empty/invalid geometries, geometry types, bounds and fields with their null counts. Call this first on every layer.
Args: path: Path to a vector file (GeoPackage, Shapefile, GeoJSON, KML, FlatGeobuf...). layer: Layer name inside a multi-layer file such as a GeoPackage (optional).
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| layer | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds the meaningful behavioral detail that the call performs a full scan (invalid geometry detection, per-field null counts) and reports a degrees/CRS check, which primes the agent for what the call inspects. It omits cost hints for very large layers and what happens when a multi-layer file is passed without the layer argument.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose and the "call this first" directive, then a clearly separated Args block. The enumeration of return contents is dense but earns its place by signalling scan depth; only the return-value listing mildly overlaps the existing output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read-only inspection tool with an output schema, the description covers purpose, sequencing, both parameters, and the scope of what is examined. The remaining ambiguity (layer resolution on multi-layer files, runtime on large inputs) is minor and does not affect correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and does so: it names supported vector formats for path (GeoPackage, Shapefile, GeoJSON, KML, FlatGeobuf) and explains that layer is the optional layer name inside a multi-layer file such as a GeoPackage. Both parameters gain meaning that the bare schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (describe a vector layer) and immediately enumerates the concrete outputs: CRS with a degrees flag, feature count, missing/empty/invalid geometries, geometry types, bounds, and per-field null counts. The siblings are all analysis tools, and the description makes clear this is the metadata/inspection counterpart an agent should run before them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Call this first on every layer" and "before any analysis" give an explicit precondition for invocation, which is exactly what an agent needs for sequencing. It stops short of naming any sibling tools or stating when-not to use it, so it falls just short of the top band.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plots_in_strataARead-onlyIdempotent
Check monitoring or inventory plots against the strata: plots outside every stratum (with distance), plots whose declared stratum differs from the stratum they fall in, plots on overlapping strata, plots close to the boundary and duplicated coordinates. Distances are measured in the local UTM zone unless a CRS is given.
Args: plots_path: Point layer with plot centres. strata_path: Polygon layer with the strata. stratum_field: Stratum attribute in the strata layer. plot_stratum_field: Stratum declared for each plot in the plots layer (optional). plot_id_field: Plot identifier attribute (optional). edge_distance_m: Flag plots closer than this to the strata boundary (0 = off). plots_layer: Layer name inside the plots file (optional). strata_layer: Layer name inside the strata file (optional). crs: Projected CRS for distances (optional).
| Name | Required | Description | Default |
|---|---|---|---|
| crs | No | ||
| plots_path | Yes | ||
| plots_layer | No | ||
| strata_path | Yes | ||
| strata_layer | No | ||
| plot_id_field | No | ||
| stratum_field | Yes | ||
| edge_distance_m | No | ||
| plot_stratum_field | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered; the description adds real behavioral context beyond them, notably that distances use the local UTM zone unless a CRS is supplied and that edge_distance_m=0 disables boundary flagging. It also tells the agent what categories of findings are produced, which is not derivable from the annotations. It stops short of describing granularity of results or how findings are keyed, which the output schema presumably covers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the outcome-oriented summary before the parameter block, and both parts earn their space. The multi-clause opening sentence is dense but readable, and the per-argument lines are terse; only the redundant 'Layer name inside the X file' phrasing could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter geospatial validation tool, the definition covers all required inputs plus the optional ones and explains the distance/CRS behavior. An output schema exists, so return values need not be explained. Only input format expectations (CRS syntax, file type expectations) are missing, a modest gap given the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% (only bare titles), so the Args block carries the full documentation burden and does so for all nine parameters, including which are optional and that edge_distance_m defaults to off. The gap is format guidance: it does not say what a CRS string looks like (EPSG code vs WKT) or what file formats plots_path/strata_path accept, which an agent must guess.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Check monitoring or inventory plots against the strata') and enumerates the exact conditions it detects: plots outside every stratum, mismatched declared stratum, overlapping strata, near-boundary plots, and duplicate coordinates. This is far more specific than a restatement of the name, though it never names or distinguishes itself from siblings such as check_overlap or data_completeness.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the list of checks performed (a QA/validation pass on plot geometry against a strata layer), so an agent can infer the scenario. However, there is no explicit when-to-use guidance, no exclusion criteria, and no pointer to the sibling tools that might be the better choice (e.g., check_overlap for pure overlap testing).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.1.0- First observed
area_by_stratum - First observed
check_overlap - First observed
compare_declared_area - First observed
data_completeness - First observed
forest_loss_in_area - First observed
layer_info - First observed
plots_in_strata
TDQS
Scored across 7 tools
Each tool has a clearly separate analytical purpose (inspection, area measurement, declared-area comparison, cross-layer overlap, plot QA, raster forest loss, attribute completeness). The only real overlap is between layer_info and data_completeness, since layer_info already reports per-field null counts while data_completeness goes deeper on blanks/distinct values; the descriptions make the distinction (structural describe vs. attribute QA) reasonably clear.
All names are snake_case and read predictably. The stem style is mixed—verb-led (compare_declared_area, check_overlap) versus noun/domain-led (layer_info, plots_in_strata, forest_loss_in_area, data_completeness)—but each name accurately telegraphs its operation.
Seven tools is well-scoped for a geo-validation server; each one covers a distinct step in carbon-project spatial verification (inspect, measure, compare, cross-check, plot QA, forest loss, attribute QA). No tool appears redundant or filler.
The surface covers the core QA lifecycle for project-area data: layer health, equal-area measurement, declared-vs-actual reconciliation, overlap detection, plot placement checks, forest-loss quantification and attribute completeness. Minor gaps exist—no reprojection/export or generic raster statistics beyond lossyear, and no written report output—but agents can work around these.
Maintenance
Related MCP Connectors
Screen farm plots for EUDR deforestation risk with the official EU JRC maps.
GIS tools for AI agents: 65 free tools + 8 paid (hazard/site-scouting/GeoJSON export)
Sourced carbon emission factors + audit-traced calculations an AI can cite.
Verifiable geospatial tools: distances, topology, isochrones, Overture Maps, with sources.
Related MCP Servers
AlicenseAqualityAmaintenanceEnables AI agents to perform professional-grade geoprocessing tasks such as buffers, overlays, reprojections, and terrain analysis with deterministic tools and verifiable provenance.29396 PyPI2AGPL 3.0- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to perform geospatial analysis, spatial data processing, vector and raster operations, coordinate transformations, spatial statistics, mapping, and access to climate, satellite, and other geospatial data through MCP-compatible clients.MIT
- AlicenseNot gradedqualityCmaintenanceEnables an AI assistant to run pre-ingest QA on utility power-grid GIS exports: score readiness, list issues with coordinates, reconcile registers against survey/LiDAR detections, map codes to library types, and draft a data request. It exposes the same checks, reconciliation and reporting operations as callable tools so a deployment engineer can work conversationally in any MCP client.MIT
- AlicenseAqualityCmaintenanceGives AI assistants read-only, key-free access to Sentinel-2 NDVI time series, ESA WorldCover land-cover shares, and Copernicus 30 m elevation and slope for a point or small area, returning the scene IDs, units, and caveats behind every number. Built-in sanity checks and a verify tool recompute key values through an independent path so the assistant can flag cloudy, low-confidence, or mismatched results instead of guessing.6MIT