# io.github.cyanheads/unhcr-refugees-mcp-server

> Query UNHCR refugee, IDP, and stateless populations, asylum decisions, returns, and resettlement.

- name: io.github.cyanheads/unhcr-refugees-mcp-server
- version: 0.2.0
- connection class: R0 (autonomous)
- trust: 94/100
- quality: 84/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/io.github.cyanheads%2Funhcr-refugees-mcp-server
- tools: https://api.protogrid.dev/v1/servers/io.github.cyanheads%2Funhcr-refugees-mcp-server/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "unhcr-refugees-mcp-server": {
      "type": "http",
      "url": "https://unhcr-refugees.caseyjhand.com/mcp"
    }
  }
}
```


## Trust

- hygiene: 100
- liveness: 100
- freshness: 100
- provenance: 80
- drivers: +repository +namespace-matches-repo +reachable +uptime-100% +updated-1d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 84/100 (good)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 86 (weight 30)

- pass `tools.descriptions`: every tool has a description
- pass `tools.description_length`: descriptions are concise
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 8 of 8 tools declare readOnlyHint or destructiveHint
- fail `tools.directory_hints`: no tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: unhcr_list_reference (destructiveHint); unhcr_get_solutions (destructiveHint); unhcr_get_population (destructiveHint); …
- pass `tools.token_cost`: about 6,873 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 75 (weight 15)

- warn `stability.changes`: 7 tool changes in 30 days
- pass `stability.rug_pull`: no tool changed its meaning under the same name

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: deps.dev does not know @cyanheads/unhcr-refugees-mcp-server@0.2.0, @cyanheads/unhcr-refugees-mcp-server@0.2.0

- tools: 8, about 6,873 tokens to load them all
- tool set hash: 974048b7795f5fbe18d71f6cf13bfcc7
- tools last changed: 2026-10-20T11:29:37.447Z
- badge: [![protogrid quality](https://protogrid.dev/badge/io.github.cyanheads/unhcr-refugees-mcp-server.svg)](https://protogrid.dev/servers/io.github.cyanheads/unhcr-refugees-mcp-server)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-20 `unhcr_dataframe_query` changed (description, inputSchema, outputSchema)
  - before: Run a single-statement SELECT against the dataframes staged by the unhcr_get_* tools. Check a dataframe’s columns with unhcr_dataframe_describe first. Read-only: writes, DDL, DROP, COPY, PRAGMA, ATTACH, external-file functions, and system catalogs (information_schema, pg_catalog, sqlite_master, duckdb_*) are rejected. Optional register_as saves the result as a new dataframe with a fresh TTL. Recompute rates from summed counts rather than averaging rate columns.
  - after: Run a single-statement SELECT against the dataframes staged by the unhcr_get_* tools. Check a dataframe’s columns with unhcr_dataframe_describe first. Writes, DDL, DROP, COPY, PRAGMA, ATTACH, file references, external-data functions, engine introspection, dynamic table lookup, and system catalogs are rejected; query() accepts only a single SQL string literal, checked by the same gate. Optional register_as saves the result as a new dataframe with a fresh TTL. Recompute rates from summed counts rather than averaging rate columns.
- 2026-10-20 `unhcr_dataframe_describe` changed (outputSchema)
- 2026-10-20 `unhcr_get_solutions` changed (inputSchema)
- 2026-10-20 `unhcr_get_asylum_decisions` changed (inputSchema)
- 2026-10-20 `unhcr_get_asylum_applications` changed (inputSchema)
- 2026-10-20 `unhcr_get_demographics` changed (inputSchema)
- 2026-10-20 `unhcr_get_population` changed (inputSchema)

Full history: https://api.protogrid.dev/v1/servers/io.github.cyanheads%2Funhcr-refugees-mcp-server/changes

## Dependencies

- npm @cyanheads/unhcr-refugees-mcp-server@0.2.0: unknown
- npm @cyanheads/unhcr-refugees-mcp-server@0.2.0: unknown

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0.

## Remotes

- https://unhcr-refugees.caseyjhand.com/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

- npm @cyanheads/unhcr-refugees-mcp-server@0.2.0
- npm @cyanheads/unhcr-refugees-mcp-server@0.2.0

## Tools (8)

- `unhcr_dataframe_describe`: Describe a dataframe (df_XXXXX_XXXXX) staged by the unhcr_get_* tools — any response carrying a dataset handle staged its full result here — or list them all where this deployment allows listing. Each entry gives the source tool, query parameters, creation and expiry time, row count, whether the upstream fetch was complete, and the column schema. Read the columns here before writing SQL for unhcr_dataframe_query.
- `unhcr_dataframe_query`: Run a single-statement SELECT against the dataframes staged by the unhcr_get_* tools. Check a dataframe’s columns with unhcr_dataframe_describe first. Writes, DDL, DROP, COPY, PRAGMA, ATTACH, file references, external-data functions, engine introspection, dynamic table lookup, and system catalogs are rejected; query() accepts only a single SQL string literal, checked by the same gate. Optional register_as saves the result as a new dataframe with a fresh TTL. Recompute rates from summed counts rather than averaging rate columns.
- `unhcr_get_asylum_applications`: Get asylum applications lodged per year (2000 to the latest year) by country of origin and/or asylum, split by default into application stage — new, repeat, appeal, and the combined stages some countries report — so new claims are not added to appeals of old ones. Counts given as cases are never added to counts of persons; each row states its unit. Decode stage, authority, and decision-level codes with unhcr_list_reference (topic asylum_codes).
- `unhcr_get_asylum_decisions`: Get asylum decisions per year (2000 to the latest year) by country of origin and/or asylum: recognized as refugees, complementary protection, rejected, and otherwise closed, with UNHCR's Refugee Recognition Rate and Total Protection Rate computed over substantive decisions (otherwise-closed cases excluded). By default all decision levels are summed and each row lists the levels it includes; appeal-stage decisions can concern people already decided at first instance, so split_by decision_level or filter decision_levels to FI for first-instance rates. Cases and persons are never added together.
- `unhcr_get_demographics`: Get UNHCR year-end stocks (2001 to the latest year) broken down by population type, sex, and age band (0–4, 5–11, 12–17, 18–59, 60+, unknown age), by country of origin and/or asylum. Coverage is partial: each row gives the share of its total that UNHCR could disaggregate by sex, and age bands are null where no breakdown exists. These totals come from a separate collection and need not match unhcr_get_population.
- `unhcr_get_population`: Get UNHCR year-end displacement stocks (1951 to the latest year) by country of origin and/or asylum: refugees, asylum-seekers, other people in need of international protection, IDPs, stateless people, others of concern, and host communities, plus refugees and IDPs who returned during the year. Stocks count people in a situation on 31 December, not arrivals. Palestine refugees under UNRWA's mandate and IDMC's conflict-IDP estimate are separate series shown beside each row. Set include_nowcast for UNHCR's current-year estimate by asylum country; for sex and age breakdowns, use unhcr_get_demographics.
- `unhcr_get_solutions`: Get durable solutions per year (1959 to the latest year) by country of origin and/or asylum: refugees who returned home, refugees resettled to a third country, refugees naturalised, and IDPs who returned. The asylum country means something different per column: the country refugees returned from, the country they were resettled to, the country that naturalised them; IDP returns sit on the origin country itself. Null means the figure was not collected for that country and year, not zero.
- `unhcr_list_reference`: Decode the vocabulary the unhcr_* tools take as input: countries (ISO3, ISO2, UNHCR code, names, UNHCR and UN regions), UNHCR’s regional bureaus, each dataset’s first and latest year, population-type definitions, and the asylum authority, stage, decision-level, and unit codes. Filter countries with name_contains to turn a country name into the ISO3 code that origin and asylum take.
