Passport Casework MCP Server
by iNileshW
README.md
# Build a research assistant over HM Passport Office casework
A passport-casework assistant answers two kinds of question. Simple lookups —
_"what's the status of application 500123?"_ — are handled by governed MCP tools. But most
management questions are analytical — _"what's our median processing time by office, and
where is the backlog worst?"_ — and no one can pre-build a tool for each one, so the
assistant writes and runs its own Python. Running model-written code is the dangerous part —
which is what this morning was about.
**You edit one file.** Everything here is built and runs, except the containment inside
`analysis_tool.py`, which you finish. Then you run the assistant and watch it work.
## Setup
Plain Python — no Docker, no Git.
```
pip install -r requirements.txt
python seed.py # builds the caseload: data/passport_applications.csv
python test_analysis.py # 3 of 4 pass until you finish the task below
```
## The task — finish `analysis_tool.py`
This is the **only file you change.** It already runs the model's code in a child process,
over the caseload, under a wall-clock timeout. Three containment pieces are missing, each
marked `# TODO (you)` in the file:
| # | Add | Where in `analysis_tool.py` |
| --- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | **No network** — wrap the child in `unshare -r -m -n` (the control whose absence let "Sol" out) | `_unshare_available()` — make the probe return `True`; **and** the `argv` branch in `run_analysis()` marked `# <- replace this branch` |
| 2 | **CPU-time cap** — `RLIMIT_CPU` | `_set_limits()` |
| 3 | **File-size cap** — `RLIMIT_FSIZE` | `_set_limits()` |
For the two caps, copy the shape of the `RLIMIT_AS` / `RLIMIT_NPROC` lines already sitting in
`_set_limits()`. You do not touch `server.py`, `assistant.py`, or `test_analysis.py`.
You are done when:
```
python test_analysis.py # 4/4 — the outbound call is now BLOCKED, and a real analysis still returns 640
```
## Then — run the assistant
`assistant.py` is written for you. Once your containment is in place, just run it:
```
python assistant.py "Which two processing offices are most in need of extra staff this quarter, and what is the evidence?"
```
Watch it work: it searches the caseload with the governed MCP tools, computes the medians and
backlogs with your `run_analysis`, cites the service standard, and answers. That is the whole
point — **the governed tools run trusted, in-process; the one open-ended capability, arbitrary
code, is the only thing contained.**
### If you want to go further (optional)
- Add to the research surface in `server.py` — a filter by date range or fraud flag, a
per-office resource. Watch the boundary: lookups belong on the server, aggregates stay in
the sandbox.
- Give it an open brief — _"write the quarterly processing note for the board"_ — and see how
far the tool-plus-sandbox pattern carries a multi-step answer.
## Where containment stops
The child process, `setrlimit` and the network namespace stop resource exhaustion and close
egress — but do not fully confine the filesystem. For genuinely hostile code you would add a
container (`--network=none --read-only --cap-drop=ALL` + seccomp), then gVisor or a microVM.
Here the code is the department's own model, not an adversary, so Tier 2 is a defensible floor.
## Files
| File | |
| --------------------------------- | -------------------------------------------------------------------------------------- |
| **`analysis_tool.py`** | **The one file you edit** — finish the containment. |
| `test_analysis.py` | The battery that tells you when you're done. Run it; don't edit it. |
| `assistant.py` | The assistant — provided and runnable. |
| `server.py` | The governed MCP server (lookups + guidance). Provided; extend only if you go further. |
| `seed.py`, `data/`, `guidance.md` | The caseload, and the service-standard resource. |
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues