Control Plane
Data Plane
Gateways
Architecture
Loading…
💻
MCP Client
VS Code Copilot · Copilot CLI · Claude
Authorization: Bearer <Entra JWT>
🪪
Microsoft Entra ID
issues JWT to client · validates via OIDC discovery
OAuth 2.0 + PKCE
User authentication
☁ Azure VNet
⎈ AKS Cluster
🌐
NGINX Ingress
gw.mikegcoleman.com · TLS / Let's Encrypt
management only
🛠
Control Plane
admin API
config & catalogs
checking…
🔀
Data Plane
validates JWT via sidecar
routes MCP traffic
checking…
plugin calls (authenticate · get_connection_headers · oauth-*)
🔌
entra-sidecar
JWT validation · credential delegation
OAuth broker (DCR + PKCE)
Authorization injected per server
🦆
DuckDuckGo MCP
in-cluster · no auth
empty headers
🐙
GitHub MCP
in-cluster · per-user PAT
static credential pattern
🔐
Azure Key Vault
per-user GitHub PATs
OAuth token bundles
pending OAuth state
↑ accessed by entra-sidecar via workload identity
🗄
Azure PostgreSQL
gateway state
tenants · sessions · audit
↑ accessed by Control Plane & Data Plane (private endpoint)
egress to upstream MCP endpoints & external APIs (internet)
🦆
api.duckduckgo.com
called by DuckDuckGo MCP
🌐
api.github.com
called by GitHub MCP
📝
mcp.granola.ai
OAuth-protected MCP
(no in-cluster wrapper)
🔄 First Granola call (per user, per ~90 days)
Sidecar discovers Granola's OAuth metadata, dynamically registers an OAuth client (RFC 7591 DCR), generates a PKCE challenge, and returns an auth URL. User clicks it → signs in at mcp-auth.granola.ai → IdP redirects to https://gw.mikegcoleman.com/oauth/callback → NGINX routes to sidecar:5555 → token bundle persisted in Key Vault. Subsequent calls inject the cached access token; refresh tokens rotate it silently as needed.