Skip to main content
Glama

gbif-biodiversity-mcp-server

Occurrence Facet Aggregation

gbif_occurrence_facets
Read-onlyIdempotent

Aggregate occurrence counts across a dimension (COUNTRY, STATE_PROVINCE, YEAR, BASIS_OF_RECORD, DATASET_KEY, KINGDOM_KEY, etc.). Returns one page of facet values ranked by count descending — the top facetLimit at facetOffset 0, a later slice of the same ranking past that. No record payloads returned. Core tool for distribution analysis and trend queries: "which countries have the most records for this species?", "how has observation volume changed since 2010?". Scope the aggregation with taxonKey, country (uppercase ISO 3166-1 alpha-2), publishingCountry, stateProvince, year, geometry, basisOfRecord, datasetKey, occurrenceStatus, or iucnRedListCategory filters. Also the way to split a result set too large for gbif_search_occurrences to page (offset+limit caps at 100,001): facet by DATASET_KEY, then search each datasetKey on its own. Aggregates sightings only by default, matching gbif_search_occurrences and gbif_count_occurrences; to measure the presence/absence split itself, pass facet OCCURRENCE_STATUS with occurrenceStatus ANY.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
yearNoYear or year range (e.g., "2020,2024") to scope the aggregation. Both endpoints inclusive. Omit the field to aggregate across every year — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered aggregation.
facetYesDimension to aggregate by (e.g., COUNTRY, YEAR, BASIS_OF_RECORD, SPECIES_KEY, OCCURRENCE_STATUS, IUCN_RED_LIST_CATEGORY). DATASET_KEY is the dimension to split on when a result set is too large to page: every occurrence carries exactly one datasetKey, so its buckets sum to totalOccurrences with no gap and no overlap, and it has the cardinality to cut a large scope into pageable pieces. BASIS_OF_RECORD and PUBLISHING_COUNTRY are gap-free too and both have a matching filter on the occurrence tools, so either can drive a further split of a bucket still too large — but on that same scope they return 9 and 41 buckets against DATASET_KEY's 550, so neither replaces it as the first cut. A dimension a record can lack silently drops that record: faceting one 60,290,950-record scope by YEAR returned 224 buckets summing to 59,407,400, leaving 883,550 undated records in no bucket at all, and MONTH, STATE_PROVINCE, and SPECIES_KEY lose records the same way — stateProvince included, even though the occurrence tools can now filter on it. Sums are comparable only across the same occurrenceStatus scope.
countryNoISO 3166-1 alpha-2 code, uppercase, of where the occurrence was recorded, to scope to one country. Not the publisher's country — that is publishingCountry, and the two disagree on most records. Scope to one country, or pass back a value this tool returned under facet COUNTRY to drill into that bucket. Lowercase and alpha-3 forms ("gb", "USA") match nothing upstream, which is why only the uppercase two-letter form is accepted here.
geometryNoWKT polygon to scope the aggregation to a geographic area (e.g., POLYGON((8 47, 9 47, 9 48, 8 48, 8 47))). Coordinates are longitude latitude. Omit the field to aggregate everywhere — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered aggregation.
taxonKeyNoBackbone taxon key to scope the aggregation. Matches the given taxon and all descendant taxa (subspecies, varieties, etc.).
datasetKeyNoScope the aggregation to a single dataset by its GBIF dataset UUID (8-4-4-4-12 hex). Obtain one from gbif_search_datasets, gbif_get_dataset, a DATASET_KEY facet, or the datasetKey field on an occurrence record. Omit the field to aggregate across every dataset — an empty string is rejected rather than read as no scope, because GBIF answers a blank datasetKey with the unfiltered aggregation.
facetLimitNoMaximum number of facet values to return (default 10, max 100).
facetOffsetNoZero-based offset into the ranked facet values, for paging past the first facetLimit values on high-cardinality dimensions like DATASET_KEY. Advance by facetLimit to fetch the next page (0, then facetLimit, then 2×facetLimit, …).
basisOfRecordNoScope to a specific basis of record.
stateProvinceNoState, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. Pass back a value this tool returned under facet STATE_PROVINCE rather than a guessed one: GBIF stores what each dataset recorded without normalizing it, so "England", "England - Greater London", and "Greater London" are three distinct values, "england" is none of them, and an unmatched value aggregates zero records rather than erroring. Omit the field to aggregate across every state or province — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered aggregation.
occurrenceStatusNoPresence/absence scope. Defaults to PRESENT so the aggregation counts sightings, not the surveys that looked and found nothing, and agrees with gbif_count_occurrences on the same filters. Use ANY for both — required to see both buckets when facet is OCCURRENCE_STATUS — or ABSENT for non-observations alone.PRESENT
publishingCountryNoISO 3166-1 alpha-2 code, uppercase, of the organization that published the record — not where the occurrence was observed, which is country. Scope to one publisher country, or pass back a value this tool returned under facet PUBLISHING_COUNTRY to drill into that bucket. Lowercase and alpha-3 forms ("us", "USA") match nothing upstream, which is why only the uppercase two-letter form is accepted here.
iucnRedListCategoryNoScope to records whose taxon carries this IUCN Red List category: CR Critically Endangered, EN Endangered, VU Vulnerable, NT Near Threatened, LC Least Concern, DD Data Deficient, EX Extinct, EW Extinct in the Wild, CD Conservation Dependent. Leave unset and facet on IUCN_RED_LIST_CATEGORY to see the whole distribution instead.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
capNofacetLimit applied when the page was capped. Re-call with facetOffset advanced by this value to page on. Absent otherwise.
errorNoPresent when the call failed. Absent on success.
facetNoThe facet dimension aggregated.
shownNoFacet values returned in this page when the page was capped. Absent otherwise.
countsNoFacet values ranked by count descending — one page of up to facetLimit entries starting at facetOffset, not necessarily the top ones.
noticeNoGuidance when no facet values were returned, the page came back full and more values may remain, a verbatim stateProvince filter matched nothing, or a presence/absence filter narrowed the aggregation. Absent only when none applies.
truncatedNoHeuristic continuation flag: present and true when this page returned a full facetLimit of values, so more distinct values may exist past facetOffset + facetLimit. GBIF exposes no total distinct-value count, so this is an estimate, not exact. Absent when the page came back short, which is the only proof the ranking is exhausted.
facetLimitNoMaximum facet values requested.
facetOffsetNoZero-based offset applied to the ranked facet values.
occurrenceStatusNoThe presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what totalOccurrences and every bucket cover.
totalOccurrencesNoTotal matching occurrences across all facet values.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Even with readOnlyHint, openWorldHint, and idempotentHint annotations, the description adds substantial behavioral context: it explains the paging ranking and offset semantics, warns that some dimensions silently drop records (the YEAR example with 883,550 undated records), notes that stateProvince is matched verbatim and case-sensitive, and explains that blank values are rejected rather than dropped by GBIF. These are critical execution behaviors not captured by annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact yet dense; every sentence earns its place. It front-loads the core purpose and examples, then adds the large-set splitting strategy and edge-case behaviors. Despite covering many nuances, there is no filler or redundant repetition of schema content. The structure (purpose → examples → caveats) is logical and scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 13 parameters and an output schema, the description covers all critical usage aspects: the paging mechanism (facetLimit, facetOffset), the default occurrenceStatus behavior, the splitting workaround for large result sets, and the data-loss caveats for certain dimensions. It also points to sibling tools for obtaining datasetKey. Nothing an agent needs to correctly call this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description provides tool-level guidance (paging, splitting, default scope) but does not add per-parameter semantic detail beyond what the schema already documents. The schema descriptions themselves are exhaustive, so the description's role is more about usage context than parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Aggregate occurrence counts across a dimension' and lists the dimensions explicitly (COUNTRY, YEAR, DATASET_KEY, etc.). It differentiates from siblings by contrasting with gbif_search_occurrences ('No record payloads returned') and notes it complements gbif_count_occurrences. The purpose is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit when-to-use scenarios: 'Core tool for distribution analysis and trend queries' with concrete example questions, and a specific alternative routing: 'Also the way to split a result set too large for gbif_search_occurrences to page (offset+limit caps at 100,001): facet by DATASET_KEY, then search each datasetKey on its own.' It also clarifies the default occurrenceStatus to match sibling tools, giving the agent clear decision criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.5/5.0
Disambiguation5/5

Each tool targets a distinct action and resource pair: matching (single and batch), retrieving species details, hierarchy traversal, searching occurrences, counting, aggregating by facets, and searching datasets/publishers. There is no functional overlap or ambiguity between tools.

Naming Consistency4/5

The naming is largely consistent with the gbif_ prefix followed by a verb and noun (e.g., gbif_match_species, gbif_count_occurrences, gbif_get_dataset). However, a few tools use a search_<noun> pattern (e.g., gbif_search_datasets) and one uses a noun phrase without a verb (gbif_occurrence_facets), introducing a minor inconsistency.

Tool Count5/5

13 tools is well within the optimal range for a domain-specific API. The tools cover taxonomy resolution, species lookup and hierarchy, occurrence search/count/aggregation, and dataset/publisher discovery—no unnecessary bloat or sparse coverage.

Completeness4/5

The surface covers the core GBIF workflows: match → search/get occurrences, get species details and classification, and find datasets/publishers. Missing bulk download is explicitly acknowledged and not served by this tool, and searching datasets by taxon is indirect (via occurrence datasetKey), but these are workable gaps rather than blockers.