Nigeria Postcode

Registre officiel Autres

Validate, look up and resolve addresses to Nigeria's NIPOST digital postcodes (NDAPS).

Installation

Ajoutez ceci à la configuration MCP de votre client (Claude Desktop : claude_desktop_config.json ; Cursor : .cursor/mcp.json ; VS Code et les autres utilisent la même forme « mcpServers »).

PYPI package ng-postcode-mcp
Claude Code
claude mcp add nigeria-postcode -e 'NG_POSTCODE_API_KEY=<your ng_postcode_api_key>' -e 'NG_POSTCODE_MAX_LEVEL=1' -e 'NG_POSTCODE_MAX_PAID_CALLS=25' -e 'NG_POSTCODE_BASE_URL=https://api.postcode.gov.ng' -e 'NG_GEOCODER_URL=<NG_GEOCODER_URL>' -e 'NG_GEOCODER_CONTACT=<NG_GEOCODER_CONTACT>' -e 'NG_POSTCODE_TRANSPORT=stdio' -e 'NG_POSTCODE_HOST=127.0.0.1' -e 'NG_POSTCODE_PORT=8000' -e 'NG_POSTCODE_ALLOW_SHARED_KEY=<NG_POSTCODE_ALLOW_SHARED_KEY>' -e 'NG_POSTCODE_ALLOWED_HOSTS=<NG_POSTCODE_ALLOWED_HOSTS>' -- uvx ng-postcode-mcp==0.6.3
Configuration JSON (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "nigeria-postcode": {
            "command": "uvx",
            "args": [
                "ng-postcode-mcp==0.6.3"
            ],
            "env": {
                "NG_POSTCODE_API_KEY": "<your ng_postcode_api_key>",
                "NG_POSTCODE_MAX_LEVEL": "1",
                "NG_POSTCODE_MAX_PAID_CALLS": "25",
                "NG_POSTCODE_BASE_URL": "https://api.postcode.gov.ng",
                "NG_GEOCODER_URL": "<NG_GEOCODER_URL>",
                "NG_GEOCODER_CONTACT": "<NG_GEOCODER_CONTACT>",
                "NG_POSTCODE_TRANSPORT": "stdio",
                "NG_POSTCODE_HOST": "127.0.0.1",
                "NG_POSTCODE_PORT": "8000",
                "NG_POSTCODE_ALLOW_SHARED_KEY": "<NG_POSTCODE_ALLOW_SHARED_KEY>",
                "NG_POSTCODE_ALLOWED_HOSTS": "<NG_POSTCODE_ALLOWED_HOSTS>"
            }
        }
    }
}

Variables d'environnement

  • NG_POSTCODE_API_KEY secret NIPOST Postcode API key from dashboard.postcode.gov.ng. Validation works without it.
  • NG_POSTCODE_MAX_LEVEL Highest lookup level tools may request. Levels 2 and up consume NIPOST credits.
  • NG_POSTCODE_MAX_PAID_CALLS How many paid lookups one run of the server may make with its own key.
  • NG_POSTCODE_BASE_URL Alternative API host, such as a staging stack.
  • NG_GEOCODER_URL Nominatim server used by resolve_address to place described addresses. Ideally your own instance.
  • NG_GEOCODER_CONTACT URL or email identifying you to the geocoder. Required for the public Nominatim.
  • NG_POSTCODE_TRANSPORT stdio (default), or http to serve streamable HTTP at /mcp on NG_POSTCODE_HOST and NG_POSTCODE_PORT.
  • NG_POSTCODE_HOST Address the HTTP transport listens on.
  • NG_POSTCODE_PORT Port the HTTP transport listens on.
  • NG_POSTCODE_ALLOW_SHARED_KEY Set to 1 to let the HTTP transport start with a server key on a public address.
  • NG_POSTCODE_ALLOWED_HOSTS Host names the HTTP transport answers to, separated by commas. Required with a server key on a public address.
NPM package ng-postcode-mcp
Claude Code
claude mcp add nigeria-postcode -e 'NG_POSTCODE_API_KEY=<your ng_postcode_api_key>' -e 'NG_POSTCODE_MAX_LEVEL=1' -e 'NG_POSTCODE_MAX_PAID_CALLS=25' -e 'NG_POSTCODE_BASE_URL=https://api.postcode.gov.ng' -- npx -y ng-postcode-mcp@0.4.2
Configuration JSON (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "nigeria-postcode": {
            "command": "npx",
            "args": [
                "-y",
                "ng-postcode-mcp@0.4.2"
            ],
            "env": {
                "NG_POSTCODE_API_KEY": "<your ng_postcode_api_key>",
                "NG_POSTCODE_MAX_LEVEL": "1",
                "NG_POSTCODE_MAX_PAID_CALLS": "25",
                "NG_POSTCODE_BASE_URL": "https://api.postcode.gov.ng"
            }
        }
    }
}

Variables d'environnement

  • NG_POSTCODE_API_KEY secret NIPOST Postcode API key from dashboard.postcode.gov.ng. Validation works without it.
  • NG_POSTCODE_MAX_LEVEL Highest lookup level tools may request. Levels 2 and up consume NIPOST credits.
  • NG_POSTCODE_MAX_PAID_CALLS How many paid lookups one run of the server may make with its own key.
  • NG_POSTCODE_BASE_URL Alternative API host, such as a staging stack.

Documentation

Tirée du README du projet sur GitHub, actualisée chaque semaine. Les liens ouvrent GitHub.

Sommaire
  1. ng-postcode
  2. Packages
  3. Quick start
  4. For coding agents
  5. The format
  6. Passing a postcode between systems
  7. Design
  8. Status
  9. Development
  10. License

ng-postcode

Developer tools for Nigeria's National Digital Alphanumeric Postcode System (NDAPS), the building-level postcode NIPOST launched in October 2026: libraries for Rust and Python (ng-postcode), JavaScript (ng-postcode-js on npm), and Java (ng-postcode-api), MCP servers for AI assistants on PyPI and npm, and a resolver that turns described addresses into postcodes.

A postcode has 11 characters in five segments, written EK-01-A03-FK-01: state, LGA, district, area and building unit. NIPOST's own example, FC 02 A09 DB 09, is the same shape with spaces.

Packages

PackageWhat it doesInstallSource
ng-postcode (Rust)Parse, validate and format codes offline; client for the postcode.gov.ng APIcargo add ng-postcodesrc/, docs
ng-postcode (Python)The same behaviour, with sync and async clientspip install ng-postcodepython/
ng-postcode-jsThe same behaviour for JavaScript and TypeScript, with a fetch clientnpm install ng-postcode-jsjs/packages/ng-postcode-js
ng-postcode and ng-postcode-api (Java)The same behaviour for Java 17 and later; the core has no dependenciesio.github.adeniyikayodee:ng-postcode-apijava/
ng-postcode-mcpMCP server: validate, look up, autocomplete, find by location, resolve addressesuvx ng-postcode-mcpmcp/
ng-postcode-mcp (npm)The same server for Node, without address resolutionnpx ng-postcode-mcpjs/packages/ng-postcode-mcp
ng-postcode-polarsPolars expressions that parse, format and group codes by place, compiled from the Rust corepip install ng-postcode-polarsnative/polars
ng_postcode (PostgreSQL)The postcode as native 8-byte types with index support, compiled from the Rust corePackage from Releases, then CREATE EXTENSION ng_postcodenative/pg
ng_postcode (DuckDB)The same functions as a DuckDB extension, compiled from the Rust coreINSTALL ng_postcode FROM community (DuckDB 1.5.6)ng-postcode-duckdb
ng-address-resolverResolve free-text addresses to postcodes, only as precisely as the evidence allows (pre-alpha)pip install ng-address-resolveragent/

Each package has its own README with full usage.

For databases, sql/ holds the postcode as a PostgreSQL domain and as DuckDB macros, in plain SQL that runs the same shared cases.

Two names are easy to get wrong. On npm the library is ng-postcode-js, because ng-postcode there is another project. ng-address-resolver is imported as ng_address.

For online stores, ng-postcode-woocommerce is a WooCommerce plugin built on the same rules and the same shared test cases: it checks and tidies the postcode at checkout, finds it from the customer's location, and makes shipping zones match on postcode prefixes.

For React and Next.js, templates/nigerian-address-form is a checkout address form built with shadcn/ui and ng-postcode-js. Add it with npx shadcn@latest add https://adeniyikayodee.github.io/ng-postcode/r/nigerian-address-form.json, or deploy the folder as an app.

Quick start

Parsing and validation are offline and need no key.

Python

from ng_postcode import Postcode, parse

match parse("ek 01 a03 fk 01"):
    case Postcode() as code:
        print(code, code.compact)  # EK-01-A03-FK-01 EK01A03FK01
    case error:
        print(error)               # e.g. "invalid lga segment"

JavaScript and TypeScript

import { Postcode, parse } from "ng-postcode-js";

const code = parse("ek 01 a03 fk 01");
if (code instanceof Postcode) {
  console.log(String(code), code.compact); // EK-01-A03-FK-01 EK01A03FK01
} else {
  console.log(String(code));               // e.g. "invalid lga segment"
}

Java

import io.github.adeniyikayodee.ngpostcode.Postcode;

if (Postcode.parse("ek 01 a03 fk 01") instanceof Postcode code) {
    System.out.println(code + " " + code.compact()); // EK-01-A03-FK-01 EK01A03FK01
}

Rust

use ng_postcode::{Postcode, Segment};

let code: Postcode = "ek 01 a03 fk 01".parse()?;
assert_eq!(code.to_string(), "EK-01-A03-FK-01");
assert_eq!(code.prefix(Segment::Area), "EK-01-A03-FK");

AI assistants

The MCP server works with any MCP client. It runs over stdio as uvx ng-postcode-mcp, with the API key in the environment. Most clients take this entry in their MCP settings:

{
  "mcpServers": {
    "ng-postcode": {
      "command": "uvx",
      "args": ["ng-postcode-mcp"],
      "env": { "NG_POSTCODE_API_KEY": "nipost_live_..." }
    }
  }
}

To run it with Node, use "command": "npx" and "args": ["-y", "ng-postcode-mcp"]; that edition has every tool except address resolution. Per-client steps for Cursor, VS Code, Codex, Claude and others are in the MCP server README. Validation works without a key; the other tools need one from the NIPOST developer dashboard. The server is listed in the MCP Registry as io.github.Adeniyikayodee/ng-postcode.

PostgreSQL

Load the plain SQL file with psql -f sql/postgres.sql. It needs no extension, so it runs on managed services.

CREATE TABLE customers (
    id       bigint PRIMARY KEY,
    postcode ng_postcode            -- refuses anything that is not a compact code
);

INSERT INTO customers VALUES (1, ng_postcode_parse('ek 01 a03 fk 01'));

SELECT ng_postcode_format(ng_postcode_truncate(postcode, 'district')) AS district, count(*)
FROM customers
GROUP BY 1;
-- EK-01-A03 | 1

On a server where you can install an extension, the native extension has the same functions and stores a code in 8 bytes. Unpack the package for your PostgreSQL version from Releases, then run CREATE EXTENSION ng_postcode.

DuckDB

Load the same functions with duckdb my.db < sql/duckdb.sql.

SELECT ng_postcode_parse('ek 01 a03 fk 01');
-- EK01A03FK01

The compiled extension, ng-postcode-duckdb, has the same functions: on DuckDB 1.5.6, run INSTALL ng_postcode FROM community, then LOAD ng_postcode.

Polars

import polars as pl
import ng_postcode_polars  # pip install ng-postcode-polars

frame = pl.DataFrame({"postcode": ["ek 01 a03 fk 01", "EK-01-A03-ZZ-14", "100001"]})

print(frame.with_columns(code=pl.col("postcode").ng.parse(), ok=pl.col("postcode").ng.is_valid()))
# ek 01 a03 fk 01  EK01A03FK01  true
# EK-01-A03-ZZ-14  EK01A03ZZ14  true
# 100001           null         false

A CSV file

pip install ng-postcode
ng-postcode --column postcode customers.csv --out checked.csv

The output keeps every row and adds the compact code, a status of valid, suggested, invalid, or empty, a suggested correction, and the reason for each invalid row.

For coding agents

Language models trained before October 2026 expect a six-digit Nigerian postcode. To point a coding agent at the current format, paste this into your project's AGENTS.md, CLAUDE.md, or editor rules:

Nigerian postcodes: since 1 October 2026 a building's postcode is NIPOST's 11-character
digital postcode (NDAPS), such as EK-01-A03-FK-01, and a six-digit pattern does not match it.
Validate and format it with ng-postcode (pip, cargo), ng-postcode-js (npm), or
io.github.adeniyikayodee:ng-postcode (Maven). On npm, ng-postcode is a different project.
Reference: https://adeniyikayodee.github.io/ng-postcode/llms.txt

The format

SegmentExampleShape
StateEK2 letters
LGA012 digits, 01 to 99
DistrictA033 letters or digits
AreaFK2 letters
Building unit012 digits, 01 to 99
FormExampleUse it to
CanonicalEK-01-A03-FK-01Write a code and pass it between systems
SpacedEK 01 A03 FK 01Show a code to people
CompactEK01A03FK01Store and compare codes

Input may be hyphenated, spaced or compact, in either case. The compact form matches ^[A-Z]{2}(0[1-9]|[1-9][0-9])[A-Z0-9]{3}[A-Z]{2}(0[1-9]|[1-9][0-9])$. A well-formed code is not necessarily assigned to a building; only the NIPOST API can confirm that.

Passing a postcode between systems

docs/schemas/postcode-reference.schema.json defines a small JSON object for handing a location from one system or AI agent to another: the code, its level (state to building), and optionally a confidence and whether NIPOST confirmed it. A resolved or partial resolve_address answer already fits it.

For a whole address, docs/address-record.md wraps the reference in an address record and maps it onto ISO 20022, FHIR, schema.org, vCard, and UPU's address layout for Nigeria.

Design

  • One behaviour, four languages: Rust, Python, JavaScript and Java all run the cases in spec/, so they cannot drift apart. The Node MCP server registers its tools from spec/mcp.json, which the Python server generates.
  • Offline first: parsing and validation never touch the network. API access is a separate, optional layer.
  • Errors are values: expected failures, such as a malformed code or a rejected API key, come back as return values.
  • Careful with money and guesses: the MCP server caps lookups at the free level unless told otherwise, and never corrects a mistyped code into a paid call. The resolver gives an area or district code when that is all the evidence supports.

Status

  • The NIPOST API needs a key for every endpoint, from the developer dashboard. Offline validation needs nothing.
  • The API layer is tested against responses captured from the live API with a level 1 key, kept in spec/responses.json. Run scripts/live_check.py with your own key to repeat the comparison. Lookup levels 2 and up need a higher-access key and are tested only against NIPOST's documented examples.
  • The resolver and the resolve_address tool are pre-release. They work against the live API, but their accuracy on real addresses is unmeasured. Described addresses need a geocoder you run or pay for; text alone rarely identifies a building, so ask users for a location pin when the exact building matters.
  • Notes for integrators on how the live API behaves, each with the date it was observed, are in docs/api-differences.md.

Development

See CONTRIBUTING.md for the shared spec, how to add a language, and the commit standards.

cargo test --all-features                              # Rust
cd python && uv run --group dev pytest                 # Python library
cd mcp && uv run --group dev pytest                    # MCP server
cd agent && uv run --group dev pytest                  # resolver
cd js && npm ci && npm test                            # JavaScript library and Node MCP server
cd java && ./mvnw verify                               # Java libraries

CI runs formatting, linting, type checks and tests for every package. Releases publish from tags (v* to crates.io; py-v*, mcp-v* and agent-v* to PyPI and the MCP Registry; js-v* and js-mcp-v* to npm) through trusted publishing, so no tokens are stored. Maven Central has no trusted publishing, so java-v* uses a token and a signing key held as environment secrets, and the upload is published by hand. An mcp-v* release also creates a GitHub release, which Glama rebuilds its listing from, and republishes the Smithery bundle with a key held the same way.

License

MIT

Questions fréquentes

Qu'est-ce que Nigeria Postcode ?

Validate, look up and resolve addresses to Nigeria's NIPOST digital postcodes (NDAPS).

Comment installer Nigeria Postcode ?

Il s'exécute sur votre machine. Dans Claude Code : claude mcp add nigeria-postcode -e 'NG_POSTCODE_API_KEY=<your ng_postcode_api_key>' -e 'NG_POSTCODE_MAX_LEVEL=1' -e 'NG_POSTCODE_MAX_PAID_CALLS=25' -e 'NG_POSTCODE_BASE_URL=https://api.postcode.gov.ng' -e 'NG_GEOCODER_URL=<NG_GEOCODER_URL>' -e 'NG_GEOCODER_CONTACT=<NG_GEOCODER_CONTACT>' -e 'NG_POSTCODE_TRANSPORT=stdio' -e 'NG_POSTCODE_HOST=127.0.0.1' -e 'NG_POSTCODE_PORT=8000' -e 'NG_POSTCODE_ALLOW_SHARED_KEY=<NG_POSTCODE_ALLOW_SHARED_KEY>' -e 'NG_POSTCODE_ALLOWED_HOSTS=<NG_POSTCODE_ALLOWED_HOSTS>' -- uvx ng-postcode-mcp==0.6.3. Pour les autres clients, collez la configuration JSON de cette page dans leurs réglages MCP.

Faut-il une clé API pour Nigeria Postcode ?

Oui. Il attend NG_POSTCODE_API_KEY, à renseigner dans sa configuration.

Nigeria Postcode est-il open source ?

Oui. Son code est sur GitHub sous licence MIT.

Qui maintient Nigeria Postcode ?

Il est publié par Adeniyikayodee. AI.tn le référence sans le maintenir ni le recommander.

Issu du registre MCP officiel. Être listé n'est pas une recommandation : vérifiez le code et les permissions d'un serveur avant de lui donner accès à vos données.