gbif-biodiversity-mcp-server
An MCP server that allows agents to search the Global Biodiversity Information Facility (GBIF) database. It provides tools to match scientific names against the backbone taxonomy, search and aggregate over 3.9 billion occurrence records using Darwin Core filters, and retrieve metadata for datasets and publishers.
Endpoint and access
No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.
https://gbif-biodiversity.caseyjhand.com/mcpWhat its tools do
13 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.
Checks and signals
Each line is separate evidence, not a trust score.
- Passed Endpoint answered the live check ·
- Availability 1 of 1 checks passed in 30 days
What you can do with it
- Match scientific names to GBIF backbone taxonomy
- Search occurrence records by taxon, place, or date
- Search datasets by keyword or publishing organization
- Aggregate occurrence counts by country or year
Source and maintenance
- Maintenance checked
Protocol and capabilities
- Server
- gbif-biodiversity-mcp-server 0.8.0
- MCP protocol negotiated in check
- 2025-11-25
- Tools
- 13 advertised
- Resources
- 1 advertised
- Resource templates
- 3 advertised
- Prompts
- 0 advertised
{
"tools": {
"listChanged": true
},
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"extensions": {
"io.modelcontextprotocol/skills": {
"directoryRead": true
}
}
}Server-provided instructions
Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.
Tools
13 advertised
gbif_match_species — Match Species Name
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 name GBIF matched is a synonym — the queried name, or the higher taxon a HIGHERRANK match falls back to — 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. matchType HIGHERRANK is GBIF's label for a match made at a higher rank: a misspelled or unknown species falls back to its genus or even its kingdom, at a confidence that can exceed 90, and a bare genus name carries the label too, matched as that genus. taxonKey then covers that whole taxon, or its accepted taxon when it is a synonym, and a notice names it. 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; when GBIF reports several equal matches, as for a genus name shared by an animal and a plant, set kingdom to pick one.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "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": {
"enum": [
"KINGDOM",
"PHYLUM",
"CLASS",
"ORDER",
"FAMILY",
"GENUS",
"SPECIES",
"SUBSPECIES"
],
"type": "string",
"description": "Expected taxonomic rank. Use to avoid matching a genus when you expect a species."
},
"strict": {
"type": "boolean",
"default": false,
"description": "When true, only return an exact match. When false (default), GBIF applies fuzzy matching — useful for minor spelling variations and abbreviated names."
},
"kingdom": {
"type": "string",
"description": "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."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
}
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"rank": {
"type": "string",
"description": "Taxonomic rank of the matched taxon."
},
"class": {
"type": "string",
"description": "Class of the matched taxon."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"no_match",
"invalid_filter"
],
"description": "Machine-readable failure mode. Declared by this tool: `no_match`: matchType is NONE — no candidate met the match threshold, or several equal candidates tied; the message then carries GBIF's note. `invalid_filter`: kingdom was supplied blank or whitespace-only, which disambiguates nothing. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"genus": {
"type": "string",
"description": "Genus of the matched taxon."
},
"order": {
"type": "string",
"description": "Order of the matched taxon."
},
"family": {
"type": "string",
"description": "Family of the matched taxon."
},
"notice": {
"type": "string",
"description": "Guidance when matchType is HIGHERRANK — naming the taxon and rank GBIF matched and what taxonKey covers — or when the matched name was a synonym and taxonKey was resolved to the accepted taxon. A higher-rank match on a synonym carries both. Absent on an EXACT or FUZZY match of an accepted name."
},
"phylum": {
"type": "string",
"description": "Phylum of the matched taxon."
},
"status": {
"type": "string",
"description": "Taxonomic status: ACCEPTED, SYNONYM, or DOUBTFUL."
},
"kingdom": {
"type": "string",
"description": "Kingdom of the matched taxon."
},
"species": {
"type": "string",
"description": "Species canonical name of the matched taxon."
},
"classKey": {
"type": "number",
"description": "Backbone taxon key for the class."
},
"genusKey": {
"type": "number",
"description": "Backbone taxon key for the genus."
},
"orderKey": {
"type": "number",
"description": "Backbone taxon key for the order."
},
"taxonKey": {
"type": "number",
"description": "GBIF backbone taxon key to pass to downstream tools. The accepted taxon's key when the name GBIF matched is a synonym, otherwise the matched taxon's own key."
},
"familyKey": {
"type": "number",
"description": "Backbone taxon key for the family."
},
"matchType": {
"type": "string",
"description": "EXACT, FUZZY, HIGHERRANK, or NONE. HIGHERRANK means GBIF matched at a higher rank — a misspelled species falls back to its genus or kingdom, and a bare genus name carries it too — and taxonKey covers that whole taxon, or its accepted taxon when it is a synonym. NONE means no usable match."
},
"phylumKey": {
"type": "number",
"description": "Backbone taxon key for the phylum."
},
"confidence": {
"type": "number",
"description": "Match confidence score 0–100. Below 80 warrants review. A HIGHERRANK match can score above 90, so read matchType too."
},
"kingdomKey": {
"type": "number",
"description": "Backbone taxon key for the kingdom."
},
"speciesKey": {
"type": "number",
"description": "Backbone taxon key for the species."
},
"canonicalName": {
"type": "string",
"description": "Scientific name without authorship."
},
"scientificName": {
"type": "string",
"description": "Full scientific name with authorship."
},
"matchedTaxonKey": {
"type": "number",
"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."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_bulk_match_species — Bulk Match Species Names
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 processed name. By default, an oversized batch processes the first 50 and returns the remainder in unprocessedNames. A name GBIF matched at a higher rank yields matchType HIGHERRANK with a note naming the taxon matched and what its taxonKey covers: that whole taxon, or its accepted taxon when it is a synonym — a misspelled species can fall back to its genus or kingdom at a confidence above 90, and a bare genus name carries the label too, matched as that genus. A name with no backbone match yields matchType NONE (no taxonKey) instead of failing the batch, with a note carrying GBIF's explanation when it gives one, such as several equal matches for a name shared across kingdoms; 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 the name GBIF matched is a synonym — the queried name, or the higher taxon a HIGHERRANK match falls back to — 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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"names"
],
"properties": {
"names": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A scientific name to match, e.g. \"Panthera leo\"."
},
"minItems": 1,
"description": "Scientific names to match against the GBIF backbone. Up to 50 are matched in parallel; additional names are returned in unprocessedNames when read-limit clamping is enabled (default). Every submitted name must be valid."
},
"strict": {
"type": "boolean",
"default": false,
"description": "When true, require an exact match for every name (no fuzzy matching). When false (default), GBIF applies fuzzy matching to tolerate minor misspellings."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"results"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Requested and applied batch size when names exceed the 50-name workload cap."
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"matchType"
],
"properties": {
"name": {
"type": "string",
"description": "The input name this entry corresponds to."
},
"note": {
"type": "string",
"description": "On HIGHERRANK, names the taxon and rank GBIF matched and what taxonKey covers: that whole taxon, or its accepted taxon when it is a synonym. On NONE, GBIF's own explanation when it gave one — for a name shared across kingdoms, its report of several equal matches, with a pointer to retry that name through gbif_match_species with kingdom. Absent on EXACT, FUZZY, and ERROR entries, and on a NONE GBIF did not explain."
},
"rank": {
"type": "string",
"description": "Taxonomic rank of the matched taxon."
},
"error": {
"type": "string",
"description": "Failure message when matchType is ERROR. Absent otherwise."
},
"reason": {
"type": "string",
"description": "Machine-readable failure identifier when matchType is ERROR and the failure was classified. Absent when the failure carried no classification, and absent on every non-ERROR entry."
},
"status": {
"type": "string",
"description": "Taxonomic status: ACCEPTED, SYNONYM, or DOUBTFUL."
},
"taxonKey": {
"type": "number",
"description": "GBIF backbone taxon key to pass to gbif_search_occurrences, gbif_count_occurrences, and gbif_occurrence_facets — the accepted taxon's key when the name GBIF matched is a synonym, otherwise the matched taxon's own key. Absent when matchType is NONE or ERROR."
},
"matchType": {
"type": "string",
"description": "EXACT or FUZZY for a match; HIGHERRANK when GBIF matched at a higher rank — a misspelled species falls back to its genus or kingdom, and a bare genus name carries it too — so taxonKey covers that whole taxon, or its accepted taxon when it is a synonym (see note); NONE when GBIF found no usable match; ERROR when the lookup itself failed for this name (see error)."
},
"confidence": {
"type": "number",
"description": "Match confidence 0–100. Below 80 warrants review; a HIGHERRANK match can score above 90, so read matchType too. Absent on ERROR."
},
"canonicalName": {
"type": "string",
"description": "Matched scientific name without authorship. Absent when unmatched."
},
"scientificName": {
"type": "string",
"description": "Full matched scientific name with authorship. Absent when unmatched."
},
"matchedTaxonKey": {
"type": "number",
"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."
}
},
"description": "Match outcome for one input name.",
"additionalProperties": false
},
"description": "One result per processed input name, in input order (at most 50)."
},
"unprocessedNames": {
"type": "array",
"items": {
"type": "string"
},
"description": "Names beyond the first 50, in original order including duplicates. Submit these names in another call. Absent when every name was processed."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_get_species — Get Species Record
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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"taxonKey"
],
"properties": {
"taxonKey": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "GBIF backbone taxon key from gbif_match_species or another taxonomy tool."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
}
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"key": {
"type": "number",
"description": "GBIF backbone taxon key."
},
"rank": {
"type": "string",
"description": "Taxonomic rank (SPECIES, GENUS, FAMILY, etc.)."
},
"class": {
"type": "string",
"description": "Class classification."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found",
"invalid_filter"
],
"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 value outside the 32-bit signed integer range. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"genus": {
"type": "string",
"description": "Genus classification."
},
"order": {
"type": "string",
"description": "Order classification."
},
"family": {
"type": "string",
"description": "Family classification."
},
"parent": {
"type": "string",
"description": "Name of the immediate parent taxon."
},
"phylum": {
"type": "string",
"description": "Phylum classification."
},
"extinct": {
"type": "boolean",
"description": "True when the taxon is explicitly flagged as extinct. Absent on most records."
},
"kingdom": {
"type": "string",
"description": "Kingdom classification."
},
"species": {
"type": "string",
"description": "Species canonical name."
},
"accepted": {
"type": "string",
"description": "Scientific name of the accepted taxon when this record is a synonym."
},
"classKey": {
"type": "number",
"description": "Taxon key for the class."
},
"genusKey": {
"type": "number",
"description": "Taxon key for the genus."
},
"orderKey": {
"type": "number",
"description": "Taxon key for the order."
},
"familyKey": {
"type": "number",
"description": "Taxon key for the family."
},
"parentKey": {
"type": "number",
"description": "Taxon key of the immediate parent."
},
"phylumKey": {
"type": "number",
"description": "Taxon key for the phylum."
},
"authorship": {
"type": "string",
"description": "Taxonomic authorship of the name."
},
"kingdomKey": {
"type": "number",
"description": "Taxon key for the kingdom."
},
"speciesKey": {
"type": "number",
"description": "Taxon key for the species."
},
"acceptedKey": {
"type": "number",
"description": "Backbone key of the accepted taxon when this record is a synonym."
},
"publishedIn": {
"type": "string",
"description": "Original description citation when available."
},
"canonicalName": {
"type": "string",
"description": "Scientific name without authorship."
},
"numDescendants": {
"type": "number",
"description": "Count of child taxa in the backbone under this taxon."
},
"numOccurrences": {
"type": "number",
"description": "Occurrence record count, when GBIF includes one. Its taxon record endpoint does not, so this is normally absent — count with gbif_count_occurrences and the taxonKey instead."
},
"scientificName": {
"type": "string",
"description": "Full scientific name with authorship."
},
"vernacularName": {
"type": "string",
"description": "English common name when available."
},
"taxonomicStatus": {
"type": "string",
"description": "ACCEPTED, SYNONYM, DOUBTFUL, etc. SYNONYM means acceptedKey/accepted are populated."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_search_species — Search Species Taxonomy
Search or browse the GBIF backbone taxonomy by default, or an explicit checklist datasetKey. 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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"description": "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 name index and a whitespace-only one with nothing, and neither is the search a caller who filled the field was asking for."
},
"rank": {
"enum": [
"KINGDOM",
"PHYLUM",
"CLASS",
"ORDER",
"FAMILY",
"GENUS",
"SPECIES",
"SUBSPECIES"
],
"type": "string",
"description": "Filter to a specific taxonomic rank."
},
"genus": {
"type": "string",
"description": "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": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Number of records to return (default 20, max 1000)."
},
"family": {
"type": "string",
"description": "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": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset."
},
"kingdom": {
"type": "string",
"description": "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": {
"type": "boolean",
"description": "Filter to extinct (true) or extant (false) taxa."
},
"datasetKey": {
"type": "string",
"description": "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."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"taxa",
"totalCount",
"offset",
"limit",
"endOfRecords"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"taxa": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "number",
"description": "Taxon usage key within the source checklist; not necessarily a backbone key."
},
"rank": {
"type": "string",
"description": "Taxonomic rank."
},
"class": {
"type": "string",
"description": "Class classification."
},
"genus": {
"type": "string",
"description": "Genus classification."
},
"order": {
"type": "string",
"description": "Order classification."
},
"family": {
"type": "string",
"description": "Family classification."
},
"nubKey": {
"type": "number",
"description": "Mapped backbone taxon key for occurrence queries, when GBIF supplies it. Otherwise resolve the name with gbif_match_species."
},
"phylum": {
"type": "string",
"description": "Phylum classification."
},
"extinct": {
"type": "boolean",
"description": "True when explicitly flagged as extinct."
},
"kingdom": {
"type": "string",
"description": "Kingdom classification."
},
"datasetKey": {
"type": "string",
"description": "Source checklist dataset UUID, when GBIF supplies it."
},
"canonicalName": {
"type": "string",
"description": "Scientific name without authorship."
},
"numDescendants": {
"type": "number",
"description": "Count of child taxa in the backbone."
},
"numOccurrences": {
"type": "number",
"description": "Occurrence record count, present only when GBIF supplies a positive value. GBIF's species search sends 0 on every row as a placeholder, so this is normally absent; for a count, pass nubKey as taxonKey to gbif_count_occurrences, or facet by SPECIES_KEY with gbif_occurrence_facets."
},
"scientificName": {
"type": "string",
"description": "Full scientific name with authorship."
},
"vernacularName": {
"type": "string",
"description": "Common name. GBIF's own vernacularName when the row carries one. Otherwise one of the row's English (eng) vernacular names: the first that contains q, case-insensitively, when q is set and does not occur in the row's canonicalName or scientificName; else the first English one. Absent when the row carries neither."
},
"taxonomicStatus": {
"type": "string",
"description": "ACCEPTED, SYNONYM, DOUBTFUL, etc."
}
},
"description": "A checklist taxon usage with classification, status, common name, and descendant count.",
"additionalProperties": false
},
"description": "Matching taxa."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_filter",
"unresolved_taxon_scope",
"conflicting_taxon_scope"
],
"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."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"limit": {
"type": "number",
"description": "Records returned in this page."
},
"notice": {
"type": "string",
"description": "Guidance when results are empty, paging overshot, or an oversized read limit was clamped. Absent when none applies."
},
"offset": {
"type": "number",
"description": "Current pagination offset."
},
"taxonScope": {
"type": "string",
"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."
},
"totalCount": {
"type": "number",
"description": "Total matches before pagination."
},
"endOfRecords": {
"type": "boolean",
"description": "True when there are no more results after this page."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_get_species_classification — Get Species Classification
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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"taxonKey"
],
"properties": {
"taxonKey": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "GBIF backbone taxon key from gbif_match_species or another taxonomy tool."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"classification"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found",
"invalid_filter"
],
"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 value outside the 32-bit signed integer range. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Guidance when the chain is empty because the taxon sits at the root of the backbone. Absent when the chain has entries."
},
"classification": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "number",
"description": "Backbone taxon key for this rank."
},
"name": {
"type": "string",
"description": "Canonical name at this rank."
},
"rank": {
"type": "string",
"description": "Taxonomic rank (KINGDOM, PHYLUM, CLASS, etc.)."
},
"scientificName": {
"type": "string",
"description": "Full scientific name with authorship."
}
},
"description": "A single rank entry in the classification chain.",
"additionalProperties": false
},
"description": "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."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_get_species_children — Get Species Children
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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"taxonKey"
],
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Number of children to return (default 20, max 1000)."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset."
},
"taxonKey": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "GBIF backbone taxon key from gbif_match_species or another taxonomy tool."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"children",
"offset",
"limit",
"endOfRecords"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"cap": {
"type": "number",
"description": "Limit applied when the result was truncated. Re-call with offset to page on."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found",
"invalid_filter"
],
"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 value outside the 32-bit signed integer range. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"limit": {
"type": "number",
"description": "Records returned in this page."
},
"shown": {
"type": "number",
"description": "Children returned in this page when the result was truncated."
},
"notice": {
"type": "string",
"description": "Guidance when a valid taxon has no children, more pages remain, or an oversized limit was clamped. Absent when none applies."
},
"offset": {
"type": "number",
"description": "Current pagination offset."
},
"children": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "number",
"description": "GBIF backbone taxon key."
},
"rank": {
"type": "string",
"description": "Taxonomic rank."
},
"canonicalName": {
"type": "string",
"description": "Scientific name without authorship."
},
"numDescendants": {
"type": "number",
"description": "Count of child taxa under this node."
},
"numOccurrences": {
"type": "number",
"description": "Occurrence record count, present only when GBIF supplies one. GBIF's children listing does not, so this is normally absent; for a count, pass key as taxonKey to gbif_count_occurrences."
},
"scientificName": {
"type": "string",
"description": "Full scientific name with authorship."
},
"vernacularName": {
"type": "string",
"description": "Common name when available."
},
"taxonomicStatus": {
"type": "string",
"description": "ACCEPTED, SYNONYM, DOUBTFUL, etc."
}
},
"description": "A direct child taxon with key, name, rank, and status.",
"additionalProperties": false
},
"description": "Direct child taxa."
},
"truncated": {
"type": "boolean",
"description": "True when more children exist beyond this page. Absent on the final page."
},
"endOfRecords": {
"type": "boolean",
"description": "True when there are no more results after this page."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_search_occurrences — Search Occurrences
Search 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, gadmGid (a GADM administrative-area code GBIF derives from coordinates), bounding box (decimalLatitude/decimalLongitude ranges), WKT polygon geometry, year range, month, basis of record, coordinate filter, dataset key, catalogNumber, institutionCode, recordedBy (collector), and mediaType. 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. BASIS_OF_RECORD and PUBLISHING_COUNTRY are gap-free second cuts for a dataset bucket still over the cap; YEAR, MONTH, STATE_PROVINCE, and SPECIES_KEY lose records lacking that dimension. Repeat every biological filter on the facet call and each partition search, including the same occurrenceStatus, and compare sub-split sums against the bucket total. Bulk retrieval is outside this server: use the asynchronous GBIF Download API with a GBIF.org account or the monthly GBIF Parquet snapshot on AWS Open Data.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"year": {
"type": "string",
"description": "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": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Number of records to return (default 20, max 300)."
},
"month": {
"type": "integer",
"maximum": 12,
"minimum": 1,
"description": "Calendar month (1–12). Useful for seasonal distribution queries."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "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": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"description": "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."
},
"gadmGid": {
"type": "string",
"description": "GADM administrative-area GID at any level: country (ESP), state or province (ESP.1_1), county or district (ESP.1.5_1), or municipality (ESP.1.6.3_1). GBIF derives a record's GIDs from its coordinates, so records without coordinates match none, and the unit can differ from the verbatim stateProvince the record carries. Matched exactly and case-sensitively, and a GID holds only uppercase letters, digits, dots, and underscores — any other character is rejected. Take one from a GADM_LEVEL_0_GID, GADM_LEVEL_1_GID, GADM_LEVEL_2_GID, or GADM_LEVEL_3_GID facet on gbif_occurrence_facets, or from the gadm field of gbif_get_occurrence; a well-formed GID GBIF does not hold matches zero records rather than erroring. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"geometry": {
"type": "string",
"description": "WKT polygon for geographic filtering (e.g., POLYGON((8 47, 9 47, 9 48, 8 48, 8 47))). Coordinates are longitude latitude. All supplied spatial filters intersect: decimalLatitude and decimalLongitude remain active and restrict results to the overlap. 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": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "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.)."
},
"mediaType": {
"enum": [
"StillImage",
"MovingImage",
"Sound",
"InteractiveResource"
],
"type": "string",
"description": "Only records carrying at least one media item of this type: StillImage (photographs, scans), MovingImage (video), Sound (audio), or InteractiveResource. Records without media are excluded when this is set."
},
"datasetKey": {
"type": "string",
"description": "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."
},
"recordedBy": {
"type": "string",
"description": "Collector or observer, matched against each name in the record's recordedBy list (GBIF splits it on \"|\") exactly and case-sensitively: \"Charles Darwin\" and \"charles darwin\" differ, and one person written two ways (\"Charles Darwin\", \"Darwin, C.\") is two values. Take a value from a RECORDED_BY facet on gbif_occurrence_facets scoped the same way and pass it back unchanged; an unmatched value matches zero records rather than erroring. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"isInCluster": {
"type": "boolean",
"description": "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": {
"enum": [
"HUMAN_OBSERVATION",
"MACHINE_OBSERVATION",
"PRESERVED_SPECIMEN",
"LIVING_SPECIMEN",
"MATERIAL_SAMPLE",
"MATERIAL_CITATION",
"OCCURRENCE",
"LITERATURE",
"FOSSIL_SPECIMEN",
"OBSERVATION",
"UNKNOWN"
],
"type": "string",
"description": "Filter by how the occurrence was recorded. HUMAN_OBSERVATION covers citizen science. PRESERVED_SPECIMEN covers natural history collections."
},
"catalogNumber": {
"type": "string",
"description": "Catalog number a collection assigned to the specimen or record (e.g. \"L.1592880\"), matched as the whole value, case-insensitively. Not unique across collections — one number can name records in several datasets, so pair it with institutionCode or datasetKey to single one out. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"hasCoordinate": {
"type": "boolean",
"description": "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": {
"type": "string",
"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. 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": {
"type": "string",
"description": "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": {
"type": "string",
"description": "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."
},
"institutionCode": {
"type": "string",
"description": "Code of the institution holding the record (e.g. \"K\", \"CLO\"), matched as the whole value, case-insensitively — part of a code or of a multi-word code matches nothing. An INSTITUTION_CODE facet on gbif_occurrence_facets lists the codes in a scope, lowercased, and this filter takes them unchanged. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"decimalLongitude": {
"type": "string",
"description": "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": {
"enum": [
"PRESENT",
"ABSENT",
"ANY"
],
"type": "string",
"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."
},
"publishingCountry": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 code, uppercase, of the organization that published the record — distinct from where the occurrence was observed, which is country. 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": {
"enum": [
"CR",
"EN",
"VU",
"NT",
"LC",
"DD",
"EX",
"EW",
"CD"
],
"type": "string",
"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."
},
"coordinateUncertaintyInMeters": {
"type": "string",
"description": "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."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"occurrences",
"scope",
"totalCount",
"offset",
"limit",
"endOfRecords",
"occurrenceStatus"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"pagination_cap_exceeded",
"invalid_filter"
],
"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 — a string filter other than country and publishingCountry supplied blank or whitespace-only (a blank country or publishingCountry fails earlier, at its uppercase pattern, as -32602 invalid_arguments), a datasetKey that is not an 8-4-4-4-12 hex UUID, a gadmGid holding a character other than an uppercase letter, digit, dot, or underscore, 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."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"limit": {
"type": "number",
"description": "Records returned in this page."
},
"scope": {
"type": "object",
"description": "Effective supplied biological filters, with occurrenceStatus always included; excludes pagination and facet controls.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": [
"string",
"number",
"boolean"
]
}
},
"notice": {
"type": "string",
"description": "Guidance when results are empty, paging overshot, a read limit was clamped, the match is larger than the pagination cap can reach, or a presence/absence filter narrowed the result. Absent only when none applies."
},
"offset": {
"type": "number",
"description": "Current pagination offset."
},
"totalCount": {
"type": "number",
"description": "Total matching occurrences before pagination."
},
"occurrences": {
"type": "array",
"items": {
"type": "object",
"properties": {
"day": {
"type": "number",
"description": "Observation day. May be absent."
},
"key": {
"type": "number",
"description": "GBIF occurrence key for gbif_get_occurrence chaining."
},
"rank": {
"type": "string",
"description": "Taxonomic rank of the identified taxon."
},
"year": {
"type": "number",
"description": "Observation year. May be absent."
},
"month": {
"type": "number",
"description": "Observation month (1–12). May be absent."
},
"issues": {
"type": "array",
"items": {
"type": "string"
},
"description": "GBIF data quality issue flags for this record."
},
"country": {
"type": "string",
"description": "Country name. May be absent."
},
"locality": {
"type": "string",
"description": "Locality description. May be absent."
},
"taxonKey": {
"type": "number",
"description": "Backbone taxon key."
},
"eventDate": {
"type": "string",
"description": "Observation date as ISO 8601 string. May be absent."
},
"eventTime": {
"type": "string",
"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."
},
"datasetKey": {
"type": "string",
"description": "UUID of the source dataset."
},
"recordedBy": {
"type": "string",
"description": "Collector name(s). May be absent."
},
"countryCode": {
"type": "string",
"description": "ISO 3166-1 alpha-2 country code. May be absent."
},
"datasetName": {
"type": "string",
"description": "Name of the source dataset. May be absent."
},
"basisOfRecord": {
"type": "string",
"description": "How the occurrence was recorded."
},
"canonicalName": {
"type": "string",
"description": "Canonical name without authorship."
},
"catalogNumber": {
"type": "string",
"description": "Catalog number the holding collection assigned — the value the catalogNumber filter matches. May be absent."
},
"stateProvince": {
"type": "string",
"description": "State or province name. May be absent."
},
"scientificName": {
"type": "string",
"description": "Scientific name from occurrence record."
},
"decimalLatitude": {
"type": "number",
"description": "Latitude in decimal degrees (WGS84). May be absent."
},
"individualCount": {
"type": "number",
"description": "Number of individuals. May be absent."
},
"institutionCode": {
"type": "string",
"description": "Code of the institution holding the record — the value the institutionCode filter matches. May be absent."
},
"taxonomicStatus": {
"type": "string",
"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."
},
"decimalLongitude": {
"type": "number",
"description": "Longitude in decimal degrees (WGS84). May be absent."
},
"occurrenceStatus": {
"type": "string",
"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."
},
"publishingCountry": {
"type": "string",
"description": "Country code of the publishing organization."
},
"iucnRedListCategory": {
"type": "string",
"description": "IUCN Red List category of the taxon — CR, EN, VU, NT, LC, DD, EX, EW, or CD. May be absent."
},
"coordinateUncertaintyInMeters": {
"type": "number",
"description": "Coordinate uncertainty radius in meters. May be absent."
}
},
"description": "A single occurrence record with location, taxon, date, and provenance fields.",
"additionalProperties": false
},
"description": "Occurrence records matching the filters."
},
"endOfRecords": {
"type": "boolean",
"description": "True when there are no more results after this page."
},
"occurrenceStatus": {
"type": "string",
"description": "The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what totalCount and the returned records cover."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_count_occurrences — Count Occurrences
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, gadmGid, scientificName, spatial ranges and geometry (intersected), month, basisOfRecord, hasCoordinate (alias isGeoreferenced), isInCluster, coordinateUncertaintyInMeters, datasetKey, year, catalogNumber, institutionCode, recordedBy, mediaType, 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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"year": {
"type": "string",
"description": "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."
},
"month": {
"type": "integer",
"maximum": 12,
"minimum": 1,
"description": "Calendar month (1–12), matching the occurrence search filter."
},
"country": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"description": "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."
},
"gadmGid": {
"type": "string",
"description": "GADM administrative-area GID at any level: country (ESP), state or province (ESP.1_1), county or district (ESP.1.5_1), or municipality (ESP.1.6.3_1). GBIF derives a record's GIDs from its coordinates, so records without coordinates match none, and the unit can differ from the verbatim stateProvince the record carries. Matched exactly and case-sensitively, and a GID holds only uppercase letters, digits, dots, and underscores — any other character is rejected. Take one from a GADM_LEVEL_0_GID, GADM_LEVEL_1_GID, GADM_LEVEL_2_GID, or GADM_LEVEL_3_GID facet on gbif_occurrence_facets, or from the gadm field of gbif_get_occurrence; a well-formed GID GBIF does not hold matches zero records rather than erroring. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"geometry": {
"type": "string",
"description": "WKT polygon in longitude latitude order. All supplied spatial filters intersect: decimalLatitude and decimalLongitude remain active and restrict results to the overlap. Omit to leave geometry unfiltered; blank or whitespace-only is rejected."
},
"taxonKey": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "GBIF backbone taxon key from gbif_match_species. Matches the given taxon and all descendant taxa (subspecies, varieties, etc.)."
},
"mediaType": {
"enum": [
"StillImage",
"MovingImage",
"Sound",
"InteractiveResource"
],
"type": "string",
"description": "Only records carrying at least one media item of this type: StillImage (photographs, scans), MovingImage (video), Sound (audio), or InteractiveResource. Records without media are excluded when this is set."
},
"datasetKey": {
"type": "string",
"description": "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."
},
"recordedBy": {
"type": "string",
"description": "Collector or observer, matched against each name in the record's recordedBy list (GBIF splits it on \"|\") exactly and case-sensitively: \"Charles Darwin\" and \"charles darwin\" differ, and one person written two ways (\"Charles Darwin\", \"Darwin, C.\") is two values. Take a value from a RECORDED_BY facet on gbif_occurrence_facets scoped the same way and pass it back unchanged; an unmatched value matches zero records rather than erroring. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"isInCluster": {
"type": "boolean",
"description": "True counts likely duplicates; false excludes them. Omit to include all records. GBIF exposes membership only, with no cluster identifier."
},
"basisOfRecord": {
"enum": [
"HUMAN_OBSERVATION",
"MACHINE_OBSERVATION",
"PRESERVED_SPECIMEN",
"LIVING_SPECIMEN",
"MATERIAL_SAMPLE",
"MATERIAL_CITATION",
"OCCURRENCE",
"LITERATURE",
"FOSSIL_SPECIMEN",
"OBSERVATION",
"UNKNOWN"
],
"type": "string",
"description": "Filter by how the occurrence was recorded; accepts every GBIF BasisOfRecord vocabulary member."
},
"catalogNumber": {
"type": "string",
"description": "Catalog number a collection assigned to the specimen or record (e.g. \"L.1592880\"), matched as the whole value, case-insensitively. Not unique across collections — one number can name records in several datasets, so pair it with institutionCode or datasetKey to single one out. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"hasCoordinate": {
"type": "boolean",
"description": "True counts records with coordinates; false counts only records without coordinates. Omit for both. Alias isGeoreferenced may be supplied alone or with the same value; conflicts fail as invalid_filter."
},
"stateProvince": {
"type": "string",
"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. 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."
},
"scientificName": {
"type": "string",
"description": "Scientific name; does not match synonyms. With taxonKey GBIF takes their union (OR), not their intersection. Omit to leave names unfiltered; blank or whitespace-only is rejected."
},
"decimalLatitude": {
"type": "string",
"description": "Latitude or latitude range \"min,max\" in decimal degrees (WGS84). All supplied spatial filters intersect, including geometry. Omit to leave latitude unbounded; blank or whitespace-only is rejected."
},
"institutionCode": {
"type": "string",
"description": "Code of the institution holding the record (e.g. \"K\", \"CLO\"), matched as the whole value, case-insensitively — part of a code or of a multi-word code matches nothing. An INSTITUTION_CODE facet on gbif_occurrence_facets lists the codes in a scope, lowercased, and this filter takes them unchanged. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"isGeoreferenced": {
"type": "boolean",
"description": "Alias for hasCoordinate. True counts only georeferenced records; false only non-georeferenced records. Supplying both requires equal values."
},
"decimalLongitude": {
"type": "string",
"description": "Longitude or longitude range \"min,max\" in decimal degrees (WGS84). All supplied spatial filters intersect, including geometry. Omit to leave longitude unbounded; blank or whitespace-only is rejected."
},
"occurrenceStatus": {
"enum": [
"PRESENT",
"ABSENT",
"ANY"
],
"type": "string",
"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."
},
"publishingCountry": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 code, uppercase, of the organization that published the record — distinct from where the occurrence was observed, which is country. 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": {
"enum": [
"CR",
"EN",
"VU",
"NT",
"LC",
"DD",
"EX",
"EW",
"CD"
],
"type": "string",
"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."
},
"coordinateUncertaintyInMeters": {
"type": "string",
"description": "Coordinate uncertainty radius in meters, e.g. \"0,1000\"; range endpoints inclusive. Omit for any uncertainty; blank or whitespace-only is rejected."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"count",
"scope",
"occurrenceStatus"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"count": {
"type": "number",
"description": "Total occurrences matching the supplied filters."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_filter"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: A string filter other than country and publishingCountry was supplied blank or whitespace-only (a blank country or publishingCountry fails earlier, at its uppercase pattern, as -32602 invalid_arguments), hasCoordinate conflicts with isGeoreferenced, datasetKey is not an 8-4-4-4-12 hex UUID, gadmGid holds a character other than an uppercase letter, digit, dot, or underscore, 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."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"scope": {
"type": "object",
"description": "Effective supplied biological filters, with occurrenceStatus always included; excludes pagination and facet controls.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": [
"string",
"number",
"boolean"
]
}
},
"notice": {
"type": "string",
"description": "Guidance when the count is zero under an exact-match stateProvince, gadmGid, or recordedBy filter, larger than gbif_search_occurrences can page to, or narrowed by a presence/absence filter. Absent when none applies."
},
"occurrenceStatus": {
"type": "string",
"description": "The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what the count covers."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_get_occurrence — Get Occurrence Record
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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"occurrenceKey"
],
"properties": {
"occurrenceKey": {
"type": "integer",
"maximum": 9007199254740991,
"description": "GBIF occurrence key from gbif_search_occurrences results.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
}
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"day": {
"type": "number",
"description": "Observation day. May be absent."
},
"key": {
"type": "number",
"description": "GBIF occurrence key."
},
"sex": {
"type": "string",
"description": "Sex of the individual(s). May be absent."
},
"gadm": {
"type": "object",
"properties": {
"level0": {
"type": "object",
"properties": {
"gid": {
"type": "string",
"description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). Pass it as gadmGid to gbif_search_occurrences, gbif_count_occurrences, or gbif_occurrence_facets to filter on this unit. May be absent."
},
"name": {
"type": "string",
"description": "Administrative-unit name. May be absent."
}
},
"description": "GADM level 0 — country. May be absent.",
"additionalProperties": false
},
"level1": {
"type": "object",
"properties": {
"gid": {
"type": "string",
"description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). Pass it as gadmGid to gbif_search_occurrences, gbif_count_occurrences, or gbif_occurrence_facets to filter on this unit. May be absent."
},
"name": {
"type": "string",
"description": "Administrative-unit name. May be absent."
}
},
"description": "GADM level 1 — state/province. May be absent.",
"additionalProperties": false
},
"level2": {
"type": "object",
"properties": {
"gid": {
"type": "string",
"description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). Pass it as gadmGid to gbif_search_occurrences, gbif_count_occurrences, or gbif_occurrence_facets to filter on this unit. May be absent."
},
"name": {
"type": "string",
"description": "Administrative-unit name. May be absent."
}
},
"description": "GADM level 2 — county/district. May be absent.",
"additionalProperties": false
},
"level3": {
"type": "object",
"properties": {
"gid": {
"type": "string",
"description": "GADM GID — stable administrative-unit identifier (e.g. SWE, SWE.2_1). Pass it as gadmGid to gbif_search_occurrences, gbif_count_occurrences, or gbif_occurrence_facets to filter on this unit. May be absent."
},
"name": {
"type": "string",
"description": "Administrative-unit name. May be absent."
}
},
"description": "GADM level 3 — municipality/ward, the finest level GBIF indexes. Absent where the country does not subdivide that far.",
"additionalProperties": false
}
},
"description": "GADM administrative geography — stable GIDs and names at levels 0–3. May be absent.",
"additionalProperties": false
},
"year": {
"type": "number",
"description": "Observation year. May be absent."
},
"class": {
"type": "string",
"description": "Class classification. May be absent."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found"
],
"description": "Machine-readable failure mode. Declared by this tool: `not_found`: The occurrenceKey does not exist in GBIF. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"genus": {
"type": "string",
"description": "Genus classification."
},
"media": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Media type (StillImage, Sound, etc.)."
},
"title": {
"type": "string",
"description": "Media title."
},
"format": {
"type": "string",
"description": "MIME format of the media."
},
"license": {
"type": "string",
"description": "License for the media."
},
"identifier": {
"type": "string",
"description": "URL to the media file."
}
},
"description": "A media item (image, audio, video) associated with the occurrence.",
"additionalProperties": false
},
"description": "Associated media (images, audio, video). May be absent."
},
"month": {
"type": "number",
"description": "Observation month (1–12). May be absent."
},
"order": {
"type": "string",
"description": "Order classification."
},
"family": {
"type": "string",
"description": "Family classification."
},
"issues": {
"type": "array",
"items": {
"type": "string"
},
"description": "GBIF data quality issue flags."
},
"phylum": {
"type": "string",
"description": "Phylum classification."
},
"country": {
"type": "string",
"description": "Country name. May be absent."
},
"kingdom": {
"type": "string",
"description": "Kingdom classification."
},
"species": {
"type": "string",
"description": "Species canonical name."
},
"classKey": {
"type": "number",
"description": "Backbone taxon key for the class. May be absent."
},
"locality": {
"type": "string",
"description": "Locality description. May be absent."
},
"taxonKey": {
"type": "number",
"description": "Backbone taxon key."
},
"continent": {
"type": "string",
"description": "Continent name. May be absent."
},
"eventDate": {
"type": "string",
"description": "Observation date as ISO 8601 string. May be absent."
},
"eventTime": {
"type": "string",
"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."
},
"lifeStage": {
"type": "string",
"description": "Life stage of the individual(s). May be absent."
},
"taxonRank": {
"type": "string",
"description": "Taxonomic rank of the identified taxon."
},
"datasetKey": {
"type": "string",
"description": "UUID of the source dataset."
},
"recordedBy": {
"type": "string",
"description": "Collector name(s). May be absent."
},
"countryCode": {
"type": "string",
"description": "ISO 3166-1 alpha-2 country code. May be absent."
},
"identifiers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Identifier type (e.g. URL, DOI, GBIF_PORTAL). May be absent."
},
"identifier": {
"type": "string",
"description": "The identifier value. May be absent."
}
},
"description": "An alternative identifier for the occurrence record.",
"additionalProperties": false
},
"description": "Alternative record identifiers from the source. May be absent."
},
"identifiedBy": {
"type": "string",
"description": "Identifier name(s). May be absent."
},
"occurrenceID": {
"type": "string",
"description": "Darwin Core occurrenceID — the source record identifier, often a URL back to the origin record. May be absent."
},
"basisOfRecord": {
"type": "string",
"description": "How the occurrence was recorded."
},
"canonicalName": {
"type": "string",
"description": "Canonical name without authorship."
},
"catalogNumber": {
"type": "string",
"description": "Catalog number within the collection. May be absent."
},
"stateProvince": {
"type": "string",
"description": "State or province. May be absent."
},
"collectionCode": {
"type": "string",
"description": "Collection code within the institution. May be absent."
},
"scientificName": {
"type": "string",
"description": "Scientific name from occurrence record."
},
"decimalLatitude": {
"type": "number",
"description": "Latitude in decimal degrees (WGS84). May be absent."
},
"individualCount": {
"type": "number",
"description": "Number of individuals. May be absent."
},
"institutionCode": {
"type": "string",
"description": "Code of the contributing institution. May be absent."
},
"taxonomicStatus": {
"type": "string",
"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."
},
"decimalLongitude": {
"type": "number",
"description": "Longitude in decimal degrees (WGS84). May be absent."
},
"occurrenceStatus": {
"type": "string",
"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."
},
"publishingCountry": {
"type": "string",
"description": "Country code of the publishing organization."
},
"iucnRedListCategory": {
"type": "string",
"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."
},
"coordinateUncertaintyInMeters": {
"type": "number",
"description": "Coordinate uncertainty radius in meters. May be absent."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_occurrence_facets — Occurrence Facet Aggregation
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?". Key dimensions (KINGDOM_KEY through SPECIES_KEY, DATASET_KEY) return bare keys; includeLabels names the taxon or dataset behind each one on the page. Scope the aggregation with taxonKey, country (uppercase ISO 3166-1 alpha-2), publishingCountry, stateProvince, gadmGid, year, scientificName, latitude/longitude ranges, month, hasCoordinate, isInCluster, coordinateUncertaintyInMeters, geometry (all spatial filters intersect), basisOfRecord, datasetKey, catalogNumber, institutionCode, recordedBy, mediaType, 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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"facet"
],
"properties": {
"year": {
"type": "string",
"description": "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": {
"enum": [
"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",
"GADM_LEVEL_0_GID",
"GADM_LEVEL_1_GID",
"GADM_LEVEL_2_GID",
"GADM_LEVEL_3_GID",
"INSTITUTION_CODE",
"MEDIA_TYPE",
"RECORDED_BY"
],
"type": "string",
"description": "Dimension to aggregate by (e.g., COUNTRY, YEAR, BASIS_OF_RECORD, SPECIES_KEY, OCCURRENCE_STATUS, IUCN_RED_LIST_CATEGORY). DATASET_KEY is the first cut when a result set is too large to page: every occurrence carries exactly one datasetKey, so its buckets cover totalOccurrences with no gap or overlap. BASIS_OF_RECORD and PUBLISHING_COUNTRY are gap-free second cuts for a dataset bucket still too large; both have a matching filter on the occurrence tools. A dimension a record can lack drops that record from every bucket: YEAR loses undated records; MONTH, STATE_PROVINCE, SPECIES_KEY, INSTITUTION_CODE, MEDIA_TYPE, and RECORDED_BY lose records lacking that dimension; GADM_LEVEL_0_GID, GADM_LEVEL_1_GID, GADM_LEVEL_2_GID, and GADM_LEVEL_3_GID lose records without coordinates or outside every GADM unit at that level — each even where the occurrence tools can filter on it. MEDIA_TYPE and RECORDED_BY buckets also overlap: a record with two media types or two collectors counts in each, so their sums can exceed totalOccurrences. GADM buckets are GIDs to pass back as gadmGid; INSTITUTION_CODE buckets come back lowercased and institutionCode takes them unchanged; RECORDED_BY buckets are the exact spellings recordedBy matches. Sums are comparable only across the same occurrenceStatus scope."
},
"month": {
"type": "integer",
"maximum": 12,
"minimum": 1,
"description": "Calendar month (1–12), matching the occurrence search filter."
},
"country": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"description": "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."
},
"gadmGid": {
"type": "string",
"description": "GADM administrative-area GID at any level: country (ESP), state or province (ESP.1_1), county or district (ESP.1.5_1), or municipality (ESP.1.6.3_1). GBIF derives a record's GIDs from its coordinates, so records without coordinates match none, and the unit can differ from the verbatim stateProvince the record carries. Matched exactly and case-sensitively, and a GID holds only uppercase letters, digits, dots, and underscores — any other character is rejected. Take one from a GADM_LEVEL_0_GID, GADM_LEVEL_1_GID, GADM_LEVEL_2_GID, or GADM_LEVEL_3_GID facet on gbif_occurrence_facets, or from the gadm field of gbif_get_occurrence; a well-formed GID GBIF does not hold matches zero records rather than erroring. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"geometry": {
"type": "string",
"description": "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. All supplied spatial filters intersect: decimalLatitude and decimalLongitude remain active and restrict results to the overlap. 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": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Backbone taxon key to scope the aggregation. Matches the given taxon and all descendant taxa (subspecies, varieties, etc.)."
},
"mediaType": {
"enum": [
"StillImage",
"MovingImage",
"Sound",
"InteractiveResource"
],
"type": "string",
"description": "Only records carrying at least one media item of this type: StillImage (photographs, scans), MovingImage (video), Sound (audio), or InteractiveResource. Records without media are excluded when this is set."
},
"datasetKey": {
"type": "string",
"description": "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": {
"type": "integer",
"default": 10,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Maximum number of facet values to return (default 10, max 100)."
},
"recordedBy": {
"type": "string",
"description": "Collector or observer, matched against each name in the record's recordedBy list (GBIF splits it on \"|\") exactly and case-sensitively: \"Charles Darwin\" and \"charles darwin\" differ, and one person written two ways (\"Charles Darwin\", \"Darwin, C.\") is two values. Take a value from a RECORDED_BY facet on gbif_occurrence_facets scoped the same way and pass it back unchanged; an unmatched value matches zero records rather than erroring. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"facetOffset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 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, …)."
},
"isInCluster": {
"type": "boolean",
"description": "True includes likely duplicates; false excludes them. Omit to include all records. GBIF exposes membership only, with no cluster identifier."
},
"basisOfRecord": {
"enum": [
"HUMAN_OBSERVATION",
"MACHINE_OBSERVATION",
"PRESERVED_SPECIMEN",
"LIVING_SPECIMEN",
"MATERIAL_SAMPLE",
"MATERIAL_CITATION",
"OCCURRENCE",
"LITERATURE",
"FOSSIL_SPECIMEN",
"OBSERVATION",
"UNKNOWN"
],
"type": "string",
"description": "Scope to a specific basis of record."
},
"catalogNumber": {
"type": "string",
"description": "Catalog number a collection assigned to the specimen or record (e.g. \"L.1592880\"), matched as the whole value, case-insensitively. Not unique across collections — one number can name records in several datasets, so pair it with institutionCode or datasetKey to single one out. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"hasCoordinate": {
"type": "boolean",
"description": "True includes records with coordinates; false only records without coordinates. Omit for both."
},
"includeLabels": {
"type": "boolean",
"default": false,
"description": "True names the taxon or dataset behind each bucket on the returned page with a label: the canonicalName for a KINGDOM_KEY, PHYLUM_KEY, CLASS_KEY, ORDER_KEY, FAMILY_KEY, GENUS_KEY, or SPECIES_KEY bucket, the dataset title for a DATASET_KEY bucket. Costs one extra GBIF request per bucket, up to facetLimit, all bounded by one 10 s deadline; a bucket whose lookup fails or misses it comes back without a label and is counted in notice. Every other dimension ignores it. Leave it false when keys are enough, as when partitioning by DATASET_KEY."
},
"stateProvince": {
"type": "string",
"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. 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."
},
"scientificName": {
"type": "string",
"description": "Scientific name; does not match synonyms. With taxonKey GBIF takes their union (OR), not their intersection. Omit to leave names unfiltered; blank or whitespace-only is rejected."
},
"decimalLatitude": {
"type": "string",
"description": "Latitude or latitude range \"min,max\" in decimal degrees (WGS84). All supplied spatial filters intersect, including geometry. Omit to leave latitude unbounded; blank or whitespace-only is rejected."
},
"institutionCode": {
"type": "string",
"description": "Code of the institution holding the record (e.g. \"K\", \"CLO\"), matched as the whole value, case-insensitively — part of a code or of a multi-word code matches nothing. An INSTITUTION_CODE facet on gbif_occurrence_facets lists the codes in a scope, lowercased, and this filter takes them unchanged. Omit the field to leave it unfiltered — a blank or whitespace-only value is rejected rather than dropped, because GBIF answers one with the unfiltered scope."
},
"decimalLongitude": {
"type": "string",
"description": "Longitude or longitude range \"min,max\" in decimal degrees (WGS84). All supplied spatial filters intersect, including geometry. Omit to leave longitude unbounded; blank or whitespace-only is rejected."
},
"occurrenceStatus": {
"enum": [
"PRESENT",
"ABSENT",
"ANY"
],
"type": "string",
"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."
},
"publishingCountry": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"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."
},
"iucnRedListCategory": {
"enum": [
"CR",
"EN",
"VU",
"NT",
"LC",
"DD",
"EX",
"EW",
"CD"
],
"type": "string",
"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."
},
"coordinateUncertaintyInMeters": {
"type": "string",
"description": "Coordinate uncertainty radius in meters, e.g. \"0,1000\"; range endpoints inclusive. Omit for any uncertainty; blank or whitespace-only is rejected."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"facet",
"totalOccurrences",
"counts",
"scope",
"facetLimit",
"facetOffset",
"occurrenceStatus"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"cap": {
"type": "number",
"description": "facetLimit applied when the page was capped. Re-call with facetOffset advanced by this value to page on. Absent otherwise."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_filter"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: A string scope filter other than country and publishingCountry was supplied blank or whitespace-only (a blank country or publishingCountry fails earlier, at its uppercase pattern, as -32602 invalid_arguments), datasetKey is not an 8-4-4-4-12 hex UUID, gadmGid holds a character other than an uppercase letter, digit, dot, or underscore, a two-letter country or publishingCountry code is one GBIF does not know, or GBIF rejected another filter as malformed. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"facet": {
"type": "string",
"description": "The facet dimension aggregated."
},
"scope": {
"type": "object",
"description": "Effective supplied biological filters, with occurrenceStatus always included; excludes pagination and facet controls.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": [
"string",
"number",
"boolean"
]
}
},
"shown": {
"type": "number",
"description": "Facet values returned in this page when the page was capped. Absent otherwise."
},
"counts": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"count"
],
"properties": {
"name": {
"type": "string",
"description": "Facet value (country code, year, basisOfRecord, etc.)."
},
"count": {
"type": "number",
"description": "Occurrence count for this facet value."
},
"label": {
"type": "string",
"description": "Name of the taxon (its canonicalName) or dataset (its title) the key identifies. Present only with includeLabels on a KINGDOM_KEY through SPECIES_KEY or DATASET_KEY facet, and only when the lookup for this bucket succeeded."
}
},
"description": "A facet value with its occurrence count.",
"additionalProperties": false
},
"description": "Facet values ranked by count descending — one page of up to facetLimit entries starting at facetOffset, not necessarily the top ones."
},
"notice": {
"type": "string",
"description": "Guidance when no facet values were returned, a read limit was clamped, a lookahead bucket proves more remain, includeLabels left buckets without a label, an exact-match stateProvince, gadmGid, or recordedBy filter matched nothing, or a presence/absence filter narrowed the aggregation. Absent only when none applies."
},
"truncated": {
"type": "boolean",
"description": "Present and true only when an extra upstream bucket proves another page exists. Absent on the final page, including an exactly full final page."
},
"facetLimit": {
"type": "number",
"description": "Maximum facet values requested."
},
"facetOffset": {
"type": "number",
"description": "Zero-based offset applied to the ranked facet values."
},
"occurrenceStatus": {
"type": "string",
"description": "The presence/absence filter applied upstream — PRESENT, ABSENT, or ANY when no filter was sent. Says what totalOccurrences and every bucket cover."
},
"totalOccurrences": {
"type": "number",
"description": "Total matching occurrences across all facet values."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_search_datasets — Search Datasets
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, DOI, and the publishing organization's key and name; the key goes back in as publishingOrg. 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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"description": "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 every indexed dataset and a whitespace-only one with none, and neither is the search a caller who filled the field was asking for."
},
"type": {
"enum": [
"OCCURRENCE",
"CHECKLIST",
"METADATA",
"SAMPLING_EVENT"
],
"type": "string",
"description": "Filter by dataset type. OCCURRENCE for observation records, CHECKLIST for species lists."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Number of datasets to return (default 20, max 1000)."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset."
},
"hostingOrg": {
"type": "string",
"description": "UUID (8-4-4-4-12 hex, lowercase — matched case-sensitively, as publishingOrg is) of the organization whose installation serves the dataset — distinct from 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. Supplied together the two filters are intersected, not combined."
},
"publishingOrg": {
"type": "string",
"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. The organization that serves it is hostingOrg, which matches a different set. 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": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"description": "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."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"datasets",
"totalCount",
"offset",
"limit",
"endOfRecords"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_filter"
],
"description": "Machine-readable failure mode. Declared by this tool: `invalid_filter`: A string filter other than publishingCountry was supplied blank or whitespace-only (a blank publishingCountry fails earlier, at its uppercase pattern, as -32602 invalid_arguments), 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."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"limit": {
"type": "number",
"description": "Datasets returned in this page."
},
"notice": {
"type": "string",
"description": "Guidance when results are empty, paging overshot, or an oversized read limit was clamped. Absent when none applies."
},
"offset": {
"type": "number",
"description": "Current pagination offset."
},
"datasets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"doi": {
"type": "string",
"description": "DOI for citation. May be absent."
},
"key": {
"type": "string",
"description": "Dataset UUID for gbif_get_dataset chaining."
},
"type": {
"type": "string",
"description": "Dataset type (OCCURRENCE, CHECKLIST, etc.)."
},
"title": {
"type": "string",
"description": "Dataset title."
},
"license": {
"type": "string",
"description": "License identifier. May be absent."
},
"description": {
"type": "string",
"description": "Brief description, truncated to a 300-character preview. May be absent."
},
"recordCount": {
"type": "number",
"description": "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."
},
"publishingCountry": {
"type": "string",
"description": "Country code of the publisher."
},
"descriptionTruncated": {
"type": "boolean",
"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."
},
"publishingOrganizationKey": {
"type": "string",
"description": "UUID of the organization that published the dataset. Pass it back to gbif_search_datasets as publishingOrg for every dataset this organization published. Absent when GBIF omits it."
},
"publishingOrganizationTitle": {
"type": "string",
"description": "Name of the organization that published the dataset, as GBIF records it. Absent when GBIF omits it."
}
},
"description": "A GBIF dataset with key, title, type, license, and record count.",
"additionalProperties": false
},
"description": "Matching datasets."
},
"totalCount": {
"type": "number",
"description": "Total matching datasets before pagination."
},
"endOfRecords": {
"type": "boolean",
"description": "True when there are no more results after this page."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_get_dataset — Get Dataset
Fetch full dataset metadata by UUID key — title, description, citation text, contacts, license, DOI, record count, numConstituents (sub-datasets), temporal/geographic coverage, and the publishing organization key, which gbif_search_datasets takes as publishingOrg. 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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"datasetKey"
],
"properties": {
"datasetKey": {
"type": "string",
"description": "Dataset UUID (8-4-4-4-12 hex) from gbif_search_datasets or an occurrence record."
},
"contactLimit": {
"type": "integer",
"default": 10,
"maximum": 9007199254740991,
"minimum": 0,
"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."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
}
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"cap": {
"type": "number",
"description": "contactLimit applied when the list was capped. Raise it (max 100) to see more. Absent otherwise."
},
"doi": {
"type": "string",
"description": "DOI for citation. May be absent."
},
"key": {
"type": "string",
"description": "Dataset UUID."
},
"type": {
"type": "string",
"description": "Dataset type (OCCURRENCE, CHECKLIST, etc.)."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"not_found",
"invalid_filter"
],
"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."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"shown": {
"type": "number",
"description": "Contacts included in this response when the list was capped. Absent otherwise."
},
"title": {
"type": "string",
"description": "Dataset title."
},
"notice": {
"type": "string",
"description": "How to reach contacts held back, or requested/applied values when contactLimit was clamped. Absent when neither applies."
},
"license": {
"type": "string",
"description": "License identifier. May be absent."
},
"contacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Contact type (e.g., ADMINISTRATIVE_POINT_OF_CONTACT)."
},
"email": {
"type": "array",
"items": {
"type": "string"
},
"description": "Contact email addresses. May be absent."
},
"lastName": {
"type": "string",
"description": "Last name. May be absent."
},
"firstName": {
"type": "string",
"description": "First name. May be absent."
},
"organization": {
"type": "string",
"description": "Organization name. May be absent."
}
},
"description": "A dataset contact with role, name, organization, and email.",
"additionalProperties": false
},
"description": "Dataset contacts, capped at contactLimit. Absent when the dataset has no contacts or contactLimit is 0."
},
"truncated": {
"type": "boolean",
"description": "True when the dataset carries more contacts than contactLimit allowed through. Absent when every contact was returned."
},
"description": {
"type": "string",
"description": "Full dataset description. May be absent."
},
"recordCount": {
"type": "number",
"description": "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": {
"type": "string",
"description": "Full citation text for academic reference. May be absent."
},
"contactsTotal": {
"type": "number",
"description": "Total contacts on the dataset before applying contactLimit. Present when the dataset has any contacts."
},
"numConstituents": {
"type": "number",
"description": "Number of constituent sub-datasets. May be absent."
},
"contactsReturned": {
"type": "number",
"description": "Number of contacts included in this response (≤ contactLimit). Present when the dataset has any contacts."
},
"publishingCountry": {
"type": "string",
"description": "Country code of the publishing organization."
},
"recordCountNotice": {
"type": "string",
"description": "Explains an unavailable supplementary count and how to retry. Absent after a successful lookup or a declared count."
},
"temporalCoverages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"end": {
"type": "string",
"description": "Coverage end as an ISO 8601 date-time. May be absent."
},
"date": {
"type": "string",
"description": "Single coverage date as supplied by GBIF. May be absent."
},
"type": {
"type": "string",
"description": "Verbatim period type. May be absent."
},
"@type": {
"type": "string",
"description": "GBIF coverage representation: range, single, or verbatim. May be absent on legacy ranges."
},
"start": {
"type": "string",
"description": "Coverage start as an ISO 8601 date-time. May be absent."
},
"period": {
"type": "string",
"description": "Verbatim coverage period. May be absent."
}
},
"description": "A temporal coverage range, single date, or verbatim period.",
"additionalProperties": false
},
"description": "Temporal coverage declared by the dataset, preserving supplied dates and verbatim periods. May be absent."
},
"geographicCoverages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {
"type": "string",
"description": "Geographic coverage description (e.g. \"Worldwide\"). May be absent."
}
},
"description": "A geographic coverage entry.",
"additionalProperties": false
},
"description": "Geographic coverage descriptions declared by the dataset. May be absent."
},
"temporalCoverageNotice": {
"type": "string",
"description": "Discloses unsupported or unusable temporal entries omitted from the response. May be absent."
},
"publishingOrganizationKey": {
"type": "string",
"description": "UUID of the organization that published the dataset. Pass it to gbif_search_datasets as publishingOrg for every dataset this organization published; gbif_search_datasets rows also carry the organization's name. Absent when GBIF omits it."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}gbif_search_publishers — Search Publishers
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.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"description": "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 every registered organization."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 9007199254740991,
"minimum": 1,
"description": "Number of organizations to return (default 20, max 1000)."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset."
},
"country": {
"type": "string",
"description": "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 every registered organization."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"publishers",
"totalCount",
"offset",
"limit",
"endOfRecords"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"invalid_filter"
],
"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."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"limit": {
"type": "number",
"description": "Organizations returned in this page."
},
"notice": {
"type": "string",
"description": "Guidance when results are empty, paging overshot, or an oversized read limit was clamped. Absent when none applies."
},
"offset": {
"type": "number",
"description": "Current pagination offset."
},
"publishers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "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."
},
"city": {
"type": "string",
"description": "City. May be absent."
},
"title": {
"type": "string",
"description": "Organization name."
},
"country": {
"type": "string",
"description": "ISO 3166-1 alpha-2 country code."
}
},
"description": "A GBIF-registered publishing organization.",
"additionalProperties": false
},
"description": "Matching organizations."
},
"totalCount": {
"type": "number",
"description": "Total matching organizations before pagination."
},
"endOfRecords": {
"type": "boolean",
"description": "True when there are no more results after this page."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true
}Prompts
0 advertised
Resources
1 advertised
gbif-biodiversity-guide
Use with gbif_* tools to map where and when a taxon was recorded, list the species of a group in a region, reconcile a name list, or trace records to collections, datasets, and publishers. Covers where each key comes from, which region filter selects which records, and the checks to run before quoting a count, a trend, or an absence.
skill://gbif-biodiversity-guide/SKILL.mdgbif-species — GBIF Species Record
Taxon record from the GBIF backbone — classification, authorship, synonymy status, vernacular name. Stable URI for caching and injection as context.
gbif://species/{taxonKey}gbif-dataset — GBIF Dataset
Dataset metadata — title, description, citation, license, contacts, coverage, and the publishing organization key that gbif_search_datasets takes as publishingOrg. Stable URI for provenance context. Use the dataset UUID from gbif_search_datasets or an occurrence record's datasetKey field.
gbif://dataset/{datasetKey}io.modelcontextprotocol/skills
skill://{+path}90-day uptime
A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.
- 2026-11-07: 1 of 1 checks answered
- 2026-11-09: 1 of 1 checks answered
30-day availability
Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.
- Successful checks
- 1 of 1 (100%)
- Average latency
- 674 ms
- 95th percentile latency
- 674 ms
Maintenance history
Public check and source-refresh events. Editorial and ownership records remain private.
- · probe · passed · 674 ms · metadata changed · 13 tool(s), 1 resource(s), 3 resource template(s), 0 prompt(s)
Connect from your client
Each snippet registers the same endpoint; pick the client you use.
Claude Code
claude mcp add --transport http gbif-biodiversity-mcp-server-caseyjhand https://gbif-biodiversity.caseyjhand.com/mcpCodex
codex mcp add gbif-biodiversity-mcp-server-caseyjhand --url https://gbif-biodiversity.caseyjhand.com/mcpCursor
{
"mcpServers": {
"gbif-biodiversity-mcp-server-caseyjhand": {
"url": "https://gbif-biodiversity.caseyjhand.com/mcp"
}
}
}Cline
{
"mcpServers": {
"gbif-biodiversity-mcp-server-caseyjhand": {
"type": "streamableHttp",
"url": "https://gbif-biodiversity.caseyjhand.com/mcp",
"disabled": false
}
}
}VS Code
{
"servers": {
"gbif-biodiversity-mcp-server-caseyjhand": {
"type": "http",
"url": "https://gbif-biodiversity.caseyjhand.com/mcp"
}
}
}Gemini CLI
gemini mcp add --transport http gbif-biodiversity-mcp-server-caseyjhand https://gbif-biodiversity.caseyjhand.com/mcpClaude Desktop
https://gbif-biodiversity.caseyjhand.com/mcpWindsurf
{
"mcpServers": {
"gbif-biodiversity-mcp-server-caseyjhand": {
"serverUrl": "https://gbif-biodiversity.caseyjhand.com/mcp"
}
}
}Let your agent find its tools
Find servers like gbif-biodiversity-mcp-server from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.