Back to Browse

Ng Postcode MCP Server

Developer ToolsLow Risk9.7MCP RegistryLocal
Free

Server data from the Official MCP Registry

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

About

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

Security Report

9.7
Low Risk9.7Low Risk

Valid MCP server (3 strong, 2 medium validity signals). No known CVEs in dependencies. ⚠️ Package registry links to a different repository than scanned source. Imported from the Official MCP Registry. 1 finding(s) downgraded by scanner intelligence.

13 files analyzed · 2 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

env_vars

Check that this permission is expected for this type of plugin.

What You'll Need

Set these up before or after installing:

NIPOST Postcode API key from dashboard.postcode.gov.ng. Validation works without it.Required

Environment variable: NG_POSTCODE_API_KEY

Highest lookup level tools may request. Levels 2 and up consume NIPOST credits.Optional

Environment variable: NG_POSTCODE_MAX_LEVEL

Nominatim server used by resolve_address to place described addresses. Ideally your own instance.Optional

Environment variable: NG_GEOCODER_URL

URL or email identifying you to the geocoder. Required for the public Nominatim.Optional

Environment variable: NG_GEOCODER_CONTACT

stdio (default), or http to serve streamable HTTP at /mcp on NG_POSTCODE_HOST and NG_POSTCODE_PORT.Optional

Environment variable: NG_POSTCODE_TRANSPORT

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-adeniyikayodee-ng-postcode": {
      "env": {
        "NG_GEOCODER_URL": "your-ng-geocoder-url-here",
        "NG_GEOCODER_CONTACT": "your-ng-geocoder-contact-here",
        "NG_POSTCODE_API_KEY": "your-ng-postcode-api-key-here",
        "NG_POSTCODE_MAX_LEVEL": "your-ng-postcode-max-level-here",
        "NG_POSTCODE_TRANSPORT": "your-ng-postcode-transport-here"
      },
      "args": [
        "-y",
        "ng-postcode-mcp"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

ng-postcode

CI crates.io PyPI MCP server npm npm MCP server

Developer tools for Nigeria's National Digital Alphanumeric Postcode System (NDAPS), the building-level postcode NIPOST launched in October 2026: libraries for Rust, Python, JavaScript, and Java, 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.

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

Quick start

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 server is listed in the MCP Registry as io.github.Adeniyikayodee/ng-postcode.

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");

The format

SegmentExampleShape
StateEK2 letters
LGA012 digits, 01 to 99
DistrictA033 letters or digits
AreaFK2 letters
Building unit012 digits, 01 to 99

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.

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.

Where the live API differs from its docs

Observed on 3 October 2026:

  • Every endpoint needs a key, including search, assembly and level 1 lookup, which the docs describe as public.
  • Lookup also returns status (valid, not_found, invalid) and verified. A malformed code is answered with HTTP 200 and status: invalid.
  • Autocomplete suggestions carry only code, the value of the next segment. The documented label is not sent.
  • Reverse geocoding also returns depth.
  • Nearby search, which the docs leave unspecified, returns a list of postcode, display and distance_m, nearest first.
  • Asking for a level the key lacks returns 403 level_not_granted.
  • An empty autocomplete query never gets a response, so the libraries refuse to send one.
  • EK-01-A03-FK-01, the example used throughout NIPOST's docs, is reported as not assigned.

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.

License

MIT

Reviews

No reviews yet

Be the first to review this server!