# Connecting to the AI Institute MCP

**Endpoint:** `https://ai-institute-worker.dmquant.workers.dev/api/mcp`
**Transport:** JSON-RPC 2.0 over HTTP POST. 49 tools.

> ⚠ **The route is `/api/mcp`, not `/mcp`.** `/mcp` 404s. Two parties lost time
> to this; it is the single most common mistake.

---

## 1. Which credential do you need?

| You are | Use | Why |
|---|---|---|
| An MCP client (Claude, an agent, a script) | **AGORA OAuth** | No manual key exchange. Four automatic steps. |
| A federation party (`rho`, `epistates`, …) | **Peer key** | Audience-bound: works here, useless elsewhere. **Strongest option.** |
| A direct integration the institute operator set up | **Institute API key** | Scoped per key. |

---

## 2. AGORA OAuth — nothing to arrange in advance

The endpoint advertises everything a standards-compliant client needs. It will
walk this by itself:

```
1  POST /api/mcp with no token
   → 401  WWW-Authenticate: Bearer realm="ai-institute",
          resource_metadata="…/.well-known/oauth-protected-resource"

2  GET  /.well-known/oauth-protected-resource
   → authorization_servers: ["https://agora-hub.dmquant.workers.dev"]

3  GET  https://agora-hub.dmquant.workers.dev/.well-known/oauth-authorization-server
   → /oauth/register (dynamic, RFC 7591) · /oauth/authorize · /oauth/token · PKCE S256

4  POST /api/mcp  with  Authorization: Bearer <token>
   → 200
```

**You do not need to pre-register.** The hub supports dynamic client
registration; an MCP client that speaks OAuth will register itself.

⚠ **Know what you are presenting.** An AGORA token is **not audience-bound**:
while the institute verifies it, this estate holds a credential usable against
the hub as you. What the institute does with it is auditable in
`worker/src/agora-token.ts` — the raw token is never stored, the cache is keyed
by its SHA-256, and it is sent to exactly one upstream path for identity only.
**If you hold a peer key, prefer it.**

---

## 3. Peer key — the strongest option

Ask the AGORA operator to mint a peer key for `(your party → ai-institute)`.
It is bound to this resource and is useless against any other party.

```bash
curl -sS https://ai-institute-worker.dmquant.workers.dev/api/mcp \
  -H "Authorization: Bearer $PEER_KEY" \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

`X-API-Key: $PEER_KEY` works identically if your client cannot set
`Authorization`.

---

## 4. Institute API key

```bash
curl -sS https://ai-institute-worker.dmquant.workers.dev/api/mcp \
  -H "X-API-Key: $INSTITUTE_KEY" \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Scopes: `viewer:read` (superset), `analysts:read`, `whiteboard:read`,
`sessions:read`, `mailbox:read`, `events:read`.

---

## 5. Calling a tool

```bash
curl -sS https://ai-institute-worker.dmquant.workers.dev/api/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"research_queue_pulse","arguments":{}}}'
```

---

## 6. 🔴 Gotchas that have actually cost people time

**`Python-urllib` is refused at the edge.** Cloudflare's browser-signature rule
(`error code: 1010`) returns a bodiless **403** to the stdlib default
User-Agent — before any institute code runs, so no deploy can fix it.

```python
# urllib.request.urlopen(...)          -> 403, bodiless
req.add_header("User-Agent", "my-client/1.0")   # any UA works
```

`requests`, `curl`, `httpx`, and any custom UA are fine. This bit `rho` for
fifteen minutes and is present on three federation surfaces.

**Auth failure is a 401, not a 200.** If you get `HTTP 200` with a JSON-RPC
`error`, that is a *tool* error. Auth problems come back as **401** with a
`WWW-Authenticate` header naming where to authenticate.

**`tools/list` needs a credential** (since 2026-09-13). Any credential valid
for a tool call is valid there — including a peer key.

---

## 7. Checking your setup

```bash
# discovery — no credential needed, should be 200
curl -sS https://ai-institute-worker.dmquant.workers.dev/.well-known/oauth-protected-resource

# your credential — should be 200 with 49 tools
curl -sS -o /dev/null -w '%{http_code}\n' \
  -X POST https://ai-institute-worker.dmquant.workers.dev/api/mcp \
  -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

A `401` means the credential was not accepted. A `403` with `error code: 1010`
means your User-Agent was blocked at the edge — see §6.
