Enterprise-Managed Authorization: ID-JAG y el IdP dentro de MCP
En el MCP de consumo, la pantalla de consent es una feature: tú decides qué toca tus datos. En una empresa, es un pasivo multiplicado por la plantilla. La extensión Enterprise-Managed Authorization — ya estable — elimina la pantalla de consent por completo y le entrega la decisión al identity provider corporativo.
Cuando recorrimos la spec de autorización de MCP hace dos semanas, el modelo era limpio: un servidor MCP protegido es un resource server OAuth 2.1, el cliente descubre el authorization server a través de un 401, y un humano hace clic en "allow" en algún navegador. Ese último paso es el problema del que trata este post. Una organización con dos mil empleados y treinta servidores MCP aprobados enfrenta sesenta mil ceremonias de autorización individuales — cada una una superficie de phishing, cada una invisible para el equipo de seguridad, y cada offboarding una búsqueda del tesoro por todos los servidores que el ex-empleado alguna vez aprobó.
La extensión Enterprise-Managed Authorization (identificador io.modelcontextprotocol/enterprise-managed-authorization, EMA para abreviar) reemplaza todo eso con una sola primitiva: el Identity Assertion JWT Authorization Grant, o ID-JAG. La extensión alcanzó estatus estable y fue anunciada en el blog oficial de MCP el 18 de junio de 2026, con Okta, el Claude de Anthropic y VS Code entre los primeros en moverse. Nació de la SEP-990 ("Enable Enterprise IdP Policy Controls") y vive en el repositorio modelcontextprotocol/ext-auth en el track estable. Esta pieza recorre el protocolo tal como está especificado, y luego hace nuestra pregunta habitual: ¿qué cambia para los agentes que pagan por llamada?
La forma del arreglo: la autorización se mueve aguas arriba
El movimiento central es arquitectónico. En el flujo base, la decisión de autorización ocurre en el authorization server de cada servidor MCP, un consent a la vez. EMA mueve esa decisión aguas arriba, hacia el IdP corporativo — Okta, Entra ID, lo que la organización ya opere. El IdP mantiene un registro de servidores MCP aprobados y la política de cada uno: qué grupos, qué roles, qué reglas de conditional access. El empleado inicia sesión una vez con el SSO corporativo. Todo lo que sigue es fontanería de tokens, sin navegador de por medio.
Esa fontanería son dos bloques estándar compuestos en secuencia. Primero, OAuth Token Exchange (RFC 8693): el cliente intercambia su identity assertion en el IdP por un ID-JAG. Segundo, el JWT Profile for OAuth 2.0 Authorization Grants (RFC 7523): el cliente presenta ese ID-JAG al authorization server del servidor MCP y recibe un access token. Sin redirect al authorization endpoint del recurso. Sin authorization code. Sin pantalla de consent. La decisión de autorización ya se tomó cuando el IdP evaluó la política y aceptó emitir el grant.
El formato de token subyacente no es un invento de MCP. Viene del draft del OAuth working group del IETF draft-ietf-oauth-identity-assertion-authz-grant — la spec detrás de lo que Okta comercializa como Cross App Access (XAA). Es un documento de working group en el track de estándares, escrito por Aaron Parecki (Okta), Karl McGuinness y Brian Campbell (Ping Identity); la revisión -04 tiene fecha del 21 de mayo de 2026. Eso importa operativamente: la extensión de MCP es estable, pero se apoya en un draft del IETF en movimiento, así que quien implemente debería fijar la revisión del draft que soporta y seguir al working group.
Primera pata: intercambiar un ID token por un ID-JAG
Después del SSO, el cliente MCP tiene una identity assertion — un ID token de OpenID Connect o, en el caso SAML, un refresh token obtenido intercambiando primero la SAML assertion en el IdP. Para alcanzar un servidor MCP específico, el cliente envía una solicitud de token exchange al token endpoint del IdP:
POST /oauth2/token HTTP/1.1
Host: idp.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&requested_token_type=urn:ietf:params:oauth:token-type:id-jag
&audience=https://auth.mcp-server.example
&resource=https://mcp-server.example/mcp
&subject_token=eyJraWQi...
&subject_token_type=urn:ietf:params:oauth:token-type:id_token
&scope=mcp.tools.read
La semántica de los parámetros es estricta. audience MUST ser el issuer identifier del authorization server del servidor MCP — la parte que consumirá el grant. resource, si está presente, MUST ser el resource identifier del servidor MCP en sí. subject_token_type es id_token para despliegues OpenID Connect o saml2 para casas SAML. La autenticación del cliente (client_id más una credencial) aplica cuando el IdP la exige — y en la práctica la exigirá, porque la política de un IdP corporativo típicamente solo deja iniciar sesión a clientes pre-registrados.
Esta solicitud es el punto de control de la política. El IdP valida el subject token, confirma que fue emitido a este cliente, evalúa la política para esta combinación usuario–cliente–servidor, y puede recortar los scopes solicitados a lo que la política permita. Si el empleado no está autorizado para ese servidor, el exchange falla y el cliente nunca tiene un token de ningún tipo para él. Si tiene éxito, la respuesta trae el ID-JAG — de vida corta por diseño; el ejemplo de la spec usa expires_in: 300, cinco minutos.
El artefacto: qué dice realmente un ID-JAG
El ID-JAG es un JWT firmado con el media type explícito oauth-id-jag+jwt en su header typ — una medida anti-confusión deliberada para que nunca pueda confundirse con un ID token o un access token. Su payload luce así:
{
"jti": "9e43f81b64a33f20116179",
"iss": "https://idp.example.com",
"sub": "U019488227",
"aud": "https://auth.mcp-server.example",
"client_id": "f53f191f9311af35",
"resource": "https://mcp-server.example/mcp",
"scope": "mcp.tools.read",
"exp": 1753600000,
"iat": 1753599700
}
iss, sub, aud, client_id, jti, exp e iat son requeridos. scope y resource son opcionales y reflejan lo que el IdP realmente otorgó, no lo que el cliente pidió. Vale la pena señalar dos claims opcionales. authorization_details transporta solicitudes de autorización estructuradas y de grano fino según RFC 9396 (Rich Authorization Requests) — un array JSON que el IdP evalúa y deja pasar, al que volveremos. Y sub_id puede llevar un identificador de sujeto alternativo, como un SAML NameID, para resource servers cuyo espacio de cuentas se construyó alrededor de federación SAML.
Segunda pata: canjear el grant
El cliente ahora presenta el ID-JAG al authorization server del servidor MCP como un JWT authorization grant:
POST /oauth2/token HTTP/1.1
Host: auth.mcp-server.example
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion=eyJ0eXAiOiJvYXV0aC1pZC1qYWcrand0...
&client_id=https://client.example/oauth-client-metadata
Nota el client_id: puede ser una URL de Client ID Metadata Document, el mismo mecanismo CIMD en el que se apoya la spec de autorización core de MCP en lugar del dynamic client registration. Los deberes de validación del authorization server están enumerados, y es donde se concentra la seguridad de todo el esquema. MUST confirmar que el header typ es oauth-id-jag+jwt; verificar la firma contra el JWKS publicado del IdP; comprobar que aud coincide exactamente con su propio issuer identifier, rechazando con invalid_grant en caso contrario; verificar el binding del client_id contra el cliente que lo presenta; y hacer cumplir la expiración. Si todo se sostiene, mapea sub a una cuenta local y emite su propio access token — restringido en audiencia al servidor MCP, con la vida útil que él elija (el ejemplo de la spec usa 24 horas). El lado del recurso nunca cede la emisión de tokens; cede solo la decisión de consent.
El account linking tiene reglas explícitas: usar sub como identificador estable primario, y recurrir a email solo para emparejar cuentas preexistentes creadas antes de configurar la autorización enterprise. El email es mutable y reasignable; los identificadores de sujeto se supone que no.
Discovery y el empaquetado MCP
¿Cómo sabe un cliente que un authorization server dado habla este perfil? Metadata. Un resource authorization server que acepta ID-JAGs anuncia urn:ietf:params:oauth:grant-profile:id-jag en el campo authorization_grant_profiles_supported de su authorization server metadata. Del lado del IdP, el soporte para emitir el tipo de token se señala vía identity_chaining_requested_token_types_supported. El propio draft reconoce un hueco abierto para clientes autónomos: sin metadata, la única opción de un agente es intentar el exchange y ver qué pasa.
En la capa MCP, el empaquetado sigue el mecanismo de extensiones que formalizó la revisión 2026-07-28 del protocolo. Un cliente declara soporte durante el initialize:
{
"capabilities": {
"extensions": {
"io.modelcontextprotocol/enterprise-managed-authorization": {}
}
}
}
Los servidores que exigen enterprise-managed auth declaran la extensión en su authorization metadata, y el cliente sabe que no debe arrancar un flujo de redirect de navegador que nunca le iban a dejar terminar. Las extensiones son opt-in y nunca están activas por defecto.
Quién lo lanzó, y qué revocó
El anuncio del 18 de junio listó un mapa de adopción concreto. Del lado IdP, Okta, vía su protocolo Cross App Access. Del lado cliente, Claude — Anthropic cableó el soporte a través de la capa MCP compartida, así que Claude, Claude Code y Cowork lo heredan — y VS Code. Del lado servidor: Asana, Atlassian, Canva, Figma, Granola, Linear y Supabase, con Slack en progreso. Tom Moor, head of engineering de Linear, resumió el efecto de cara al usuario sin rodeos: "Logging in once and automatically having all your MCP connectors automatically setup is pretty magical." Atlassian publicó su propio write-up de ingeniería el 29 de junio describiendo la implementación de Rovo MCP, actualmente en private beta.
La ganancia operativa es simétrica a la del onboarding, y posiblemente mayor. La revocación ocurre en el IdP: desactiva la cuenta o quita la membresía del grupo, y el siguiente ID-JAG de cinco minutos nunca se emite, en todos los clientes y todos los servidores a la vez. Compara eso con cazar grants OAuth de larga vida por servidor, un dashboard a la vez. Los access tokens ya emitidos siguen corriendo hasta su expiración — que es exactamente por qué la asimetría entre un grant de cinco minutos y un access token de 24 horas es una decisión de política que cada resource server debería tomar conscientemente, no copiar del ejemplo.
Los límites que importan para agentes
Tres restricciones en los drafts actuales merecen atención de cualquiera que opere flotas autónomas en lugar de empleados humanos.
El sujeto es un usuario, no un agente. Cada cadena de claims en ID-JAG resuelve a una identidad de empleado: sub es la persona que hizo SSO. El draft reconoce cadenas de delegación — existen un parámetro actor_token y un claim act en el vocabulario de token exchange — pero declina explícitamente definir procesamiento normativo para ellos, difiriéndolo a perfiles futuros. Hasta que eso llegue, un agente operando bajo EMA es indistinguible de su operador en la capa de identidad. Es el mismo hueco que señalamos en Web Bot Auth, donde las firmas identifican al proveedor, no al agente individual: la industria sigue estandarizando identidad un nivel por encima de donde realmente viven los agentes autónomos.
Solo clientes confidenciales. El draft dice que este perfil SHOULD limitarse a confidential clients — los public clients se quedan en el authorization code grant. Un runtime de agente headless puede ser un confidential client, pero implica que la gestión de credenciales es una precondición, no una idea tardía.
Un grant, un salto. Un ID-JAG está atado a una sola relación de confianza vía aud, y la spec prohíbe reutilizarlo en saltos aguas abajo; cada salto de una cadena multi-servicio necesita su propio grant emitido por el IdP. Para sistemas multi-agente que hacen fan-out servicio a servicio, eso significa que el IdP queda en el loop para cada arista del grafo de llamadas — una feature de política y un impuesto de latencia, a la vez.
Qué significa para LLM4Agents
EMA es la puerta de procurement del MCP enterprise. Los clientes que importan en despliegues corporativos — Claude, VS Code — ya lo hablan, y las organizaciones que lo adopten esperarán cada vez más que toda superficie MCP que compren sea gobernable desde la consola del IdP. LLM4Agents expone sus capacidades como servidor MCP; soportar la extensión es lo que hace esa superficie desplegable dentro de un entorno gobernado por Okta o Entra sin pedirle una excepción al departamento de IT. La alternativa es ser el único conector que todavía necesita sesenta mil pantallas de consent.
El punto más profundo es que el rail de identidad y el rail de pago responden preguntas distintas, y EMA hace el corte preciso. ID-JAG responde si el cliente de esta persona puede conectarse a este servidor, con estos scopes. No dice nada de metering, settlement, o cuánto cuesta una llamada. x402 responde quién paga esta llamada específica — con una autorización EIP-3009 firmada, sin IdP de por medio. La auditoría de ERC-8004 nos enseñó que el settlement es la única señal que resiste la falsificación; EMA no cambia eso, lo complementa. El compuesto natural para una flota enterprise es acceso gobernado por identidad con settlement de pago por uso debajo: el IdP decide qué agentes de qué empleados pueden alcanzar el gateway, y la capa de billing del gateway decide cómo liquida su uso. El claim sub nos da el identificador estable para atribuir uso por empleado dentro de un tenant — account linking para billing, siguiendo la misma regla sub-primario, email-fallback que manda la spec.
Hay también una convergencia que vale nombrar. El claim opcional authorization_details transporta grants estructurados RFC 9396 a través del IdP hasta el access token. Es el mismo patrón de allowance que seguimos encontrando en todo el stack de pagos — el objeto allowance de ACP, los permisos ERC-7715, el scheme upto de x402: un principal autoriza un sobre acotado, y la infraestructura hace cumplir la cota. Un IdP que pueda decir "el agente de este usuario puede llamar estas tools con este techo de gasto por día" — y un gateway que lo haga cumplir en el settle — es la versión enterprise del spend permission. Las piezas ya existen en ambos rails.
Cómo mantenerse en la frontera
Secuencia concreta, en orden de dependencia.
Primero, aceptar el grant. Agregar soporte de urn:ietf:params:oauth:grant-type:jwt-bearer al authorization server del gateway, validar ID-JAGs según el checklist (typ, firma contra el JWKS del IdP configurado, match exacto de aud, binding del cliente, expiración), y anunciar urn:ietf:params:oauth:grant-profile:id-jag en authorization_grant_profiles_supported. Fijar el draft -04 y documentar la revisión fijada, porque el texto del IETF sigue en movimiento.
Segundo, declarar la extensión en el servidor MCP y verificar el flujo end-to-end contra los dos clientes que ya lo traen — Claude y VS Code — con un tenant Okta de prueba. Esto es trabajo de días, no de meses, y es la diferencia entre aparecer o no aparecer en una client matrix enterprise.
Tercero, cablear el account linking al billing. Mapear el sub del ID-JAG a atribución de uso por empleado dentro de las cuentas de tenant, para que un cliente enterprise obtenga acceso gobernado por IdP y metering por usuario de la misma integración.
Cuarto, seguir el perfil de actor. El hueco de act/actor_token es donde va a aterrizar la identidad por agente en este stack. Cuando el OAuth WG o un perfil de MCP defina el procesamiento normativo, LLM4Agents debería implementarlo temprano — identidad a nivel de agente encadenada bajo política a nivel de usuario es exactamente la primitiva que necesita un gateway de flotas, y encaja en el trabajo de identidad de agentes que ya hacemos.
Quinto, prototipar el compuesto. Un endpoint gobernado por ID-JAG cuyo settlement corre sobre x402 debajo, con authorization_details llevando un techo de gasto que el gateway hace cumplir en el settle. La identidad decide la entrada; el settlement escribe el audit trail. Quien demuestre ese compuesto primero define cómo se facturan las flotas de agentes enterprise.
Opera tu flota sobre rails que componen
Gateway OpenAI-compatible, identidad amigable con el IdP, y settlement en stablecoins por llamada.
Registra tu agente