关于 faostat-mcp-server
faostat-mcp-server 基于本地 SQLite 镜像提供联合国 FAOSTAT 的食品与农业统计数据,适合查询全球观测数据、解析代码或用 SQL 分析较大的结果集。
主要功能
- 01浏览统计域及本地索引状态
- 02解析地区、商品和要素代码
- 03按地理区域、商品和年份查询观测数据
- 04汇总商品生产与贸易概况
- 05用只读 SQL 分析暂存结果
适用场景
- 01比较各国农业产量
- 02追踪年度产量和商品贸易
- 03对大型观测数据集执行 SQL 分析
MCP 相关
向 MCP 客户端提供 FAOSTAT 统计域发现、代码解析、观测查询、商品概况和 DataCanvas SQL 工具。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://faostat.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-faostat https://faostat.caseyjhand.com/mcp{"mcpServers":{"cyanheads-faostat":{"type":"http","url":"https://faostat.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"cyanheads-faostat":{"type":"http","url":"https://faostat.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"cyanheads-faostat":{"type":"http","url":"https://faostat.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-faostat":{"serverUrl":"https://faostat.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
6| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| code | string | 否 | 按域代码精确查找(例如 "RL"),不区分大小写。返回该域的完整记录,且仅占一页。提供此参数时优先于 `topic` / `indexed_only`。 |
| limit | integer | 否 | 此页最多返回的域数(最大 200;高于目录大小,因此调高后可一次性获取全部内容)。域描述较长,默认值可使浏览请求保持精简。 |
| topic | string | 否 | 对域代码、名称和主题执行不区分大小写的子字符串筛选(例如 "trade"、"emissions"、"QCL")。省略则列出完整目录。 |
| offset | integer | 否 | 对匹配的域进行从零开始的分页偏移(按代码排序)。响应报告 truncated 时,将返回的 nextOffset 传入此参数以获取下一页。精确代码查询时忽略(始终为单页)。 |
| indexed_only | boolean | 否 | 为 true 时,仅返回本地镜像中已编入索引的域(当前可查询)。 |
详细介绍
@cyanheads/faostat-mcp-server
通过 MCP 提供联合国 FAOSTAT 批量下载语料库中的全球粮食与农业统计数据。数据由本地 SQLite 镜像提供,并配有 DataCanvas SQL 查询界面。支持 STDIO 或 Streamable HTTP。
概述
联合国 FAOSTAT 提供的全球粮食与农业统计数据:自 1961 年以来,涵盖 245 个以上国家和地区的生产、贸易、食物平衡、粮食安全、土地利用、化肥和排放数据。解析商品和国家代码、查询数据,并对大型结果运行 SQL。
工具
| 工具 | 描述 |
|---|---|
faostat_list_domains | 查看 FAOSTAT 统计领域及其代码、描述、最后更新日期、上游行数和本地索引状态。查询入口——每次查询都需要领域代码。 |
faostat_resolve_codes | 将自然语言术语解析为查询所需的不透明整数代码(地区、商品、要素),并标明各地区是国家还是集合区域。 |
faostat_query_observations | 按地区、商品、要素和年份范围查询某个领域的数据立方体。小型结果以内联预览显示;大型结果存入 DataCanvas 表。 |
faostat_commodity_profile | 工作流:一次调用即可从生产和贸易领域汇总某种商品的主要生产者、生产趋势和贸易流向。 |
faostat_dataframe_query | 对分析工具暂存的画布表运行只读 SQL SELECT 查询。 |
faostat_dataframe_describe | 列出本会话暂存的画布表,并显示每张表的数据来源、行数和列结构。 |
faostat_dataframe_drop | 在 2 小时 TTL 到期前删除一张暂存的画布表。默认关闭——只有在 FAOSTAT_DATAFRAME_DROP_ENABLED=true 时才能调用。 |
能力参考
faostat_list_domains 工具
- 从批量清单实时读取完整的 FAOSTAT 目录(约 69 个领域),并标注本地镜像状态
- 使用
code精确查找领域;使用topic按代码、名称或主题进行子字符串筛选;使用indexed_only仅列出可从本地镜像查询的领域 - 使用
offset+limit(上限为 200,默认值为 20)分页浏览目录 — 响应会报告totalMatches、truncated和nextOffset - 每个条目会报告
indexed/index_ready标志、本地行数和最近一次已完成的同步
faostat_resolve_codes 工具
- 在某个
dimension中使用 FTS5 全文query、子字符串name_contains或精确的code查找;dimension可为area、item或element - Item / element 匹配结果仅包含给定
domain立方体中存在的代码;area 代码在各领域间通用 - 每个 area 匹配结果都标记为
country或aggregate(代码 ≥ 5000,以及中国 = 351 等经过整理的低于阈值的汇总项) - 使用
limit(上限为 200,默认值为 50)+offset分页浏览匹配结果集 - 类型化错误:
unknown_domain、index_not_ready、query_timeout
faostat_query_observations 工具
- 按
area_codes/item_codes/element_codes筛选,并限定包含起止年份的year_start/year_end范围 - 默认排除汇总地区(
include_aggregates: false);显式指定area_codes时则不受此排除规则影响 limit限制内联页面的大小(默认值为 200,上限为 1000);如果匹配结果超过此上限,则会将完整结果写入 DataCanvas 表(暂存上限为 50,000 行)— 使用faostat_dataframe_describe查看其列,再通过faostat_dataframe_query执行 SQL- 每一行都保留数据质量
flag(A/E/I/B/M/T/X,以及各领域的其他标记)— 不会丢弃 - 类型化错误:
domain_not_indexed、index_not_ready、canvas_disabled、canvas_not_found、invalid_year_range、query_timeout
faostat_commodity_profile 工具
- 使用
item_code或item_query选择一个 QCL 商品项(优先使用代码),然后对主要生产国、出口国和进口国进行排名,并返回年度产量趋势 - 选择查询项时,优先使用去除首尾空白、合并连续空白并忽略大小写后唯一匹配的精确标签;否则要求有唯一的相关性匹配。对于
maize或milk等含义不明确的词,调用faostat_resolve_codes,参数为domain: "QCL"、dimension: "item"和该查询词,然后传入所选的item_code(例如,玉米籽粒的代码为56) - 排名按国家和单位对数据求和,每个国家使用其最新报告年份;仅包含国家(排除汇总项)
- 如果贸易领域(TCL)尚未建立索引或仍在同步,则返回部分的、仅包含产量的资料,并附带说明,而不是失败
top_n限制每个排名列表的大小(上限为 50);如果合并后的观测结果集过大而无法内联,则会将其写入 DataCanvas 表 — 使用faostat_dataframe_describe查看其列,再使用faostat_dataframe_query执行更多 SQL- 说明中会报告每种暂存结果:暂存的表、可内联的数据集、暂存失败或画布已禁用
- 类型化错误:
missing_item、ambiguous_item、no_match、domain_not_indexed、index_not_ready、invalid_year_range、canvas_not_found、query_timeout
faostat_dataframe_query 工具
- 对暂存的
faostat_xxxxxxxx表执行单条只读SELECT语句 — 支持连接、聚合、窗口函数和 CTE - 会拒绝写入操作、DDL、
DROP、COPY、PRAGMA、ATTACH、外部文件函数和系统目录(information_schema、sqlite_master、duckdb_*) - 会拒绝引擎设置内省、
query_table、动态query()SQL 和文件表引用;仍支持使用单条字面量只读SELECT的query() row_limit限制响应行数(默认值为 1000,上限为 10000);truncated表示还有更多行,但此路径不会计算精确总数- 类型化错误:
canvas_disabled、canvas_not_found、missing_table、system_catalog_access、invalid_sql
faostat_dataframe_describe 工具
- 列出暂存表及其来源工具、查询参数、行数、列架构和创建/到期时间(滑动 TTL 为 2 小时)
name会直接描述一张表;否则通过offset+limit分页列出表格,最多 100 条,默认 20 条,按最新优先排序- 类型化错误:
canvas_disabled、canvas_not_found、missing_table
faostat_dataframe_drop 工具
- 选择启用:默认注册为禁用状态——会在落地页列出并提示如何启用,但不会出现在
tools/list中;除非设置FAOSTAT_DATAFRAME_DROP_ENABLED=true - 从会话画布中删除一张暂存的
faostat_xxxxxxxx表及其溯源信息,或从canvas_id指定的画布中删除 - 幂等:如果该画布上没有暂存指定名称的表,则返回
dropped: false并附带提示,不作任何更改 - 类型化错误:
canvas_disabled、canvas_not_found
功能
基于 @cyanheads/mcp-ts-core 构建:支持 stdio 和 Streamable HTTP 传输、可插拔身份验证(none / jwt / oauth)、可切换存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及支持可选 OpenTelemetry 跟踪的结构化日志。
FAOSTAT 特有功能:
- 通过框架的
MirrorService持久化本地 FAOSTAT 批量数据镜像,并对用于驱动代码解析的维度标签建立 FTS5 全文搜索索引 - 流式批量 ZIP 导入器:如果上游更新时间未推进,则跳过相应领域;并将规范化 CSV 流式解析到 SQLite,无需在内存中完整载入文件
- 由配置驱动的领域选择(
FAOSTAT_DOMAINS)——无需更改代码即可扩展索引集合,同时完整目录始终可供浏览 - 用于对溢出结果集执行
GROUP BY、排名和时间序列分析的 DataCanvas SQL 接口(DuckDB)
面向 Agent 的输出:
- 为每个地区标注国家或汇总数据的分类,默认从求和中排除汇总数据——避免将世界/洲级行与其成员国重复计数
- 数据质量溯源——每条观测值都会携带其 FAOSTAT 标志(
A/E/I/B/M/T/X,以及各领域中的其他标志),不会从输出中移除 - 优雅处理部分结果——如果贸易领域未建立索引,
faostat_commodity_profile会返回仅包含生产数据的概况并附带提示,而不是失败 - 类型化错误约定——
index_not_ready、domain_not_indexed、canvas_disabled等错误均包含明确的恢复提示
开始使用
公共托管实例
可使用公共实例:https://faostat.caseyjhand.com/mcp,无需安装。该实例提供 Streamable HTTP;各客户端的配置格式有所不同。
对于 Claude Code:
claude mcp add --transport http faostat-mcp-server https://faostat.caseyjhand.com/mcp
对于 Cline(cline_mcp_settings.json):
{
"mcpServers": {
"faostat-mcp-server": {
"type": "streamableHttp",
"url": "https://faostat.caseyjhand.com/mcp"
}
}
}
对于 Cursor(mcp.json):
{
"mcpServers": {
"faostat-mcp-server": {
"url": "https://faostat.caseyjhand.com/mcp"
}
}
}
Claude Desktop 可在 Settings → Connectors 下添加远程服务。
自托管/本地
将以下内容添加到 MCP 客户端配置文件中。服务完全在本地镜像上运行,因此请先构建镜像,然后再进行查询。
{
"mcpServers": {
"faostat-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/faostat-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
也可使用 npx(无需 Bun):
{
"mcpServers": {
"faostat-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/faostat-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
也可使用 Docker:
{
"mcpServers": {
"faostat-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-v", "faostat-mirror:/usr/src/app/.faostat-mirror",
"ghcr.io/cyanheads/faostat-mcp-server:latest"
]
}
}
}
如需使用 Streamable HTTP,请设置传输方式并启动服务:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
无需 API 密钥——FAOSTAT 批量下载服务公开且无需密钥。
前置条件
- Bun v1.4.0 或更高版本(或 Node.js v24+)。
- 本地镜像所需的磁盘空间。默认领域集合(
QCL,TCL,FBS,FS,RL,GLE,RFN,QV,约 3700 万行)需要数 GB 空间;TCL(约 1700 万行)占主要部分,在磁盘空间受限的主机上可从FAOSTAT_DOMAINS中移除。
安装
- 克隆仓库:
git clone https://github.com/cyanheads/faostat-mcp-server.git
- 进入目录:
cd faostat-mcp-server
- 安装依赖:
bun install
- 配置环境:
cp .env.example .env
# edit .env to override the default domain set, mirror path, or refresh cron
构建镜像
语料库不会随包提供。在数据工具能够响应查询之前,先将选定的领域同步到本地镜像:
bun run mirror:init # one-time bootstrap — downloads and indexes the FAOSTAT_DOMAINS set
bun run mirror:refresh # re-sync domains whose upstream update date has advanced; build missing planner statistics
bun run mirror:verify # report sync status, local row counts, and sample reads
mirror:init 可幂等地按领域运行并支持断点续传——中断后重新运行时,只会重新流式传输尚未完成的领域 ZIP。FAOSTAT_DOMAINS 用于选择要编入索引的领域;目录中的其他领域会显示在 faostat_list_domains 中,并标记为 indexed: false,直到将其添加并重新同步。使用 HTTP 传输时,设置 FAOSTAT_REFRESH_CRON 可按计划在进程内刷新;使用 stdio 时,在进程外运行 mirror:refresh。首次同步完成前,读取工具会返回 index_not_ready。
对于已选定但尚无查询规划器统计信息的领域,mirror:refresh 也会生成统计信息(ANALYZE),即使该领域的数据在上游没有变化也一样——例如由旧版本同步的镜像,或上次构建失败的镜像。其他情况下,服务器会在首次读取该领域的数据时,在后台工作线程中自行生成统计信息,同时继续响应请求。
配置
| 变量 | 说明 | 默认值 |
|---|---|---|
FAOSTAT_DOMAINS | 要编入本地镜像的 FAOSTAT 领域代码,以逗号分隔。不在此集合中的领域会显示在 faostat_list_domains 中,但添加并重新同步之前无法查询。 | QCL,TCL,FBS,FS,RL,GLE,RFN,QV |
FAOSTAT_MIRROR_PATH | 存放各领域 SQLite 数据库和共享维度数据库的目录。如果不存在则会创建。 | ./.faostat-mirror |
FAOSTAT_BULK_BASE_URL | FAOSTAT 批量下载服务的基础 URL(清单和各领域 ZIP)。 | https://bulks-faostat.fao.org/production |
FAOSTAT_REFRESH_CRON | 进程内增量刷新的 Cron 表达式(仅适用于 HTTP 传输)。省略此项可禁用,并在进程外运行 mirror:refresh。 | — |
CANVAS_PROVIDER_TYPE | DataCanvas 引擎。duckdb 会启用 SQL 接口;设置为 none 可禁用分析暂存(此时 dataframe_* 工具会报告 canvas_disabled,大型查询也会拒绝溢写)。 | duckdb |
FAOSTAT_DATAFRAME_DROP_ENABLED | 设置为 true 可调用 faostat_dataframe_drop。关闭时,该工具会注册为禁用状态:不会出现在 tools/list 中,并会在首页显示此提示。 | false |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_SESSION_MODE | HTTP 会话模式:stateless、stateful 或 auto(解析为 stateful)。服务器在 src/index.ts 中声明为 stateless——没有工具会在处理程序执行过程中要求调用方输入;设置此项会覆盖该声明。 | stateless |
MCP_HTTP_PORT | HTTP 服务的端口。 | 3010 |
MCP_AUTH_MODE | 身份验证模式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(RFC 5424)。 | info |
LOGS_DIR | 日志文件目录(仅限 Node.js)。 | <project-root>/logs |
完整的可选覆盖项列表请参阅 .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 suite under Bun, then under Node bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t faostat-mcp-server .
docker run --rm -p 3010:3010 -v faostat-mirror:/usr/src/app/.faostat-mirror faostat-mcp-server
Dockerfile 默认使用 HTTP 传输、无状态会话模式,并将日志写入 /var/log/faostat-mcp-server。专用的依赖阶段会为目标平台安装生产依赖树(包括 DuckDB 预构建的原生绑定),因此精简运行时镜像不包含构建工具链,多架构构建也不会在仿真环境下运行 Bun。默认会安装 OpenTelemetry 对等依赖——构建时使用 --build-arg OTEL_ENABLED=false 可省略这些依赖。在镜像路径挂载卷,以便在容器重建后保留语料库,并在容器内初始化:
docker exec <container> bun run mirror:init # one-time bootstrap
docker exec <container> bun run mirror:verify # sync status + sample reads
docker exec <container> bun run mirror:refresh # re-sync updated domains; build missing planner statistics
项目结构
| 目录 | 用途 |
|---|---|
src/index.ts | createApp() 入口 — 注册七个工具(faostat_dataframe_drop 由其选择加入标志控制),在 setup() 中连接镜像和画布,并安排 HTTP 刷新。 |
src/config | 使用 Zod 解析和验证特定于服务的环境变量。 |
src/mcp-server/tools/definitions | 工具定义(*.tool.ts)。 |
src/services/faostat-mirror | 批量下载镜像服务 — 清单发现、流式 ZIP 导入器、CSV 解析、维度存储、由 SQLite 支持的 MirrorService 连接,以及双工作线程读取池(read-pool.ts、read-worker.ts),用于在主线程之外执行多维数据读取和统计数据构建。 |
src/services/canvas-accessor.ts、canvas-staging.ts | DataCanvas 访问器及溢出/查询/描述/丢弃暂存层。 |
scripts/faostat-mirror-*.ts | mirror:init / mirror:refresh / mirror:verify 命令行工具。 |
tests/ | 与 src/ 对应的单元测试和集成测试。 |
开发指南
开发指南和架构规则请参阅 CLAUDE.md/AGENTS.md。简而言之:
- 处理程序抛出异常,框架负责捕获 — 工具逻辑中不要使用
try/catch - 使用
ctx.log进行请求范围的日志记录,使用ctx.state进行租户范围的存储 - 在
src/index.ts的createApp()数组中注册新工具 - 包装外部数据:验证原始数据 → 规范化为领域类型 → 返回输出架构;切勿编造缺失字段,并保留数据质量标志
数据归属
数据来源于联合国粮食及农业组织(FAO)的统计司 FAOSTAT。FAOSTAT 数据依据 CC BY-4.0 发布;在下游使用中请注明 FAO 为来源。本项目与 FAO 无关,也未获得 FAO 认可。
贡献
欢迎提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
许可证
Apache-2.0 — 详情请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。