·
Every remote MCP server used to mean its own OAuth consent screen. EMA, stable since June 2026, turns that into a single SSO decision. Here is how it works, and what it still does not do.
A dozen remote MCP servers and a hundred employees is twelve hundred consent screens. That is the consent tax, and it is the worst part of the experience we described when we argued that OAuth is where remote MCP servers break in production: one authorization click-through per person, per server, before anyone gets any work done. MCP's Enterprise-Managed Authorization (EMA) extension, which went stable on June 18, 2026, is the answer to exactly that problem. It is also more qualified than the headline suggests: the consent screen disappears for users, but somebody still has to do the touching, and that somebody is your identity-provider admin.
EMA turns per-server OAuth consent into a one-time, org-managed decision. Instead of every employee authorizing every server individually, the company's identity provider grants access once, during single sign-on, and approved servers connect automatically on first login. Its extension identifier is io.modelcontextprotocol/enterprise-managed-authorization, and it is currently the only MCP auth extension at stable status: the Client Credentials extension is still draft. It fixes three things at once:
The mechanism has a name: the Identity Assertion JWT Authorization Grant, or ID-JAG. The usual one-line description, that the client picks up an ID-JAG token during sign-in, is wrong in both halves. The client does not get it during sign-in, and it is not a token you can use. What actually happens is two separate exchanges, both after the SSO session already exists and while the client is holding the ID token from it:
The asymmetry between the two credentials is the part to internalize. The ID-JAG is an assertion, not a bearer credential, and the exchange response says so explicitly with a token type of N_A and, in the spec's example, a five-minute lifetime. The access token it buys is an ordinary Bearer token good for a day, which the MCP extension requires to be audience-restricted to the resource it was requested for. Because the client never redirects the user to the MCP authorization server's /authorize endpoint, no consent screen is rendered on this path.
Four URNs show up across the flow, and they are easy to conflate:
# Leg 1, at the IdP's token endpoint: SSO ID token -> ID-JAG assertion
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
requested_token_type=urn:ietf:params:oauth:token-type:id-jag
# -> {"token_type": "N_A", "expires_in": 300, ...}
# Leg 2, at the MCP server's authorization server: ID-JAG -> access token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
assertion=<the ID-JAG>
# -> {"token_type": "Bearer", "expires_in": 86400, ...}
# Advertised in the server's metadata, under
# authorization_grant_profiles_supported:
urn:ietf:params:oauth:grant-profile:id-jagThe assertion itself carries a JWT header type of oauth-id-jag+jwt. The most reliable source of implementation bugs is treating aud and resource as interchangeable: aud is the issuer of the MCP server's authorization server, while resource is the MCP server's own resource identifier as defined by RFC 9728. Different values, and the error you get for swapping them is not obvious.
Zero-touch is the user's half. This is the other half, drawn from the implementations that have published documentation.
On the client side, VS Code reads a policy-managed setting, mcp.enterpriseManagedAuth.idp, delivered by Group Policy on Windows, managed preferences on macOS, or /etc/vscode/policy.json on Linux. It deliberately never travels through settings sync. Individual servers then opt in inside mcp.json:
"oauth": { "enterpriseManaged": true }On the identity-provider side, Okta wants a paid Okta for AI Agents subscription (the price is not published), the Cross App Access Early Access feature turned on for your org, which is no longer self-service and requires Okta Support to enable it, and an AI Agent registered with an owner (Okta recommends at least two) and an RSA key-pair. The documented failure modes on the identity-provider side are all easy to hit:
openid, profile, email) are stripped during the ID-JAG exchange and produce an invalid_scope error.This is the caveat to absorb before planning a rollout around it. EMA reaching stable means the MCP extension is final: the proposal opened in June 2025 and landed roughly twelve months later, and the extension adds only a few sentences of new normative text and no new error codes. The grant it profiles is a different story. ID-JAG lives in the IETF draft draft-ietf-oauth-identity-assertion-authz-grant, currently at draft 04, published May 21, 2026, with an expiry date of November 22, 2026. It has grown from 27 pages to 65 in eight months, and its three authors come from Okta, Ping Identity, and one independent. VS Code's release notes put it bluntly: ID-JAG "is still an emerging standard and isn't widely adopted yet." There is already version skew in the wild, with MCP pinning draft 04 while VS Code's own notes link draft 03.
The extension itself is identity-provider-agnostic. It leans on RFC 8693 and RFC 7523 and contains nothing Okta-specific, and Cross App Access is not Okta branding either: the IETF draft's own abstract says the pattern "is informally referred to as Cross-App Access (XAA)." In practice, though, you need an identity provider that has actually shipped it, and that list is short. The launch cohort was real, but calling it broad day-one support would be wrong on two counts: VS Code shipped its preview two weeks before the extension left draft, and Anthropic's implementation is waitlisted.
| Layer | Component | Status as of August 2026 |
|---|---|---|
| Identity provider | Okta, as Cross App Access | Early Access; Okta says Okta Integration Network catalog availability for Workforce customers begins August 2026 |
| Identity provider | Auth0 | Early Access shipped; the XAA docs (including the ID-JAG rate-limit note above) are live |
| Identity provider | Athenz, Keycloak | Beta, in progress as announced at launch; we have not seen a GA announcement since |
| Client | Claude, Claude Code, Cowork | Beta, Team and Enterprise plans, still waitlisted; Okta is the only supported IdP at beta launch |
| Client | VS Code 1.123 | Preview, shipped June 3, 2026 |
| Server | Asana, Canva, Figma, Granola, Linear, Supabase | Announced at launch |
| Server | Atlassian, for Rovo MCP | Private beta |
| Server | Slack | Announced as coming |
One discrepancy to know about if you go looking for confirmation: when we last checked (late July 2026), MCP's own client support matrix showed exactly one client with Enterprise Auth checked, Archestra.AI, and carried no rows at all for Claude Code or Cowork. The vendor announcements are the better guide for now, but no announcement is a promise about your particular stack.
The spec is unusually direct about its own boundary. The visibility the identity provider gains "is limited to the process of issuing the access token, but does not extend to the actual MCP traffic between the MCP Client and Server." EMA is authorization-time control. It is not tool-call auditing, and it is not data-loss prevention. If the reason you want central MCP governance is "I need to know which tools got called with which arguments," EMA does not answer that question and no amount of identity-provider configuration will make it.
Two smaller edges are worth planning around. Scope precision is capped by the server: governing which scopes a user can request works only "depending on the granularity of the OAuth scopes defined at the MCP server," so a server that defines one coarse scope hands your admin one coarse lever. And when migrating existing users, identify people by sub, falling back to email for accounts that predate EMA.
The strongest argument for EMA is not really the consent screens. It is what cheap re-authorization does to token lifetimes. Anthropic's write-up makes the point the MCP announcement leaves out: because checking access with the identity provider is frictionless, admins can shorten access token lifetimes without hurting productivity, so a deprovisioned employee's connector access expires quickly instead of lingering on a long-lived token. That reframes EMA from a convenience feature into an offboarding control, and offboarding is exactly where long-lived per-server OAuth grants bite hardest. Ramp reports running it across 2,000 employees provisioned through Okta with "zero extra steps."
If you run a single MCP server for yourself, EMA changes nothing for you: you will keep doing the normal OAuth dance, and the paid Okta for AI Agents subscription rules it out on price alone. Where it matters is the case we keep coming back to: a team pointing many people at many remote MCP servers. That is exactly where the consent-screen tax compounds, and it is the situation Yaw MCP exists to manage. EMA does not replace orchestration: you still decide which servers to run and how their tools land in context, which is its own budget problem. It removes the authorization friction that made "connect the whole team to the whole fleet" a non-starter.
EMA is the enterprise half of the fix for the OAuth problem we flagged earlier, and the mechanism is sound: one SSO decision, an assertion exchange, audience-restricted tokens, no consent screens. Two things to hold alongside that. The extension is stable, but the grant it profiles is an IETF draft that expires in November. And the pieces you would actually deploy on today are in Early Access, preview, or private beta. Worth designing toward. Not yet worth assuming.
Published by Yaw Labs.