Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Search GBIF species taxonomy, occurrence records, datasets, and publishers.

README.md

<div align="center"> <h1>@cyanheads/gbif-biodiversity-mcp-server</h1> <p><b>Search GBIF species taxonomy, occurrence records, datasets, and publishers via MCP. STDIO or Streamable HTTP.</b> <div>13 Tools • 2 Resources</div> </p> </div>

<div align="center">

![Version](./CHANGELOG.md) ![License](./LICENSE) ![Docker](https://github.com/users/cyanheads/packages/container/package/gbif-biodiversity-mcp-server) ![MCP SDK](https://modelcontextprotocol.io/) ![npm](https://www.npmjs.com/package/@cyanheads/gbif-biodiversity-mcp-server) ![TypeScript](https://www.typescriptlang.org/) ![Bun](https://bun.sh/)

</div>

<div align="center">

![Install in Claude Desktop](https://github.com/cyanheads/gbif-biodiversity-mcp-server/releases/latest/download/gbif-biodiversity-mcp-server.mcpb) ![Install in Cursor](https://cursor.com/en/install-mcp?name=gbif-biodiversity-mcp-server&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjeWFuaGVhZHMvZ2JpZi1iaW9kaXZlcnNpdHktbWNwLXNlcnZlciJdfQ==) ![Install in VS Code](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22gbif-biodiversity-mcp-server%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40cyanheads%2Fgbif-biodiversity-mcp-server%22%5D%7D)

![Framework](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)

Public Hosted Server: https://gbif-biodiversity.caseyjhand.com/mcp

</div>

---

Tools

13 tools for working with GBIF species taxonomy, occurrence records, datasets, and publishers:

| Tool | Description | |:---|:---| | gbif_match_species | Match a species name against the GBIF backbone taxonomy — returns taxonKey, confidence score, and full classification | | gbif_bulk_match_species | Match up to 50 scientific names to backbone taxon keys in one call — results in input order, per-name NONE/ERROR isolation | | gbif_get_species | Fetch a single backbone taxon by key — full classification, authorship, synonymy, vernacular name, descendant count | | gbif_search_species | Search or browse the GBIF backbone taxonomy by name fragment, rank, kingdom, family, or genus | | gbif_get_species_classification | Return the root-to-parent classification chain for a taxon — root-first ordered array from kingdom to the queried taxon's immediate parent (the taxon itself is not included) | | gbif_get_species_children | List direct children of a backbone taxon — genera within a family, species within a genus | | gbif_search_occurrences | Search 2.4B+ GBIF occurrence records with Darwin Core filters — country, bounding box, WKT geometry, year, month, basis of record | | gbif_count_occurrences | Count occurrences matching a filter without fetching records — fast single-number response | | gbif_get_occurrence | Fetch a single occurrence record by key — full Darwin Core record with GADM geography, media, and quality flags | | gbif_occurrence_facets | Aggregate occurrence counts by a dimension — country, year, basis of record, dataset, kingdom, and more | | gbif_search_datasets | Search GBIF datasets by keyword, type, country, or publishing organization | | gbif_get_dataset | Fetch full dataset metadata by UUID — title, description, citation, contacts, license, DOI, coverage | | gbif_search_publishers | Search GBIF-registered publishing organizations by name fragment or country |

gbif_match_species

Match a scientific or common name against the GBIF backbone taxonomy.

  • Fuzzy matching handles minor typos and vernacular names; set strict: true for exact-only matching
  • Returns taxonKey — the backbone key required by gbif_search_occurrences, gbif_count_occurrences, and gbif_occurrence_facets
  • Confidence score 0–100; below 80 warrants review
  • Full classification hierarchy with keys at each rank: kingdom, phylum, class, order, family, genus, species
  • matchType NONE indicates no usable match — try removing strict mode or broadening the name
  • Resolves synonyms: always returns the accepted backbone key regardless of which name form was queried

---

gbif_bulk_match_species

Match up to 50 scientific names against the GBIF backbone taxonomy in a single call.

  • The batch counterpart to gbif_match_species — built for checklist, inventory, and species-list workflows that would otherwise need one round trip per name
  • Returns one result per input name, in input order; each carries taxonKey, matchType, and confidence
  • Per-name isolation: an unmatched name yields matchType NONE and a per-name lookup failure yields matchType ERROR — neither sinks the rest of the batch
  • strict: true requires an exact match for every name; common names are not supported (use gbif_search_species)

---

gbif_get_species

Fetch a complete taxon record by GBIF backbone key.

  • Full classification, authorship string, and vernacular (English) name when available
  • taxonomicStatus: ACCEPTED, SYNONYM, DOUBTFUL — when SYNONYM, acceptedKey and accepted identify the current name
  • numDescendants and numOccurrences for scope at a glance
  • extinct field present only when explicitly flagged — not false on unlabeled taxa
  • publishedIn carries the original description citation when available

---

gbif_search_species

Search or browse the GBIF backbone taxonomy.

  • Accepts name fragments matching scientific and vernacular names
  • Filter by rank, kingdom, family, or genus to scope browsing
  • isExtinct filter for extinct vs. extant taxa
  • Scope to a specific checklist dataset with datasetKey (omit for the GBIF backbone)
  • Paginated — limit up to 1000, use offset to walk through large groups

---

gbif_get_species_classification

Return the root-to-parent classification chain for a taxon as an ordered array.

  • Root-first from kingdom down to the immediate parent of the queried taxon (kingdom → phylum → class → … → parent)
  • The queried taxon itself is not included — use gbif_get_species for its own record
  • Each entry: rank, canonical name, scientific name, taxon key
  • Useful for building taxonomic trees or placing an unfamiliar taxon in context without manual backbone navigation

---

gbif_get_species_children

List direct children of a backbone taxon.

  • Genera within a family, species within a genus, subspecies within a species
  • Each child: key, name, rank, taxonomic status, common name, occurrence count, descendant count
  • Paginated — limit up to 1000, iterate with offset for large groups like Coleoptera

---

gbif_search_occurrences

Search 2.4B+ GBIF occurrence records with full Darwin Core filtering.

  • Use taxonKey from gbif_match_species for reliable results — resolves synonyms automatically; scientificName filter does not
  • Geographic filters: country (ISO 3166-1 alpha-2), bounding box (decimalLatitude/decimalLongitude ranges as "min,max"), or WKT polygon (geometry)
  • Temporal filters: year as single year or range, month (1–12) for seasonal queries
  • basisOfRecord enum: HUMAN_OBSERVATION, PRESERVED_SPECIMEN, MACHINE_OBSERVATION, and more
  • hasCoordinate to require or exclude georeferenced records
  • Pagination capped at offset+limit ≈ 100,000 — use gbif_occurrence_facets for aggregate analysis beyond this

---

gbif_count_occurrences

Count occurrences matching a filter without fetching any records.

  • Backed by the lightweight /occurrence/count endpoint — fast single-number response
  • Supported filters: taxonKey, country, isGeoreferenced, datasetKey, year
  • Use to assess result set size before deciding whether to paginate a full search

---

gbif_get_occurrence

Fetch a single occurrence record by GBIF occurrence key.

  • Complete Darwin Core record — all coordinate fields, administrative geography (continent, country, state/province, locality), dates
  • occurrenceID, full classification (class/classKey), GADM administrative units (levels 0–2, each with a stable GID and name), and source identifiers
  • Collections metadata: institution code, collection code, catalog number
  • Collector and identifier names, individual count, sex, life stage
  • Associated media (images, audio, video) with URLs and license
  • GBIF data quality issue flags for provenance assessment

---

gbif_occurrence_facets

Aggregate occurrence counts across a dimension.

  • Facets: COUNTRY, YEAR, BASIS_OF_RECORD, DATASET_KEY, KINGDOM_KEY, PHYLUM_KEY, CLASS_KEY, ORDER_KEY, FAMILY_KEY, GENUS_KEY, SPECIES_KEY, PUBLISHING_COUNTRY, MONTH
  • Scope with taxonKey, country, year, geometry, or basisOfRecord filters
  • Returns top-N values ranked by count (up to facetLimit, max 100) — no record payloads
  • Page past the first facetLimit with facetOffset (advance by facetLimit per page) to walk high-cardinality facets like DATASET_KEY; enrichment echoes the applied facetOffset and sets moreValuesLikely when a full page suggests more values remain
  • Core tool for distribution analysis ("which countries have the most records?") and trend queries ("how has observation volume changed since 2010?")

---

gbif_search_datasets

Search GBIF datasets by keyword, type, country, or publishing organization.

  • Filters: free-text query, dataset type (OCCURRENCE, CHECKLIST, METADATA, SAMPLING_EVENT), publishing country, hosting organization UUID
  • Returns title, type, description, license, DOI, and record count. The description is a 300-character preview — descriptionTruncated flags when it was shortened, and gbif_get_dataset returns the full text
  • Use hostingOrg from gbif_search_publishers to scope to datasets from one organization
  • Paginated — limit up to 1000

---

gbif_get_dataset

Fetch full dataset metadata by UUID.

  • Full description, citation text (for academic reference), license, DOI
  • Contacts with role, name, organization, and email
  • Temporal and geographic coverage ranges when the publisher declares them
  • numConstituents for aggregate datasets (e.g. iNaturalist, eBird)
  • Use after gbif_search_datasets or when an occurrence record's datasetKey needs provenance detail

---

gbif_search_publishers

Search organizations registered with GBIF.

  • Filter by name fragment or country
  • Returns organization key, title, and country — sufficient to chain into gbif_search_datasets with hostingOrg
  • Paginated — limit up to 1000

Resources

| Type | Name | Description | |:---|:---|:---| | Resource | gbif://species/{taxonKey} | Taxon record from the GBIF backbone — classification, authorship, synonymy status, vernacular name | | Resource | gbif://dataset/{datasetKey} | Dataset metadata — title, description, citation, license, contacts, coverage |

Features

Built on @cyanheads/mcp-ts-core:

  • Declarative tool definitions — single file per tool, framework handles registration and validation
  • Unified error handling across all tools
  • Pluggable auth (none, jwt, oauth)
  • Swappable storage backends: in-memory, filesystem, Supabase, Cloudflare KV/R2/D1
  • Structured logging with optional OpenTelemetry tracing
  • Runs locally (stdio/HTTP) or on Cloudflare Workers from the same codebase

GBIF-specific:

  • Full GBIF REST API v1 coverage: species taxonomy, occurrences, datasets, and publishers
  • gbif_match_species as the entry point — resolves synonyms to backbone taxon keys used throughout
  • Occurrence pagination cap detection with paginationNote — redirects to facet aggregation before hitting the ~100,000 row limit
  • WKT polygon geometry support for geographic occurrence queries
  • Darwin Core field mapping with explicit provenance on sparse upstream fields

Agent-friendly output:

  • gbif_match_species is the mandatory first step — all downstream tools document which key they expect
  • Graceful sparse-field handling — optional fields absent from the API response are omitted rather than null-filled
  • Discriminated error contracts with typed reasons, structured recovery hints, and when documentation per tool

Getting started

Self-Hosted / Local

Add the following to your MCP client configuration file.

{
  "mcpServers": {
    "gbif-biodiversity-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/gbif-biodiversity-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "gbif-biodiversity-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/gbif-biodiversity-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "gbif-biodiversity-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/gbif-biodiversity-mcp-server:latest"]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

Installation

  1. Clone the repository:
git clone https://github.com/cyanheads/gbif-biodiversity-mcp-server.git
  1. Navigate into the directory:
cd gbif-biodiversity-mcp-server
  1. Install dependencies:
bun install

Configuration

All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:

| Variable | Description | Default | |:---|:---|:---| | MCP_TRANSPORT_TYPE | Transport: stdio or http | stdio | | MCP_HTTP_PORT | HTTP server port | 3010 | | MCP_HTTP_ENDPOINT_PATH | HTTP endpoint path where the MCP server is mounted | /mcp | | MCP_PUBLIC_URL | Public origin override for TLS-terminating reverse-proxy deployments | none | | MCP_AUTH_MODE | Authentication: none, jwt, or oauth | none | | MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.) | info | | MCP_GC_PRESSURE_INTERVAL_MS | Opt-in Bun-only forced-GC pressure loop (ms). Try 60000 if RSS grows under sustained HTTP load. | 0 (disabled) | | LOGS_DIR | Directory for log files (Node.js only) | <project-root>/logs | | STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1 | in-memory | | GBIF_BASE_URL | GBIF API base URL override | https://api.gbif.org/v1 | | GBIF_REQUEST_TIMEOUT_MS | HTTP request timeout in milliseconds | 10000 | | OTEL_ENABLED | Enable OpenTelemetry | false |

Running the server

Local development

  • Build and run the production version:
  # One-time build
  bun run rebuild

  # Run the built server
  bun run start:http
  # or
  bun run start:stdio
  • Run checks and tests:
  bun run devcheck  # Lints, formats, type-checks, and more
  bun run test      # Runs the test suite

Project structure

| Directory | Purpose | |:---|:---| | src/mcp-server/tools | Tool definitions (*.tool.ts). Thirteen tools across species taxonomy, occurrences, datasets, and publishers. | | src/mcp-server/resources | Resource definitions. Species and dataset stable-URI resources. | | src/services/gbif | GBIF REST API service layer — client, request handling, type definitions. | | src/config | Server-specific environment variable parsing and validation with Zod. | | tests/ | Unit and integration tests, mirroring the src/ structure. |

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for logging, ctx.state for storage
  • Register new tools and resources in the createApp() arrays

Contributing

Issues and pull requests are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

This project is licensed under the Apache 2.0 License. See the LICENSE file for details.

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Search servers.