# Apollo MCP Server POC

## What this is
A proof-of-concept for connecting Claude Code to the Orchard's self-hosted Apollo federated GraphQL graph via the Apollo MCP Server. This enables natural language interaction with the graph: schema discovery, query validation, and execution.

## Architecture
- **Apollo MCP Server** (v1.11.0) runs as a Docker container exposing MCP tools over `streamable_http` on port 8000
- Points at the **QA Apollo Router** (`graphql-theorchard@qa`) which federates 16 subgraphs
- Claude Code connects via `npx mcp-remote http://127.0.0.1:8000/mcp`

## Key files
- `mcp.yaml` — Apollo MCP Server config (endpoint, headers, introspection, operations)
- `.env` — secrets and auth tokens (gitignored, see `.env.example`)
- `operations/` — `.graphql` files that become MCP tools (hot-reloaded)
- `docs/research.md` — research findings on infrastructure and MCP server capabilities

## Subgraphs (16 active, all QA)
abacus, account, analytics, audience, collaborator, content-review, distribution, knowledge, knowledge-search, neighbouring-rights, participant, product, publishing, sr-delivery, tax-payment, user

QA URL pattern: `https://qa-graphql-{service}.theorchard.io/graphql`

## Required headers
The router enforces `apollographql-client-name`. Auth requires: `authorization` (Bearer JWT), `orchard-identity-id`, `orchard-profile-id`, `orchard-profile-type`, `orchard-profile-uuid`, `orchard-identity-uuid`.

Note: in browser apps (see ows-coda), clients send only `Authorization: Bearer <jwt>`. The `ows-grass` API gateway decodes the JWT's `https://grass.theorchard.com/identity` claim and injects the `orchard-*` headers downstream. In the auth-proxy setup, the proxy validates the token, resolves the grass identity claim via Auth0 `/userinfo`, and injects the `orchard-*` headers before forwarding to the router. Do **not** add those headers to `mcp.yaml`; they are proxy-managed.

## Auth — confirmed values (prod, verified 2026-04-22 via DevTools)

| Field | Prod | QA (unverified — extrapolated) |
|---|---|---|
| Auth0 domain | `login.distroauth.com` | `qalogin.theorchard.com` |
| Client ID | `zHwVS8k6KMbZCjO9aGZud9GWQ2CGxY6t` | `x937kb4f5c3hJRGazmCm5NDrx0hVk8eg` |
| Audience | `https://workstation.theorchard.com/api` | `https://workstation.qaorch.com/api` |
| Issuer | `https://login.distroauth.com/` | `https://qalogin.theorchard.com/` |
| Scopes | `openid profile email offline_access` | same |

**Critical: grass identity claim is in the ID token, NOT the access token.** The access token payload is minimal (`iss`, `aud`, `sub`, `exp`, `scope` only). The `https://grass.theorchard.com/identity` object (which contains `id`, `profiles`, `userTypes`, etc.) is only present in the ID token.

**Consequence for auth-proxy:** After validating the Bearer access token via JWKS, the proxy cannot extract `orchard-*` headers from the token payload alone. It must call the Auth0 userinfo endpoint:

```
GET https://{AUTH0_DOMAIN}/userinfo
Authorization: Bearer <access_token>
```

The userinfo response includes the grass identity claim. Cache the result keyed on `(sub, exp)` to avoid calling Auth0 on every MCP request.

Follow-up ask for platform team: add grass claim to access tokens via an Auth0 Action (same way it's added to ID tokens). That would remove the userinfo round-trip.

localStorage key pattern (for manual token extraction during dev):
`@@auth0spajs@@::{client_id}::{audience}::openid profile email offline_access`

## Running
```bash
# Start MCP server
docker run -it --rm --name apollo-mcp -p 8000:8000 \
  --env-file .env \
  -v $(pwd)/mcp.yaml:/config.yaml \
  -v $(pwd)/operations:/operations \
  -v $(pwd)/schema.graphql:/schema.graphql \
  ghcr.io/apollographql/apollo-mcp-server:v1.11.0 /config.yaml

# Connect Claude Code
claude mcp add apollo-mcp -- npx mcp-remote http://127.0.0.1:8000/mcp
```

## Adding operations
Each `.graphql` file in `operations/` becomes an MCP tool. Use `#` comments above the operation for tool descriptions. Files hot-reload automatically.

## References
- [Apollo MCP Server docs](https://www.apollographql.com/docs/apollo-mcp-server)
- [graphql-router repo](https://github.com/theorchard/graphql-router)
- [Notion: Techweek Workshop](https://www.notion.so/10397177520f80b78f62d6f2e7e5125e) — local router setup
- [Notion: Testing with local router](https://www.notion.so/32d97177520f808ea35fc903a1595dbf) — recent guide
