← Blog
1 de septiembre, 2026 · 15 min

CIMD en produccion: identidad de agente sin registro

MCP deprecio Dynamic Client Registration el 28 de julio y convirtio una URL en la identidad de cliente preferida. Crawleamos el registry entero, resolvimos 3.450 authorization servers y contamos cuantos tomaron el camino nuevo.

Un agente que quiere llamar a un MCP server protegido tiene un problema antes de tener un problema de pagos. Necesita un client_id. Durante una decada OAuth asumio que un desarrollador humano iria a una consola, registraria una aplicacion y pegaria una credencial en un archivo de configuracion. Esa suposicion no sobrevive al contacto con software autonomo que descubre un server en runtime y nunca conocio a su operador.

La respuesta del Model Context Protocol, desde la revision 2026-07-28, son los Client ID Metadata Documents. El cliente deja de pedir que lo registren y publica sus propios datos de registro en una URL HTTPS. Esa URL es el client ID. El authorization server la busca cuando ve una.

Es una idea limpia con una superficie de seguridad real, y llego atada a una deprecacion. Queriamos saber si la deprecacion obliga a algo. Asi que leimos las tres revisiones del draft del IETF, las diffeamos y despues medimos el ecosistema desplegado.

El mecanismo en un parrafo

draft-ietf-oauth-client-id-metadata-document es un documento del working group Web Authorization Protocol, de Aaron Parecki (Okta) y Emelia Smith, standards track. La revision -00 salio el 8 de octubre de 2025, la -01 el 2 de marzo de 2026 y la -02 el 6 de julio de 2026, con vencimiento el 7 de enero de 2027. Define una Client Identifier URL: una URL https que MUST contener un componente de path, MUST NOT contener componente userinfo ni fragment, SHOULD NOT contener query, y MAY contener puerto. El documento al que resuelve es metadata OAuth de cliente comun mas una regla: MUST contener una propiedad client_id que coincida con la Client Identifier URL y con la URL que el server efectivamente busco.

La comparacion es byte a byte. El draft es explicito en que https://example.com/client y https://example.com:443/client son identificadores distintos aunque 443 sea el puerto por defecto de https. Servir el documento en un / pelado es NOT RECOMMENDED. Los acortadores de URL son inutilizables, porque funcionan redirigiendo y la spec prohibe que el server siga redirects.

El documento tampoco puede llevar un secreto. token_endpoint_auth_method MUST NOT incluir client_secret_post, client_secret_basic, client_secret_jwt ni ningun otro metodo construido sobre un secreto simetrico compartido, y client_secret directamente MUST NOT aparecer. Lo fuerza el medio: el documento es legible por cualquiera, por definicion. La autenticacion, si la hay, es asimetrica.

El linaje es anterior a la ola de agentes. Los agradecimientos citan Solid-OIDC, IndieAuth y OpenID Federation, y nombran los Client Identifier Documents dereferenciables de Solid-OIDC como la inspiracion directa.

Que endurecio el working group, y cuando

Las tres revisiones no son ediciones cosmeticas. El documento paso de 26.867 bytes a 47.328. Contando keywords normativas en el texto crudo, MUST va de 17 a 22 a 30, y MUST NOT va de 8 a 9 a 12. Dos de esos agregados importan mas que el resto, y el propio change log del draft los fecha con precision.

La revision -01 agrego "Require HTTP 200 response for fetching metadata". Tambien introdujo la regla de que el authorization server MUST NOT seguir automaticamente redirects HTTP al recuperar el documento. Ninguna de las dos frases existe en -00. Sin ellas, un atacante que consiga servir un redirect desde un dominio reputado puede apuntar una Client Identifier URL a un host confiable en apariencia y hacer que la metadata se resuelva desde otro lado.

La revision -02 reescribio la seccion de SSRF. En -00 el texto dice que los authorization servers "SHOULD avoid fetching any URLs using private or loopback addresses and consider network policies or other measures to prevent making requests to these addresses". En -02 dice:

Authorization servers MUST NOT fetch a Client ID Metadata Document URL or any URLs contained within a Client ID Metadata Document that resolve to special-use IP addresses as defined in [RFC6890].

Es un SHOULD promovido a MUST NOT, con una excepcion angosta para deployments de desarrollo que corren sobre loopback ellos mismos, y un explicito "Authorization servers MUST NOT apply this exception in production deployments". El cambio importa porque una Client Identifier URL es input provisto por el atacante que el authorization server esta obligado a dereferenciar. Eso es una primitiva de server-side request forgery por construccion, y el draft ahora la trata como tal.

La revision -02 tambien agrego una seccion completa de Privacy Considerations que -00 no tenia. Volvemos a eso, porque un cliente real la activa hoy.

El gap de la referencia

La spec de authorization de MCP cita el draft por revision exacta. Todos los links son a -00.

La pagina de security considerations es donde esto pega. Su seccion de Client ID Metadata Document dice que los authorization servers "SHOULD consider Server-Side Request Forgery (SSRF) risks", linkeando a la seccion 6 de -00. No dice absolutamente nada sobre redirects HTTP. Un implementador que siga la referencia normativa de MCP al pie de la letra se queda con el threat model de octubre de 2025: SSRF es un consejo, perseguir redirects no esta contemplado y la regla de solo-200 no existe.

MCP si agrega dos requisitos que el draft del IETF no trae, ambos apuntados a la misma debilidad. Dice sin rodeos que "Client ID Metadata Documents cannot prevent localhost URL impersonation by themselves", y despues exige que los authorization servers MUST mostrar claramente el hostname del redirect URI durante la autorizacion y SHOULD advertir sobre redirect URIs que sean solo localhost. Es un aporte genuino. Tambien es una mitigacion de interfaz de usuario para un problema machine-to-machine, que es la forma recurrente de toda esta area.

El gap es angosto pero real — CIMD -00 y -02 son el mismo protocolo. No son el mismo threat model. Quien construya un authorization server MCP hoy deberia implementar -02 y tratar la cita a -00 de MCP como un pin viejo, no como un techo.

El censo

La pregunta interesante no es que dicen las specs. Es si un agente, en el campo, puede efectivamente usar una URL como identidad. El SDK de MCP lo hace medible, porque filtra estrictamente. En el SDK de TypeScript en HEAD dcc0102 (31 de agosto de 2026), la decision es una linea:

// packages/client/src/client/auth.ts
const supportsUrlBasedClientId = metadata?.client_id_metadata_document_supported === true;
const shouldUseUrlBasedClientId = supportsUrlBasedClientId && clientMetadataUrl;

if (shouldUseUrlBasedClientId) {
  // SEP-991: URL-based Client IDs
  clientInformation = { client_id: clientMetadataUrl, issuer };
} else {
  // Fallback to dynamic registration
}

Igualdad estricta contra true. Si el authorization server no publica el flag client_id_metadata_document_supported registrado en IANA, el SDK toma en silencio el camino deprecado. El mismo archivo lleva el aviso de deprecacion sobre registerClient: deprecado a partir de la version de protocolo 2026-07-28 bajo SEP-2577, "Remains functional during the deprecation window (at least twelve months)".

Asi que un solo booleano, publicado en la metadata del authorization server, decide si el mecanismo nuevo se usa o no. Lo contamos.

El 1 de septiembre de 2026 paginamos hasta agotarla la API del registry oficial de MCP: 872 paginas, 87.160 entradas, de las cuales 86.161 estan marcadas como activas y 26.120 son la ultima version de su server. Eso dio 14.868 endpoints remotos HTTPS distintos — otras 211 entradas se descartaron porque sus URLs son templates sin resolver como https://{HAPI_FQDN}:{HAPI_PORT}/mcp. Deduplicando por origin quedaron 10.382 hosts.

Para cada origin pedimos la protected resource metadata de RFC 9728, tanto en el well-known de raiz como en la forma con el path del recurso como sufijo. 3.791 origins devolvieron un documento valido, 36,5 por ciento; 623 no conectaron o dieron timeout. De los documentos devueltos, 149 no traian ningun array authorization_servers. El resto resolvio a 3.498 issuers distintos de authorization server.

Despues buscamos la metadata de authorization server de cada issuer, probando tanto la forma de insercion de path de RFC 8414 como la forma de discovery de OpenID Connect. Respondieron 3.450 de 3.498, una tasa de resolucion del 98,6 por ciento. Esto es lo que publican.

// Censo 2026-09-01

3.450 authorization servers de MCP

client_id_metadata_document_supported: true — 592 servers, 17,2 por ciento.

Explicitamente false — 179 servers, 5,2 por ciento. Flag ausente por completo — 2.679 servers, 77,7 por ciento.

registration_endpoint presente — 3.232 servers, 93,7 por ciento.

Cinco semanas despues de que MCP depreciara Dynamic Client Registration, el 93,7 por ciento de los authorization servers detras de los endpoints MCP listados en el registry siguen publicando un endpoint de DCR, y el 82,8 por ciento no le da a un cliente del SDK ninguna forma de usar una URL como identidad.

La adopcion es aditiva, no una migracion

El cruce es mas filoso que el titular. De los 592 servers que soportan CIMD, 524 tambien publican un registration_endpoint. Eso es 88,5 por ciento. Solo 68 servers en toda la poblacion — 2,0 por ciento — soportan CIMD y efectivamente apagaron DCR.

Nadie esta migrando. Estan agregando una segunda puerta y dejando la primera abierta. Es defendible durante una ventana de deprecacion de doce meses, y tambien significa que la deprecacion hoy no cambia nada de lo que un atacante puede hacer: el endpoint de registro que motivo SEP-991 sigue ahi, sigue aceptando nombres de cliente auto-declarados, en el 94 por ciento de los servers.

En el otro extremo, 150 servers (4,3 por ciento) no publican ni CIMD ni endpoint de registro. Bajo la prioridad de registro de cliente de MCP en cuatro pasos — pre-registro, despues CIMD, despues DCR, despues preguntarle al usuario — esos servers caen en el paso cuatro. Un agente autonomo no tiene paso cuatro.

El soporte que si existe esta concentrado en plataformas, no en operadores individuales. Agrupando los 592 por dominio, 66 son tenants de WorkOS AuthKit (de 75 issuers de AuthKit que vimos), 33 estan en mcpize.run, 6 son Scalekit, 3 son Smithery. El resto es una cola larga de deployments de un solo tenant. Un vendor cambiando un default mueve este numero mas que cien autores de servers leyendo la spec.

El espacio negativo es mas ruidoso. Los MCP servers propios de Cloudflare — observability, bindings, builds, radar, containers, browser y otros — devuelven client_id_metadata_document_supported: false de forma explicita, 14 de los 15 issuers de Cloudflare en nuestro censo, mientras siguen ofreciendo DCR. No es un descuido; declarar el flag en false es un acto deliberado. Clerk muestra CIMD habilitado en 3 de 77 issuers, algo que su propio changelog explica: la funcion esta en beta, los workspaces tienen que contactar a soporte para activarla, y publicarla es un segundo toggle aparte. La capacidad existe y viene apagada por defecto. Stytch muestra 2 en true contra 4 explicitamente en false. Auth0 muestra 3 de 11.

Los endpoints de Google y Microsoft en nuestra muestra no publican ni el flag de CIMD ni un endpoint de registro. Para los agentes, los proveedores de identidad mas grandes del mundo son hoy el paso cuatro.

El lado del cliente, y un canal lateral

El censo de servers mide solo la mitad del handshake. Del lado del cliente hay un deployment de produccion inequivoco y verificable: Visual Studio Code. Su documento esta vivo en https://vscode.dev/oauth/client-metadata.json, 477 bytes, HTTP 200, sin redirects, comodo dentro del limite de lectura de 5 kilobytes del draft:

{
  "client_id": "https://vscode.dev/oauth/client-metadata.json",
  "client_name": "Visual Studio Code",
  "client_uri": "https://vscode.dev/product",
  "application_type": "native",
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token",
                   "urn:ietf:params:oauth:grant-type:device_code"],
  "redirect_uris": ["http://127.0.0.1:33418/", "https://vscode.dev/redirect"]
}

Es conforme. Tambien es instructivo por dos motivos.

Primero, tanto este documento como el de Insiders en insiders.vscode.dev se sirven con cache-control: no-store, no-cache, max-age=0. El draft dice que los authorization servers SHOULD respetar los headers de cache HTTP. Respetarlos significa volver a buscar el documento en cada request de autorizacion. La nueva seccion 9.1 de la -02 describe exactamente lo que eso produce:

the timing and frequency of requests to a Client Identifier URI can indicate when, and how often, users are attempting to authorize with a particular authorization server.

Un cliente que prohibe el cacheo convierte cada intento de autorizacion contra cada server de internet en un request entrante a un host que el controla. No estamos alegando intencion — no-store es el default sensato para un archivo que queres poder rotar. Pero es la configuracion maximamente observable, y es la razon por la que la -02 crecio una seccion de privacidad. Para una flota de agentes la misma propiedad es peor: la URL de identidad de un agente se vuelve una baliza que reporta con que endpoints pagos esta negociando, y cuando.

Segundo, los dos documentos comparten el client name "Visual Studio Code", el mismo logo del canal estable y el mismo redirect de loopback http://127.0.0.1:33418/. Este es precisamente el riesgo de impersonacion en localhost que SEP-991 marco cuando Paul Carleton y Aaron Parecki lo abrieron en julio de 2025, y que la pagina de seguridad de MCP admite que CIMD no puede resolver por si solo. Cualquier documento que reclame ese nombre y ese puerto es indistinguible en la capa de protocolo.

La palanca que no se puede accionar

La defensa estructural principal del draft contra la impersonacion esta en la seccion 8.1: un authorization server "may impose restrictions or relationships between the redirect_uris and the client_id or client_uri properties, for example to restrict the redirect_uri to the same-origin as the Client ID Metadata Document". El binding same-origin es lo que vuelve significativo el control del dominio: ata el lugar donde se entrega el code al dominio que publico la identidad.

Los clientes nativos no pueden cumplirlo. El authorization code de VS Code tiene que volver a http://127.0.0.1:33418/, que no es same-origin con vscode.dev, y nunca puede serlo. La forma dominante de cliente MCP — un proceso local en un puerto de loopback — es estructuralmente incompatible con la palanca mas fuerte que ofrece la especificacion. El draft lo reconoce de forma oblicua al preservar redirect_uris sin restriccion por compatibilidad con Solid-OIDC, y al agregar un apendice entero sobre "CIMD Services" para que los desarrolladores que no pueden hostear un documento publico tengan algun camino.

Lo que queda es reputacion. La seccion 8.9 sugiere advertir a los primeros 100 usuarios de un client_id, revisar hace cuanto se registro el dominio y mantener allowlists de patrones confiables como *.example.com. Son heuristicas sensatas para un humano frente a una pantalla de consentimiento. Ninguna esta disponible para un agente que se autoriza solo a las tres de la manana.

Que significa para LLM4Agents

CIMD es el primer mecanismo de identidad de agente en este espacio que cuesta casi nada adoptar y es genuinamente portable. MCP enuncia la propiedad directamente: los client IDs basados en Client ID Metadata Documents son portables entre authorization servers, porque son URLs auto-hosteadas resueltas bajo demanda, asi que no hace falta re-registrarse cuando cambia el authorization server. Para un gateway cuyos agentes se abren hacia muchas herramientas, esa es la diferencia entre una identidad y N filas de registro.

Encaja en nuestro stack en tres lugares. Como cliente, cuando un agente que corre a traves del gateway llama a un MCP server protegido, el gateway deberia presentar una Client Identifier URL estable en vez de registrar dinamicamente una identidad nueva por server — el patron que defendimos en nuestra lectura de la authorization de MCP. Como resource server, nuestros propios endpoints protegidos deberian aceptar client IDs de tipo URL. Y como operador, el censo de arriba es un input de ruteo: el 82,8 por ciento de los authorization servers de MCP dejan a DCR como unico camino, asi que cualquier cliente que shippeemos tiene que cargar los dos caminos durante al menos la ventana de doce meses.

La amenaza que introduce es la que vale la pena planificar. Una Client Identifier URL es una dependencia en el camino de autorizacion. Si nuestro documento de identidad queda inalcanzable, todos los intentos de autorizacion fallan de golpe — un punto unico de falla sin analogo bajo DCR, donde un registro ya obtenido sigue funcionando. Y el canal lateral de fetch significa que nuestro host de identidad aprende, y podria filtrar, la forma del uso de herramientas de nuestros agentes. Es la misma categoria de fuga que medimos en las convenciones GenAI de OpenTelemetry, entrando por otra puerta.

Por ultimo, CIMD resuelve identidad y nada mas. Le dice a un server que cliente esta preguntando. No dice nada sobre cuanto puede gastar ese cliente, y por eso compone con — en vez de reemplazar — los controles del lado de pagos que auditamos en los caps por defecto de x402, y la capa de workload identity de WIMSE y SPIFFE. Un agente necesita un nombre, un presupuesto y una credencial de workload. Son tres documentos separados.

Como mantenerse en la frontera

En orden:

Publicar una Client Identifier URL ya, e implementar -02, no -00. Una URL HTTPS estable con path, un client_id que coincida, sin secreto, un documento chico y un lifetime de cache real. No copiar el no-store de VS Code; poner un max-age moderado para que los authorization servers puedan cachear y el canal lateral de fetch se angoste. Servirla desde infraestructura con el mismo objetivo de disponibilidad que el gateway, porque ahora esta en el camino critico.

Shippear ambos caminos de registro e instrumentar el fallback. Con 93,7 por ciento de disponibilidad de DCR contra 17,2 por ciento de CIMD, un agente que solo habla CIMD no puede alcanzar a la mayoria de los servers hoy. Loguear que camino toma cada autorizacion. Esa proporcion, medida contra los servers que efectivamente llamamos y no contra el registry entero, es la senal que nos dice cuando soltar DCR — no la fecha de deprecacion.

Tratar el documento de identidad como una dependencia de disponibilidad. Monitorearlo como monitoreamos un facilitator. Servirlo desde un dominio que controlamos punta a punta, no desde un host de documentacion ni un alias de CDN, y nunca desde un redirect. Rotar la URL tampoco es gratis: la seccion 8.3 de la -02 nota que una Client Identifier URL cambiada le parece a cada authorization server un cliente enteramente nuevo, lo que significa perder el consentimiento acumulado.

Del lado de resource server, publicar el flag y aplicar las reglas endurecidas. Si protegemos endpoints MCP, publicar client_id_metadata_document_supported: true — el SDK no intentara CIMD de otro modo. Despues implementar los requisitos de la -02 que la cita a -00 permite saltear: rechazar redirects, exigir 200, bloquear direcciones de uso especial segun RFC 6890, capear la lectura en 5 kilobytes y nunca buscar logo_uri ni jwks_uri sin las mismas restricciones.

No confundir control de dominio con confianza. Un documento conforme prueba que alguien controla un hostname. No prueba que el cliente sea lo que dice ser, y la defensa same-origin no esta disponible para clientes de loopback. Donde se mueve valor, mantener identidad y autoridad separadas: la URL de identidad dice quien llama, la autorizacion de pago dice cuanto puede gastar, y ninguna deberia poder responder por la otra.

Mirar el draft, no la cita. La revision -02 vence el 7 de enero de 2027. El delta de -00 a -02 fueron dos requisitos duros nuevos y una seccion de privacidad; el delta a -03 va a caer dentro de nuestra ventana de deprecacion. Seguir el documento del working group directamente y volver a correr este censo cada trimestre — el numero que importa no es lo que MCP recomienda, es lo que publican los servers que efectivamente llamamos.

La identidad es un documento. El presupuesto es otro.

LLM4Agents le da a los agentes autonomos un gateway compatible con OpenAI que paga por llamada en stablecoins — con los spend controls que la identidad sola no puede dar.

Registrar un agente