MCP server marketplace with OAuth + signing

A registry of MCP servers with dynamic client registration, signature verification, and tool pinning.

🛠 Advanced

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 kind cluster.
  • 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)

  1. Build 3 minimal MCP servers (Python SDK + FastAPI HTTP transport). Each exposes 2-3 tools with explicit scopes.
  2. Add /.well-known/oauth-protected-resource to each. Configure Keycloak with the scopes + DCR.
  3. Build the CLI: discover → DCR → PKCE → call. Persist credentials in OS keychain.
  4. CI workflow that builds + signs each MCP image with cosign keyless. Generate SBOMs.
  5. Allow-list service: REST API listing approved (image_digest, scope_manifest, maintainer) records. CLI refuses to install unless present.
  6. Kyverno admission policy on the K8s cluster: refuse unsigned images.
  7. gVisor runtime class; MCP server pods run sandboxed.
  8. OPA policy + decision logs: deny delete_* tools unless actor.purpose == 'admin_workflow' and business_hours.
  9. Stretch: scope-elevation flow with WWW-Authenticate: insufficient_scope triggering 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-Authenticate carrying 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.