Unhcr Refugees Mcp Server

io.github.cyanheadsPublished by GitHub account cyanheadsv0.3.0Updated Nov 4, 2026

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

VerifiedStreamable HTTPWeb executableDatabasesData & Analytics

Overview

AI-generated overview

Queries UNHCR Refugee Data Finder statistics — refugee, IDP and stateless stocks, asylum applications and decisions, returns and resettlement — with read-only…

What you can do
  • Look up reference data: countries and ISO codes, regions, dataset coverage years, population types and asylum codes
  • Fetch year-end displacement stocks by origin and asylum country, with optional demographics by sex and age band
  • Retrieve annual asylum applications and decisions, including recognition and protection rates
  • Get durable solutions flows: refugee returns, resettlement, naturalisation and IDP returns
  • Describe staged result tables and run one read-only SQL SELECT across them, optionally saving the result as a new table
When to use it
Useful when an assistant needs authoritative, citable displacement figures for research, reporting or analysis, or when large UNHCR result sets must be aggregated and joined with SQL rather than read inline.
Requirements
Runs as a hosted remote endpoint or locally via npx (Node.js) or Docker; UNHCR's API is keyless, so no account or API key is needed. All environment variables are optional (transport, port, auth mode, cache, row caps, dataframe TTL). Dataframes need DuckDB, which the npm and Docker installs include.
Before you install
The hosted instance shares one request queue and one dataframe workspace across all callers, so staged tables are visible to others and listing is disabled there. Staged tables expire (24 hours by default) and are evicted past a row budget. Counts below 5 (below 10 for asylum decisions) are rounded, nulls mean not applicable rather than zero, and UNRWA/IDMC series are third-party data with their own terms; figures are CC BY 4.0 and the server is not endorsed by UNHCR.

Installation

In SourceWeft

  1. Open Unhcr Refugees Mcp Server in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.cyanheads%2Funhcr-refugees-mcp-server/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

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

README

@cyanheads/unhcr-refugees-mcp-server

Query UNHCR refugee, IDP, and stateless populations, asylum decisions, returns, and resettlement via MCP. STDIO or Streamable HTTP.

8 Tools (+1 opt-in)


Overview

Refugee and displacement statistics from the UNHCR Refugee Data Finder: refugee, asylum-seeker, IDP, and stateless populations since 1951, asylum applications and decisions since 2000, and returns and resettlement since 1959. Pull annual figures by country of origin and asylum, and run SQL over large results. No API key required.

Tools

ToolDescription
unhcr_list_referenceDecode countries (ISO3, ISO2, and UNHCR codes, names, regions), regional bureaus, dataset coverage years, population types, and asylum codes
unhcr_get_populationYear-end displacement stocks by origin and/or asylum country from 1951, with UNRWA and IDMC series alongside and an optional current-year nowcast
unhcr_get_demographicsYear-end stocks by population type, sex, and age band from 2001, with the share UNHCR could disaggregate
unhcr_get_asylum_applicationsAsylum applications lodged per year from 2000, split by application stage by default
unhcr_get_asylum_decisionsAsylum decisions per year from 2000 by outcome, with the Refugee Recognition Rate and Total Protection Rate
unhcr_get_solutionsRefugee returns, resettlement, naturalisation, and IDP returns per year from 1959
unhcr_dataframe_describeDescribe a staged dataframe by name, or list them all where listing is on, with provenance, expiry, completeness, and column schema
unhcr_dataframe_queryRun one read-only SQL SELECT across staged dataframes, optionally saving the result as a new one
unhcr_dataframe_dropDrop a staged dataframe before its TTL — opt-in, absent from tools/list by default

unhcr_dataframe_drop is registered only when UNHCR_DATAFRAME_DROP_ENABLED=true; the other eight tools are always advertised.

Dataframe workflow

  1. A unhcr_get_* call whose full result exceeds limit, or that sets stage: true, stages every row as a df_XXXXX_XXXXX table and returns its handle in dataset (nowcast_dataset for unhcr_get_population's nowcast).
  2. unhcr_dataframe_describe lists the staged tables with their columns, source call, and expiry. Listing is off over HTTP with MCP_AUTH_MODE=none, so there describe each table by the name in dataset or nowcast_dataset.
  3. unhcr_dataframe_query runs one read-only DuckDB SELECT across them; register_as saves the result as a new table for the next query.
  4. Tables expire after UNHCR_DATASET_TTL_SECONDS (24 hours by default). With UNHCR_DATAFRAME_DROP_ENABLED=true, unhcr_dataframe_drop removes one sooner. Once a tenant's staged rows pass 1,000,000, the oldest tables are evicted first, and the call that pushed the total over names them in evicted.

Dataframes run on DuckDB's native binding, which the npm and Docker installs carry. The Claude Desktop .mcpb bundle ships without it, so there the data tools answer inline only. Set CANVAS_PROVIDER_TYPE=none to turn dataframes off anywhere.

Agent skill

skills/unhcr-refugees-guide is a published Agent Skill. It covers the checks to make before summing or comparing UNHCR figures: which columns a total adds, stateless people under origin XXA, the two Palestine refugee series, the nowcast's missing origin, bureau and EU totals in SQL, filters that drop whole countries, units that switch between years, demographic shares, and footnotes. Plugin installs and the .mcpb bundle pick it up from the skills/ folder, and MCP clients that support skills read it as skill://unhcr-refugees-guide/SKILL.md.

Capability reference

The five unhcr_get_* tools share one contract:

  • Scope: origin and asylum take ISO3 codes, case-insensitive, as a string or a list, up to 250 distinct codes each, enough to list every country. ISO2 codes are rewritten to ISO3; UNHCR's own codes and country names are rejected. Each listed code returns its own rows, and an omitted dimension is summed into one row unless expand (origin, asylum, or both) lists every country. year_from / year_to default to the dataset's span and are clamped to it.
  • Rows: the full result is sorted by sort_by, then cut to limit (default 25, cap 2,000). A larger limit is served at 2,000 with a notice naming the requested and effective values, even for an empty or small result; with UNHCR_CLAMP_LIMITS=false it is rejected instead. Where dataframes are on, the full set of a larger result is staged, and stage: true stages a result that fits too.
  • Output: total_rows, complete (false when UNHCR_MAX_ROWS stopped the fetch), measure (stock or flow), applied_scope, latest_year, dataset when staged, data_notes, and attribution.
  • Errors: unknown_country_code, invalid_year_window, year_out_of_coverage, conflicting_scope, too_many_country_codes, and the retryable upstream_busy, which carries retryAfter.

unhcr_list_reference tool

  • topic: countries, regions, coverage, population_types, or asylum_codes. With countries, name_contains keeps countries whose names contain every word given, or whose ISO3, ISO2, or UNHCR code equals one; there is no fuzzy matching
  • coverage gives each dataset's first_year, latest_year, and measure, plus the month of the current nowcast
  • Countries, regions, and coverage come from the live API and are cached for 24 hours; population types and asylum codes are static, and asylum codes UNHCR's methodology does not define carry documented: false

unhcr_get_population tool

  • Year-end stocks refugees, asylum_seekers, oip, idps, stateless, ooc, and hst, plus returned_refugees and returned_idps, which are flows during the year; sort_by takes any of them or year
  • unrwa_refugees (Palestine refugees registered with UNRWA) and idmc_conflict_idps (IDMC's conflict-IDP estimate) sit beside a row when that series has one and are never added into UNHCR's counts. Matching UNHCR footnotes come back too, up to 20, with footnotes_total; caveats on the inline rows come first
  • include_nowcast: true appends UNHCR's current-year monthly estimate of refugees and asylum-seekers by asylum country, sorted by refugees or asylum_seekers when sort_by names one, cut to limit with nowcast_total, and staged as its own dataframe (nowcast_dataset) when it overflows or stage is set; it is skipped when origin lists codes

unhcr_get_demographics tool

  • population_types filters to REF, ASY, OIP, IDP, STA, OOC, HST, RET, or RDP; sort_by takes year or total
  • Each row is one population type: total, fourteen sex × age bands (female_0_4 … female_60_plus, female_unknown_age, female_total, and the male_* twins), disaggregated, and sex_disaggregated_share (0–1). Bands are null where UNHCR has no breakdown
  • Totals come from a separate collection and need not match unhcr_get_population; matching footnotes come back as there

unhcr_get_asylum_applications tool

  • split_by names which of authority, stage, and decision_level stay separate rows (default ["stage"]; [] gives one total per year, scope, and unit). stages filters before summing, e.g. ["N"] for new applications; sort_by takes year or applied
  • Each row lists the authorities, stages, and decision_levels codes summed into it, its unit (persons or cases), and applied. Cases are never added to persons

unhcr_get_asylum_decisions tool

  • split_by names which of authority and decision_level stay separate rows (default [], all summed, as UNHCR does for its rates). decision_levels filters before summing, e.g. ["FI"] for first instance
  • Each row carries recognized, complementary_protection, rejected, otherwise_closed, total_decisions, substantive_decisions, and a unit, plus refugee_recognition_rate and total_protection_rate as percentages of substantive decisions. A rate is null when that denominator is 0 or null
  • sort_by takes year or a count (total_decisions, substantive_decisions, recognized, rejected); rates are not sortable

unhcr_get_solutions tool

  • Flows returned_refugees, resettlement, naturalisation, and returned_idps; sort_by takes any of them or year. Matching footnotes come back as with population
  • 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

unhcr_dataframe_describe tool

  • Optional name (df_XXXXX_XXXXX); omit it to list every staged table, newest first. Over HTTP with MCP_AUTH_MODE=none listing is off and name is required
  • Each entry gives source_tool, query_params, created_at, expires_at, row_count, complete, incomplete_sources, providers, and column_schema. Saved descendants retain original incomplete-source handles after their ancestors expire or are evicted. Staged tables add origin_unhcr_region, origin_unsd_region, asylum_unhcr_region, and asylum_unsd_region columns the inline rows omit

unhcr_dataframe_query tool

  • sql is one DuckDB SELECT of at most 20,000 characters; joins, aggregates, window functions, and CTEs work. Writes, DDL, PRAGMA, ATTACH, file references, external-data functions, engine introspection (current_setting, current_schema, current_schemas, in_search_path), dynamic table lookup (query_table), and system catalogs are rejected with a typed reason. query() accepts only a single SQL string literal, checked by the same gate
  • row_limit caps the rows the query materializes, and row_count_capped flags a capped result. It defaults to 1,000, or to the canvas row cap (CANVAS_DEFAULT_ROW_LIMIT, 10,000 by default) when that is lower, and a larger value returns the canvas row cap with a notice naming requested and effective values. register_as saves the whole result under a new df_XXXXX_XXXXX name with a fresh TTL. It counts toward the 1,000,000-row staging budget, and a result that alone exceeds it fails register_as_too_large
  • preview sets the rows returned inline: default 25, at most 1,500 or row_limit, whichever is lower, with the same notice above the cap. preview: 0 returns the columns and counts with no rows. With UNHCR_CLAMP_LIMITS=false, a row_limit above the canvas row cap or a preview above 1,500 fails validation instead
  • SUM and COUNT values come back as strings (BIGINT). attribution credits the third-party series of every table the SQL reads
  • complete and incomplete_sources describe upstream coverage independently of display truncation: aggregates, joins and saved descendants remain partial if an original source was partial
  • Every returned value is whole on both surfaces. Results with plain labels and cells use Markdown tables; values needing exact whitespace, control characters, nested structures or Markdown syntax use fenced JSON

unhcr_dataframe_drop tool

  • name (df_XXXXX_XXXXX); returns dropped: false when nothing matched, so repeating a call is safe
  • Registered only when UNHCR_DATAFRAME_DROP_ENABLED=true; otherwise the per-table TTL reclaims staged tables

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

UNHCR-specific:

  • Keyless client for the API behind UNHCR's Refugee Data Finder (api.unhcr.org/population/v1). The API ignores unknown parameters and lone year bounds rather than rejecting them, so the server sends only allowlisted parameters, always pairs the year bounds, and pins ISO3 country matching (cf_type=ISO)
  • Shared request queue: paced request starts (UNHCR_REQUESTS_PER_SECOND), at most two in flight, a cooldown after a 429, identical requests collapsed into one, a response cache, and a 45-second budget per call
  • UNHCR's reading of the numbers: stocks and flows labelled as such, UNHCR's "-" returned as null rather than zero, cases never added to persons, recognition rates over UNHCR's substantive-decision denominator
  • UNHCR rounds counts below 5 (below 10 for asylum decisions) to the nearest multiple of 5, so small values are approximate
  • Every result carrying UNHCR figures cites the "UNHCR Refugee Population Statistics Database" (CC BY 4.0) with a link to UNHCR's Terms of Use for Datasets. UNRWA and IDMC figures are those providers' own series, carried through UNHCR's API; attribution.providers credits them whenever they appear, since their own conditions may apply

Agent-friendly output:

  • Provenance on every data result: applied_scope echoes the codes, year window, and ISO2 rewrites actually sent, alongside latest_year, measure, complete, and attribution
  • Caveats as data: data_notes say how to read each result (stock or flow, rounding, what null means), and matching UNHCR footnotes arrive with rows_matched
  • Typed failures with recovery hints: unknown_country_code suggests the ISO3 for a UNHCR code, year_out_of_coverage names the dataset's span, upstream_busy carries retryAfter
  • Nothing trimmed silently: year and limit clamps, empty-result hints, truncation, and where the full set was staged all arrive as a notice in the response

Getting started

Connect to the hosted instance, no install:

sh
claude mcp add --transport http unhcr-refugees-mcp-server https://unhcr-refugees.caseyjhand.com/mcp

Every caller of the hosted instance shares one UNHCR request queue and one dataframe workspace, so unhcr_dataframe_describe takes a table's exact name there; listing is off.

Or run it locally:

sh
claude mcp add unhcr-refugees-mcp-server -- npx -y @cyanheads/unhcr-refugees-mcp-server

For other clients, add this to the MCP config file:

json
{  "mcpServers": {    "unhcr-refugees-mcp-server": {      "command": "npx",      "args": ["-y", "@cyanheads/unhcr-refugees-mcp-server"]    }  }}

UNHCR's API is keyless, so no key or account is needed, and every variable under Configuration is optional. For Docker or a source build, see Running the server.

Configuration

VariableDescriptionDefault
UNHCR_REQUESTS_PER_SECONDUpstream request starts per second for the whole process (1–10). Every caller of an HTTP instance shares it.4
UNHCR_MAX_ROWSMost upstream rows one tool call fetches (10,000–500,000). A larger result stops at the cap and reports complete: false.150000
UNHCR_CACHE_MAX_MBResponse-cache budget in MB; 0 disables it. Reference data (countries, regions, coverage, footnotes) has its own cache, always on.64
UNHCR_DATASET_TTL_SECONDSLifetime of a staged dataframe, in seconds (minimum 60).86400
UNHCR_DATAFRAME_DROP_ENABLEDSet true to register unhcr_dataframe_drop.false
UNHCR_CLAMP_LIMITSServes limit, preview, and row_limit above their cap at the cap, with a notice. Set false to advertise each cap as a schema maximum and reject a larger value.true
CANVAS_PROVIDER_TYPEDataframe engine: duckdb, or none to turn dataframes off.duckdb
CANVAS_DEFAULT_ROW_LIMITMost rows one unhcr_dataframe_query call materializes; the cap on row_limit, and its default when below 1,000.10000
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTHTTP server port.3010
MCP_SESSION_MODEHTTP session mode: stateless, stateful, or auto.stateless
MCP_AUTH_MODEAuthentication: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (debug, info, warning, error, etc.).info
LOGS_DIRDirectory for log files (Node.js only).<app-root>/logs
STORAGE_PROVIDER_TYPEStorage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1.in-memory
OTEL_ENABLEDEnable OpenTelemetry.false

See .env.example for the full list of optional overrides.

Running the server

Local development

Requires Bun v1.4.0 or higher (or Node.js v24+).

  • Clone and install:

    sh
    git clone https://github.com/cyanheads/unhcr-refugees-mcp-server.gitcd unhcr-refugees-mcp-server && bun installcp .env.example .env   # optional: every variable has a working default
  • Build and run the production version:

    sh
    # One-time buildbun run rebuild
    # Run the built serverbun run start:http# orbun run start:stdio
  • Run checks and tests:

    sh
    bun run devcheck   # Lints, formats, type-checks, and morebun run test       # Runs the test suitebun run test:live  # Opt-in: re-checks the upstream behaviors the client relies on against api.unhcr.org

Docker

sh
docker run --rm -p 3010:3010 ghcr.io/cyanheads/unhcr-refugees-mcp-server:latest

The image defaults to HTTP transport, stateless session mode, and logs to /var/log/unhcr-refugees-mcp-server. To run it over stdio from an MCP client, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/unhcr-refugees-mcp-server:latest"]. To build locally, docker build -t unhcr-refugees-mcp-server .; OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

DirectoryPurpose
src/index.tscreateApp() entry point: server instructions, tool registration, service setup.
src/configServer-specific environment variable parsing and validation with Zod.
src/mcp-server/tools/definitionsTool definitions (*.tool.ts) and the registration list that gates unhcr_dataframe_drop.
src/mcp-server/tools/sharedScope inputs, output schemas, result shaping, and markdown rendering shared by the data tools.
src/services/unhcrUNHCR API client — request builder, paced fetch, response cache, reference data, normalization, asylum aggregation, footnote matching.
src/services/canvas-bridgeAdapter to the framework DataCanvas — dataframe naming, provenance, expiry, and the read-only SQL gate.
skills/The published agent skill, served over MCP and shipped in every package.
tests/Unit tests mirroring the src/ and scripts/ structure, plus the opt-in live suite in tests/live/.

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for logging, ctx.state for storage
  • Register new tools in buildToolDefinitions() in src/mcp-server/tools/definitions/index.ts
  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

sh
bun run devcheckbun run test

License

This project is licensed under the Apache 2.0 License. See the LICENSE file for details.

The data belongs to UNHCR and is published under CC BY 4.0 and UNHCR's Terms of Use for Datasets. This project is independent of UNHCR and not endorsed by it.

Source: README.md at commit 7d1cb41

Tools

8

unhcr_list_reference

UNHCR reference vocabulary

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.

Parameterstopicrequiredname_contains

unhcr_get_population

UNHCR displacement stocks

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.

Parameterslimitstageasylumexpandoriginsort_byyear_toyear_frominclude_nowcast

unhcr_get_demographics

UNHCR 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.

Parameterslimitstageasylumexpandoriginsort_byyear_toyear_frompopulation_types

unhcr_get_asylum_applications

UNHCR 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).

Parameterslimitstageasylumexpandoriginstagessort_byyear_tosplit_byyear_from

unhcr_get_asylum_decisions

UNHCR 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.

Parameterslimitstageasylumexpandoriginsort_byyear_tosplit_byyear_fromdecision_levels

unhcr_get_solutions

UNHCR durable 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.

Parameterslimitstageasylumexpandoriginsort_byyear_toyear_from

unhcr_dataframe_describe

Describe staged dataframes

Describe a dataframe (df_XXXXX_XXXXX) staged by the unhcr_get_* tools — any response carrying a dataset or nowcast_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.

Parametersname

unhcr_dataframe_query

Query staged dataframes

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.

Parameterssqlrequiredpreviewrow_limitregister_as

Version history

4
  1. v0.3.0LatestNov 4, 2026
  2. v0.2.0Oct 20, 2026
  3. v0.1.2Oct 4, 2026
  4. v0.1.1Sep 27, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts