关于 inaturalist-mcp-server
inaturalist-mcp-server 将 MCP 客户端连接到 iNaturalist 的野生动植物观察数据,支持搜索记录、查看鉴定讨论、分析季节性和获取分类单元资料,且无需 API 密钥。
主要功能
- 01按地点、日期、分类单元和条件搜索观察记录
- 02获取包含鉴定讨论的观察记录
- 03统计物种及贡献者排名
- 04按季节或日期绘制记录分布
- 05查找易混淆分类单元及物种资料
适用场景
- 01查找特定地区和日期范围内的野生生物记录
- 02查看某条观察记录的社区鉴定过程
- 03比较某分类单元的季节性观察模式
- 04了解常见的物种鉴定混淆
MCP 相关
向 MCP 客户端提供 10 个工具和两个领域资源,支持 STDIO 与 Streamable HTTP 传输。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://inaturalist.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-inaturalist https://inaturalist.caseyjhand.com/mcp{"mcpServers":{"cyanheads-inaturalist":{"type":"http","url":"https://inaturalist.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"cyanheads-inaturalist":{"type":"http","url":"https://inaturalist.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"cyanheads-inaturalist":{"type":"http","url":"https://inaturalist.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-inaturalist":{"serverUrl":"https://inaturalist.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
10| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| topic | enum | 是 | 要解读的词汇表。controlled_terms 会实时获取并缓存;其余为根据规范生成的静态表。controlled_terms | quality_grades | licenses | ranks | iconic_taxa | conservation_status_codes |
| taxon_id | integer | 否 | 添加该分类单元的已观测注释用法,并按每个属性/值对的记录频次排序。仅在 topic controlled_terms 时有效。使用 inaturalist_resolve_name 将名称解析为 ID。 |
详细介绍
@cyanheads/inaturalist-mcp-server
通过 MCP 搜索野生动物目击记录、阅读鉴定讨论串、按区域排列物种、绘制物候图表,并查找相似分类群。支持 STDIO 或 Streamable HTTP。
概述
iNaturalist 收录了超过 3.87 亿条带地理坐标的公民科学观测记录,涵盖植物、动物和真菌。按区域、日期、分类群和标注搜索目击记录;阅读记录背后的鉴定讨论串;绘制分类群出现时间图表;排列某个区域的物种;并查看外形相似的物种最常与哪些物种混淆。无需 API 密钥。
工具
| 工具 | 描述 |
|---|---|
inaturalist_list_reference | 解码其他工具用于筛选的受控词表:标注属性和值、质量等级、许可、分类等级、标志性分类群、保护状态代码 |
inaturalist_resolve_name | 将俗名或学名解析为分类单元 ID,或将地点、项目或观察者名称解析为对应 ID,并按排名列出候选项 |
inaturalist_find_places | 将地点名称解析为地点 ID,或列出覆盖地图区域的地点,并提供每个地点的边界框和包含链 |
inaturalist_search_observations | 按区域、日期、分类单元、质量等级、标注、保护状态、观察者、项目和许可搜索带地理坐标的观察记录 |
inaturalist_get_observation | 按 ID 获取最多 10 条观察记录,并附上社群鉴定讨论串和共识分类单元 |
inaturalist_get_species_counts | 按记录数量从多到少,排列某区域和时段内记录的不同物种;也可选按某位观察者或项目筛选 |
inaturalist_get_histogram | 为某个分类单元在某区域生成物候直方图,显示记录所在的月份、周或年份 |
inaturalist_get_leaderboard | 按区域、时段和分类单元排列最活跃的观察者或鉴定者 |
inaturalist_get_similar_species | 列出某属或更细分类单元最常被误认成的分类单元,并按纠正次数排序 |
inaturalist_get_taxon | 获取分类单元简介:分类路径、各主管机构的保护名录、百科摘要、照片和子级分类单元 |
资源
| 资源 | 描述 |
|---|---|
inaturalist://taxa/{taxon_id} | 按数字分类单元 ID 获取分类单元简介,作为可注入的上下文 |
inaturalist://observations/{observation_id} | 获取一条观察记录,并展开其鉴定讨论串,作为可注入的上下文 |
这两个资源提供的数据也可通过 inaturalist_get_taxon 和 inaturalist_get_observation 访问,供不展示 MCP 资源的客户端使用。
已发布的 inaturalist-guide 介绍了标识符来源、匹配队列、标注以及各调用的证据覆盖情况。该指南随 npm、插件、MCPB 和 Docker 安装包一同提供;支持 MCP 技能发现的客户端可以直接获取。SDK 还会在这两个领域资源旁提供技能资源。
功能参考
inaturalist_list_reference 工具
topic选择一张表:controlled_terms(实时获取)、quality_grades、licenses、ranks、iconic_taxa或conservation_status_codes;仅在controlled_terms下有效的taxon_id会添加observed_usage,即该分类单元记录的标注属性值对及其数量source为upstream或static;标注属性及其值带有数字 ID,需作为term_id和term_value_id传入,因为不同属性可能使用相同标签
inaturalist_resolve_name 工具
q加上type:taxon(默认;按名称前缀自动补全,因此可通过“monarch”找到结果,而“monarch butterfly”可能找不到;可选提供rank),或place/project/user/any(跨类别的评分搜索);应用后的limit最高为 30,默认值为 10- 每个候选项都包含
kind和id,用户候选项还包含login;未找到时会返回包含guidance的found: false,而不是错误
inaturalist_find_places 工具
- 必须且只能提供
q(地点名称前缀),或全部四个参数nelat、nelng、swlat、swlng;否则返回invalid_geography;应用后的per_page最高为 30(默认值为 10),且仅适用于地图框查询,每个列表分别计算 q会返回places[],地图框查询会返回standard[]和community[];每个地点都包含id、bbox、ancestor_place_ids、place_type、admin_level和location,并会剥除边界多边形
inaturalist_search_observations 工具
- 一种区域形式,以及
taxon_id、d1/d2、quality_grade、captive、term_id+term_value_id、iconic_taxa、hrank/lrank、csi、threatened/native/introduced/endemic、user_id或user_login、project_id和q+search_on;应用后的per_page上限为 25,默认值为 10;可选的sounds用于筛选带音频的记录,而include可扩展返回photos、annotations、sounds(鉴定讨论串由inaturalist_get_observation提供) page可遍历前 10,000 条结果;超过此范围后,按id降序排序,并将每页的next_cursor作为cursor传入。返回total_results(实时估算值)和has_more,并回显applied_filterslicense/photo_license接受七种 CC 代码,以 OR 连接;photo_license匹配符合该代码的任意照片,与记录自身的license_code无关- 完整序列化回复的大小不超过 50,000 UTF-8 字节,方法是仅返回完整记录组成的前缀。按顺序排列的
deferred观测 ID 标识未返回的后缀;在继续获取上游页面前,使用相同的include通过inaturalist_get_observation获取这些记录
inaturalist_get_observation 工具
- 提交 1–100 个
observation_id:重复项会按首次出现的顺序去除,前 10 个不同 ID 会在一个上游请求中尝试,其余 ID 会列在deferred中;禁用限制钳制时,最多接受 10 个提交的 ID。include默认为["identifications"],也可使用comments、photos、annotations和sounds - 已解析的记录按请求顺序放在
observations中,尝试但未找到的记录放在unresolved中;仅当没有任何记录解析成功且没有延后项时,才会以not_found失败。添加community_taxon、description和已填充的observation_fields;字符串保持完整,因此详情回复没有通用的字节上限 - 鉴定、评论和观测字段共用 40 条目的额度:每条记录在每个数组中保留
max(4, floor(40 / records returned))个条目,并在*_shown旁报告*_total
inaturalist_get_species_counts 工具
- 一种区域形式,以及物种分类群、日期、质量等级、圈养状态、注释、标志性分类群、观察者和项目的搜索筛选条件;应用后的
per_page上限为 50,默认值为 25,page用于偏移 - 各行包含
position(从第 1 页起计算的绝对位置)、taxon_id和observation_count;truncationCeiling为显示的最后一个计数,页外记录的计数均不会超过此值
inaturalist_get_histogram 工具
interval:季节曲线可用month_of_year(默认值)或week_of_year,绝对日期可用year/month/week/day/hour;date_field为observed(默认值)或created;taxon_id为可选项,且注释对(Life Stage1= Larva6)或iconic_taxa可缩小曲线范围- 按顺序返回所有分桶,包括计数为零的分桶,并附带所有分桶的
total;从范围起始处最多返回 800 个分桶,并提供truncated/shown/cap d1/d2限定观测日期;created_d1/created_d2单独限定上传日期。date_field选择用于分桶的日期,但不会更改这两组筛选条件
inaturalist_get_leaderboard 工具
kind:observers或identifiers,以及一种区域形式、taxon_id、d1/d2和quality_grade;应用后的per_page上限为 250,默认值为 25- 仅可访问前 500 个名次,因此
page × per_page超过 500 时会以leaderboard_window_exceeded失败;条目包含rank、login和count(按count_metric计算),观察者条目还包含species_count - 匹配结果已耗尽时,最后一页即使已满也会报告
truncated: false
inaturalist_get_similar_species 工具
taxon_id必须是属或更细的分类单元,否则返回taxon_rank_too_coarse;可选的区域、d1/d2、quality_grade和captive用于限定范围;应用的limit最高为 50,默认为 20- 按
misidentification_count排序;当limit截断结果集时,会提供truncationCeiling
inaturalist_get_taxon 工具
- 一个
taxon_id;sections可从summary、taxonomy、children、conservation、photos和encyclopedia中选择;未知名称会返回unknown_section kind: "full"包含完整档案;当档案超出限制时,kind: "outline"会列出各部分及其字节大小。指定的部分始终会完整返回,因此请求多个部分前,请先汇总大纲中的大小
inaturalist://taxa/{taxon_id} 资源
- 完整的投影分类单元文档,格式为
application/json;资源读取无法指定部分,因此要获取大纲,请使用inaturalist_get_taxon taxon_id来自inaturalist_resolve_name;缓存六小时
inaturalist://observations/{observation_id} 资源
- 一条格式为
application/json的观测记录,包含前 40 条鉴定和前 40 个已填写的观测字段;每项均附有_total和_shown observation_id来自inaturalist_search_observations;缓存十五分钟
功能
基于 @cyanheads/mcp-ts-core:支持 stdio 和 Streamable HTTP 传输、可插拔身份验证(none / jwt / oauth)、可切换存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及支持可选 OpenTelemetry 跟踪的结构化日志记录。
iNaturalist 专属功能:
- 无需密钥,即可只读访问 iNaturalist v1 API。上游会忽略自身的
fields=参数,因此每个响应都会在进程内进行投影(常见的分类单元记录大小为 95 KB) - 限定区域的工具接受一种区域形式:
place_id、lat+lng+radius(单位为公里,最多 500),或由四个角点构成的框。部分填写或混用形式会报错invalid_geography;d1晚于d2则会报错inverted_date_range - 每个端点都有参数允许列表,并会在进程内拒绝上游会悄悄扩大范围或返回零结果的输入:单独的
term_value_id、不可能的日期、未知许可代码 - 流量节奏由服务控制:错开请求启动时间、限制并发数,并设置按 UTC 日计算的预算;超出预算时会报错
rate_budget_exhausted。计数器按进程计算,因此所有调用者共用托管实例的预算。分类单元、地点、受控术语、直方图和相似项集合会缓存;观测查询不会 - 按原样转发许可信息:
license_code为 null 表示保留所有权利;照片的attribution必须与图片一同传递;照片仅提供链接,绝不代理。obscured坐标表示一个地点区域;观察者仅通过login标识
便于 Agent 使用的输出:
- 回显已应用的默认值:搜索、物种计数、直方图和排行榜会返回
applied_filters(默认仅包含研究级和野生记录,以及游标强制应用的任何排序)。captive: true仅选择圈养或栽培记录;false仅选择野生记录 - 无结果提示会指出最可能导致无结果的筛选条件,以及可用于解码该条件的工具(词汇表使用
inaturalist_list_reference,因为无法识别的值会返回空结果);超出末页时会指出最后一个有结果的页面 - 所有路径都会披露截断情况:
truncated、shown和cap;降序排名还会返回truncationCeiling - 空筛选数组会被忽略并附带提示;非空注释值仍要求属性数组非空。
include: []会保留其显式扩展选择 - 未知的
place_id会返回带类型的unknown_place_id指引,提示使用inaturalist_find_places解析 - 上游自由文本会按原样渲染为带引号的内容,保留行分隔符、HTML、实体,以及经 CommonMark 解析后的完整字符串。包含 NUL 的字符串会使用带标签的 JSON 字符串字面量;URL 字段会渲染为链接。存在的空扩展、零计数,以及 null 或空描述都会保留显示
开始使用
公共托管实例
公共实例位于 https://inaturalist.caseyjhand.com/mcp,无需安装。通过 Streamable HTTP 将任意 MCP 客户端指向该实例:
{
"mcpServers": {
"inaturalist-mcp-server": {
"type": "streamable-http",
"url": "https://inaturalist.caseyjhand.com/mcp"
}
}
}
自托管 / 本地运行
将以下内容添加到 MCP 客户端配置文件中。
{
"mcpServers": {
"inaturalist-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/inaturalist-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
或使用 npx(无需 Bun):
{
"mcpServers": {
"inaturalist-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/inaturalist-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
或使用 Docker:
{
"mcpServers": {
"inaturalist-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/inaturalist-mcp-server:latest"]
}
}
}
使用 Streamable HTTP 时,设置传输方式并启动服务:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
前提条件
- Bun v1.4.0 或更高版本(或 Node.js v24+)。
- 无需 API 密钥:iNaturalist v1 API 无需密钥。已发布的条款要求客户端标识自身,因此默认会发送包含联系 URL 的
User-Agent;覆盖INATURALIST_USER_AGENT时也请保留联系 URL。
安装
- 克隆代码仓库:
git clone https://github.com/cyanheads/inaturalist-mcp-server.git
- 进入目录:
cd inaturalist-mcp-server
- 安装依赖:
bun install
- 配置环境(可选):
cp .env.example .env
# edit .env to override defaults — no required vars
配置
| 变量 | 描述 | 默认值 |
|---|---|---|
INATURALIST_USER_AGENT | 每次向 api.inaturalist.org 发送请求时使用的 User-Agent。任何覆盖值中都应包含联系 URL。 | inaturalist-mcp-server/<version> (+<repo url>) |
INATURALIST_MIN_REQUEST_INTERVAL_MS | 向外发送请求的启动间隔下限,单位为毫秒。默认值可将速率维持在每分钟约 54 次。 | 1100 |
INATURALIST_MAX_CONCURRENT_REQUESTS | 同时进行的向外请求数上限。 | 4 |
INATURALIST_DAILY_REQUEST_BUDGET | 每个 UTC 日允许的向外请求数,在进程内计数,并在重启时重置。 | 9000 |
INATURALIST_CLAMP_LIMITS | 严格布尔值。将超出范围的列表限制截断为 30/30/25/50/50/250,分别用于名称解析、附近地点、搜索、物种计数、相似物种和排行榜,并显示提示、记录日志和计数器。设为 false 可恢复之前公开的架构上限,并拒绝超出范围的输入。 | true |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_HTTP_PORT | HTTP 服务端口。 | 3010 |
MCP_SESSION_MODE | HTTP 会话模式:stateless、stateful 或 auto。 | stateless |
MCP_AUTH_MODE | 身份验证方式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(debug、info、notice、warning、error)。 | info |
LOGS_DIR | 日志文件目录(仅限 Node.js)。 | <project-root>/logs |
STORAGE_PROVIDER_TYPE | 响应缓存的存储后端:in-memory、filesystem、supabase、cloudflare-kv/r2/d1。 | in-memory |
OTEL_ENABLED | 启用 OpenTelemetry。 | false |
可查看 .env.example 了解可选覆盖项的完整列表。
运行服务
本地开发
-
构建并运行生产版本:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
运行检查和测试:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t inaturalist-mcp-server .
docker run --rm -p 3010:3010 inaturalist-mcp-server
Dockerfile 默认使用 HTTP 传输、无状态会话模式,并将日志写入 /var/log/inaturalist-mcp-server。默认会安装 OpenTelemetry 对等依赖;如需省略这些依赖,请使用 --build-arg OTEL_ENABLED=false 构建。
项目结构
| 目录 | 用途 |
|---|---|
src/index.ts | createApp() 入口:身份信息、服务端说明、工具和资源注册、服务初始化。 |
src/config | 使用 Zod 解析和验证服务专用环境变量。 |
src/mcp-server/tools | 工具定义(*.tool.ts),以及共享的筛选器、观测记录和分类单元文档辅助程序。 |
src/mcp-server/resources | 资源定义(*.resource.ts):分类单元和观测。 |
src/services/inaturalist | iNaturalist 服务层:允许列表客户端、请求节流器、每日预算、缓存和响应投影。 |
tests/ | 单元、集成和冒烟测试,结构与 src/ 对应。 |
开发指南
开发指南和架构规则请参阅 CLAUDE.md。简而言之:
- 处理器抛出异常,框架负责捕获——工具逻辑中不要使用
try/catch - 使用
ctx.log记录日志,使用ctx.state存储数据 - 在
src/index.ts的createApp()数组中注册新工具和资源 - 封装外部 API 调用:验证原始数据 → 规范化为领域类型 → 返回输出架构;绝不伪造缺失字段
贡献
欢迎提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
许可证
本项目采用 Apache 2.0 许可证。详情请参阅 LICENSE 文件。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。