Tools and playbooks
The server exposes six callable tools and three research playbooks. The playbooks matter as much as the tools: the server is designed as a guided research interface, not a collection of unrelated API calls, and the tool descriptions themselves point clients at the playbook to read first.
The six tools¶
| Tool | What it does | Typical place in a workflow |
|---|---|---|
search_indicators | Searches topics and statistical variables matching a natural-language concept; can optionally verify availability for named places | First step for normal indicator discovery |
search_child_indicators | Searches for indicators with data for the child places of a parent geography, checked against a sample of them | First step when a question spans the countries within the world, a continent, a UN region or another geographic grouping |
get_variable_metadata | Retrieves definitions, source facets, date coverage, provenance and entity coverage for candidate variables | Qualification step before retrieving observations |
get_observations | Retrieves observations for one statistical variable at one target place | Final retrieval step for the normal single-place workflow |
get_child_observations | Retrieves observations for a variable across child places of a specified type within a parent place | Final retrieval step for child-place workflows |
get_multi_entity_observations | Retrieves observations for variables involving multiple entity dimensions, such as bilateral flows | Retrieval step for multi-entity variables |
The tool schemas visible in the MCP Inspector are the best source for the exact current parameters. You do not need to memorise them.
search_indicators¶
Searches the UN System Data Commons’ index of topics and statistical variables for a
natural-language query — for example, simply population. The tool can also be scoped
to particular places to check whether matching indicators have data for those places.
This is usually the best first tool for a new research question, and its candidates are
the identifiers the rest of the workflow uses.
get_variable_metadata¶
Retrieves detailed metadata for selected statistical variables, including structural
information, temporal coverage, provenance and entity coverage. Use it after indicator
discovery and before requesting large amounts of observation data; its variable_dcids
should be candidates from the preceding search.
get_observations¶
Retrieves observations for one statistical variable at one target place. The
date parameter selects what comes back — see Date modes below. Its
variable_dcid should normally be the candidate selected in the preceding discovery and
assessment steps: the tool retrieves whatever variable it is given, so keeping research
within the corpus is the discipline of the research rules, not a
property of the tool.
search_child_indicators¶
Searches for indicators available for the child places within a parent geography. The
tool takes the parent and a sample of five or six of its children and reports which of
the sample have data for each candidate; the playbook treats that sample as a proxy for
every child of that type. The parent–child relation is the knowledge graph’s containment
hierarchy, at any level. In the current workflows the parent is the world, a continent,
a UN region or another geographic grouping, and the children are countries — the
countries within Sub-Saharan Africa, the countries returned for the Small Island
Developing States. A search for the provinces of a country succeeds and returns no
variables, because no subnational observations are currently loaded; see
Geographic scope. Read
skill://data-commons-child-places-researcher/SKILL.md before using this workflow.
get_child_observations¶
Retrieves observations across child places within a parent geography. It requires a
statistical variable, a parent place and a child place type. For the current
country-comparison workflows, use Country as the child place type, with the world, a
continent, a UN region or another geographic grouping as the parent. The countries
returned for a grouping are those the knowledge graph records as contained in it, which
need not coincide with an official membership list. A supranational place itself is
queried as a single place with get_observations. As with get_observations, the
variable should be the one selected from a search_child_indicators result. Use
latest or a bounded range (date="range" with date_range_start and
date_range_end) to avoid unnecessarily large responses.
On the current platform a large answer, such as every country in the world, is
complete in its observations but not in its labels: entityMetadata lists every place
DCID, and for the tail of the list beyond roughly 150 countries the name is blank and
typeOf empty. No observation is missing. Use the DCID where the name is blank, as
Walkthrough B does; where names are needed, take them
from the dcidNameMappings of a search that named those places, or read ->name on
the graph’s node endpoint as on
Inspecting the graph.
get_multi_entity_observations¶
Retrieves observations for statistical variables that describe relationships between
multiple entities — foreign aid flows, bilateral trade, international migration.
Instead of a single place, the request supplies named entity dimensions such as donor
and recipient. Its variable_dcid, like the others’, comes from discovery: a candidate
whose observation_properties carry the entity roles. Read
skill://data-commons-multi-entity-researcher/SKILL.md first.
On this instance the tool has no applicable target, and not for want of an example:
the UN corpus models a counterpart, origin or destination as a constraint in the
statistical variable’s identity, and its observation store filters only on the standard
components (place, date, facet, unit, provenance), so no UN variable carries entity
roles and no entity filter can be applied. Walkthrough C
shows the evidence and the single-place alternative. Do not reach for a variable from
outside the corpus to exercise the tool.
Current tool schemas¶
The tables in this section are generated from the live server when the site is
built — the same tools/list the Inspector shows — so they cannot drift from what
the server accepts. The curated table above says when to use a tool; this section
says exactly what it takes. The schema carries types, defaults and required flags but
no per-parameter descriptions, which is why the descriptions and the
date modes above matter. The descriptions are the upstream Data Commons
server’s generic text. Where they say sub-national coverage, or give County and
State as example child place types, they describe what the tools can traverse, not
the data loaded here: read the countries within a region or geographic grouping — see
Geographic scope. Where get_multi_entity_observations illustrates
its parameters with Amount_EconomicActivity_GrossODA, that identifier comes from the
wider Data Commons graph, not from this corpus: obtain a variable through the search
tools rather than copying it — see Statistical scope.
search_indicators¶
CRITICAL: Before calling this tool for the first time in a session, you MUST read the playbook resource by calling your platform’s standard MCP resource-reading capability for the URI ‘skill://data-commons-researcher/SKILL.md’.
Search the Data Commons Knowledge Graph for topics and statistical variables (indicators) matching a natural language query. Returns candidate indicator DCIDs, names, and data availability mappings. Can be optionally scoped to a list of target places to verify data presence.
| Parameter | Type | Required | Default |
|---|---|---|---|
query | string | yes | |
places | array | null | no | |
per_search_limit | integer | no | 10 |
include_topics | boolean | no | true |
search_child_indicators¶
CRITICAL: Before calling this tool for the first time in a session, you MUST read the playbook resource by calling your platform’s standard MCP resource-reading capability for the URI ‘skill://data-commons-child-places-researcher/SKILL.md’.
Search the Data Commons Knowledge Graph for statistical indicators available at the child-place level within a parent geographic entity. Returns candidate indicator DCIDs and child place data availability mappings. Requires providing a parent place and a diverse sample list of its child places to verify sub-national coverage.
| Parameter | Type | Required | Default |
|---|---|---|---|
query | string | yes | |
parent_place | string | yes | |
sample_child_places | array | yes | |
per_search_limit | integer | no | 10 |
include_topics | boolean | no | true |
get_variable_metadata¶
Retrieve detailed structural metadata, including definitions, temporal coverage, and provenances, for a list of statistical variables. Returns a dictionary mapping variables to their source facets and entity coverages. Use this to assess and qualify variables before fetching heavy observation data.
| Parameter | Type | Required | Default |
|---|---|---|---|
variable_dcids | array | yes | |
entity_dcids | array | yes |
get_observations¶
Retrieve time-series numerical observations for a specific statistical variable at a target place. Returns an array of dated observation values and their source metadata. Operates in single-place mode; for child-level containment data, use get_child_observations.
| Parameter | Type | Required | Default |
|---|---|---|---|
variable_dcid | string | yes | |
place_dcid | string | yes | |
source_override | string | null | no | |
date | string | no | "latest" |
date_range_start | string | null | no | |
date_range_end | string | null | no |
get_child_observations¶
Retrieve time-series numerical observations for a statistical variable across all child places of a specific type within a parent geographic entity. Returns an array of dated observation values for each child place and their source metadata. Requires specifying the child place type (e.g., ‘County’ or ‘State’) and a bounded date range or ‘latest’ filter to prevent payload saturation.
| Parameter | Type | Required | Default |
|---|---|---|---|
variable_dcid | string | yes | |
parent_place_dcid | string | yes | |
child_place_type | string | yes | |
source_override | string | null | no | |
date | string | no | "latest" |
date_range_start | string | null | no | |
date_range_end | string | null | no |
get_multi_entity_observations¶
Fetches time-series observations for multi-entity relationship statistical variables (e.g. foreign aid flows, bilateral trade, international migration).
Parameters¶
variable_dcid(required, string): Statistical variable DCID (e.g.,"Amount_EconomicActivity_GrossODA").entities(required, dictionary of string lists): Map of entity property names to list of entity DCIDs (e.g.{"donor": ["country/ARE"], "recipient": ["country/AFG"]}).parent_entity_property(optional, string): Entity property name for child place expansion (e.g."recipient").parent_entity_dcid(optional, string): Parent place DCID for child place expansion (e.g."Earth").child_entity_type(optional, string): Child place type for child place expansion (e.g."Country").source_override(optional, string): Filter by a specific data source provenance DCID.date(optional, string): Specific date (e.g.,"2024"),"all"(for complete historical time series), or"latest"(default).date_range_start/date_range_end(optional, string): Date range boundaries.
Important: parent_entity_property, parent_entity_dcid, and child_entity_type are co-dependent. If requesting child expansion, all three must be specified together.
Usage Example (Direct Bilateral Pair)¶
{
"variable_dcid": "Amount_EconomicActivity_GrossODA",
"entities": {
"donor": ["country/ARE"],
"recipient": ["country/AFG"]
}
}Usage Example (Child Entity Expansion)¶
{
"variable_dcid": "Amount_EconomicActivity_GrossODA",
"entities": {
"donor": ["country/ARE"]
},
"parent_entity_property": "recipient",
"parent_entity_dcid": "Earth",
"child_entity_type": "Country"
}| Parameter | Type | Required | Default |
|---|---|---|---|
variable_dcid | string | yes | |
entities | object | yes | |
parent_entity_property | string | null | no | |
parent_entity_dcid | string | null | no | |
child_entity_type | string | null | no | |
source_override | string | null | no | |
date | string | no | "latest" |
date_range_start | string | null | no | |
date_range_end | string | null | no |
Date modes¶
The observation tools share one date parameter, and the schema does not explain it.
The playbooks do:
date | Returns |
|---|---|
"latest" (the default when no date parameter is given) | the most recent observation in the facet the server selects, see below |
"all" | the complete series |
"range" with date_range_start and/or date_range_end | a bounded series; either bound alone is inclusive and open-ended on the other side |
a literal YYYY, YYYY-MM or YYYY-MM-DD | that single period |
Set date="range" explicitly whenever you pass a bound. On the current server the
bounds take effect only with date="range"; supplied while date keeps its default
"latest", they are silently ignored and one latest value comes back. The playbooks’
wording (“define a narrow window using date_range_start and date_range_end”) does
not say so. The intended contract is that such a call is either applied as a range or
rejected.
Two rules from the child-places playbook: with child_place_type active never set
date="all" — use "latest" or a narrow range — because the answer multiplies by the
number of child places.
"latest" means the most recent observation in the facet the server selects for the
call, which is not necessarily the most recent year. Where a variable has monthly,
quarterly and annual facets, as ILO’s unemployment rate does, the default answer can be
a monthly or quarterly value with a YYYY-MM date, with the annual series listed under
alternativeSources. If you need annual data, read the facets in
get_variable_metadata, pick the one whose observationPeriod is P1Y, and pass its
id as source_override. A year label is also not always a simple annual measurement:
some source series date an assessment or a multi-year average to a single year, so
check the source’s definition before treating consecutive years as a comparable annual
series.
source_override on the observation tools takes a facet id (such as
9589496361978137601, the facet column of the metadata response), not a provenance
DCID: undata/p/UNICEF passed there matches nothing and returns no rows. The metadata
response names both, so read the id from the facet you chose.
The playbooks¶
The three SKILL.md resources are the operational guidance for clients using the
server (they were introduced on What the server does):
skill://data-commons-researcher/SKILL.md
skill://data-commons-child-places-researcher/SKILL.md
skill://data-commons-multi-entity-researcher/SKILL.mdEach also has a _manifest resource listing its files and their content hashes. They are
rendered verbatim in this book — general research,
child places,
multi-entity — or read them from the
Inspector under Resources, or from the command line:
URL='https://unsd-datacommons.gcp.un-icc.cloud/mcp'
npx -y @modelcontextprotocol/inspector@2.6.0 --cli "$URL" \
--transport http --method resources/read \
--uri 'skill://data-commons-researcher/SKILL.md'The general playbook defines a three-step pipeline and two routing rules:
If the question is about statistics across the places contained in a parent geography — today, the countries within the world, a continent, a UN region or another geographic grouping — read the child-places skill instead.
If candidate metadata shows multiple observation entity properties, read the multi-entity skill and use the multi-entity observation tool.
Operating rules from the general playbook¶
The data-commons-researcher playbook currently establishes these minimum rules, and
this deployment adds two of its own, on identifiers and on separating concept from
place:
Search one semantic concept at a time. Split compound requests into separate indicator searches.
Treat search results as candidates, not final selections.
For place-specific research, call
search_indicatorsbefore metadata or observation retrieval.Use
get_variable_metadatato verify source, date range and coverage before fetching time series.Do not guess or import statistical-variable DCIDs. Use the identifiers the search tools return. Shared place identifiers (
country/RWA,Earth,africa) may be used for geographic identity and navigation. The research rules hold this in one place.Keep the statistical concept and the place separate during discovery. Put the concept in
queryand the geography inplaces,parent_placeorsample_child_places:query="total population"withplaces=["Rwanda"], notquery="population of Rwanda". The search component is there to identify the statistical concept; the place arguments resolve and qualify the geography. With the current server a place name inside the query text pulls the search towards unrelated variables or returns nothing at all, so this is the recommended workflow for the present MCP rather than a permanent rule. A place that is part of the concept itself, such as the country of origin in refugees from Afghanistan, stays in the query.In the
placesparameter ofsearch_indicators, use qualified human-readable place names rather than place DCIDs, and qualify ambiguous names. The playbook’s example isWashington, DC, USAversusWashington State, USA; the case that bites on this instance isGeorgia, which resolves to the US state (a place without data here) unless writtenGeorgia, Asiafor the country.Keep the default
per_search_limit=10unless there is a reason to request more.Use
include_topics=truefor exploratory questions and considerinclude_topics=falsefor a narrowly targeted indicator search.Observation retrieval defaults to the latest value when no date parameters are supplied; use bounded ranges for historical retrieval where possible, and set
date="range"explicitly with either bound, because bounds without it are ignored on the current server (Date modes).Attribute every data point. The server’s own instructions require it: “every data point retrieved must be attributed to its original source provided in the tool output; never present statistics as known facts without citing the specific organization or dataset they originated from.” The provenance is in every observation response.
Prompts¶
The server currently returns an empty list from prompts/list:
{
"prompts": []
}This is normal. The main interface at present is through tools and resources.