Search / io.github.cyanheads/faostat-mcp-server
faostat-mcp-server
R0· no sign-inUN FAOSTAT global food & agriculture statistics over a local SQLite mirror, via MCP.
v0.4.0 · active · repository · descriptor JSON · versions
Search / io.github.cyanheads/faostat-mcp-server
R0· no sign-inUN FAOSTAT global food & agriculture statistics over a local SQLite mirror, via MCP.
v0.4.0 · active · repository · descriptor JSON · versions
{
"mcpServers": {
"faostat-mcp-server": {
"type": "http",
"url": "https://faostat.caseyjhand.com/mcp"
}
}
}claude mcp add --transport http faostat-mcp-server https://faostat.caseyjhand.com/mcp[mcp_servers.faostat-mcp-server]
url = "https://faostat.caseyjhand.com/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"faostat-mcp-server": {
"type": "remote",
"url": "https://faostat.caseyjhand.com/mcp",
"enabled": true
}
}
}{
"mcpServers": {
"faostat-mcp-server": {
"type": "http",
"url": "https://faostat.caseyjhand.com/mcp"
}
},
"deeplink": "cursor://anysphere.cursor-deeplink/mcp/install?name=faostat-mcp-server&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vZmFvc3RhdC5jYXNleWpoYW5kLmNvbS9tY3AifQ%3D%3D"
}{
"servers": {
"faostat-mcp-server": {
"type": "http",
"url": "https://faostat.caseyjhand.com/mcp"
}
}
}{
"mcpServers": {
"faostat-mcp-server": {
"httpUrl": "https://faostat.caseyjhand.com/mcp"
}
}
}extensions:
"faostat-mcp-server":
enabled: true
name: "faostat-mcp-server"
type: streamable_http
uri: "https://faostat.caseyjhand.com/mcp"
timeout: 300
protocol.modernsupports 2026-07-28 (server/discover)protocol.statelessanswers without a sessionprotocol.transportstreamable HTTPprotocol.list_ttltools/list declares ttlMs 0, so clients re-fetch it on every useauth.prm, auth.as_metadata, auth.cimdno remote uses OAuthauth.secret_in_urlno templated URLtools.descriptionsevery tool has a descriptiontools.description_length2 tools have descriptions over 1,024 characters, which crowds the contexttools.schemasevery tool has an object input schematools.annotations6 of 6 tools declare readOnlyHint or destructiveHinttools.directory_hintsno tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: faostat_list_domains (destructiveHint); faostat_dataframe_describe (destructiveHint); faostat_resolve_codes (destructiveHint); …tools.token_costabout 3,615 tokens to load every tooltools.api_dumptools are not a one-to-one API dumpstability.changes5 tool changes in 30 daysstability.rug_pullno tool changed its meaning under the same namedeps.known_vulns, deps.mcp_sdk_version, deps.resolvabledeps.dev does not know @cyanheads/[email protected], @cyanheads/[email protected]faostat_commodity_profilechangeddescription, input schema, output schemaAssemble a global profile for one commodity in a single call: top-producing countries, the annual production trend, and trade flows (top exporters and importers). Accepts a commodity name, resolves it to item codes, then queries the production (QCL) and trade (TCL) domains and merges the results. Each ranking is a per-country sum across the resolved items, taken at that country's own latest year with data and grouped by unit so incomparable quantities are never added. The trend is returned inline as year/value points. Country-level only (aggregates excluded). The production domain (QCL) is required. When the trade domain (TCL) is not indexed locally, returns a production-only profile with a notice naming the gap rather than failing. When the merged observation set is too large to inline, it spills to a DataCanvas table (canvas_id + table_name) — call faostat_dataframe_describe for its columns, then faostat_dataframe_query for deeper SQL.
Assemble a global profile for one QCL item in a single call: top-producing countries, the annual production trend, and trade flows (top exporters and importers). Supply item_code or item_query; code wins when both are supplied. A query selects a unique normalized exact label, otherwise a unique relevance match; ambiguous queries require an explicit code. Each ranking uses the selected item at each country's own latest year with data, grouped by unit. The trend is returned inline as year/value points. Country-level only (aggregates excluded). QCL is required; unavailable TCL yields a production-only profile with a notice. When the merged observation set is too large to inline, it spills to a DataCanvas table (canvas_id + table_name) — call faostat_dataframe_describe for its columns, then faostat_dataframe_query for deeper SQL.
faostat_dataframe_querychangedinput schemafaostat_commodity_profilechangeddescription, output schemaAssemble a global profile for one commodity in a single call: top-producing countries, the annual production trend, and trade flows (top exporters and importers). Accepts a commodity name, resolves it to item codes, then queries the production (QCL) and trade (TCL) domains and merges the results. Each ranking is a per-country sum across the resolved items, taken at that country's own latest year with data and grouped by unit so incomparable quantities are never added. The trend is returned inline as year/value points. Country-level only (aggregates excluded). When a required domain is not indexed locally, returns a partial profile with a notice naming the gap rather than failing. The full merged observation set spills to a DataCanvas table for deeper SQL via faostat_dataframe_query.
Assemble a global profile for one commodity in a single call: top-producing countries, the annual production trend, and trade flows (top exporters and importers). Accepts a commodity name, resolves it to item codes, then queries the production (QCL) and trade (TCL) domains and merges the results. Each ranking is a per-country sum across the resolved items, taken at that country's own latest year with data and grouped by unit so incomparable quantities are never added. The trend is returned inline as year/value points. Country-level only (aggregates excluded). The production domain (QCL) is required. When the trade domain (TCL) is not indexed locally, returns a production-only profile with a notice naming the gap rather than failing. When the merged observation set is too large to inline, it spills to a DataCanvas table (canvas_id + table_name) — call faostat_dataframe_describe for its columns, then faostat_dataframe_query for deeper SQL.
faostat_query_observationschangeddescription, output schemaQuery a FAOSTAT domain's data cube by area(s), item(s), element(s), and year range, returning observations (area, item, element, year, value, unit, and the data-quality flag). Resolve codes first with faostat_resolve_codes — the cube is unqueryable without them. Aggregate regions (World, continents, economic groupings) are EXCLUDED by default so a naive SUM does not double-count a region with its member countries; set include_aggregates=true to get the regional roll-ups, or pass explicit area_codes to query exactly what you name. Small result sets return inline; large ones spill to a DataCanvas table (returned canvas_id + table_name) for GROUP BY / ranking / time-series analysis via faostat_dataframe_query. Every row carries its flag — commonly A=Official, B=time-series break, E=Estimated, I=Imputed, M=Missing (value cannot exist), T=Unofficial, X=from an international organization, plus others FAOSTAT defines per domain — so honor it, treat any unrecognized flag as informational, and never assume an estimated, imputed, or unrecognized value is official.
Query a FAOSTAT domain's data cube by area(s), item(s), element(s), and year range, returning observations (area, item, element, year, value, unit, and the data-quality flag). Resolve codes first with faostat_resolve_codes — the cube is unqueryable without them. Aggregate regions (World, continents, economic groupings) are EXCLUDED by default so a naive SUM does not double-count a region with its member countries; set include_aggregates=true to get the regional roll-ups, or pass explicit area_codes to query exactly what you name. Small result sets return inline; large ones spill to a DataCanvas table (returned canvas_id + table_name) — call faostat_dataframe_describe for its columns, then faostat_dataframe_query for GROUP BY / ranking / time-series analysis. Every row carries its flag — commonly A=Official, B=time-series break, E=Estimated, I=Imputed, M=Missing (value cannot exist), T=Unofficial, X=from an international organization, plus others FAOSTAT defines per domain — so honor it, treat any unrecognized flag as informational, and never assume an estimated, imputed, or unrecognized value is official.
faostat_resolve_codeschangedoutput schemaFull history: list_changes · trend: quality JSON.
Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed. How it is computed.
+repository +namespace-matches-repo +reachable +uptime-100% +updated-2d-ago
Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed. How it is computed.
@cyanheads/[email protected] npmthis version is not known to the dependency resolver
@cyanheads/[email protected] npmthis version is not known to the dependency resolver
Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0. The graph is what a clean install of this version resolves today; nothing was installed or run. How it is checked.
| remote | auth | reachable | uptime 30d | p50 | protocol | last ok |
|---|---|---|---|---|---|---|
https://faostat.caseyjhand.com/mcp streamable-http | none | yes | 100% | 187 ms | 2026-07-28 | 2026-10-20 |
| package | registry | version | runtime | secrets |
|---|---|---|---|---|
@cyanheads/faostat-mcp-server | npm | 0.4.0 | npx | |
@cyanheads/faostat-mcp-server | npm | 0.4.0 | npx |
faostat_commodity_profileread-only | Assemble a global profile for one QCL item in a single call: top-producing countries, the annual production trend, and trade flows (top exporters and importers). Supply item_code or item_query; code wins when both are supplied. A query selects a unique normalized exact label, otherwise a unique relevance match; ambiguous queries require an explicit code. Each ranking uses the selected item at each country's own latest year with data, grouped by unit. The trend is returned inline as year/value points. Country-level only (aggregates excluded). QCL is required; unavailable TCL yields a production-only profile with a notice. When the merged observation set is too large to inline, it spills to a DataCanvas table (canvas_id + table_name) — call faostat_dataframe_describe for its columns, then faostat_dataframe_query for deeper SQL. |
faostat_dataframe_describeread-only | List the canvas tables (faostat_xxxxxxxx) staged by faostat_query_observations and faostat_commodity_profile, each with its source tool, the query parameters that produced it, creation/expiry timestamps, row count, and column schema. Call this before faostat_dataframe_query to discover the exact table and column names to reference in SQL. Tables are listed newest-first and paged: pass `name` to describe one table outright, or page with `offset` + `limit` — when the response reports `truncated`, pass the returned `nextOffset` to fetch the rest. |
faostat_dataframe_queryread-only | Run a single-statement SELECT against the canvas tables staged by faostat_query_observations and faostat_commodity_profile (table names look like faostat_xxxxxxxx). Use this for cross-country and cross-item aggregation, GROUP BY rankings, joins, and time-series analysis over the full result set the inline preview only sampled. Standard DuckDB SQL — joins, aggregates, window functions, CTEs all work. Read-only: writes, DDL, DROP, COPY, PRAGMA, ATTACH, and external-file table functions are rejected; system catalogs (information_schema, sqlite_master, duckdb_*) are denied — list staged tables via faostat_dataframe_describe. Every row carries its data-quality `flag` — commonly A=Official, B=time-series break, E=Estimated, I=Imputed, M=Missing (value cannot exist), T=Unofficial, X=from an international organization, plus others FAOSTAT defines per domain — keep it in projections, treat any unrecognized flag as informational, and never assume it is official. |
faostat_list_domainsread-only | Discover FAOSTAT statistical domains (production, trade, food balances, food security, land use, agri-emissions, prices, value) with their codes, descriptions, last-update date, upstream row count, and local index status. Every query keys on a domain code from here. The `indexed` flag tells you which domains are queryable right now; un-indexed domains exist in the catalog but must be added to FAOSTAT_DOMAINS and re-synced before faostat_query_observations can read them. The catalog runs to ~69 domains with long descriptions, so responses are paged: narrow with `topic` / `indexed_only`, pass `code` to fetch one domain outright, or page with `offset` + `limit` — when the response reports `truncated`, pass the returned `nextOffset` to fetch the rest. |
faostat_query_observationsread-only | Query a FAOSTAT domain's data cube by area(s), item(s), element(s), and year range, returning observations (area, item, element, year, value, unit, and the data-quality flag). Resolve codes first with faostat_resolve_codes — the cube is unqueryable without them. Aggregate regions (World, continents, economic groupings) are EXCLUDED by default so a naive SUM does not double-count a region with its member countries; set include_aggregates=true to get the regional roll-ups, or pass explicit area_codes to query exactly what you name. Small result sets return inline; large ones spill to a DataCanvas table (returned canvas_id + table_name) — call faostat_dataframe_describe for its columns, then faostat_dataframe_query for GROUP BY / ranking / time-series analysis. Every row carries its flag — commonly A=Official, B=time-series break, E=Estimated, I=Imputed, M=Missing (value cannot exist), T=Unofficial, X=from an international organization, plus others FAOSTAT defines per domain — so honor it, treat any unrecognized flag as informational, and never assume an estimated, imputed, or unrecognized value is official. |
faostat_resolve_codesread-only | Resolve human terms to the opaque integer codes faostat_query_observations needs, within a dimension: areas (countries/regions), items (commodities), or elements (metrics like production, yield, import quantity). Pass `query` for fuzzy full-text matching ("maize" → item 56), `name_contains` for a substring filter, or `code` for an exact-code lookup; omit all three to list the whole dimension. Item and element results are scoped to the requested domain — only codes present in that domain's cube are returned, so a resolved code is always queryable there (areas are shared across domains). Page large listings with `offset` + `limit`: when the response reports `truncated`, pass the returned `nextOffset` to fetch the next page. Every area match is flagged `country` or `aggregate` — aggregates (World, continents, economic groupings — codes ≥ 5000 plus a few curated sub-threshold roll-ups such as China=351, which sums mainland + Taiwan + Hong Kong + Macao) double-count if summed with their member countries, so resolve before querying and exclude aggregates unless you want the regional roll-up. |
Schemas: list_tools.
And 140 more from this publisher.
{
"name": "io.github.cyanheads/faostat-mcp-server",
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"remotes": [
{
"url": "https://faostat.caseyjhand.com/mcp",
"type": "streamable-http"
}
],
"version": "0.4.0",
"packages": [
{
"version": "0.4.0",
"transport": {
"type": "stdio"
},
"identifier": "@cyanheads/faostat-mcp-server",
"runtimeHint": "npx",
"registryType": "npm",
"registryBaseUrl": "https://registry.npmjs.org",
"environmentVariables": [
{
"name": "FAOSTAT_DOMAINS",
"format": "string",
"default": "QCL,TCL,FBS,FS,RL,GLE,RFN,QV",
"description": "Comma-separated FAOSTAT domain codes to index into the local mirror."
},
{
"name": "FAOSTAT_MIRROR_PATH",
"format": "string",
"default": "./.faostat-mirror",
"description": "Directory holding the per-domain SQLite mirror databases and the shared dimension database."
},
{
"name": "FAOSTAT_BULK_BASE_URL",
"format": "string",
"default": "https://bulks-faostat.fao.org/production",
"description": "FAOSTAT bulk-download service base URL (manifest + per-domain ZIPs)."
},
{
"name": "CANVAS_PROVIDER_TYPE",
"format": "string",
"default": "duckdb",
"description": "Set to 'duckdb' to enable the DataCanvas SQL surface (default), or 'none' to disable analytical staging."
},
{
"name": "FAOSTAT_DATAFRAME_DROP_ENABLED",
"format": "boolean",
"default": "false",
"description": "Set to 'true' to make faostat_dataframe_drop callable, so a staged table can be dropped before its 2-hour TTL. Off by default: the tool is registered disabled."
},
{
"name": "MCP_LOG_LEVEL",
"format": "string",
"default": "info",
"description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn')."
}
]
},
{
"version": "0.4.0",
"transport": {
"url": "http://localhost:3010/mcp",
"type": "streamable-http"
},
"identifier": "@cyanheads/faostat-mcp-server",
"runtimeHint": "npx",
"registryType": "npm",
"registryBaseUrl": "https://registry.npmjs.org",
"environmentVariables": [
{
"name": "MCP_TRANSPORT_TYPE",
"value": "http",
"format": "string",
"description": "Selects the HTTP transport."
},
{
"name": "MCP_HTTP_HOST",
"format": "string",
"default": "127.0.0.1",
"description": "The hostname for the HTTP server."
},
{
"name": "MCP_HTTP_PORT",
"format": "string",
"default": "3010",
"description": "The port to run the HTTP server on."
},
{
"name": "MCP_HTTP_ENDPOINT_PATH",
"format": "string",
"default": "/mcp",
"description": "The endpoint path for the MCP server."
},
{
"name": "MCP_AUTH_MODE",
"format": "string",
"default": "none",
"description": "Authentication mode to use: 'none', 'jwt', or 'oauth'."
},
{
"name": "FAOSTAT_DOMAINS",
"format": "string",
"default": "QCL,TCL,FBS,FS,RL,GLE,RFN,QV",
"description": "Comma-separated FAOSTAT domain codes to index into the local mirror."
},
{
"name": "FAOSTAT_MIRROR_PATH",
"format": "string",
"default": "./.faostat-mirror",
"description": "Directory holding the per-domain SQLite mirror databases and the shared dimension database."
},
{
"name": "FAOSTAT_BULK_BASE_URL",
"format": "string",
"default": "https://bulks-faostat.fao.org/production",
"description": "FAOSTAT bulk-download service base URL (manifest + per-domain ZIPs)."
},
{
"name": "FAOSTAT_REFRESH_CRON",
"format": "string",
"description": "Cron expression for the in-process incremental mirror refresh (HTTP transport only). Omit to disable."
},
{
"name": "CANVAS_PROVIDER_TYPE",
"format": "string",
"default": "duckdb",
"description": "Set to 'duckdb' to enable the DataCanvas SQL surface (default), or 'none' to disable analytical staging."
},
{
"name": "FAOSTAT_DATAFRAME_DROP_ENABLED",
"format": "boolean",
"default": "false",
"description": "Set to 'true' to make faostat_dataframe_drop callable, so a staged table can be dropped before its 2-hour TTL. Off by default: the tool is registered disabled."
},
{
"name": "MCP_LOG_LEVEL",
"format": "string",
"default": "info",
"description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn')."
}
]
}
],
"repository": {
"url": "https://github.com/cyanheads/faostat-mcp-server",
"source": "github"
},
"description": "UN FAOSTAT global food & agriculture statistics over a local SQLite mirror, via MCP."
}