Skip to content

feat(mcp): multi-tenant Entra ID validation#2629

Open
fahreddinozcan wants to merge 2 commits into
masterfrom
ctx7-1655-azure-apim-integration
Open

feat(mcp): multi-tenant Entra ID validation#2629
fahreddinozcan wants to merge 2 commits into
masterfrom
ctx7-1655-azure-apim-integration

Conversation

@fahreddinozcan
Copy link
Copy Markdown
Contributor

@fahreddinozcan fahreddinozcan commented May 15, 2026

Summary

  • Detect inbound Entra v2 tokens by issuer pattern, fetch per-teamspace configuration from the Context7 app, and verify against the matching tenant's JWKS.
  • MCP server only validates — user resolution happens in the app middleware against entra_user_mappings.
  • Per-tenant JWKS cache + 5-minute in-memory config cache keyed by JWT audience.
  • Docs split out to docs(enterprise): Azure APIM deployment guide #2636 so they can land first.

Test plan

  • pnpm --filter @upstash/context7-mcp test passes (jwt.test.ts covers Entra path + Clerk path + scope enforcement)
  • Hit MCP with an Entra v2 token through APIM — token validates and forwards to the app
  • Hit MCP with an unknown-audience token — rejected with Unknown audience
  • Hit MCP with a Clerk token — still works (existing path untouched)

@linear
Copy link
Copy Markdown

linear Bot commented May 15, 2026

CTX7-1655

@mintlify
Copy link
Copy Markdown

mintlify Bot commented May 15, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
context7 🟢 Ready View Preview May 15, 2026, 2:45 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Detect inbound Entra v2 tokens by issuer pattern, fetch per-teamspace
configuration (tenantId, audience, requiredScope) from the Context7
app, and verify the token against the matching tenant's JWKS. The MCP
server only validates — user resolution happens in the app middleware
against the entra_user_mappings table.

Per-tenant JWKS cache and a 5-minute in-memory config cache keyed by
JWT audience reduce overhead under load.
@fahreddinozcan fahreddinozcan force-pushed the ctx7-1655-azure-apim-integration branch from f98154f to 741781f Compare May 18, 2026 15:48
@fahreddinozcan fahreddinozcan changed the title feat(mcp): multi-tenant Entra ID validation + Azure APIM docs feat(mcp): multi-tenant Entra ID validation May 18, 2026
Resolves prettier/eslint errors blocking the test workflow, and refreshes
the changeset to match the actual MCP-side behavior (validate only; user
resolution lives in the app middleware).
requiredScope: string | null;
}

const CONFIG_TTL_MS = 5 * 60 * 1000;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caching null results under the same 5-minute TTL means one transient failure (5xx, network blip, JSON parse error) locks every Entra token for that audience out of the server for 5 minutes with a misleading Unknown audience error.
Suggest only negative-caching on an explicit 404 - anything else should bypass the cache so the next request retries:
if (res.ok) {
value = (await res-json()) as EntraConfig;
} else if (res status != 404) {
return null; // transient - don't cache
}

In the app we have

  • 404 when getEntraConfigByAudience(audience) returns null — that's the authoritative "this audience is not configured" answer. Safe to cache.
  • 400 for missing audience (won't happen from the MCP server).
  • 500 in the catch block — any exception thrown by Redis or the service layer. That's the "I don't know" case. Not safe to cache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants