
Gbif Mcp Server
io.github.cyanheads由 GitHub 帳號 cyanheads 發布v0.1.7更新於 Nov 2, 2026
Search GBIF species taxonomy, occurrence records, datasets, and publishers.
概覽
檢索 GBIF 生物多樣性資料:物種分類、出現紀錄、資料集與發布機構,提供 13 個工具與 2 個資源。
- 可以做什麼
- 將學名比對到 GBIF 骨幹分類,支援單筆或批次,並讀取分類單元紀錄、分類鏈與下層分類單元
- 依分類單元、地點、日期、紀錄類型、有無紀錄與 IUCN 類別搜尋、計數並分面統計出現紀錄,取得完整 Darwin Core 紀錄
- 搜尋資料集與發布機構,讀取資料集中繼資料,如引用、授權、DOI、聯絡人與涵蓋範圍
- 以 MCP 資源形式讀取物種與資料集紀錄
- 適用情境
- 適合需要權威生物多樣性資料的情境:解析物種名稱、查詢某物種在何地何時被記錄,或引用這些紀錄背後的資料集與發布機構。
- 執行需求
- 可使用公開託管的 Streamable HTTP 端點,或透過 bunx、npx、Docker 在本機執行;需要 Bun v1.4.0 以上或 Node.js v24 以上。GBIF 介面公開,無需憑證。GBIF_API_KEY 為選用,可提高速率上限;GBIF_USER_AGENT 可用來標示你的整合。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Gbif Mcp Server,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。
交給代理程式安裝
把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。
閱讀 https://sourceweft.com/mcp/io.github.cyanheads%2Fgbif-mcp-server/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。其他 MCP 客戶端
把它新增到你客戶端的 mcpServers 設定中。
{
"mcpServers": {
"gbif": {
"type": "http",
"url": "https://gbif.caseyjhand.com/mcp"
}
}
}README
@cyanheads/gbif-biodiversity-mcp-server
Search GBIF species taxonomy, occurrence records, datasets, and publishers via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://gbif-biodiversity.caseyjhand.com/mcp
Overview
Species taxonomy, occurrence records, datasets, and publishers from the Global Biodiversity Information Facility (GBIF). Match names to the backbone taxonomy, search and aggregate 3.9B+ occurrence records with Darwin Core filters, and trace records back to their datasets and publishers.
Tools
Resources
Both resources are also reachable via gbif_get_species and gbif_get_dataset; many MCP clients are tool-only and never surface resources.
Skills
Capability reference
gbif_match_species tool
- One scientific
name(common names go togbif_search_species), with optionalstrict, akingdomto disambiguate, and an expectedrank - Returns
taxonKey, the accepted taxon to pass to the occurrence tools, plusmatchedTaxonKeywhen a synonym was resolved,matchType(EXACT,FUZZY, orHIGHERRANK: a match at a higher rank, such as a misspelled species falling back to its genus or kingdom, wheretaxonKeycovers that whole taxon, or its accepted taxon when the taxon GBIF fell back to is a synonym, and anoticenames it),confidence0–100 (review below 80; aHIGHERRANKmatch can score above 90), and the classification with a key at each rank matchTypeNONEfails asno_match, carrying GBIF's note when it gives one (for several equal matches, setkingdom); a blankkingdomfails asinvalid_filter
gbif_bulk_match_species tool
- Scientific
nameswithstrict; the first 50 are processed in input order. With read-limit clamping enabled (default), extra names are returned inunprocessedNames, preserving order and duplicates for the next call - Each result carries
nameandmatchType, and on a matchtaxonKey,matchedTaxonKey(synonyms), andconfidence; aHIGHERRANKrow carries anotenaming the higher taxon GBIF matched and what itstaxonKeycovers: that taxon, or its accepted taxon when it is a synonym. An unmatched name isNONE, with GBIF's explanation innotewhen it gives one (such as several equal matches for a name shared across kingdoms); a failed lookup isERRORwitherrorand, when classified,reason, and neither fails the batch
gbif_get_species tool
- One backbone
taxonKey, a non-negative integer (0is the backbone kingdom incertae sedis); a key not in the backbone fails asnot_found, one past the 32-bit range asinvalid_filter, and a fraction or negative key fails at the schema - Returns the classification with rank keys,
authorship,vernacularName,numDescendants,publishedIn, andparentKey; ataxonomicStatusofSYNONYMcomes withacceptedKeyandaccepted. GBIF's taxon record carries no occurrence count: usegbif_count_occurrences
gbif_search_species tool
qname fragment (scientific and vernacular),rank,isExtinct, and a checklistdatasetKey(omit for the backbone); up to 1,000 per page with integerlimitandoffset- Taxa carry the checklist usage
key, optional sourcedatasetKeyand mapped backbonenubKey,rank,taxonomicStatus, classification names,vernacularName(GBIF's own, else the first English vernacular name containingqwhenqis not part of the row's own scientific name, else the first English one), andnumDescendants.numOccurrencesappears only when GBIF supplies a positive value; its species search sends a0placeholder on every row, so count withgbif_count_occurrencesonnubKeyor aSPECIES_KEYfacet. Enrichment reportstotalCount,endOfRecords, and thetaxonScopeapplied. Occurrence queries usenubKeywhen supplied; otherwise resolve the name withgbif_match_species. OmitteddatasetKeyselects GBIF Backbone Taxonomyd7dddbf4-2cf0-4f39-9b2a-bb099caae36c kingdom,family, andgenustake names, matched exactly as GBIF capitalizes them; the narrowest one scopes, andkingdombeside a narrower one disambiguates it. An unknown name fails asunresolved_taxon_scope, a genus outside the named family asconflicting_taxon_scope, and a scope paired with a non-backbonedatasetKeymatches nothing. A blank filter or a malformeddatasetKeyfails asinvalid_filter
gbif_get_species_classification tool
- One
taxonKey; returnsclassificationroot-first from kingdom to the immediate parent, each entry withkey,rank,name, andscientificName - The queried taxon is not included (use
gbif_get_species); a root taxon returns an empty chain with a notice, an unknown key fails asnot_found, one past the 32-bit range asinvalid_filter, and a fraction or negative key fails at the schema
gbif_get_species_children tool
- One
taxonKey(a non-negative integer;0is the backbone's incertae sedis kingdom), up to 1,000 children per page with integerlimitandoffset; no filters. A fraction or negative value fails at the schema; an unknown key fails asnot_found, one past GBIF's 32-bit range asinvalid_filter - Each child carries
key,canonicalName,rank,taxonomicStatus,vernacularNamewhen GBIF has one, andnumDescendants; GBIF sends no occurrence count, so usegbif_count_occurrenceswith the child'skey. GBIF reports no total, soendOfRecords(withtruncatedwhile more remain) is the continuation signal - An empty later page gives offset-reset guidance; only an empty first page for an existing taxon means no direct children
gbif_search_occurrences tool
- Filters:
taxonKey(preferred;scientificNamedoes not match synonyms),country,publishingCountry,stateProvince,gadmGid, adecimalLatitude/decimalLongitudebox or WKTgeometry,year,month,basisOfRecord,hasCoordinate,isInCluster,coordinateUncertaintyInMeters,datasetKey,catalogNumber,institutionCode,recordedBy,mediaType,occurrenceStatus,iucnRedListCategory; up to 300 per page gadmGidis an uppercase GADM GID (ESP.1_1) GBIF derives from each record's coordinates, so records without coordinates match none; take one from aGADM_LEVEL_0_GID–GADM_LEVEL_3_GIDfacet orgbif_get_occurrence'sgadmfield.catalogNumberandinstitutionCodematch the whole value case-insensitively,recordedByone collector exactly and case-sensitively (take a spelling from aRECORDED_BYfacet), andmediaTypeisStillImage,MovingImage,Sound, orInteractiveResource.taxonKey,month,limit, andoffsetare integers- All supplied spatial filters intersect: combining
geometrywith latitude or longitude ranges restricts results to their overlap - Records carry
key,taxonKey,taxonomicStatus, coordinates,eventDateandeventTime,basisOfRecord,occurrenceStatus,iucnRedListCategory,datasetKey,institutionCode,catalogNumber, andissues; enrichment reportstotalCount,endOfRecords, and theoccurrenceStatusapplied - Search, count and facets echo the same
scope: effective supplied biological filters, withoccurrenceStatusalways included and pagination controls excluded.ANYis echoed but omitted upstream.taxonKeyandscientificNamecombine with OR. All 11 GBIF basis-of-record values are accepted, includingFOSSIL_SPECIMEN,OBSERVATION, andUNKNOWN - Latitude, longitude and coordinate uncertainty are independent optional facts; text renders each supplied value, including zero, in decimal degrees or meters
offset + limitcaps at 100,001 and GBIF has no cursor; a deeper request fails aspagination_cap_exceeded, and a larger match is reached by partitioning on aDATASET_KEYfacet fromgbif_occurrence_facets. A rejected filter value fails asinvalid_filter
gbif_count_occurrences tool
- Accepts every biological filter listed for
gbif_search_occurrences, with the same constraints and spatial intersection.isGeoreferencedremains an alias forhasCoordinate; either alone or both equal works, conflicting values fail asinvalid_filter - Returns
count, with theoccurrenceStatusapplied in the enrichment; a count above 100,001 carries a notice naming the partition route, and a rejected filter value fails asinvalid_filter
gbif_get_occurrence tool
- One
occurrenceKeyfrom a search result, a positive integer (a non-positive or fractional key is rejected at the schema); an unknown key fails asnot_found - The full Darwin Core record:
occurrenceStatus(ABSENTis a survey that found nothing, not a sighting), coordinates, GADM levels 0–3 undergadm, dates witheventTime,taxonomicStatus,iucnRedListCategory, institution, collection, and catalog codes,recordedByandidentifiedBy,media,identifiers, andissues
gbif_occurrence_facets tool
facetis one ofCOUNTRY,STATE_PROVINCE,YEAR,MONTH,BASIS_OF_RECORD,DATASET_KEY,PUBLISHING_COUNTRY,KINGDOM_KEY,PHYLUM_KEY,CLASS_KEY,ORDER_KEY,FAMILY_KEY,GENUS_KEY,SPECIES_KEY,OCCURRENCE_STATUS,IUCN_RED_LIST_CATEGORY,GADM_LEVEL_0_GID–GADM_LEVEL_3_GID,INSTITUTION_CODE,MEDIA_TYPE,RECORDED_BY; up to 100 values per page (facetLimit, default 10), paged withfacetOffset- Accepts every biological filter listed for
gbif_search_occurrences, with the same constraints and spatial intersection. Repeat them on the facet call and each partition search to preserve the population. ReturnstotalOccurrencesandcountsranked by count; a rejected scope value fails asinvalid_filter - Each facet request fetches one extra bucket to prove continuation.
truncated,shown, andcapappear only when that bucket exists; advancefacetOffsetby the exposed page size. An exactly full final page carries no truncation flag. Empty later pages give offset-reset guidance; an empty first page distinguishes zero matching occurrences from a dimension with no data DATASET_KEYbuckets sum to the scope's full total, so it is the facet for partitioning a search too large to page;YEAR,MONTH,STATE_PROVINCE,SPECIES_KEY,INSTITUTION_CODE,MEDIA_TYPE, andRECORDED_BYdrop records that lack the field, and the GADM levels drop records without coordinates or outside every GADM unit at that level.MEDIA_TYPEandRECORDED_BYbuckets overlap (a record with two media types or two collectors counts in each), so their sums can exceedtotalOccurrences.INSTITUTION_CODEbuckets come back lowercased andinstitutionCodetakes them unchanged. Passfacet: OCCURRENCE_STATUSwithoccurrenceStatus: ANYfor the presence/absence splitincludeLabels: truenames each bucket on aKINGDOM_KEY–SPECIES_KEYorDATASET_KEYpage:counts[].labelis the taxon'scanonicalNameor the datasettitle. It costs one GBIF request per exposed bucket (never the lookahead), at most 8 in flight server-wide, no retries, and one 10 s deadline per page; a bucket whose lookup fails or misses it has nolabeland is counted innotice. Other dimensions ignore it, and without it a facet call is one request
gbif_search_datasets tool
- Filters:
q,type(OCCURRENCE,CHECKLIST,METADATA,SAMPLING_EVENT),publishingCountry,publishingOrg,hostingOrg; up to 1,000 per page - Returns
key,title,type,license,doi,recordCount,publishingOrganizationKeyandpublishingOrganizationTitle, and a 300-characterdescriptionpreview, withdescriptionTruncatedflagging a cut (gbif_get_datasethas the full text).publishingOrganizationKeygoes back in aspublishingOrg.limitandoffsetare integers publishingOrgmatches the organization whose data it is and is the usual chain fromgbif_search_publishers;hostingOrgmatches the organization whose installation serves it, and the two together intersect. Both take the lowercase UUID form; anything else, like any rejected filter value, fails asinvalid_filter
gbif_get_dataset tool
- One
datasetKeyUUID andcontactLimit(default 10, max 100;0drops contact detail but keepscontactsTotal); a malformed key fails asinvalid_filter, an unknown one asnot_found - Returns
description,citationText,license,doi,publishingOrganizationKey(goes intogbif_search_datasetsaspublishingOrg; the detail record carries no organization name),recordCount,numConstituents,contactswithcontactsTotalandcontactsReturned,temporalCoverages, andgeographicCoverages
gbif_search_publishers tool
qname fragment andcountry(alpha-2 or alpha-3, any case); up to 1,000 per page with integerlimitandoffset- Returns organization
key,title,country, andcity; the key chains intogbif_search_datasetsaspublishingOrg - A blank
q, an emptycountry, or a country GBIF cannot parse fails asinvalid_filter
gbif://species/{taxonKey} resource
- Taxon record as
application/json: classification names,authorship,vernacularName,taxonomicStatuswithacceptedKeyandaccepted,numDescendants taxonKeyis a whole signed decimal integer within the signed 32-bit range;0is the backbone kingdom incertae sedis. The segment is URI-decoded once and surrounding whitespace is trimmed; leading+, zero padding and their percent-encoded equivalents are accepted. An unknown key fails asnot_found; malformed escapes, suffixes, fractions, exponents, hexadecimal forms, embedded whitespace and out-of-range values fail asinvalid_filterbefore a request. Use a backbone key fromgbif_match_speciesor a search result'snubKey, resolving its name when that mapping is absent
gbif://dataset/{datasetKey} resource
- The
gbif_get_datasetrecord asapplication/json, includingpublishingOrganizationKey, with contacts fixed at 10 datasetKeycomes fromgbif_search_datasetsor an occurrence record; an unknown key fails asnot_found, a malformed one asinvalid_filter
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
GBIF-specific:
- GBIF API v1 species, occurrence, dataset, and organization endpoints, keyless, with an identifying
User-Agenton every request - Synonym-safe keys:
gbif_match_speciesresolves a synonym to its accepted taxon, and the occurrence tools filter on thattaxonKey - Sightings by default: the search, count, and facet tools default
occurrenceStatustoPRESENT, excluding absence records. DatasetrecordCountspans every status, so it can exceed agbif_count_occurrencestotal for the same key - Strict country codes:
country(where a record was observed) andpublishingCountry(the publisher's country) on the occurrence tools, andpublishingCountryongbif_search_datasets, accept only uppercase ISO 3166-1 alpha-2, because other forms silently match nothing there.stateProvincematches verbatim and case-sensitively, so take values from aSTATE_PROVINCEfacet - Blank filters rejected: GBIF reads an empty parameter as no filter, so an optional filter sent blank or whitespace-only fails as
invalid_filterinstead of widening the query. The exception is a blankcountryorpublishingCountryon the occurrence tools, or a blankpublishingCountryongbif_search_datasets, which fails earlier at the uppercase pattern as-32602 invalid_arguments. Omit a field to leave it off
Agent-friendly output:
- Scope echo: enrichment reports
totalCount,endOfRecords, theoccurrenceStatusapplied, and the resolvedtaxonScope, with notices on empty results, over-cap totals, and astateProvince,gadmGid, orrecordedBythat matched nothing - Graceful partial failure:
gbif_bulk_match_speciesreturns aNONEorERRORrow per name instead of failing the batch - Typed errors:
invalid_filter,not_found,no_match,unresolved_taxon_scope,conflicting_taxon_scope, andpagination_cap_exceeded, each with a recovery hint - Sparse fields omitted rather than null-filled:
extinctappears only on taxa GBIF explicitly flags - Dataset metadata preserves temporal ranges, single dates, and verbatim periods such as
1975-current; unsupported coverage entries are disclosed. An unavailable supplementary record count carriesrecordCountNoticewhile retaining metadata - Publisher descriptions retain paragraph breaks and decode numeric character references once; Markdown output renders publisher text literally
Getting started
Public Hosted Instance
A public instance is available at https://gbif-biodiversity.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
Self-Hosted / Local
Add the following to your MCP client configuration file.
Or with npx (no Bun required):
Or with Docker:
For Streamable HTTP, set the transport and start the server:
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- No credentials: the GBIF endpoints this server calls are public.
Installation
- Clone the repository:
- Navigate into the directory:
- Install dependencies:
- Configure environment:
Configuration
See .env.example for the full list of optional overrides.
Running the server
Local development
-
Build and run the production version:
-
Run checks and tests:
Docker
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/gbif-biodiversity-mcp-server. OpenTelemetry peer dependencies are installed by default; build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor logging,ctx.statefor storage - Register new tools and resources in the
createApp()arrays insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
來源:README.md,提交 4b29653
工具
0版本歷史
1- v0.1.7最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通必需25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式必需10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分