
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 分