Quickstart¶
The repository ships with a one-command bring-up that gives you a fully-running stack: Postgres, Keycloak (with a pre-seeded realm), the binary in foreground, the portal embedded.
make dev does:
docker compose -f docker-compose.dev.yml up -d postgres keycloak- Polls each container until it's healthy and the Keycloak realm discovery endpoint responds.
- Builds the React SPA into
internal/ui/distif it isn't already. - Runs the binary in the foreground against
configs/mcp-test.live.yaml.
When it's up:
| URL | What |
|---|---|
| http://localhost:8080/portal/ | Portal — sign in with dev/dev (OIDC) or paste an API key. |
| http://localhost:8080/ | MCP streamable HTTP endpoint. Browsers redirect to the portal; MCP clients pass through. |
| http://localhost:8081/ | Keycloak admin console (admin/admin). |
| http://localhost:8080/healthz | Liveness. |
The dev API key is devkey-please-change. Override it via
MCPTEST_DEV_KEY if you want something else.
Verify it works¶
A quick curl smoke test against the running server:
KEY=devkey-please-change
# Auth challenge — no credentials → 401 with WWW-Authenticate
curl -s -i http://localhost:8080/ -H "Accept: application/json" | head -8
# RFC 9728 protected-resource metadata
curl -s http://localhost:8080/.well-known/oauth-protected-resource | jq
# Portal identity
curl -s -H "X-API-Key: $KEY" http://localhost:8080/api/v1/portal/me | jq
To exercise the MCP layer directly, talk JSON-RPC over the streamable HTTP transport:
curl -s -X POST http://localhost:8080/ \
-H "X-API-Key: $KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Protocol-Version: 2025-06-18" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}},"id":1}'
The result.instructions field in the response is the server-level
text every MCP client surfaces to the LLM as system context.
Through the portal¶
- Open http://localhost:8080/portal/.
- Click Sign in with OIDC, log in with
dev/dev. - Tools → pick
progress, click Try It, set Steps to 5, Step delay to 500ms, click Run. - Switch to Audit to see the row appear.
Faster iteration: anonymous mode¶
For UI work or tests where you don't care about auth, skip Keycloak:
Anonymous mode is also compatible with bearer/API-key clients, but the portal still requires authentication.
Stop the stack¶
That stops the containers and removes the Compose network. Volumes
(Postgres data) are kept by default; docker compose -f
docker-compose.dev.yml down -v clears them too.
Next¶
- Connect a client for Claude Code, the SDK, and raw HTTP examples.
- Configuration → YAML reference walks every key.
- Testing a gateway is what mcp-test exists for.