Skip to main content
Glama
phredi-renner

NIOS WAPI MCP Read Gateway

README.md
# NIOS WAPI MCP — read gateway

A Model Context Protocol (MCP) server that lets Claude Desktop **read** an on-prem
Infoblox **NIOS** Grid through its **WAPI** REST API — IPAM, DNS, DHCP, and grid
health, in plain language. It is read-only by design: no write tools exist in this
server, so nothing it does can change your grid.

Here's the shape. You run one server — the **gateway** — and many people connect
to it over HTTPS. Each grid is reached through its own **read-only** NIOS account
that lives on the server, so a person connecting needs no grid login at all. One
endpoint can serve several grids; the reader picks which one per conversation.

For the design reasoning and guardrail model, see `docs/DESIGN.md` and the
decision record in `docs/adr/0001-host-nios-mcp-server.md`.

> **Read-only by construction.** The gateway runs `python -m nios_mcp.gateway`,
> which never imports any write code — "read-only" is a property of the program,
> not a flag you could flip. Pair it with a read-only NIOS service account and the
> guarantee is enforced by the grid too.

---

## Run it

One server on a host, TLS in front, many readers connecting over HTTPS. Pick the
platform:

- **Docker + Caddy (Linux):** `docs/setup-hosted-docker.md` — the quickstart. Deep
  follow-along on a real Ubuntu VM: `docs/deploy-ubuntu-vm.md`.
- **Windows Server + IIS:** `docs/setup-hosted-iis.md` — same gateway, IIS instead
  of Caddy for TLS. Deep reference: `docs/deploy-windows-iis.md`.

Both run the identical `nios_mcp` package; only the run and front-door layer
differs.

### Configure the grids

The gateway's whole configuration is two files in `deploy/gateway/`:

- `grids.yaml` — the registry: one entry per grid (host, WAPI version, read-only
  account, TLS setting, default view).
- `.env` — the endpoint clients connect to (hostname + HTTPS port).

Write both by answering prompts, no hand-editing YAML:

```bash
python -m nios_mcp.gateway_setup_cli
```

It lists, adds, updates, or removes grids, sets the endpoint, and prints the
deploy command plus the Claude Desktop entry to paste. To start from the examples
instead, copy `deploy/gateway/grids.example.yaml` → `grids.yaml` and
`deploy/gateway/.env.example` → `.env` and edit them.

### Quick connectivity check

Before deploying, you can confirm an account can authenticate and read:

```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env          # fill in WAPI_PASSWORD etc.
set -a; source .env; set +a
python smoke_test.py           # expects "Auth + read OK"
```

### Connect Claude Desktop

Readers connect with **no credentials** through the `mcp-remote` bridge. The
setup CLI prints the exact config block; `nios-reader-setup.py` can also write it
for a reader. In Claude Desktop, ask `list_grids`, then `use_grid("lab")`, then
your read. There's no silent default — until a grid is chosen, the gateway says
which grids are available (a single-grid registry is selected automatically).

---

## What's configuration, not code

Nothing about *which grid you talk to* is hardcoded. Each grid entry in
`grids.yaml` carries:

- Connection: `host`, `wapi_version`, `user`, `password`, `verify_tls`
- Behavior: `default_dns_view`

Each account is **read-only**. To add or move a grid you edit the registry (or
rerun the setup CLI) — never the Python.

---

## Tools

You interact with these in plain language in Claude Desktop — the sample prompts
below are just examples. Placeholders (`example.net`, `192.0.2.x`) stand in for
your grid's real zones and networks. Every tool reads; none of them change the
grid.

### Networks & IPAM

- **search_networks** — find networks by CIDR fragment or comment, with overall
  and DHCP utilization. Big grids: ask to summarize for a utilization overview.
  _Try: "Show the networks containing 192.0.2 with their utilization."_
- **list_addresses** — every address in a network and how it's used (DNS, DHCP,
  fixed, or discovered/UNMANAGED). Big subnets: ask for a summary or fewer fields.
  _Try: "Summarize address usage in 192.0.2.0/24."_
- **next_available_ip** — the next free address(es) in a network (doesn't reserve).
  _Try: "What's the next available IP in 192.0.2.0/24?"_
- **list_network_containers** — the supernets you carve subnets out of.
  _Try: "List the network containers."_
- **next_available_network** — a free subnet of a given size inside a container.
  _Try: "Find a free /24 inside 10.0.0.0/16."_

### DNS

- **search_dns_records** — find A / host / CNAME (etc.) records by name.
  _Try: "Find DNS records with 'web' in the name."_
- **reverse_lookup** — what a given IP is used for (names, record types, MAC).
  _Try: "What is 192.0.2.10?"_
- **list_dns_zones** — the authoritative zones the grid serves.
  _Try: "List the DNS zones on the grid."_
- **list_zone_records** — every record inside a zone (big zones: ask to summarize).
  _Try: "Show all records in the example.net zone."_
- **list_dns_views** / **list_network_views** — the DNS and network view names.
  _Try: "List the DNS views."_
- **list_extensible_attributes** — the custom EA definitions on the grid.
  _Try: "List the extensible attributes."_
- **global_search** — find any object of any type by name/IP.
  _Try: "Search the grid for anything named 'web'."_
- **get_object_by_ref** / **get_grid_info** — fetch any object by its ref; grid status.

### Grid infrastructure

- **list_grid_members** — appliances: IP, platform, HA role, and per-node model
  (hwtype) + serial (hwid). Lean by default; ask to include services when you
  need health.
  _Try: "List the grid members with service status."_
- **list_licenses** — installed licenses with type and expiry, tied to each member.
  _Try: "Show the grid licenses and when they expire."_

### DHCP

- **list_dhcp_ranges** — DHCP ranges by network.
  _Try: "List the DHCP ranges in 192.0.2.0/24."_
- **list_fixed_addresses** — DHCP reservations (IP↔MAC).
  _Try: "Show the fixed addresses in 192.0.2.0/24."_
- **list_failover_associations** — DHCP failover pairs by name.
  _Try: "List the DHCP failover associations."_
- **list_dhcp_leases** — active DHCP leases (by network or address).
  _Try: "What DHCP leases are active on 192.0.2.0/24?"_

### Workflows

- **grid_health_report** — one-shot health summary: utilization hotspots, member
  service/HA issues, and licenses expiring soon.
  _Try: "Give me a grid health report."_

### Multi-grid selection

- **list_grids** — the grids this gateway serves.
  _Try: "Which grids can I read?"_
- **use_grid** — pick the grid for this conversation.
  _Try: "Use the lab grid."_