gbif-biodiversity-mcp-server
Server Details
Search GBIF species taxonomy, occurrence records, datasets, and publishers.
- Status
- Healthy
- Uptime
- 100.0% over 39 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- cyanheads/gbif-biodiversity-mcp-server
- GitHub Stars
- 1
- Server Listing
- GBIF Biodiversity MCP Server
TDQS
Scored across 13 tools
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.
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.
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.
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.
Available Tools
13 toolsgbif_bulk_match_speciesBulk Match Species NamesARead-onlyIdempotentInspect
Resolve up to 50 scientific names to GBIF backbone taxon keys in one call — the batch counterpart to gbif_match_species for checklist, inventory, and species-list workflows that would otherwise need one round trip per name. Each name is matched independently and results are returned in input order, one entry per name. A name with no backbone match yields matchType NONE (no taxonKey) instead of failing the batch; a per-name lookup failure yields matchType ERROR carrying that name's error message and, when the failure was classified, a machine-readable reason — the rest of the batch is unaffected, and the call as a whole still succeeds. When a queried name is a synonym, taxonKey is the accepted taxon it resolves to and matchedTaxonKey carries the synonym's own key. Common names are not supported — use gbif_search_species for vernacular searches. Below confidence 80, review the match.
| Name | Required | Description | Default |
|---|---|---|---|
| names | Yes | Scientific names to match against the GBIF backbone. 1–50 per call, matched in parallel. | |
| strict | No | When true, require an exact match for every name (no fuzzy matching). When false (default), GBIF applies fuzzy matching to tolerate minor misspellings. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| results | No | One result per input name, in input order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations (readOnly, openWorld, idempotent) to explain per-name independent matching, input-order results, NONE for no match, ERROR for per-name failures, batch-level success despite individual failures, synonym handling, and the semantics of taxonKey vs. matchedTaxonKey. This matches the annotations and adds essential behavior not otherwise conveyed.
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 well-structured and front-loaded with the core purpose, then expands into behavior and exclusions. Every sentence adds value—covering batch capability, result ordering, error handling, synonym resolution, unsupported names, and confidence guidance—without redundancy or fluff.
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 tool's complexity (batch handling, per-name outcomes, error types, synonym behavior) and the existence of a rich output schema, the description covers all critical aspects an agent needs to call it correctly and interpret results. The presence of an output schema means return values don't need to be re-explained, and the description fills in behavioral nuances comprehensively.
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 coverage is 100% for both parameters (names and strict), with detailed descriptions including defaults and behavior. The tool description adds no additional parameter-specific semantics beyond what the schema already provides, so it correctly stays at the baseline of 3.
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 states the verb 'resolve', the resource 'scientific names to GBIF backbone taxon keys', and explicitly distinguishes it as the batch counterpart to gbif_match_species. It also specifies the target workflows (checklist, inventory, species-list), making its purpose unambiguous and distinct from siblings.
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?
It explicitly states when to use the tool (batch workflows needing multiple names) and provides a clear exclusion: common names are not supported, with the alternative gbif_search_species recommended. It also gives a confidence threshold (`Below confidence 80, review the match`) which guides post-call actions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_count_occurrencesCount OccurrencesARead-onlyIdempotentInspect
Count occurrences matching a taxon + location filter without fetching records. Use for quick totals ("how many Aves records in Sweden?") or before deciding whether to paginate a full search. Accepts taxonKey, country (uppercase ISO 3166-1 alpha-2), publishingCountry, stateProvince, isGeoreferenced, datasetKey, year, occurrenceStatus, and iucnRedListCategory. Counts sightings only by default, matching gbif_search_occurrences — GBIF also indexes absence records, and for some taxa they are the overwhelming majority. A count above 100,001 is the signal to partition rather than page: gbif_search_occurrences cannot reach past that offset, so split the query by DATASET_KEY via gbif_occurrence_facets and search each dataset separately.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Year or year range (e.g., "2024" or "2020,2024"). Both endpoints inclusive. Omit the field to count across every year — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered total. | |
| country | No | ISO 3166-1 alpha-2 code, uppercase, of where the occurrence was recorded (e.g., "GB", "US"). Not the publisher's country — that is publishingCountry, and the two disagree on most records. Lowercase and alpha-3 forms ("gb", "USA") match nothing upstream, which is why only the uppercase two-letter form is accepted here. Take a value from a COUNTRY facet on gbif_occurrence_facets; an uppercase pair GBIF does not know ("XX") is rejected upstream by name. | |
| taxonKey | No | GBIF backbone taxon key from gbif_match_species. Matches the given taxon and all descendant taxa (subspecies, varieties, etc.). | |
| datasetKey | No | Filter to a specific dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets. Omit the field to count across every dataset — an empty string is rejected rather than read as no filter, because GBIF answers a blank datasetKey with the unfiltered total. The result is not the recordCount the dataset tools and the gbif://dataset/{datasetKey} resource report for the same key: that figure spans every occurrenceStatus, while this count applies occurrenceStatus below, PRESENT by default. | |
| stateProvince | No | State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: "England", "England - Greater London", and "Greater London" are three distinct values, and "england" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value counts zero rather than erroring. Omit the field to count across every state or province — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered total. | |
| isGeoreferenced | No | When true, count only georeferenced records. When false, count only non-georeferenced records. | |
| occurrenceStatus | No | Presence/absence filter. Defaults to PRESENT: an ABSENT record documents a survey that looked for the taxon and did not find it, so counting one inflates the total with the opposite of a sighting. Use ANY for both (GBIF's own default), or ABSENT for non-observations alone. Matches the gbif_search_occurrences default, so the two tools agree. | PRESENT |
| publishingCountry | No | ISO 3166-1 alpha-2 code, uppercase, of the organization that published the record — not where the occurrence was observed, which is country. The two differ constantly: of 60,290,950 records observed in GB, 1,548,928 were published by US organizations. Take a value from a PUBLISHING_COUNTRY facet on gbif_occurrence_facets. Lowercase and alpha-3 forms ("us", "USA") match nothing upstream, which is why only the uppercase two-letter form is accepted here. | |
| iucnRedListCategory | No | Count only 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. Records with no category are excluded when this is set. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | No | Total occurrences matching the supplied filters. |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Guidance when the count is zero under a verbatim stateProvince filter, larger than gbif_search_occurrences can page to, or narrowed by a presence/absence filter. Absent when none applies. |
| occurrenceStatus | No | The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what the count covers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description discloses critical behavioral nuances: the default occurrenceStatus of PRESENT, the absence-record caveat, the blank/whitespace rejection (vs. treating as no filter), and the difference from dataset recordCount. These are non-obvious and essential for correct use.
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 long but every sentence earns its place. It is front-loaded with the purpose, then flows logically into usage, then details each parameter's semantics. The density is high with zero filler, and the structure aids comprehension for a complex tool.
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 tool has an output schema (exempting return-value explanations) and 9 optional parameters, the description covers all necessary edge cases, default behaviors, and integration points with sibling tools. Nothing an agent needs to correctly invoke it is missing.
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?
Despite 100% schema coverage, the description adds substantial meaning: it explains why only uppercase two-letter country codes are accepted, the verbatim case-sensitive matching for stateProvince, the interaction between country and publishingCountry, and the default-and-rejection behavior for datasetKey and stateProvince. This goes far beyond repeating schema definitions.
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: 'Count occurrences matching a taxon + location filter without fetching records.' This clearly differentiates it from sibling gbif_search_occurrences, which fetches records, and states the tool's core function precisely. The scope is unambiguous.
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?
It explicitly states when to use the tool ('quick totals', 'before deciding whether to paginate') and when not to, via the 100,001 offset limitation and the recommendation to partition using gbif_occurrence_facets. It also references the sibling search tool's behavior, providing concrete, actionable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_get_datasetGet DatasetARead-onlyIdempotentInspect
Fetch full dataset metadata by UUID key — title, description, citation text, contacts, license, DOI, record count, numConstituents (sub-datasets), and temporal/geographic coverage. Use after gbif_search_datasets or when an occurrence record's datasetKey needs provenance detail. Contacts are capped by contactLimit (default 10); contactsTotal and contactsReturned report the full count.
| Name | Required | Description | Default |
|---|---|---|---|
| datasetKey | Yes | Dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets or an occurrence record. | |
| contactLimit | No | Maximum number of contacts to include (default 10, max 100). Set to 0 to omit contact detail while still reporting contactsTotal — useful when citation, license, and record count are all you need from a high-contact dataset like eBird. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | contactLimit applied when the list was capped. Raise it (max 100) to see more. Absent otherwise. |
| doi | No | DOI for citation. May be absent. |
| key | No | Dataset UUID. |
| type | No | Dataset type (OCCURRENCE, CHECKLIST, etc.). |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Contacts included in this response when the list was capped. Absent otherwise. |
| title | No | Dataset title. |
| notice | No | How to reach the contacts contactLimit held back. Absent when every contact was returned. |
| license | No | License identifier. May be absent. |
| contacts | No | Dataset contacts, capped at contactLimit. Absent when the dataset has no contacts or contactLimit is 0. |
| truncated | No | True when the dataset carries more contacts than contactLimit allowed through. Absent when every contact was returned. |
| description | No | Full dataset description. May be absent. |
| recordCount | No | Occurrence records GBIF has indexed for this dataset, matching the figure gbif_search_datasets reports. Spans every occurrenceStatus: absence records — surveys that looked for a taxon and did not find it — are counted alongside sightings, and on some datasets they are the overwhelming majority. gbif_count_occurrences with this datasetKey answers the other question, defaulting to occurrenceStatus PRESENT, so the two figures are expected to differ rather than one being wrong. Fetched separately because the detail endpoint omits it; absent when that lookup does not return in time. |
| citationText | No | Full citation text for academic reference. May be absent. |
| contactsTotal | No | Total contacts on the dataset before applying contactLimit. Present when the dataset has any contacts. |
| numConstituents | No | Number of constituent sub-datasets. May be absent. |
| contactsReturned | No | Number of contacts included in this response (≤ contactLimit). Present when the dataset has any contacts. |
| publishingCountry | No | Country code of the publishing organization. |
| temporalCoverages | No | Temporal coverage ranges declared by the dataset. May be absent. |
| geographicCoverages | No | Geographic coverage descriptions declared by the dataset. May be absent. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered. The description adds concrete behavioral detail: contacts are capped by contactLimit (default 10), and contactsTotal/contactsReturned report the full count. This goes beyond the annotations and gives the agent expectations about pagination-like behavior, earning a strong score above baseline.
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?
Two sentences with no filler. The first sentence front-loads the core purpose and main fields; the second provides usage context and the contact cap nuance. Every word earns its place, well-structured for quick comprehension.
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 output schema exists (noted in signals), the description needn't detail return structure, and it doesn't. It covers what metadata is returned, when to use it, and the contactLimit behavior. For a 2-parameter tool with full schema coverage, this is complete and leaves no obvious information gap for the agent.
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 100%, so both parameters are documented in the schema. However, the description adds value for contactLimit by explaining the 'set to 0' use case and its trade-off (omit contact detail while still reporting contactsTotal), which is not in the schema. It also reinforces datasetKey's source (from search or occurrence record), matching the schema but reaffirming context.
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 states it fetches full dataset metadata by UUID key, listing specific fields (title, description, citation, contacts, license, DOI, record count, etc.). It distinguishes itself from sibling tools by explicitly mentioning it is used after gbif_search_datasets or when provenance detail is needed, making it unambiguous which tool this is.
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 gives explicit when-to-use guidance: 'Use after gbif_search_datasets or when an occurrence record's datasetKey needs provenance detail.' It implicitly excludes searching/finding datasets (that's gbif_search_datasets) and occurrence-level retrieval (gbif_get_occurrence), providing clear contextual routing without being verbose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_get_occurrenceGet Occurrence RecordARead-onlyIdempotentInspect
Fetch a single occurrence record by its GBIF occurrence key. Returns the complete Darwin Core record — all coordinates, administrative geography (GADM levels 0–3), dates, collections metadata, collector identifiers, conservation status, media links, and quality issue flags. Check occurrenceStatus before reading the record as a sighting: ABSENT means a survey looked for the taxon and did not find it. Use the occurrence key from gbif_search_occurrences results.
| Name | Required | Description | Default |
|---|---|---|---|
| occurrenceKey | Yes | GBIF occurrence key from gbif_search_occurrences results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| day | No | Observation day. May be absent. |
| key | No | GBIF occurrence key. |
| sex | No | Sex of the individual(s). May be absent. |
| gadm | No | GADM administrative geography — stable GIDs and names at levels 0–3. May be absent. |
| year | No | Observation year. May be absent. |
| class | No | Class classification. May be absent. |
| error | No | Present when the call failed. Absent on success. |
| genus | No | Genus classification. |
| media | No | Associated media (images, audio, video). May be absent. |
| month | No | Observation month (1–12). May be absent. |
| order | No | Order classification. |
| family | No | Family classification. |
| issues | No | GBIF data quality issue flags. |
| phylum | No | Phylum classification. |
| country | No | Country name. May be absent. |
| kingdom | No | Kingdom classification. |
| species | No | Species canonical name. |
| classKey | No | Backbone taxon key for the class. May be absent. |
| locality | No | Locality description. May be absent. |
| taxonKey | No | Backbone taxon key. |
| continent | No | Continent name. May be absent. |
| eventDate | No | Observation date as ISO 8601 string. May be absent. |
| eventTime | No | Time of day of the observation, with seconds and UTC offset (e.g. 20:15:00+01:00) — the offset eventDate omits when it carries a local time. May be absent. |
| lifeStage | No | Life stage of the individual(s). May be absent. |
| taxonRank | No | Taxonomic rank of the identified taxon. |
| datasetKey | No | UUID of the source dataset. |
| recordedBy | No | Collector name(s). May be absent. |
| countryCode | No | ISO 3166-1 alpha-2 country code. May be absent. |
| identifiers | No | Alternative record identifiers from the source. May be absent. |
| identifiedBy | No | Identifier name(s). May be absent. |
| occurrenceID | No | Darwin Core occurrenceID — the source record identifier, often a URL back to the origin record. May be absent. |
| basisOfRecord | No | How the occurrence was recorded. |
| canonicalName | No | Canonical name without authorship. |
| catalogNumber | No | Catalog number within the collection. May be absent. |
| stateProvince | No | State or province. May be absent. |
| collectionCode | No | Collection code within the institution. May be absent. |
| scientificName | No | Scientific name from occurrence record. |
| decimalLatitude | No | Latitude in decimal degrees (WGS84). May be absent. |
| individualCount | No | Number of individuals. May be absent. |
| institutionCode | No | Code of the contributing institution. May be absent. |
| taxonomicStatus | No | Status of the identification carried on this record — ACCEPTED, PROVISIONALLY_ACCEPTED, SYNONYM, DOUBTFUL, and so on. Says whether the occurrence was filed under an accepted name or a synonym. May be absent. |
| decimalLongitude | No | Longitude in decimal degrees (WGS84). May be absent. |
| occurrenceStatus | No | PRESENT when the record asserts the taxon was there, ABSENT when it documents a survey that looked and did not find it. An ABSENT record is not a sighting — it carries coordinates, a date, and a recorder all the same. May be absent. |
| publishingCountry | No | Country code of the publishing organization. |
| iucnRedListCategory | No | IUCN Red List category of the taxon — 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. May be absent. |
| coordinateUncertaintyInMeters | No | Coordinate uncertainty radius in meters. May be absent. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint, openWorldHint, and idempotentHint, covering safety. The description adds valuable behavioral context: it lists the full Darwin Core record fields returned and explicitly explains the ABSENT occurrenceStatus semantic. This goes beyond the annotations and helps the agent interpret results correctly.
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?
Three well-structured sentences: the first states purpose, the second lists contents, the third gives a critical interpretation warning. No filler, no repetition, and all information is actionable. The most important constraint (check occurrenceStatus) is front-loaded after the purpose.
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 single-record fetch with an output schema and safety annotations, the description covers the essential workflow (search → get), the return envelope, and the classification nuance. Minor omissions like error behavior or rate limits are not critical for this simple read operation, so it's nearly complete.
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?
The schema already provides full coverage (100%) of the single parameter occurrenceKey with the description 'GBIF occurrence key from gbif_search_occurrences results.' The tool description repeats this same information without adding new syntax, format, or edge-case details. Since the schema carries the load, the baseline of 3 is appropriate.
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 clear and specific verb-resource pair: 'Fetch a single occurrence record by its GBIF occurrence key.' It enumerates exactly what the record contains (coordinates, GADM levels, dates, etc.), which distinguishes it from sibling getters like gbif_get_dataset or gbif_get_species. No ambiguity about what this tool does.
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?
It provides direct workflow guidance: 'Use the occurrence key from gbif_search_occurrences results' ties it to the search step. It also warns to check occurrenceStatus and explains the meaning of ABSENT, which is critical for correct interpretation. It does not explicitly name alternatives or say when not to use it, but given the tool is the only occurrence getter and has a distinct role, this is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_get_speciesGet Species RecordARead-onlyIdempotentInspect
Fetch a single backbone taxon by its GBIF taxon key. Returns full classification, authorship, taxonomic status, vernacular name, descendant count, and publication reference. Use after gbif_match_species when you need the complete record rather than the match summary. When taxonomicStatus is SYNONYM, acceptedKey and accepted fields identify the accepted taxon. The extinct field is absent (not false) on most records — only present on explicitly flagged taxa.
| Name | Required | Description | Default |
|---|---|---|---|
| taxonKey | Yes | GBIF backbone taxon key from gbif_match_species or another taxonomy tool. |
Output Schema
| Name | Required | Description |
|---|---|---|
| key | No | GBIF backbone taxon key. |
| rank | No | Taxonomic rank (SPECIES, GENUS, FAMILY, etc.). |
| class | No | Class classification. |
| error | No | Present when the call failed. Absent on success. |
| genus | No | Genus classification. |
| order | No | Order classification. |
| family | No | Family classification. |
| parent | No | Name of the immediate parent taxon. |
| phylum | No | Phylum classification. |
| extinct | No | True when the taxon is explicitly flagged as extinct. Absent on most records. |
| kingdom | No | Kingdom classification. |
| species | No | Species canonical name. |
| accepted | No | Scientific name of the accepted taxon when this record is a synonym. |
| classKey | No | Taxon key for the class. |
| genusKey | No | Taxon key for the genus. |
| orderKey | No | Taxon key for the order. |
| familyKey | No | Taxon key for the family. |
| parentKey | No | Taxon key of the immediate parent. |
| phylumKey | No | Taxon key for the phylum. |
| authorship | No | Taxonomic authorship of the name. |
| kingdomKey | No | Taxon key for the kingdom. |
| speciesKey | No | Taxon key for the species. |
| acceptedKey | No | Backbone key of the accepted taxon when this record is a synonym. |
| publishedIn | No | Original description citation when available. |
| canonicalName | No | Scientific name without authorship. |
| numDescendants | No | Count of child taxa in the backbone under this taxon. |
| numOccurrences | No | Occurrence record count in GBIF. |
| scientificName | No | Full scientific name with authorship. |
| vernacularName | No | English common name when available. |
| taxonomicStatus | No | ACCEPTED, SYNONYM, DOUBTFUL, etc. SYNONYM means acceptedKey/accepted are populated. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, covering safety. The description adds valuable non-obvious behavior: the synonym/acceptedKey field relationship and the extinct field's absence semantics. These details are not derivable from schema or annotations and help an agent interpret results correctly. No contradictions.
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?
Two sentences, no extraneous fluff. The core action and return value are front-loaded, followed by usage context and edge-case clarifications. Every sentence earns its place; nothing repetitive or vague.
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?
The tool has a rich output schema, so the description need not explain return values. It covers purpose, usage trigger, and unusual field behavior. For a single-parameter read-only tool with this much context, nothing critical is missing.
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 100% — the only parameter (taxonKey) has a descriptive schema. The description does not add extra parameter-level meaning, but given the schema already documents the parameter clearly, the baseline of 3 is appropriate.
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?
Description states a specific verb ('Fetch'), resource ('single backbone taxon'), and the key identifier ('by its GBIF taxon key'). It also enumerates the returned content (classification, authorship, status, vernacular name, descendant count, publication reference), which distinguishes it clearly from sibling tools like gbif_match_species (which returns a match summary) and gbif_get_species_children (which returns children). No ambiguity.
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?
Explicitly says 'Use after gbif_match_species when you need the complete record rather than the match summary,' providing a clear trigger and pointing to the relevant sibling. It does not state when NOT to use it (e.g., 'do not use for bulk matching'), but the positive guidance is sufficient for typical agent routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_get_species_childrenGet Species ChildrenARead-onlyIdempotentInspect
List direct children of a backbone taxon — genera within a family, species within a genus, subspecies within a species. Paginated. Use gbif_match_species to get the taxonKey first, then iterate with offset for large groups.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of children to return (default 20, max 1000). | |
| offset | No | Pagination offset. | |
| taxonKey | Yes | GBIF backbone taxon key from gbif_match_species or another taxonomy tool. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | Limit applied when the result was truncated. Re-call with offset to page on. |
| error | No | Present when the call failed. Absent on success. |
| limit | No | Records returned in this page. |
| shown | No | Children returned in this page when the result was truncated. |
| notice | No | Agent guidance — a no-children note for a valid taxon, or a pagination note when the page was capped. Absent on a complete single page. |
| offset | No | Current pagination offset. |
| children | No | Direct child taxa. |
| truncated | No | True when more children exist beyond this page. Absent on the final page. |
| endOfRecords | No | True when there are no more results after this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered. The description adds useful behavioral context about pagination (offset iteration) and that results are direct children only, which is beyond the annotations. No contradiction with annotations.
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 two sentences with no redundancy. The purpose is front-loaded, and the usage guidance is concise. Every word earns 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?
With an output schema present, return format is already documented. The description provides the full workflow: get key, list children, paginate. For a simple read-only list tool, nothing an agent needs to call it correctly is missing.
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 coverage is 100%, so baseline is 3. The description adds meaning by linking taxonKey to gbif_match_species output and explaining offset for pagination, which goes beyond the schema descriptions. This clarifies how to use the parameters in a realistic workflow.
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 states the tool lists direct children of a backbone taxon, with concrete examples (genera within a family, species within a genus). It differentiates from siblings like gbif_get_species_classification by focusing on children rather than ancestors, and mentions the dependency on gbif_match_species for the taxonKey.
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 explicitly says to use gbif_match_species to get the taxonKey first and to iterate with offset for large groups, giving clear when-to-use and how-to-use guidance. It doesn't explicitly name alternatives to avoid, but the context of listing children is unambiguous given the sibling set.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_get_species_classificationGet Species ClassificationARead-onlyIdempotentInspect
Return the parent chain for a taxon — from kingdom (or domain) down to the immediate parent of the queried taxon — as an ordered array. Each entry has its rank, canonical name, and taxon key. The array is returned root-first (kingdom → phylum → class → … → immediate parent of the queried taxon); the queried taxon itself is not included — call gbif_get_species for its own record. Useful for building taxonomic trees or understanding placement without navigating the backbone level-by-level.
| Name | Required | Description | Default |
|---|---|---|---|
| taxonKey | Yes | GBIF backbone taxon key from gbif_match_species or another taxonomy tool. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| notice | No | Guidance when the chain is empty because the taxon sits at the root of the backbone. Absent when the chain has entries. |
| classification | No | Classification chain ordered from root (kingdom) to the immediate parent of the queried taxon. The queried taxon itself is not included — call gbif_get_species for its own record. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering safety and repeatability. The description adds behavioral details beyond these: the array is returned root-first, the queried taxon is excluded, and each entry includes rank, canonical name, and taxon key. This provides a precise contract of the output. No contradictions with annotations.
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 three sentences with no filler. The first sentence defines the output and its fields, the second clarifies ordering and exclusion, and the third states the use case. Every sentence adds value and the most critical information is front-loaded.
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?
The tool has a simple single-parameter interface, and the description fully covers the output format (array, ordering, fields), the exclusion rule, and how to obtain the taxon's own record. Given the presence of an output schema, an agent has everything needed to call this tool correctly without ambiguity.
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?
The input schema has full coverage (100%) for the single parameter taxonKey, with a clear description: 'GBIF backbone taxon key from gbif_match_species or another taxonomy tool.' The tool description does not add additional semantic meaning beyond this, so the baseline score of 3 is appropriate given that the schema already carries the parameter documentation.
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 states exactly what the tool does: 'Return the parent chain for a taxon' and specifies the scope (kingdom to immediate parent), the output format (ordered array with rank, canonical name, taxon key), and explicitly excludes the queried taxon. It clearly differentiates from sibling gbif_get_species by noting that the queried taxon is not included.
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 explicitly mentions when to use the tool ('Useful for building taxonomic trees or understanding placement') and provides an alternative: 'call gbif_get_species for its own record.' It also implies efficiency by avoiding level-by-level navigation through the backbone. This gives clear guidance on when to use this tool versus siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_match_speciesMatch Species NameARead-onlyIdempotentInspect
Match a scientific name against the GBIF backbone taxonomy. Returns the best-matching taxon with full classification and a confidence score (0–100). This is the mandatory first step for any GBIF workflow — it returns the backbone taxonKey required by gbif_search_occurrences, gbif_count_occurrences, and gbif_occurrence_facets. When the queried name is a synonym, taxonKey is the accepted taxon it resolves to and matchedTaxonKey carries the synonym's own key; occurrence counts differ sharply between the two, so pass taxonKey. Below confidence 80, the match should be reviewed. matchType NONE means no usable match was found — try removing the strict flag or broadening the name.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Scientific name to match. Examples: "Parus major", "Agaricus bisporus", "Homo sapiens". Fuzzy matching handles minor spelling variations. Common names are not supported — use gbif_search_species for vernacular name searches. | |
| rank | No | Expected taxonomic rank. Use to avoid matching a genus when you expect a species. | |
| strict | No | When true, only return an exact match. When false (default), GBIF applies fuzzy matching — useful for minor spelling variations and abbreviated names. | |
| kingdom | No | Narrow the match to a specific kingdom (e.g., "Animalia", "Plantae", "Fungi") to disambiguate names that appear in multiple kingdoms. Omit the field to match against the whole backbone — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the undisambiguated match, which is indistinguishable from a match that honored the kingdom. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rank | No | Taxonomic rank of the matched taxon. |
| class | No | Class of the matched taxon. |
| error | No | Present when the call failed. Absent on success. |
| genus | No | Genus of the matched taxon. |
| order | No | Order of the matched taxon. |
| family | No | Family of the matched taxon. |
| notice | No | Guidance when the queried name was a synonym and taxonKey was resolved to the accepted taxon. Absent when the matched name is already the accepted one. |
| phylum | No | Phylum of the matched taxon. |
| status | No | Taxonomic status: ACCEPTED, SYNONYM, or DOUBTFUL. |
| kingdom | No | Kingdom of the matched taxon. |
| species | No | Species canonical name of the matched taxon. |
| classKey | No | Backbone taxon key for the class. |
| genusKey | No | Backbone taxon key for the genus. |
| orderKey | No | Backbone taxon key for the order. |
| taxonKey | No | GBIF backbone taxon key to pass to downstream tools. The accepted taxon's key when the queried name is a synonym, otherwise the matched taxon's own key. |
| familyKey | No | Backbone taxon key for the family. |
| matchType | No | EXACT, FUZZY, HIGHERRANK, or NONE. NONE means no usable match. |
| phylumKey | No | Backbone taxon key for the phylum. |
| confidence | No | Match confidence score 0–100. Below 80 warrants review. |
| kingdomKey | No | Backbone taxon key for the kingdom. |
| speciesKey | No | Backbone taxon key for the species. |
| canonicalName | No | Scientific name without authorship. |
| scientificName | No | Full scientific name with authorship. |
| matchedTaxonKey | No | Backbone key of the name that actually matched. Present only when it differs from taxonKey — that is, when a synonym was resolved to its accepted taxon. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint, openWorldHint, idempotentHint) already signal safety. The description adds high-value behavioral details like synonym resolution (taxonKey vs matchedTaxonKey), the 80-confidence review threshold, and the meaning of matchType NONE—all beyond what annotations convey.
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?
Well-structured and front-loaded: purpose first, then critical workflow context, then edge-case behavior. Every sentence serves a purpose—no filler. Approximately 200 words, acceptable given the richness of information.
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?
With an output schema present, the description complements it by explaining key output fields (taxonKey, matchedTaxonKey, matchType, confidence) and how to interpret them. Covers synonyms, confidence thresholds, and failure cases. Nothing essential for correct invocation is missing.
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 100%, so all parameters are well-documented. The description largely restates schema content (e.g., rank to avoid genus matching, strict flag behavior) without adding new meaning. It maintains baseline adequacy but does not elevate understanding beyond the schema.
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 ('Match'), a precise resource ('scientific name against the GBIF backbone taxonomy'), and describes the output (taxon with classification and confidence). It differentiates from siblings by naming the mandatory first-step role and explicitly routing vernacular name searches to gbif_search_species.
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?
Explicitly declares this as the mandatory first step for GBIF workflows, lists dependent tools, names the alternative (gbif_search_species) for common names, and provides concrete troubleshooting for matchType NONE (remove strict flag or broaden name). Guidance is direct and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_occurrence_facetsOccurrence Facet AggregationARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Year 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. | |
| facet | Yes | Dimension 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. | |
| country | No | ISO 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. | |
| geometry | No | WKT 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. | |
| taxonKey | No | Backbone taxon key to scope the aggregation. Matches the given taxon and all descendant taxa (subspecies, varieties, etc.). | |
| datasetKey | No | Scope 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. | |
| facetLimit | No | Maximum number of facet values to return (default 10, max 100). | |
| facetOffset | No | Zero-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, …). | |
| basisOfRecord | No | Scope to a specific basis of record. | |
| stateProvince | No | State, 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. | |
| occurrenceStatus | No | Presence/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 |
| publishingCountry | No | ISO 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. | |
| iucnRedListCategory | No | Scope 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
| Name | Required | Description |
|---|---|---|
| cap | No | facetLimit applied when the page was capped. Re-call with facetOffset advanced by this value to page on. Absent otherwise. |
| error | No | Present when the call failed. Absent on success. |
| facet | No | The facet dimension aggregated. |
| shown | No | Facet values returned in this page when the page was capped. Absent otherwise. |
| counts | No | Facet values ranked by count descending — one page of up to facetLimit entries starting at facetOffset, not necessarily the top ones. |
| notice | No | Guidance 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. |
| truncated | No | Heuristic 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. |
| facetLimit | No | Maximum facet values requested. |
| facetOffset | No | Zero-based offset applied to the ranked facet values. |
| occurrenceStatus | No | The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what totalOccurrences and every bucket cover. |
| totalOccurrences | No | Total matching occurrences across all facet values. |
TDQS
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.
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.
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.
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.
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.
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.
gbif_search_datasetsSearch DatasetsARead-onlyIdempotentInspect
Search GBIF datasets by keyword, type, publishing country (uppercase ISO 3166-1 alpha-2), publishing organization, or hosting organization. The two organization filters answer different questions — publishingOrg matches the organization whose data it is, hostingOrg the organization whose installation serves it — and an organization key from gbif_search_publishers usually wants publishingOrg. Returns dataset title, description, license, record count, and DOI. Use to find the source dataset behind a set of records, or to explore what data collections are available for a taxon, country, or organization.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Free-text search across dataset title and description. Omit the field to browse without a term — a blank or whitespace-only value is rejected rather than sent, because GBIF answers a blank one with all 123,527 indexed datasets and a whitespace-only one with none, and neither is the search a caller who filled the field was asking for. | |
| type | No | Filter by dataset type. OCCURRENCE for observation records, CHECKLIST for species lists. | |
| limit | No | Number of datasets to return (default 20, max 1000). | |
| offset | No | Pagination offset. | |
| hostingOrg | No | UUID (8-4-4-4-12 hex, lowercase — matched case-sensitively, as publishingOrg is) of the organization whose installation serves the dataset — not the organization that published it, which is publishingOrg. Most organizations publish through an installation someone else runs, so a key from gbif_search_publishers matches nothing here for them: of the first 25 GB organizations the registry lists, all 25 host no datasets while 13 publish one or two. Supplied together the two filters are intersected, not combined. | |
| publishingOrg | No | UUID (8-4-4-4-12 hex, lowercase — GBIF matches these two keys case-sensitively, so an upper-cased rendering of a real key matches nothing) of the organization that published the dataset — the organization whose data it is, and the question a key from gbif_search_publishers is usually asking. Not the organization that serves it, which is hostingOrg and matches a different set: Butterfly Conservation (0d72dd7f-6f05-46af-85c2-8b6e77ce5534) publishes 3 datasets and hosts none, while the National Biodiversity Network (07f617d0-c688-11d8-bf62-b8a03c50a862) hosts 984 — those 3 among them — and publishes 1. Supplied together the two filters are intersected, not combined, so the same key in both fields returns only what that organization both published and serves. | |
| publishingCountry | No | ISO 3166-1 alpha-2 code, uppercase, of the organization that published the dataset (e.g., "GB", "US", "DE", "SE"). Lowercase and alpha-3 forms ("gb", "GBR") match nothing upstream, which is why only the uppercase two-letter form is accepted here — unlike the country filter on gbif_search_publishers, which resolves either form. Take a value from a PUBLISHING_COUNTRY facet on gbif_occurrence_facets; an uppercase pair GBIF does not assign ("XX") is rejected upstream by name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| limit | No | Datasets returned in this page. |
| notice | No | Guidance when results are empty or paging overshot. Absent on successful result pages. |
| offset | No | Current pagination offset. |
| datasets | No | Matching datasets. |
| totalCount | No | Total matching datasets before pagination. |
| endOfRecords | No | True when there are no more results after this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, openWorld, idempotent), the description discloses crucial behavioral nuances: case-sensitive UUID matching, rejection of blank q values and the upstream consequences, and that the two organization filters are intersected, not combined. These details go well beyond annotations and materially affect invocation.
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?
A single dense paragraph that front-loads the core purpose and then delivers usage guidance. Though lengthy, every sentence carries distinct value (purpose, filter distinction, return list, use cases). It could be split into bullet points, but it remains efficient for the complexity.
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 read-only, entirely optional-parameter search tool with a rich output schema, the description comprehensively covers purpose, filters, return fields, and the non-obvious behaviors (case sensitivity, filter intersection, blank q handling). Combined with the schema and annotations, an agent has everything needed to select and call this tool correctly.
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?
The schema already provides 100% coverage with exhaustive per-parameter descriptions (formats, examples, rejection rules). The description adds meta-level semantics that the schema does not: which filter answers 'whose data it is' versus 'whose installation serves it,' and the recommendation to use publishingOrg for publisher keys. This enriches meaning beyond the schema.
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 ('Search') and resource ('GBIF datasets'), and enumerates the exact criteria (keyword, type, country, publishing/hosting organization). It also states what it returns (title, description, license, record count, DOI) and gives concrete use cases, differentiating it from sibling tools that search other resources.
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?
Explicit use cases are given ('find the source dataset behind a set of records, or explore what data collections are available...'). The description also routes the agent to the correct organization filter by noting that a key from gbif_search_publishers 'usually wants publishingOrg,' distinguishing it from the alternative. It does not explicitly exclude other search tools, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_search_occurrencesSearch OccurrencesARead-onlyIdempotentInspect
Search 3.9B+ GBIF occurrence records with Darwin Core filters. Use taxonKey from gbif_match_species for reliable results — it resolves synonyms automatically. Accepts country (uppercase ISO 3166-1 alpha-2, where the record was observed), publishingCountry (the publishing organization's country — a different question), stateProvince, bounding box (decimalLatitude/decimalLongitude ranges), WKT polygon geometry, year range, month, basis of record, coordinate filter, and dataset key. Returns sightings only by default — GBIF also indexes absence records (surveys that looked and found nothing), and occurrenceStatus controls whether they are included. Pagination is capped at offset+limit=100,001 and GBIF offers no cursor or scroll, so a larger result set is covered only by partitioning it — facet it by DATASET_KEY with gbif_occurrence_facets and search each datasetKey separately. This server cannot download a result set in bulk; that needs the GBIF Download API with a GBIF.org account, or the GBIF snapshot on AWS Open Data.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Year or year range. Single year: "2024". Range: "2020,2024". Filters by observation year. Both endpoints inclusive. Omit the field to search every year — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. | |
| limit | No | Number of records to return (default 20, max 300). | |
| month | No | Calendar month (1–12). Useful for seasonal distribution queries. | |
| offset | No | Pagination offset. GBIF serves offset+limit up to 100,001 and rejects anything past it, with no cursor or scroll to continue from. To reach a result set larger than that, split it into per-datasetKey searches using a DATASET_KEY facet from gbif_occurrence_facets — gap-free and high-cardinality, unlike YEAR, which leaves undated records in no bucket — rather than paging deeper. | |
| country | No | ISO 3166-1 alpha-2 code, uppercase, of where the occurrence was recorded (e.g., "GB", "US", "DE", "SE"). Not the publisher's country — that is publishingCountry, and the two disagree on most records. Lowercase and alpha-3 forms ("gb", "USA") match nothing upstream, which is why only the uppercase two-letter form is accepted here. Take a value from a COUNTRY facet on gbif_occurrence_facets; an uppercase pair GBIF does not know ("XX") is rejected upstream by name. | |
| geometry | No | WKT polygon for geographic filtering (e.g., POLYGON((8 47, 9 47, 9 48, 8 48, 8 47))). Coordinates are longitude latitude. Takes precedence over decimalLatitude/decimalLongitude. Omit the field to search everywhere — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. | |
| taxonKey | No | GBIF backbone taxon key from gbif_match_species. Preferred over scientificName — matches all synonyms automatically. Matches the given taxon and all descendant taxa (subspecies, varieties, etc.). | |
| datasetKey | No | Restrict results 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 (gbif_occurrence_facets), or the datasetKey field on an occurrence record. Omit the field to search every dataset — an empty string is rejected rather than read as no filter, because GBIF answers a blank datasetKey with the unfiltered result set. | |
| isInCluster | No | Filter to records flagged as likely duplicates (true) or exclude them (false). Omit to include all. Note: GBIF does not expose a cluster identifier — only the membership flag. To de-duplicate, set isInCluster: false to exclude all clustered records. | |
| basisOfRecord | No | Filter by how the occurrence was recorded. HUMAN_OBSERVATION covers citizen science. PRESERVED_SPECIMEN covers natural history collections. | |
| hasCoordinate | No | When true, return only georeferenced records (those with coordinates). When false, return ONLY records without coordinates. Omit the parameter entirely to include all records regardless of coordinate presence. | |
| stateProvince | No | State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: "England", "England - Greater London", and "Greater London" are three distinct values, and "england" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value returns zero records rather than an error. Omit the field to search every state or province — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. Records carrying no stateProvince match no value, so this cannot partition a scope. | |
| scientificName | No | Scientific name filter. Less precise than taxonKey — does not match synonyms. Use taxonKey from gbif_match_species for reliable results. Supplying both does not narrow the search: GBIF combines the two taxon filters with OR, so the result is the union of the two, not their intersection. Omit the field to search every name — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. | |
| decimalLatitude | No | Latitude range as "min,max" (e.g., "47.0,48.5"). Decimal degrees, WGS84. Combine with decimalLongitude for a bounding box. Omit the field to leave latitude unbounded — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. | |
| decimalLongitude | No | Longitude range as "min,max" (e.g., "8.0,9.5"). Decimal degrees, WGS84. Combine with decimalLatitude for a bounding box. Omit the field to leave longitude unbounded — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. | |
| occurrenceStatus | No | Presence/absence filter. Defaults to PRESENT: an ABSENT record documents a survey that looked for the taxon and did not find it, so including one would read as a sighting of the opposite. Use ANY for both (GBIF's own default), or ABSENT for non-observations alone. | PRESENT |
| publishingCountry | No | ISO 3166-1 alpha-2 code, uppercase, of the organization that published the record — not where the occurrence was observed, which is country. The two differ constantly: of 60,290,950 records observed in GB, 1,548,928 were published by US organizations. Take a value from a PUBLISHING_COUNTRY facet on gbif_occurrence_facets. Lowercase and alpha-3 forms ("us", "USA") match nothing upstream, which is why only the uppercase two-letter form is accepted here. | |
| iucnRedListCategory | No | Restrict 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. Records with no category are excluded when this is set. | |
| coordinateUncertaintyInMeters | No | Filter by coordinate uncertainty radius in meters. Range format: "min,max" (e.g., "0,1000" for sub-kilometer precision). Both endpoints inclusive. Omit the field to accept any uncertainty — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| limit | No | Records returned in this page. |
| notice | No | Guidance when results are empty, paging overshot, the match is larger than the pagination cap can reach, or a presence/absence filter narrowed the result. Absent only when none applies. |
| offset | No | Current pagination offset. |
| totalCount | No | Total matching occurrences before pagination. |
| occurrences | No | Occurrence records matching the filters. |
| endOfRecords | No | True when there are no more results after this page. |
| occurrenceStatus | No | The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what totalCount and the returned records cover. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnlyHint, openWorldHint, and idempotentHint, so the description rightly spends no time re-declaring safety. It adds genuinely new behavioral value: the sightings-only-by-default behavior with occurrenceStatus controlling absence records, the hard 100,001 offset+limit cap with no cursor/scroll, and the no-bulk-download limitation — all critical facts an agent needs and none derivable from the annotations.
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?
Five dense sentences front-loaded with purpose, then filters, default behavior, pagination, and the bulk-download limitation in logical order. The length is earned by the tool's 19-parameter complexity and the real gotchas it must convey; it is heavy but not padded with repetition.
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?
With an output schema covering return values and 100% schema coverage, nearly everything an agent needs is present. The description closes the remaining gaps: presence-only default, pagination ceiling and partitioning remedy, and bulk-download alternatives. For a tool of this complexity, no material calling concern is left 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 coverage is 100% with exceptionally rich per-parameter descriptions, so baseline 3 applies. The description adds strategic semantic value on top: recommending taxonKey over scientificName, the DATASET_KEY partitioning strategy for pagination, and the country-vs-publishingCountry distinction. The marginal addition is real but largely synthetic, with most param detail correctly living in the schema.
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 states a specific verb (Search), a precise resource (3.9B+ GBIF occurrence records), and a scope (Darwin Core filters). This clearly distinguishes it from siblings like gbif_count_occurrences (counting), gbif_occurrence_facets (facet aggregation), and gbif_get_occurrence (single-record retrieval), so an agent can pick it without inspecting schemas.
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 routes to gbif_match_species for taxonKey, gbif_occurrence_facets for partitioning large result sets, and the GBIF Download API / AWS Open Data for bulk download, with clear when-not guidance ('This server cannot download a result set in bulk'). It could have explicitly pointed to gbif_count_occurrences for count-only needs or gbif_get_occurrence for a single record, but the exclusions and alternatives given are strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_search_publishersSearch PublishersARead-onlyIdempotentInspect
Search organizations registered with GBIF by name fragment or country. Returns organization key, title, and country — sufficient to chain into gbif_search_datasets as publishingOrg for the datasets an organization published, or as hostingOrg for the ones its own installation serves, or to understand who publishes data for a region. publishingOrg is the usual chain: most organizations publish through an installation someone else runs, so hostingOrg matches nothing for them.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Name fragment to search for. Matches organization names. Omit the field to browse without a term — a blank or whitespace-only value is rejected rather than sent, because the registry answers either with all 3,561 registered organizations. | |
| limit | No | Number of organizations to return (default 20, max 1000). | |
| offset | No | Pagination offset. | |
| country | No | ISO 3166-1 country code to filter organizations by country. The alpha-2 form ("GB") is canonical; unlike the country codes on the occurrence tools and gbif_search_datasets, this one also resolves the alpha-3 form ("GBR") and is case-insensitive, because the registry endpoint matches the parsed country rather than the string. A value GBIF cannot parse as a country errors rather than returning an empty list. Omit the field to search every country — an empty string is rejected rather than read as no filter, because the registry answers a blank country with all 3,561 organizations. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| limit | No | Organizations returned in this page. |
| notice | No | Guidance when results are empty or paging overshot. Absent on successful result pages. |
| offset | No | Current pagination offset. |
| publishers | No | Matching organizations. |
| totalCount | No | Total matching organizations before pagination. |
| endOfRecords | No | True when there are no more results after this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, openWorld, and idempotent hints. The description adds behavioral nuances beyond these: blank or whitespace values for 'q' are rejected rather than sent, empty country strings are rejected, and invalid country codes error instead of returning empty lists. These specifics help an agent avoid mistakes. No contradiction with annotations.
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?
Three well-structured sentences: the first states the core function, the second explains return value and chain usage, the third adds an important caveat. No filler, all sentences earn their place, and key information is front-loaded.
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?
With an output schema present, the description focuses on use context, which it covers thoroughly: what it returns, how to chain it, which chain is most common, and edge-case handling. The description is complete for an agent to call it correctly and interpret results.
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 coverage is 100%, so baseline is 3. The description goes further by clarifying edge cases: omitting 'q' browses without a term, blank 'q' is rejected, country accepts alpha-2 and alpha-3 forms and is case-insensitive, and invalid country codes error. This adds meaningful semantic detail beyond the schema's descriptions.
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 states a specific verb ('Search') and resource ('organizations registered with GBIF') and clarifies scope ('by name fragment or country'). It also names the return fields and distinguishes itself from sibling tools (e.g., search_datasets) by its focus on publishers. This gives clear purpose and differentiation.
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 explicitly explains when to use the tool: to chain into gbif_search_datasets as publishingOrg or hostingOrg, and gives a concrete rule of thumb (publishingOrg is usual, hostingOrg matches nothing for most). It also conveys the purpose for regional analysis. This is explicit, practical guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gbif_search_speciesSearch Species TaxonomyARead-onlyIdempotentInspect
Search or browse the GBIF backbone taxonomy. Accepts scientific name fragments, rank filters, and higher-taxon constraints. Useful for exploring what species exist under a higher taxon (e.g., "list all families of Coleoptera"), for simple name-fragment searches, or when gbif_match_species returns too narrow a result. kingdom, family, and genus scope the browse to a higher taxon: each is resolved to its backbone key before the search runs, so the narrowest one supplied is what scopes, an alternative name resolves to the taxon it is a synonym of, and a name that matches no backbone taxon at that rank fails rather than returning the whole index. Names are capitalized as GBIF writes them ("Paridae", not "paridae") and are matched exactly, not fuzzily. Paginated — use limit and offset to walk through results.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Name fragment to search for. Matches scientific and vernacular names. Omit the field to browse without a name term — a blank or whitespace-only value is rejected rather than sent, because GBIF answers a blank one with the whole 46,623,754-name index and a whitespace-only one with nothing, and neither is the search a caller who filled the field was asking for. | |
| rank | No | Filter to a specific taxonomic rank. | |
| genus | No | Scope the search to a genus, by name — "Quercus", "Parus". Resolved to its backbone key before the search runs, and it is the narrowest of the three, so it is what scopes when kingdom or family is supplied too. Matched exactly and capitalized as GBIF writes it; a name shared across kingdoms ("Prunella", "Oenanthe") resolves only when kingdom is supplied with it. Omit the field to browse every genus; a blank or whitespace-only value is rejected rather than dropped. | |
| limit | No | Number of records to return (default 20, max 1000). | |
| family | No | Scope the search to a family, by name — "Paridae", "Fagaceae". Resolved to its backbone key before the search runs, so an alternative family name lands on the taxon it is a synonym of ("Compositae" scopes to Asteraceae). Matched exactly and capitalized as GBIF writes it; a name that is not a backbone family fails rather than being ignored. Supplied with genus, it must be that genus's own family. Omit the field to browse every family; a blank or whitespace-only value is rejected rather than dropped. | |
| offset | No | Pagination offset. | |
| kingdom | No | Scope the search to a kingdom, by name — "Animalia", "Plantae", "Fungi". Resolved to its backbone key before the search runs, and matched exactly: capitalize it as GBIF writes it, since "animalia" resolves to nothing. Supplied alongside family or genus it disambiguates that name rather than scoping on its own — "Prunella" alone names both a bird genus and a plant genus and resolves to neither. Omit the field to browse every kingdom; a blank or whitespace-only value is rejected rather than dropped. | |
| isExtinct | No | Filter to extinct (true) or extant (false) taxa. | |
| datasetKey | No | Scope to a specific checklist dataset UUID (8-4-4-4-12 hex). Omit the field to search the GBIF backbone — an empty string is rejected rather than read as no scope, because GBIF answers a blank datasetKey with the unfiltered backbone result. |
Output Schema
| Name | Required | Description |
|---|---|---|
| taxa | No | Matching taxa. |
| error | No | Present when the call failed. Absent on success. |
| limit | No | Records returned in this page. |
| notice | No | Guidance when results are empty or paging overshot. Absent on successful result pages. |
| offset | No | Current pagination offset. |
| taxonScope | No | The higher-taxon scope actually applied — which of kingdom, family, or genus scoped the search, the backbone taxon its name resolved to, and that taxon key. Absent when none of the three was supplied. |
| totalCount | No | Total matches before pagination. |
| endOfRecords | No | True when there are no more results after this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint/openWorldHint/idempotentHint annotations, disclosing concrete behaviors: higher-taxon names are resolved to backbone keys, alternative names resolve to synonyms, unmatched names fail rather than returning everything, matching is exact and capitalization-sensitive, blank values are rejected, and pagination works via limit/offset. All of this adds value beyond the annotations, and there is no contradiction.
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?
Although long, every sentence is information-dense and earns its place. The structure front-loads purpose, then usage, then behavioral nuances, and then parameter specifics. It is not padded or redundant; the length is justified by the complexity of GBIF's matching and scoping behavior.
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 9 parameters, an output schema exists, and annotations cover safety, the description thoroughly covers the operational context: matching rules, synonym resolution, exact capitalization, blank-value pitfalls, pagination, and failure modes. No critical information an agent needs to call this correctly is missing.
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 coverage is 100%, yet the description adds substantial meaning to every parameter: it explains why blank values are rejected (GBIF returns the whole 46M-name index), how genus/family/kingdom interact and disambiguate (e.g., 'Prunella'), how synonym resolution works (Compositae → Asteraceae), and constraints like genus-specific families. This is far more than the schema provides, richly compensating for the 9-parameter surface.
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-resource pair ('Search or browse the GBIF backbone taxonomy') and immediately clarifies what it accepts (name fragments, rank filters, higher-taxon constraints). It distinguishes itself from a sibling by stating it is useful 'when gbif_match_species returns too narrow a result,' so an agent can tell them apart without inspecting schemas.
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?
Explicit usage contexts are given: exploring what species exist under a higher taxon, simple name-fragment searches, and as a fallback when gbif_match_species is too narrow. It also differentiates browsing vs searching and explains when higher-taxon scope applies, giving clear when-to-use and when-not-to-use guidance.
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.
13 tool updates
- Changed
gbif_bulk_match_species6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode.", + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "results" -]
- Changed
gbif_count_occurrences6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "count", + "occurrenceStatus" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: A filter was supplied blank or whitespace-only, datasetKey is not an 8-4-4-4-12 hex UUID, a two-letter country or publishingCountry code is one GBIF does not know, or GBIF rejected another filter value as malformed. Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "count", - "occurrenceStatus" -]
- Changed
gbif_get_dataset9 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + } + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / capAdded value: +{ + "description": "contactLimit applied when the list was capped. Raise it (max 100) to see more. Absent otherwise.", + "type": "number" +} - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `not_found`: The datasetKey UUID does not match any dataset in GBIF. `invalid_filter`: datasetKey is not a UUID, or GBIF rejected the request as malformed. Other values are possible when a failure originates below the handler.", + "examples": [ + "not_found", + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - added
Output schema / properties / noticeAdded value: +{ + "description": "How to reach the contacts contactLimit held back. Absent when every contact was returned.", + "type": "string" +} - added
Output schema / properties / shownAdded value: +{ + "description": "Contacts included in this response when the list was capped. Absent otherwise.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the dataset carries more contacts than contactLimit allowed through. Absent when every contact was returned.", + "type": "boolean" +}
- Changed
gbif_get_occurrence5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + } + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `not_found`: The occurrenceKey does not exist in GBIF. `invalid_filter`: GBIF rejected the occurrenceKey as unparseable — a fraction, or a value past the largest integer the endpoint accepts. Other values are possible when a failure originates below the handler.", + "examples": [ + "not_found", + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +}
- Changed
gbif_get_species5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + } + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `not_found`: The taxonKey does not exist in the GBIF backbone. `invalid_filter`: GBIF rejected the taxonKey as unparseable — a fraction, or a value outside the 32-bit signed integer range. Other values are possible when a failure originates below the handler.", + "examples": [ + "not_found", + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +}
- Changed
gbif_get_species_children6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "children", + "offset", + "limit", + "endOfRecords" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `not_found`: The taxonKey does not exist in the GBIF backbone. `invalid_filter`: GBIF rejected the taxonKey as unparseable — a fraction, or a value outside the 32-bit signed integer range. Other values are possible when a failure originates below the handler.", + "examples": [ + "not_found", + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "children", - "offset", - "limit", - "endOfRecords" -]
- Changed
gbif_get_species_classification6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "classification" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `not_found`: The taxonKey does not exist in the GBIF backbone. `invalid_filter`: GBIF rejected the taxonKey as unparseable — a fraction, or a value outside the 32-bit signed integer range. Other values are possible when a failure originates below the handler.", + "examples": [ + "not_found", + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "classification" -]
- Changed
gbif_match_species5 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + } + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `no_match`: matchType is NONE — no candidate met the match threshold. `invalid_filter`: kingdom was supplied blank or whitespace-only, which disambiguates nothing. Other values are possible when a failure originates below the handler.", + "examples": [ + "no_match", + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +}
- Changed
gbif_occurrence_facets11 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "facet", + "totalOccurrences", + "counts", + "facetLimit", + "facetOffset", + "occurrenceStatus" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / capAdded value: +{ + "description": "facetLimit applied when the page was capped. Re-call with facetOffset advanced by this value to page on. Absent otherwise.", + "type": "number" +} - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: A scope filter was supplied blank or whitespace-only, datasetKey is not an 8-4-4-4-12 hex UUID, a two-letter country or publishingCountry code is one GBIF does not know, or GBIF rejected the geometry or year scope as malformed. Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / properties / moreValuesLikelyRemoved value: -{ - "description": "Heuristic continuation flag: true when this page returned a full facetLimit of values, so more distinct values may exist past facetOffset + facetLimit (re-call with facetOffset advanced by facetLimit). GBIF exposes no total distinct-value count, so this is an estimate, not exact.", - "type": "boolean" -} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no facet values were returned, a verbatim stateProvince filter matched nothing, or a presence/absence filter narrowed the aggregation. Absent only when none applies."New value: +"Guidance 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." - added
Output schema / properties / shownAdded value: +{ + "description": "Facet values returned in this page when the page was capped. Absent otherwise.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "Heuristic 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.", + "type": "boolean" +} - removed
Output schema / requiredRemoved value: -[ - "facet", - "totalOccurrences", - "counts", - "facetLimit", - "facetOffset", - "moreValuesLikely", - "occurrenceStatus" -]
- Changed
gbif_search_datasets6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "datasets", + "totalCount", + "offset", + "limit", + "endOfRecords" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: A filter was supplied blank or whitespace-only, publishingOrg or hostingOrg is not a lowercase 8-4-4-4-12 hex UUID, publishingCountry is a two-letter code GBIF does not assign, or GBIF rejected another filter value as malformed. Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "datasets", - "totalCount", - "offset", - "limit", - "endOfRecords" -]
- Changed
gbif_search_occurrences6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "occurrences", + "totalCount", + "offset", + "limit", + "endOfRecords", + "occurrenceStatus" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `pagination_cap_exceeded`: offset + limit exceeds 100,001, the deepest page GBIF serves. `invalid_filter`: A filter value is unusable — any filter supplied blank or whitespace-only, a datasetKey that is not an 8-4-4-4-12 hex UUID, a two-letter country or publishingCountry code GBIF does not know, or a WKT geometry or range GBIF rejects. Other values are possible when a failure originates below the handler.", + "examples": [ + "pagination_cap_exceeded", + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "occurrences", - "totalCount", - "offset", - "limit", - "endOfRecords", - "occurrenceStatus" -]
- Changed
gbif_search_publishers6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "publishers", + "totalCount", + "offset", + "limit", + "endOfRecords" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: q was supplied blank or whitespace-only, country is the empty string, or GBIF could not parse the country value as a country. Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_filter" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "publishers", - "totalCount", - "offset", - "limit", - "endOfRecords" -]
- Changed
gbif_search_species6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "taxa", + "totalCount", + "offset", + "limit", + "endOfRecords" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: q, kingdom, family, genus, or datasetKey was supplied blank or whitespace-only, datasetKey is not an 8-4-4-4-12 hex UUID, or GBIF rejected another filter value as malformed. `unresolved_taxon_scope`: kingdom, family, or genus named no GBIF backbone taxon at that rank — a misspelling, a lowercase name, a name entered under the wrong rank, or a name shared across kingdoms with no kingdom supplied to separate them. `conflicting_taxon_scope`: the supplied family and genus each resolved, but to taxa in different lineages — the genus does not sit in that family. Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_filter", + "unresolved_taxon_scope", + "conflicting_taxon_scope" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "taxa", - "totalCount", - "offset", - "limit", - "endOfRecords" -]
7 tool updates
- Changed
gbif_count_occurrences3 fields changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Filter to a specific dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets. The result is not the recordCount the dataset tools and the gbif://dataset/{datasetKey} resource report for the same key: that figure spans every occurrenceStatus, while this count applies occurrenceStatus below, PRESENT by default."New value: +"Filter to a specific dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets. Omit the field to count across every dataset — an empty string is rejected rather than read as no filter, because GBIF answers a blank datasetKey with the unfiltered total. The result is not the recordCount the dataset tools and the gbif://dataset/{datasetKey} resource report for the same key: that figure spans every occurrenceStatus, while this count applies occurrenceStatus below, PRESENT by default." - changed
Input schema / properties / stateProvince / descriptionPrevious value: -"State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: \"England\", \"England - Greater London\", and \"Greater London\" are three distinct values, and \"england\" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value counts zero rather than erroring."New value: +"State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: \"England\", \"England - Greater London\", and \"Greater London\" are three distinct values, and \"england\" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value counts zero rather than erroring. Omit the field to count across every state or province — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered total." - changed
Input schema / properties / year / descriptionPrevious value: -"Year or year range (e.g., \"2024\" or \"2020,2024\"). Both endpoints inclusive."New value: +"Year or year range (e.g., \"2024\" or \"2020,2024\"). Both endpoints inclusive. Omit the field to count across every year — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered total."
- Changed
gbif_match_species1 field changed- changed
Input schema / properties / kingdom / descriptionPrevious value: -"Narrow the match to a specific kingdom (e.g., \"Animalia\", \"Plantae\", \"Fungi\") to disambiguate names that appear in multiple kingdoms."New value: +"Narrow the match to a specific kingdom (e.g., \"Animalia\", \"Plantae\", \"Fungi\") to disambiguate names that appear in multiple kingdoms. Omit the field to match against the whole backbone — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the undisambiguated match, which is indistinguishable from a match that honored the kingdom."
- Changed
gbif_occurrence_facets4 fields changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Scope 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."New value: +"Scope 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." - changed
Input schema / properties / geometry / descriptionPrevious value: -"WKT 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."New value: +"WKT 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." - changed
Input schema / properties / stateProvince / descriptionPrevious value: -"State, 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."New value: +"State, 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." - changed
Input schema / properties / year / descriptionPrevious value: -"Year or year range (e.g., \"2020,2024\") to scope the aggregation. Both endpoints inclusive."New value: +"Year 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."
- Changed
gbif_search_datasets3 fields changed- changed
Input schema / properties / hostingOrg / descriptionPrevious value: -"UUID (8-4-4-4-12 hex) of the hosting organization. From gbif_search_publishers results."New value: +"UUID (8-4-4-4-12 hex, lowercase — matched case-sensitively, as publishingOrg is) of the organization whose installation serves the dataset — not the organization that published it, which is publishingOrg. Most organizations publish through an installation someone else runs, so a key from gbif_search_publishers matches nothing here for them: of the first 25 GB organizations the registry lists, all 25 host no datasets while 13 publish one or two. Supplied together the two filters are intersected, not combined." - added
Input schema / properties / publishingOrgAdded value: +{ + "description": "UUID (8-4-4-4-12 hex, lowercase — GBIF matches these two keys case-sensitively, so an upper-cased rendering of a real key matches nothing) of the organization that published the dataset — the organization whose data it is, and the question a key from gbif_search_publishers is usually asking. Not the organization that serves it, which is hostingOrg and matches a different set: Butterfly Conservation (0d72dd7f-6f05-46af-85c2-8b6e77ce5534) publishes 3 datasets and hosts none, while the National Biodiversity Network (07f617d0-c688-11d8-bf62-b8a03c50a862) hosts 984 — those 3 among them — and publishes 1. Supplied together the two filters are intersected, not combined, so the same key in both fields returns only what that organization both published and serves.", + "type": "string" +} - changed
Input schema / properties / q / descriptionPrevious value: -"Free-text search across dataset title and description."New value: +"Free-text search across dataset title and description. Omit the field to browse without a term — a blank or whitespace-only value is rejected rather than sent, because GBIF answers a blank one with all 123,527 indexed datasets and a whitespace-only one with none, and neither is the search a caller who filled the field was asking for."
- Changed
gbif_search_occurrences8 fields changed- changed
Input schema / properties / coordinateUncertaintyInMeters / descriptionPrevious value: -"Filter by coordinate uncertainty radius in meters. Range format: \"min,max\" (e.g., \"0,1000\" for sub-kilometer precision). Both endpoints inclusive."New value: +"Filter by coordinate uncertainty radius in meters. Range format: \"min,max\" (e.g., \"0,1000\" for sub-kilometer precision). Both endpoints inclusive. Omit the field to accept any uncertainty — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set." - changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Restrict results 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 (gbif_occurrence_facets), or the datasetKey field on an occurrence record."New value: +"Restrict results 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 (gbif_occurrence_facets), or the datasetKey field on an occurrence record. Omit the field to search every dataset — an empty string is rejected rather than read as no filter, because GBIF answers a blank datasetKey with the unfiltered result set." - changed
Input schema / properties / decimalLatitude / descriptionPrevious value: -"Latitude range as \"min,max\" (e.g., \"47.0,48.5\"). Decimal degrees, WGS84. Combine with decimalLongitude for a bounding box."New value: +"Latitude range as \"min,max\" (e.g., \"47.0,48.5\"). Decimal degrees, WGS84. Combine with decimalLongitude for a bounding box. Omit the field to leave latitude unbounded — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set." - changed
Input schema / properties / decimalLongitude / descriptionPrevious value: -"Longitude range as \"min,max\" (e.g., \"8.0,9.5\"). Decimal degrees, WGS84. Combine with decimalLatitude for a bounding box."New value: +"Longitude range as \"min,max\" (e.g., \"8.0,9.5\"). Decimal degrees, WGS84. Combine with decimalLatitude for a bounding box. Omit the field to leave longitude unbounded — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set." - changed
Input schema / properties / geometry / descriptionPrevious value: -"WKT polygon for geographic filtering (e.g., POLYGON((8 47, 9 47, 9 48, 8 48, 8 47))). Coordinates are longitude latitude. Takes precedence over decimalLatitude/decimalLongitude."New value: +"WKT polygon for geographic filtering (e.g., POLYGON((8 47, 9 47, 9 48, 8 48, 8 47))). Coordinates are longitude latitude. Takes precedence over decimalLatitude/decimalLongitude. Omit the field to search everywhere — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set." - changed
Input schema / properties / scientificName / descriptionPrevious value: -"Scientific name filter. Less precise than taxonKey — does not match synonyms. Use taxonKey from gbif_match_species for reliable results. Supplying both does not narrow the search: GBIF combines the two taxon filters with OR, so the result is the union of the two, not their intersection."New value: +"Scientific name filter. Less precise than taxonKey — does not match synonyms. Use taxonKey from gbif_match_species for reliable results. Supplying both does not narrow the search: GBIF combines the two taxon filters with OR, so the result is the union of the two, not their intersection. Omit the field to search every name — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set." - changed
Input schema / properties / stateProvince / descriptionPrevious value: -"State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: \"England\", \"England - Greater London\", and \"Greater London\" are three distinct values, and \"england\" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value returns zero records rather than an error. Records carrying no stateProvince match no value, so this cannot partition a scope."New value: +"State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: \"England\", \"England - Greater London\", and \"Greater London\" are three distinct values, and \"england\" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value returns zero records rather than an error. Omit the field to search every state or province — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set. Records carrying no stateProvince match no value, so this cannot partition a scope." - changed
Input schema / properties / year / descriptionPrevious value: -"Year or year range. Single year: \"2024\". Range: \"2020,2024\". Filters by observation year. Both endpoints inclusive."New value: +"Year or year range. Single year: \"2024\". Range: \"2020,2024\". Filters by observation year. Both endpoints inclusive. Omit the field to search every year — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered result set."
- Changed
gbif_search_publishers3 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 country code to filter organizations by country. The alpha-2 form (\"GB\") is canonical; unlike the country codes on the occurrence tools and gbif_search_datasets, this one also resolves the alpha-3 form (\"GBR\") and is case-insensitive, because the registry endpoint matches the parsed country rather than the string. A value GBIF cannot parse as a country errors rather than returning an empty list."New value: +"ISO 3166-1 country code to filter organizations by country. The alpha-2 form (\"GB\") is canonical; unlike the country codes on the occurrence tools and gbif_search_datasets, this one also resolves the alpha-3 form (\"GBR\") and is case-insensitive, because the registry endpoint matches the parsed country rather than the string. A value GBIF cannot parse as a country errors rather than returning an empty list. Omit the field to search every country — an empty string is rejected rather than read as no filter, because the registry answers a blank country with all 3,561 organizations." - changed
Input schema / properties / q / descriptionPrevious value: -"Name fragment to search for. Matches organization names."New value: +"Name fragment to search for. Matches organization names. Omit the field to browse without a term — a blank or whitespace-only value is rejected rather than sent, because the registry answers either with all 3,561 registered organizations." - changed
Output schema / properties / publishers / items / properties / key / descriptionPrevious value: -"Organization UUID for gbif_search_datasets hostingOrg parameter."New value: +"Organization UUID. Chains into gbif_search_datasets as publishingOrg for the datasets this organization published, or as hostingOrg for the ones its own installation serves — publishingOrg is the usual one, since most organizations host nothing."
- Changed
gbif_search_species6 fields changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Scope to a specific checklist dataset UUID (8-4-4-4-12 hex). Omit to search the GBIF backbone."New value: +"Scope to a specific checklist dataset UUID (8-4-4-4-12 hex). Omit the field to search the GBIF backbone — an empty string is rejected rather than read as no scope, because GBIF answers a blank datasetKey with the unfiltered backbone result." - changed
Input schema / properties / family / descriptionPrevious value: -"Scope search to a family name."New value: +"Scope the search to a family, by name — \"Paridae\", \"Fagaceae\". Resolved to its backbone key before the search runs, so an alternative family name lands on the taxon it is a synonym of (\"Compositae\" scopes to Asteraceae). Matched exactly and capitalized as GBIF writes it; a name that is not a backbone family fails rather than being ignored. Supplied with genus, it must be that genus's own family. Omit the field to browse every family; a blank or whitespace-only value is rejected rather than dropped." - changed
Input schema / properties / genus / descriptionPrevious value: -"Scope search to a genus name."New value: +"Scope the search to a genus, by name — \"Quercus\", \"Parus\". Resolved to its backbone key before the search runs, and it is the narrowest of the three, so it is what scopes when kingdom or family is supplied too. Matched exactly and capitalized as GBIF writes it; a name shared across kingdoms (\"Prunella\", \"Oenanthe\") resolves only when kingdom is supplied with it. Omit the field to browse every genus; a blank or whitespace-only value is rejected rather than dropped." - changed
Input schema / properties / kingdom / descriptionPrevious value: -"Scope search to a kingdom (e.g., \"Animalia\", \"Plantae\")."New value: +"Scope the search to a kingdom, by name — \"Animalia\", \"Plantae\", \"Fungi\". Resolved to its backbone key before the search runs, and matched exactly: capitalize it as GBIF writes it, since \"animalia\" resolves to nothing. Supplied alongside family or genus it disambiguates that name rather than scoping on its own — \"Prunella\" alone names both a bird genus and a plant genus and resolves to neither. Omit the field to browse every kingdom; a blank or whitespace-only value is rejected rather than dropped." - changed
Input schema / properties / q / descriptionPrevious value: -"Name fragment to search for. Matches scientific and vernacular names."New value: +"Name fragment to search for. Matches scientific and vernacular names. Omit the field to browse without a name term — a blank or whitespace-only value is rejected rather than sent, because GBIF answers a blank one with the whole 46,623,754-name index and a whitespace-only one with nothing, and neither is the search a caller who filled the field was asking for." - added
Output schema / properties / taxonScopeAdded value: +{ + "description": "The higher-taxon scope actually applied — which of kingdom, family, or genus scoped the search, the backbone taxon its name resolved to, and that taxon key. Absent when none of the three was supplied.", + "type": "string" +}
5 tool updates
- Changed
gbif_count_occurrences2 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 alpha-2 code of where the occurrence was recorded (e.g., \"GB\", \"US\"). Not the publisher's country — that is publishingCountry, and the two disagree on most records."New value: +"ISO 3166-1 alpha-2 code, uppercase, of where the occurrence was recorded (e.g., \"GB\", \"US\"). Not the publisher's country — that is publishingCountry, and the two disagree on most records. Lowercase and alpha-3 forms (\"gb\", \"USA\") match nothing upstream, which is why only the uppercase two-letter form is accepted here. Take a value from a COUNTRY facet on gbif_occurrence_facets; an uppercase pair GBIF does not know (\"XX\") is rejected upstream by name." - added
Input schema / properties / country / patternAdded value: +"^[A-Z]{2}$"
- Changed
gbif_occurrence_facets2 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 alpha-2 code 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."New value: +"ISO 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." - added
Input schema / properties / country / patternAdded value: +"^[A-Z]{2}$"
- Changed
gbif_search_datasets2 fields changed- changed
Input schema / properties / publishingCountry / descriptionPrevious value: -"ISO 3166-1 alpha-2 country code of the publishing organization."New value: +"ISO 3166-1 alpha-2 code, uppercase, of the organization that published the dataset (e.g., \"GB\", \"US\", \"DE\", \"SE\"). Lowercase and alpha-3 forms (\"gb\", \"GBR\") match nothing upstream, which is why only the uppercase two-letter form is accepted here — unlike the country filter on gbif_search_publishers, which resolves either form. Take a value from a PUBLISHING_COUNTRY facet on gbif_occurrence_facets; an uppercase pair GBIF does not assign (\"XX\") is rejected upstream by name." - added
Input schema / properties / publishingCountry / patternAdded value: +"^[A-Z]{2}$"
- Changed
gbif_search_occurrences2 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 alpha-2 code of where the occurrence was recorded (e.g., \"GB\", \"US\", \"DE\", \"SE\"). Not the publisher's country — that is publishingCountry, and the two disagree on most records."New value: +"ISO 3166-1 alpha-2 code, uppercase, of where the occurrence was recorded (e.g., \"GB\", \"US\", \"DE\", \"SE\"). Not the publisher's country — that is publishingCountry, and the two disagree on most records. Lowercase and alpha-3 forms (\"gb\", \"USA\") match nothing upstream, which is why only the uppercase two-letter form is accepted here. Take a value from a COUNTRY facet on gbif_occurrence_facets; an uppercase pair GBIF does not know (\"XX\") is rejected upstream by name." - added
Input schema / properties / country / patternAdded value: +"^[A-Z]{2}$"
- Changed
gbif_search_publishers1 field changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 alpha-2 country code to filter organizations by country."New value: +"ISO 3166-1 country code to filter organizations by country. The alpha-2 form (\"GB\") is canonical; unlike the country codes on the occurrence tools and gbif_search_datasets, this one also resolves the alpha-3 form (\"GBR\") and is case-insensitive, because the registry endpoint matches the parsed country rather than the string. A value GBIF cannot parse as a country errors rather than returning an empty list."
3 tool updates
- Changed
gbif_count_occurrences4 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 alpha-2 country code (e.g., \"GB\", \"US\")."New value: +"ISO 3166-1 alpha-2 code of where the occurrence was recorded (e.g., \"GB\", \"US\"). Not the publisher's country — that is publishingCountry, and the two disagree on most records." - added
Input schema / properties / publishingCountryAdded value: +{ + "description": "ISO 3166-1 alpha-2 code, uppercase, of the organization that published the record — not where the occurrence was observed, which is country. The two differ constantly: of 60,290,950 records observed in GB, 1,548,928 were published by US organizations. Take a value from a PUBLISHING_COUNTRY facet on gbif_occurrence_facets. Lowercase and alpha-3 forms (\"us\", \"USA\") match nothing upstream, which is why only the uppercase two-letter form is accepted here.", + "pattern": "^[A-Z]{2}$", + "type": "string" +} - added
Input schema / properties / stateProvinceAdded value: +{ + "description": "State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: \"England\", \"England - Greater London\", and \"Greater London\" are three distinct values, and \"england\" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value counts zero rather than erroring.", + "type": "string" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when a presence/absence filter narrowed the count. Absent when occurrenceStatus is ANY."New value: +"Guidance when the count is zero under a verbatim stateProvince filter, larger than gbif_search_occurrences can page to, or narrowed by a presence/absence filter. Absent when none applies."
- Changed
gbif_occurrence_facets5 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 alpha-2 country code to scope to one country."New value: +"ISO 3166-1 alpha-2 code 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." - changed
Input schema / properties / facet / descriptionPrevious value: -"Dimension to aggregate by (e.g., COUNTRY, YEAR, BASIS_OF_RECORD, SPECIES_KEY, OCCURRENCE_STATUS, IUCN_RED_LIST_CATEGORY)."New value: +"Dimension 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." - added
Input schema / properties / publishingCountryAdded value: +{ + "description": "ISO 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.", + "pattern": "^[A-Z]{2}$", + "type": "string" +} - added
Input schema / properties / stateProvinceAdded value: +{ + "description": "State, 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.", + "type": "string" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no facet values were returned or a presence/absence filter narrowed the aggregation. Absent only when neither applies."New value: +"Guidance when no facet values were returned, a verbatim stateProvince filter matched nothing, or a presence/absence filter narrowed the aggregation. Absent only when none applies."
- Changed
gbif_search_occurrences5 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"ISO 3166-1 alpha-2 country code (e.g., \"GB\", \"US\", \"DE\", \"SE\")."New value: +"ISO 3166-1 alpha-2 code of where the occurrence was recorded (e.g., \"GB\", \"US\", \"DE\", \"SE\"). Not the publisher's country — that is publishingCountry, and the two disagree on most records." - changed
Input schema / properties / offset / descriptionPrevious value: -"Pagination offset. GBIF serves offset+limit up to 100,001 and rejects anything past it — use gbif_occurrence_facets for aggregate analysis beyond that."New value: +"Pagination offset. GBIF serves offset+limit up to 100,001 and rejects anything past it, with no cursor or scroll to continue from. To reach a result set larger than that, split it into per-datasetKey searches using a DATASET_KEY facet from gbif_occurrence_facets — gap-free and high-cardinality, unlike YEAR, which leaves undated records in no bucket — rather than paging deeper." - added
Input schema / properties / publishingCountryAdded value: +{ + "description": "ISO 3166-1 alpha-2 code, uppercase, of the organization that published the record — not where the occurrence was observed, which is country. The two differ constantly: of 60,290,950 records observed in GB, 1,548,928 were published by US organizations. Take a value from a PUBLISHING_COUNTRY facet on gbif_occurrence_facets. Lowercase and alpha-3 forms (\"us\", \"USA\") match nothing upstream, which is why only the uppercase two-letter form is accepted here.", + "pattern": "^[A-Z]{2}$", + "type": "string" +} - added
Input schema / properties / stateProvinceAdded value: +{ + "description": "State, province, or first-level administrative division, matched as a verbatim string — exact and case-sensitive. GBIF stores what each dataset recorded without normalizing it, so there is no vocabulary to guess from: \"England\", \"England - Greater London\", and \"Greater London\" are three distinct values, and \"england\" is none of them. Take one from a STATE_PROVINCE facet on gbif_occurrence_facets scoped the same way and pass it back unchanged — an unmatched value returns zero records rather than an error. Records carrying no stateProvince match no value, so this cannot partition a scope.", + "type": "string" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when results are empty, paging overshot, or a presence/absence filter narrowed the result. Absent only when none applies."New value: +"Guidance when results are empty, paging overshot, the match is larger than the pagination cap can reach, or a presence/absence filter narrowed the result. Absent only when none applies."
6 tool updates
- Changed
gbif_count_occurrences6 fields changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Filter to a specific dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets."New value: +"Filter to a specific dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets. The result is not the recordCount the dataset tools and the gbif://dataset/{datasetKey} resource report for the same key: that figure spans every occurrenceStatus, while this count applies occurrenceStatus below, PRESENT by default." - added
Input schema / properties / iucnRedListCategoryAdded value: +{ + "description": "Count only 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. Records with no category are excluded when this is set.", + "enum": [ + "CR", + "EN", + "VU", + "NT", + "LC", + "DD", + "EX", + "EW", + "CD" + ], + "type": "string" +} - added
Input schema / properties / occurrenceStatusAdded value: +{ + "default": "PRESENT", + "description": "Presence/absence filter. Defaults to PRESENT: an ABSENT record documents a survey that looked for the taxon and did not find it, so counting one inflates the total with the opposite of a sighting. Use ANY for both (GBIF's own default), or ABSENT for non-observations alone. Matches the gbif_search_occurrences default, so the two tools agree.", + "enum": [ + "PRESENT", + "ABSENT", + "ANY" + ], + "type": "string" +} - added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when a presence/absence filter narrowed the count. Absent when occurrenceStatus is ANY.", + "type": "string" +} - added
Output schema / properties / occurrenceStatusAdded value: +{ + "description": "The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what the count covers.", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "count" -]New value: +[ + "count", + "occurrenceStatus" +]
- Changed
gbif_get_dataset1 field changed- changed
Output schema / properties / recordCount / descriptionPrevious value: -"Occurrence records GBIF has indexed for this dataset, matching the figure gbif_search_datasets reports. Fetched separately for OCCURRENCE datasets because the detail endpoint omits it; absent for other dataset types and when that lookup does not return in time."New value: +"Occurrence records GBIF has indexed for this dataset, matching the figure gbif_search_datasets reports. Spans every occurrenceStatus: absence records — surveys that looked for a taxon and did not find it — are counted alongside sightings, and on some datasets they are the overwhelming majority. gbif_count_occurrences with this datasetKey answers the other question, defaulting to occurrenceStatus PRESENT, so the two figures are expected to differ rather than one being wrong. Fetched separately because the detail endpoint omits it; absent when that lookup does not return in time."
- Changed
gbif_get_occurrence6 fields changed- added
Output schema / properties / eventTimeAdded value: +{ + "description": "Time of day of the observation, with seconds and UTC offset (e.g. 20:15:00+01:00) — the offset eventDate omits when it carries a local time. May be absent.", + "type": "string" +} - changed
Output schema / properties / gadm / descriptionPrevious value: -"GADM administrative geography — stable GIDs and names at levels 0–2. May be absent."New value: +"GADM administrative geography — stable GIDs and names at levels 0–3. May be absent." - added
Output schema / properties / gadm / properties / level3Added value: +{ + "additionalProperties": false, + "description": "GADM level 3 — municipality/ward, the finest level GBIF indexes. Absent where the country does not subdivide that far.", + "properties": { + "gid": { + "description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). May be absent.", + "type": "string" + }, + "name": { + "description": "Administrative-unit name. May be absent.", + "type": "string" + } + }, + "type": "object" +} - added
Output schema / properties / iucnRedListCategoryAdded value: +{ + "description": "IUCN Red List category of the taxon — 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. May be absent.", + "type": "string" +} - added
Output schema / properties / occurrenceStatusAdded value: +{ + "description": "PRESENT when the record asserts the taxon was there, ABSENT when it documents a survey that looked and did not find it. An ABSENT record is not a sighting — it carries coordinates, a date, and a recorder all the same. May be absent.", + "type": "string" +} - added
Output schema / properties / taxonomicStatusAdded value: +{ + "description": "Status of the identification carried on this record — ACCEPTED, PROVISIONALLY_ACCEPTED, SYNONYM, DOUBTFUL, and so on. Says whether the occurrence was filed under an accepted name or a synonym. May be absent.", + "type": "string" +}
- Changed
gbif_occurrence_facets7 fields changed- changed
Input schema / properties / facet / descriptionPrevious value: -"Dimension to aggregate by (e.g., COUNTRY, YEAR, BASIS_OF_RECORD, SPECIES_KEY)."New value: +"Dimension to aggregate by (e.g., COUNTRY, YEAR, BASIS_OF_RECORD, SPECIES_KEY, OCCURRENCE_STATUS, IUCN_RED_LIST_CATEGORY)." - changed
Input schema / properties / facet / enumPrevious value: -[ - "BASIS_OF_RECORD", - "COUNTRY", - "STATE_PROVINCE", - "YEAR", - "DATASET_KEY", - "KINGDOM_KEY", - "PHYLUM_KEY", - "CLASS_KEY", - "ORDER_KEY", - "FAMILY_KEY", - "GENUS_KEY", - "SPECIES_KEY", - "PUBLISHING_COUNTRY", - "MONTH" -]New value: +[ + "BASIS_OF_RECORD", + "COUNTRY", + "STATE_PROVINCE", + "YEAR", + "DATASET_KEY", + "KINGDOM_KEY", + "PHYLUM_KEY", + "CLASS_KEY", + "ORDER_KEY", + "FAMILY_KEY", + "GENUS_KEY", + "SPECIES_KEY", + "PUBLISHING_COUNTRY", + "MONTH", + "OCCURRENCE_STATUS", + "IUCN_RED_LIST_CATEGORY" +] - added
Input schema / properties / iucnRedListCategoryAdded value: +{ + "description": "Scope 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.", + "enum": [ + "CR", + "EN", + "VU", + "NT", + "LC", + "DD", + "EX", + "EW", + "CD" + ], + "type": "string" +} - added
Input schema / properties / occurrenceStatusAdded value: +{ + "default": "PRESENT", + "description": "Presence/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.", + "enum": [ + "PRESENT", + "ABSENT", + "ANY" + ], + "type": "string" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no facet values were returned. Absent when counts are non-empty."New value: +"Guidance when no facet values were returned or a presence/absence filter narrowed the aggregation. Absent only when neither applies." - added
Output schema / properties / occurrenceStatusAdded value: +{ + "description": "The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what totalOccurrences and every bucket cover.", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "facet", - "totalOccurrences", - "counts", - "facetLimit", - "facetOffset", - "moreValuesLikely" -]New value: +[ + "facet", + "totalOccurrences", + "counts", + "facetLimit", + "facetOffset", + "moreValuesLikely", + "occurrenceStatus" +]
- Changed
gbif_search_datasets1 field changed- changed
Output schema / properties / datasets / items / properties / recordCount / descriptionPrevious value: -"Number of records in the dataset."New value: +"Occurrence records GBIF has indexed for this dataset, spanning every occurrenceStatus: absence records — surveys that looked for a taxon and did not find it — are counted alongside sightings, and on some datasets they are the overwhelming majority. For the sightings-only figure, call gbif_count_occurrences with this key; it defaults to occurrenceStatus PRESENT, so the two figures are expected to differ rather than one being wrong."
- Changed
gbif_search_occurrences10 fields changed- added
Input schema / properties / iucnRedListCategoryAdded value: +{ + "description": "Restrict 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. Records with no category are excluded when this is set.", + "enum": [ + "CR", + "EN", + "VU", + "NT", + "LC", + "DD", + "EX", + "EW", + "CD" + ], + "type": "string" +} - added
Input schema / properties / occurrenceStatusAdded value: +{ + "default": "PRESENT", + "description": "Presence/absence filter. Defaults to PRESENT: an ABSENT record documents a survey that looked for the taxon and did not find it, so including one would read as a sighting of the opposite. Use ANY for both (GBIF's own default), or ABSENT for non-observations alone.", + "enum": [ + "PRESENT", + "ABSENT", + "ANY" + ], + "type": "string" +} - changed
Input schema / properties / scientificName / descriptionPrevious value: -"Scientific name filter. Less precise than taxonKey — does not match synonyms. Use taxonKey from gbif_match_species for reliable results."New value: +"Scientific name filter. Less precise than taxonKey — does not match synonyms. Use taxonKey from gbif_match_species for reliable results. Supplying both does not narrow the search: GBIF combines the two taxon filters with OR, so the result is the union of the two, not their intersection." - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when results are empty or paging overshot. Absent on successful result pages."New value: +"Guidance when results are empty, paging overshot, or a presence/absence filter narrowed the result. Absent only when none applies." - added
Output schema / properties / occurrenceStatusAdded value: +{ + "description": "The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what totalCount and the returned records cover.", + "type": "string" +} - added
Output schema / properties / occurrences / items / properties / eventTimeAdded value: +{ + "description": "Time of day of the observation, with seconds and UTC offset (e.g. 20:15:00+01:00) — the offset eventDate omits when it carries a local time. May be absent.", + "type": "string" +} - added
Output schema / properties / occurrences / items / properties / iucnRedListCategoryAdded value: +{ + "description": "IUCN Red List category of the taxon — CR, EN, VU, NT, LC, DD, EX, EW, or CD. May be absent.", + "type": "string" +} - added
Output schema / properties / occurrences / items / properties / occurrenceStatusAdded value: +{ + "description": "PRESENT when the record asserts the taxon was there, ABSENT when it documents a survey that looked and did not find it. An ABSENT record is not a sighting. May be absent.", + "type": "string" +} - added
Output schema / properties / occurrences / items / properties / taxonomicStatusAdded value: +{ + "description": "Status of the identification carried on this record — ACCEPTED, PROVISIONALLY_ACCEPTED, SYNONYM, DOUBTFUL, and so on. Says whether the occurrence was filed under an accepted name or a synonym. May be absent.", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "occurrences", - "totalCount", - "offset", - "limit", - "endOfRecords" -]New value: +[ + "occurrences", + "totalCount", + "offset", + "limit", + "endOfRecords", + "occurrenceStatus" +]
4 tool updates
- Changed
gbif_bulk_match_species4 fields changed- changed
Output schema / properties / results / items / properties / error / descriptionPrevious value: -"Failure reason when matchType is ERROR. Absent otherwise."New value: +"Failure message when matchType is ERROR. Absent otherwise." - added
Output schema / properties / results / items / properties / matchedTaxonKeyAdded value: +{ + "description": "Backbone key of the name that actually matched. Present only when it differs from taxonKey — that is, when a synonym was resolved to its accepted taxon.", + "type": "number" +} - added
Output schema / properties / results / items / properties / reasonAdded value: +{ + "description": "Machine-readable failure identifier when matchType is ERROR — e.g. invalid_filter when GBIF rejected a supplied value. Absent when the failure carried no classification, and absent on every non-ERROR entry.", + "type": "string" +} - changed
Output schema / properties / results / items / properties / taxonKey / descriptionPrevious value: -"Matched GBIF backbone taxon key — use in gbif_search_occurrences, gbif_count_occurrences, and gbif_occurrence_facets. Absent when matchType is NONE or ERROR."New value: +"GBIF backbone taxon key to pass to gbif_search_occurrences, gbif_count_occurrences, and gbif_occurrence_facets — the accepted taxon's key when this name is a synonym, otherwise the matched taxon's own key. Absent when matchType is NONE or ERROR."
- Changed
gbif_get_species_classification1 field changed- added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when the chain is empty because the taxon sits at the root of the backbone. Absent when the chain has entries.", + "type": "string" +}
- Changed
gbif_match_species3 fields changed- added
Output schema / properties / matchedTaxonKeyAdded value: +{ + "description": "Backbone key of the name that actually matched. Present only when it differs from taxonKey — that is, when a synonym was resolved to its accepted taxon.", + "type": "number" +} - added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when the queried name was a synonym and taxonKey was resolved to the accepted taxon. Absent when the matched name is already the accepted one.", + "type": "string" +} - changed
Output schema / properties / taxonKey / descriptionPrevious value: -"GBIF backbone taxon key. Use this in downstream tools. Absent when matchType is NONE."New value: +"GBIF backbone taxon key to pass to downstream tools. The accepted taxon's key when the queried name is a synonym, otherwise the matched taxon's own key."
- Changed
gbif_occurrence_facets1 field changed- changed
Output schema / properties / counts / descriptionPrevious value: -"Facet values ranked by count descending (top facetLimit entries)."New value: +"Facet values ranked by count descending — one page of up to facetLimit entries starting at facetOffset, not necessarily the top ones."
6 tool updates
- Changed
gbif_count_occurrences1 field changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Filter to a specific dataset UUID."New value: +"Filter to a specific dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets."
- Changed
gbif_get_dataset2 fields changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Dataset UUID from gbif_search_datasets or an occurrence record."New value: +"Dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets or an occurrence record." - changed
Output schema / properties / recordCount / descriptionPrevious value: -"Number of records in the dataset. May be absent."New value: +"Occurrence records GBIF has indexed for this dataset, matching the figure gbif_search_datasets reports. Fetched separately for OCCURRENCE datasets because the detail endpoint omits it; absent for other dataset types and when that lookup does not return in time."
- Changed
gbif_occurrence_facets1 field changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Scope the aggregation to a single dataset by its GBIF dataset UUID. Obtain one from gbif_search_datasets, gbif_get_dataset, a DATASET_KEY facet, or the datasetKey field on an occurrence record."New value: +"Scope 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."
- Changed
gbif_search_datasets1 field changed- changed
Input schema / properties / hostingOrg / descriptionPrevious value: -"UUID of the hosting organization. From gbif_search_publishers results."New value: +"UUID (8-4-4-4-12 hex) of the hosting organization. From gbif_search_publishers results."
- Changed
gbif_search_occurrences2 fields changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Restrict results to a single dataset by its GBIF dataset UUID. Obtain one from gbif_search_datasets, gbif_get_dataset, a DATASET_KEY facet (gbif_occurrence_facets), or the datasetKey field on an occurrence record."New value: +"Restrict results 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 (gbif_occurrence_facets), or the datasetKey field on an occurrence record." - changed
Input schema / properties / offset / descriptionPrevious value: -"Pagination offset. GBIF caps offset+limit at approximately 100,000 — use gbif_occurrence_facets for aggregate analysis beyond this."New value: +"Pagination offset. GBIF serves offset+limit up to 100,001 and rejects anything past it — use gbif_occurrence_facets for aggregate analysis beyond that."
- Changed
gbif_search_species1 field changed- changed
Input schema / properties / datasetKey / descriptionPrevious value: -"Scope to a specific checklist dataset UUID. Omit to search the GBIF backbone."New value: +"Scope to a specific checklist dataset UUID (8-4-4-4-12 hex). Omit to search the GBIF backbone."
3 tool updates
- Changed
gbif_get_species_classification1 field changed- changed
Output schema / properties / classification / descriptionPrevious value: -"Classification chain ordered from root (kingdom) to the immediate parent of the queried taxon."New value: +"Classification chain ordered from root (kingdom) to the immediate parent of the queried taxon. The queried taxon itself is not included — call gbif_get_species for its own record."
- Changed
gbif_occurrence_facets4 fields changed- added
Input schema / properties / facetOffsetAdded value: +{ + "default": 0, + "description": "Zero-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, …).", + "minimum": 0, + "type": "number" +} - added
Output schema / properties / facetOffsetAdded value: +{ + "description": "Zero-based offset applied to the ranked facet values.", + "type": "number" +} - added
Output schema / properties / moreValuesLikelyAdded value: +{ + "description": "Heuristic continuation flag: true when this page returned a full facetLimit of values, so more distinct values may exist past facetOffset + facetLimit (re-call with facetOffset advanced by facetLimit). GBIF exposes no total distinct-value count, so this is an estimate, not exact.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "facet", - "totalOccurrences", - "counts", - "facetLimit" -]New value: +[ + "facet", + "totalOccurrences", + "counts", + "facetLimit", + "facetOffset", + "moreValuesLikely" +]
- Changed
gbif_search_datasets2 fields changed- changed
Output schema / properties / datasets / items / properties / description / descriptionPrevious value: -"Brief description. May be absent."New value: +"Brief description, truncated to a 300-character preview. May be absent." - added
Output schema / properties / datasets / items / properties / descriptionTruncatedAdded value: +{ + "description": "True when the description was shortened to the 300-char preview; call gbif_get_dataset with this key for the full text. Omitted when the dataset has no description.", + "type": "boolean" +}
2 tool updates
- Changed
gbif_get_dataset2 fields changed- added
Output schema / properties / geographicCoveragesAdded value: +{ + "description": "Geographic coverage descriptions declared by the dataset. May be absent.", + "items": { + "additionalProperties": false, + "description": "A geographic coverage entry.", + "properties": { + "description": { + "description": "Geographic coverage description (e.g. \"Worldwide\"). May be absent.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / temporalCoveragesAdded value: +{ + "description": "Temporal coverage ranges declared by the dataset. May be absent.", + "items": { + "additionalProperties": false, + "description": "A temporal coverage range.", + "properties": { + "end": { + "description": "Coverage end as an ISO 8601 date-time. May be absent.", + "type": "string" + }, + "start": { + "description": "Coverage start as an ISO 8601 date-time. May be absent.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" +}
- Changed
gbif_get_occurrence5 fields changed- added
Output schema / properties / classAdded value: +{ + "description": "Class classification. May be absent.", + "type": "string" +} - added
Output schema / properties / classKeyAdded value: +{ + "description": "Backbone taxon key for the class. May be absent.", + "type": "number" +} - added
Output schema / properties / gadmAdded value: +{ + "additionalProperties": false, + "description": "GADM administrative geography — stable GIDs and names at levels 0–2. May be absent.", + "properties": { + "level0": { + "additionalProperties": false, + "description": "GADM level 0 — country. May be absent.", + "properties": { + "gid": { + "description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). May be absent.", + "type": "string" + }, + "name": { + "description": "Administrative-unit name. May be absent.", + "type": "string" + } + }, + "type": "object" + }, + "level1": { + "additionalProperties": false, + "description": "GADM level 1 — state/province. May be absent.", + "properties": { + "gid": { + "description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). May be absent.", + "type": "string" + }, + "name": { + "description": "Administrative-unit name. May be absent.", + "type": "string" + } + }, + "type": "object" + }, + "level2": { + "additionalProperties": false, + "description": "GADM level 2 — county/district. May be absent.", + "properties": { + "gid": { + "description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). May be absent.", + "type": "string" + }, + "name": { + "description": "Administrative-unit name. May be absent.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" +} - added
Output schema / properties / identifiersAdded value: +{ + "description": "Alternative record identifiers from the source. May be absent.", + "items": { + "additionalProperties": false, + "description": "An alternative identifier for the occurrence record.", + "properties": { + "identifier": { + "description": "The identifier value. May be absent.", + "type": "string" + }, + "type": { + "description": "Identifier type (e.g. URL, DOI, GBIF_PORTAL). May be absent.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / occurrenceIDAdded value: +{ + "description": "Darwin Core occurrenceID — the source record identifier, often a URL back to the origin record. May be absent.", + "type": "string" +}
3 tool updates
- Added
gbif_bulk_match_species - Changed
gbif_get_species_children6 fields changed- added
Output schema / properties / capAdded value: +{ + "description": "Limit applied when the result was truncated. Re-call with offset to page on.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no children are found for a valid taxon. Absent on successful result pages."New value: +"Agent guidance — a no-children note for a valid taxon, or a pagination note when the page was capped. Absent on a complete single page." - added
Output schema / properties / shownAdded value: +{ + "description": "Children returned in this page when the result was truncated.", + "type": "number" +} - removed
Output schema / properties / totalCountRemoved value: -{ - "description": "Total direct children before pagination.", - "type": "number" -} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when more children exist beyond this page. Absent on the final page.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "children", - "totalCount", - "offset", - "limit", - "endOfRecords" -]New value: +[ + "children", + "offset", + "limit", + "endOfRecords" +]
- Changed
gbif_match_species1 field changed- changed
Output schema / properties / matchType / descriptionPrevious value: -"EXACT, FUZZY, HIGHERORDER, or NONE. NONE means no usable match."New value: +"EXACT, FUZZY, HIGHERRANK, or NONE. NONE means no usable match."
2 tool updates
- Changed
gbif_occurrence_facets1 field changed- added
Input schema / properties / datasetKeyAdded value: +{ + "description": "Scope the aggregation to a single dataset by its GBIF dataset UUID. Obtain one from gbif_search_datasets, gbif_get_dataset, a DATASET_KEY facet, or the datasetKey field on an occurrence record.", + "type": "string" +}
- Changed
gbif_search_occurrences2 fields changed- added
Input schema / properties / datasetKeyAdded value: +{ + "description": "Restrict results to a single dataset by its GBIF dataset UUID. Obtain one from gbif_search_datasets, gbif_get_dataset, a DATASET_KEY facet (gbif_occurrence_facets), or the datasetKey field on an occurrence record.", + "type": "string" +} - changed
Input schema / properties / hasCoordinate / descriptionPrevious value: -"When true, return only georeferenced records. When false, include records without coordinates."New value: +"When true, return only georeferenced records (those with coordinates). When false, return ONLY records without coordinates. Omit the parameter entirely to include all records regardless of coordinate presence."
1 tool update
- Changed
gbif_get_dataset4 fields changed- added
Input schema / properties / contactLimitAdded value: +{ + "default": 10, + "description": "Maximum number of contacts to include (default 10, max 100). Set to 0 to omit contact detail while still reporting contactsTotal — useful when citation, license, and record count are all you need from a high-contact dataset like eBird.", + "maximum": 100, + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / contacts / descriptionPrevious value: -"Dataset contacts. May be absent."New value: +"Dataset contacts, capped at contactLimit. Absent when the dataset has no contacts or contactLimit is 0." - added
Output schema / properties / contactsReturnedAdded value: +{ + "description": "Number of contacts included in this response (≤ contactLimit). Present when the dataset has any contacts.", + "type": "number" +} - added
Output schema / properties / contactsTotalAdded value: +{ + "description": "Total contacts on the dataset before applying contactLimit. Present when the dataset has any contacts.", + "type": "number" +}
1 tool update
- Changed
gbif_get_species_children2 fields changed- added
Output schema / properties / totalCountAdded value: +{ + "description": "Total direct children before pagination.", + "type": "number" +} - changed
Output schema / requiredPrevious value: -[ - "children", - "offset", - "limit", - "endOfRecords" -]New value: +[ + "children", + "totalCount", + "offset", + "limit", + "endOfRecords" +]
1 tool update
- Changed
gbif_get_species_children1 field changed- changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no children are found (empty taxon or invalid key). Absent on successful result pages."New value: +"Guidance when no children are found for a valid taxon. Absent on successful result pages."
Related MCP Connectors
Search GBIF species taxonomy, occurrence records, datasets, and publishers.
Search iNaturalist sightings, identification threads, phenology, and look-alike species.
Search books and authors across Open Library, the Internet Archive open catalog.
GBIF MCP — wraps the Global Biodiversity Information Facility API v1 (free, no auth)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to query and retrieve biodiversity data from the Global Biodiversity Information Facility (GBIF), including species, occurrences, datasets, and literature.111 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables querying biodiversity data from the Global Biodiversity Information Facility (GBIF) API v1, supporting species occurrence searches and other GBIF endpoints through natural language.2 npmMIT

@pipeworx/enaofficial
AlicenseNot gradedqualityCmaintenanceEnables searching ENA's public sequencing data by organism, study, platform, country or date, retrieving FASTQ/BAM download URLs and checksums, and discovering available result types and fields.MIT- AlicenseNot gradedqualityCmaintenanceEnables queries about global taxonomic data, including scientific name matching, classification chains, common names, and synonyms from the Catalogue of Life index.2 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.