Skip to main content
Glama
README.md
# Regalport MCP Server — for AIPI's Custom MCP

This replaces the character-limited Knowledge Base text field with a live
tool the Harbour Register agent can query. Instead of pre-loading a
compressed 4,000-character summary, the agent calls a tool and gets back
exactly the entry it needs, from a dataset of **223 entries / ~40,000
characters** covering the full Regalport sourcebook and the five-session
Prelude.

## What's in this folder

| File | What it is |
|---|---|
| `server.py` | The MCP server. Three tools: `search`, `get_entry`, `list_entries`. |
| `regalport_kb.json` | The dataset — every NPC, district, faction, law, ship, session, encounter, hook, and place, each tagged PUBLIC or DM. |
| `build_data.py` | The script that generated `regalport_kb.json`. Edit this and re-run it (`python3 build_data.py`) if you want to add or change entries — don't hand-edit the JSON. |
| `requirements.txt` | One dependency: `mcp`. |
| `Dockerfile` | Builds a container that runs the server, reading `$PORT` from the environment (standard on Render/Railway/Fly). |
| `character_description.txt` | A short (1,351-character) replacement for AIPI's Character Description field — the persona now tells the agent to *call the tools* instead of embedding facts directly. |

## Why it's confirmed to work

I ran this server locally, connected a real MCP client to it over SSE, and
called all three tools (`search("Ossric")`, `get_entry("Denna Roq")`,
`get_entry("E4")`, `list_entries("district")`) — all returned correct,
properly-tagged results. AIPI's Custom MCP field only accepts **SSE
transport**, which is what `server.py` runs (`mcp.run(transport="sse", ...)`
on `/sse`).

## Deploying it (so AIPI can reach it)

AIPI's cloud backend needs to reach this server over the public internet —
it can't be `localhost` on your own machine. Any host that runs a
long-lived Python/Docker process works. **Render** is the easiest free
path:

1. Push this folder to a new GitHub repo (or a subfolder of an existing one).
2. On [render.com](https://render.com), **New → Web Service**, connect the repo.
3. Render auto-detects the `Dockerfile`. Leave the build/start commands as-is — the Dockerfile handles it.
4. Deploy. Render gives you a URL like `https://regalport-mcp.onrender.com`.
5. Check it's alive: visit `https://regalport-mcp.onrender.com/health` — should say `ok — 223 entries loaded`.
6. Your SSE endpoint for AIPI is `https://regalport-mcp.onrender.com/sse`.

**One tradeoff on Render's free tier:** it spins the service down after 15
minutes idle, so the first tool call after a quiet spell takes ~30-50
seconds to wake up (the second call is instant). Fine for casual home use;
if that first-call lag bothers you at the table, Render's cheapest paid
tier ($7/mo) or Fly.io's small always-on instance removes it.

**Alternative:** Railway.app works almost identically (auto-detects the
Dockerfile, gives you a public URL, similar free-tier idle behavior).

## Setting it up in AIPI

1. Open your Harbour Register agent's **Configuring Character** screen on `xdc.aipi.com`.
2. In **MCP Expansion → Custom MCP**, add the server URL: `https://<your-host>/sse`.
3. Replace the contents of **Character Description** with `character_description.txt`.
4. You can now leave the **Knowledge Base** text field mostly empty, or use
   it only for anything you want guaranteed-loaded with zero tool-call
   latency (e.g. the Six Laws, since those come up constantly). Everything
   else — NPCs, ships, encounters, factions, districts — is now served
   live by the MCP tools instead of being crammed into a character count.

## Extending it later

To add the island-hex material once the party makes landfall, or to update
anything here (correct a name, add an NPC, fix a secret), edit the `add(...)`
calls in `build_data.py` and re-run it — it regenerates `regalport_kb.json`
from scratch, so there's one source of truth instead of hand-edited JSON
drifting out of sync with the campaign docs. Re-deploy (push to the repo;
Render redeploys automatically on push).

## Local testing

```bash
pip install mcp
python3 server.py 8765        # starts on localhost:8765
curl http://127.0.0.1:8765/health
```

To exercise the actual tools before deploying, use the official `mcp`
client library's `sse_client` against `http://127.0.0.1:8765/sse` — that's
exactly how I verified this before handing it to you.