MCP server marketplace with OAuth + signing
A registry of MCP servers with dynamic client registration, signature verification, and tool pinning.
Goal
Build a tiny "MCP marketplace" that demonstrates the production-grade install + run lifecycle: clients discover servers, register dynamically, authenticate via OAuth 2.1, run inside signed + sandboxed images, and respect a per-tool authorization policy. Includes an enterprise allow-list mode.
Stack
- IdP: Keycloak with DCR enabled.
- MCP servers: 3 in Python (
github-mcp,linear-mcp,notion-mcp); HTTP transport. - Signing: cosign keyless via GitHub OIDC; admission via Kyverno.
- Sandbox: gVisor on a
kindcluster. - Allow-list service: FastAPI + Postgres holding approved (
image_digest,scope_manifest) pairs. - Client: Python CLI that discovers + DCR + runs the MCP server.
Architecture
CLI (mcp install github-mcp)
↓ fetches .well-known/oauth-protected-resource
↓ fetches AS metadata
↓ DCR → client_id
↓ Authorization Code + PKCE
↓ verifies cosign signature against allow-list
↓ pulls image, runs with gvisor runtime
MCP server enforces per-tool OPA policy on every call.
Audit pipeline (Loki) records (sub, actor, tool, decision, outcome).Build plan (8 days)
- Build 3 minimal MCP servers (Python SDK + FastAPI HTTP transport). Each exposes 2-3 tools with explicit scopes.
- Add
/.well-known/oauth-protected-resourceto each. Configure Keycloak with the scopes + DCR. - Build the CLI: discover → DCR → PKCE → call. Persist credentials in OS keychain.
- CI workflow that builds + signs each MCP image with cosign keyless. Generate SBOMs.
- Allow-list service: REST API listing approved
(image_digest, scope_manifest, maintainer)records. CLI refuses to install unless present. - Kyverno admission policy on the K8s cluster: refuse unsigned images.
- gVisor runtime class; MCP server pods run sandboxed.
- OPA policy + decision logs: deny
delete_*tools unlessactor.purpose == 'admin_workflow'andbusiness_hours. - Stretch: scope-elevation flow with
WWW-Authenticate: insufficient_scopetriggering re-auth in the CLI.
Acceptance criteria
- New MCP server installs via the CLI in < 60 seconds with no human in IdP admin UI.
- Unsigned image refused at deploy time.
- Scope mismatch returns 401 with
WWW-Authenticatecarrying scope hint; CLI prompts user for additional consent. - Removing the server from the allow-list breaks new installs but does not affect running ones (graceful deprecation).
- Audit log captures full chain for every tool call.
Stretch
- Add a "marketplace UI" (Streamlit) listing approved servers + maintainer + last-audit date.
- Permission diffs on upgrade: if v2 requests new scopes, require re-consent.
- Add a Sigstore Rekor verification step in CI.
- Add DPoP between CLI and MCP servers.
Interview talking points
- Why DCR matters for MCP scale.
- Difference between WWW-Authenticate scope-elevation and re-auth.
- Why an enterprise allow-list is non-negotiable for B2B.
- Signing vs scanning vs runtime detection — defense in depth.
- Cost / friction tradeoffs of gVisor vs Firecracker.