Metadata-Version: 2.5
Name: ng-postcode-mcp
Version: 0.4.0
Summary: MCP server for Nigeria's NIPOST digital postcode (NDAPS): validate, look up, reverse-geocode and resolve addresses to postcodes.
Project-URL: Repository, https://github.com/Adeniyikayodee/ng-postcode
Project-URL: Issues, https://github.com/Adeniyikayodee/ng-postcode/issues
Author: Kayode Adeniyi
License-Expression: MIT
License-File: LICENSE
Keywords: ai-agents,geocoding,mcp,mcp-server,model-context-protocol,ndaps,nigeria,nipost,postcode
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: mcp<3,>=2.3
Requires-Dist: ng-address-resolver<0.2,>=0.1.4
Requires-Dist: ng-postcode[client]<0.3,>=0.2.1
Description-Content-Type: text/markdown

# ng-postcode-mcp

MCP server for Nigeria's National Digital Alphanumeric Postcode System (NDAPS), the building-level postcode NIPOST launched in October 2026. It lets AI assistants validate postcodes offline, look them up, autocomplete them and find them by location through the [postcode.gov.ng](https://docs.postcode.gov.ng) API, and resolve described addresses to postcodes.

Built on the [`ng-postcode`](https://pypi.org/project/ng-postcode/) and [`ng-address-resolver`](https://pypi.org/project/ng-address-resolver/) libraries.

<!-- mcp-name: io.github.Adeniyikayodee/ng-postcode -->

## Tools

| Tool | What it does | Needs a key | Cost |
| --- | --- | --- | --- |
| `validate_postcode` | Checks structure offline; returns canonical forms, segments and a suggested fix for look-alike characters | No | Free |
| `lookup_postcode` | Confirms a code is assigned; level 2 adds the address, level 3 building use | Yes | Level 1 free, 2+ uses credits |
| `autocomplete_postcode` | Suggests the next segment of a partly typed code | Yes | Free tier |
| `find_postcode_at_location` | Returns the postcode of the nearest building to a coordinate | Yes | Free tier |
| `resolve_address` | Turns a described address ("back of Fabian Hotel, off NTA Road") or a location pin into a postcode, only as precisely as the evidence allows | Yes, plus a geocoder for text | Free tier |

All tools are read-only. Errors come back as messages the model can act on, such as a missing key or an exhausted credit balance.

### How `resolve_address` answers

The assistant reads the address and passes its landmarks and map searches to the tool; the server makes no model calls of its own. The answer is never more precise than its evidence:

| Evidence | Answer |
| --- | --- |
| A postcode written in the address, or a location pin on a building | Building code |
| A landmark the address *is* | Building code, medium confidence |
| A building near a landmark ("behind", "opposite") | Area code, plus a question for the user |
| A street only | District code, low confidence |
| A town only, or nothing found | No code, plus a question |

Text alone rarely identifies a building, so ask users for a location pin when the exact building matters. This tool is pre-release: it works against the live API, but its accuracy on real addresses is unmeasured.

## Install

Works with any MCP client. The server runs over stdio:

| Setting | Value |
| --- | --- |
| Command | `uvx` |
| Arguments | `ng-postcode-mcp` |
| Environment | `NG_POSTCODE_API_KEY` (optional for `validate_postcode`) |

It needs [uv](https://docs.astral.sh/uv/) installed. Get an API key from the [NIPOST developer dashboard](https://dashboard.postcode.gov.ng).

Most clients take this entry in their MCP settings:

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

| Client | How to add it |
| --- | --- |
| Claude Code | `claude mcp add ng-postcode -e NG_POSTCODE_API_KEY=nipost_live_... -- uvx ng-postcode-mcp` |
| Claude Desktop | The entry above, in its MCP server settings |
| Codex | `codex mcp add ng-postcode --env NG_POSTCODE_API_KEY=nipost_live_... -- uvx ng-postcode-mcp` |
| Cursor | The entry above, in `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global) |
| VS Code | The same server object in `.vscode/mcp.json`, under a top-level `"servers"` key instead of `"mcpServers"` |
| Others | Any client that launches stdio servers: use the command, arguments and environment above |

## Configuration

| Variable | Default | Purpose |
| --- | --- | --- |
| `NG_POSTCODE_API_KEY` | none | NIPOST API key. Read from the environment only; never passed through tools. |
| `NG_POSTCODE_MAX_LEVEL` | `1` | Highest lookup level tools may request. Levels 2+ consume credits, so raise it deliberately. |
| `NG_POSTCODE_BASE_URL` | `https://api.postcode.gov.ng` | Alternative API host, such as a staging stack. |
| `NG_GEOCODER_URL` | none | A Nominatim server `resolve_address` uses to place described addresses. Without it, only typed postcodes and location pins resolve. |
| `NG_GEOCODER_CONTACT` | none | A URL or email sent in the User-Agent. Required for the public Nominatim. |
| `NG_POSTCODE_TRANSPORT` | `stdio` | `http` serves streamable HTTP at `/mcp` instead. |
| `NG_POSTCODE_HOST`, `NG_POSTCODE_PORT` | `127.0.0.1`, `8000` | Where the HTTP transport listens. |

The public Nominatim at `https://nominatim.openstreetmap.org` allows light personal use only; a service whose main job is geocoding must run its own instance. Map data © OpenStreetMap contributors.

## HTTP and Docker

```sh
NG_POSTCODE_TRANSPORT=http uvx ng-postcode-mcp        # http://127.0.0.1:8000/mcp
docker build -t ng-postcode-mcp . && docker run --rm -i ng-postcode-mcp   # from the repository root
```

Over HTTP a caller can send its own NIPOST key in the `X-NIPOST-API-Key` header, and that key is used for that caller's requests only. A caller that sends none uses the server's key, if `NG_POSTCODE_API_KEY` is set.

To host the server for other people, leave `NG_POSTCODE_API_KEY` unset so every caller brings a key, and serve it over HTTPS so the header is encrypted. Callers are trusting the host with their key, and all of them share the host's geocoder, which answers one search a second. Validation still works without any key. If you do set a server key, anyone who can reach the server spends its credits, so keep it on loopback or behind your own authentication. `NG_POSTCODE_MAX_LEVEL` caps every caller either way.

## Safety

- The key is read from the environment or the `X-NIPOST-API-Key` header, never from tool arguments, and never appears in results or logs.
- Lookups default to level 1, which is free. A model cannot spend credits unless you raise `NG_POSTCODE_MAX_LEVEL`.
- A mistyped code is never corrected and sent to the API silently. The server returns the suggestion and asks the model to confirm it with the user.
- Levels 2 and up return house addresses. Treat them as personal data under the Nigeria Data Protection Act.
- `resolve_address` sends the search strings to the geocoder you configure. With a third-party geocoder, that shares address text with it.

## License

MIT
