Autentica a tus usuarios
Muchos servidores MCP de complementos pueden funcionar en un modo anónimo de solo lectura, pero cualquier funcionalidad que exponga datos específicos de un cliente o acciones de escritura debería autenticar a los usuarios.
Los complementos publicados pueden ejecutarse en ChatGPT y Codex. El contrato de autorización de MCP se aplica a ambos productos; esta guía señala los detalles del cliente específicos de ChatGPT cuando un callback, un documento de metadatos o una interfaz de vinculación varía según el producto.
Puedes integrar tu propio servidor de autorización cuando necesites conectarte a una aplicación existente del lado del servidor o compartir datos entre usuarios.
Autenticación personalizada con OAuth 2.1
Para un servidor MCP con autenticación, se espera que implementes un flujo de OAuth 2.1 que cumpla con la especificación de autorización de MCP.
Componentes
- Servidor de recursos: tu servidor MCP, que expone herramientas y verifica los tokens de acceso en cada solicitud.
- Servidor de autorización: tu proveedor de identidad o implementación personalizada que emite tokens y publica metadatos de descubrimiento.
- Cliente: el host de OpenAI, como ChatGPT o Codex, que actúa en nombre del usuario. Los clientes compatibles usan documentos de metadatos de ID de cliente (CIMD), registro dinámico de clientes (DCR), clientes OAuth predefinidos y PKCE.
Requisitos de la especificación de autorización de MCP
- Aloja los metadatos del recurso protegido en tu servidor MCP
- Publica metadatos de OAuth desde tu servidor de autorización
- Devuelve el mismo valor del parámetro
resourcedurante todo el flujo de OAuth - Elige cómo el host de OpenAI identifica o registra su cliente OAuth: CIMD, DCR o un cliente OAuth predefinido
- Publica los métodos de autenticación del punto de acceso de tokens que acepta tu servidor de autorización
Estos son los requisitos de la especificación, explicados en términos sencillos.
Aloja los metadatos del recurso protegido en tu servidor MCP
- Necesitas un punto de acceso HTTPS como
GET https://your-mcp.example.com/.well-known/oauth-protected-resource(o anunciar esa misma URL en un encabezadoWWW-Authenticateen las respuestas401 Unauthorized) para que ChatGPT sepa dónde obtener tus metadatos. - Ese punto de acceso devuelve un documento JSON que describe el servidor de recursos y sus servidores de autorización disponibles:
{
"resource": "https://your-mcp.example.com",
"authorization_servers": ["https://auth.yourcompany.com"],
"scopes_supported": ["files:read", "files:write"],
"resource_documentation": "https://yourcompany.com/docs/mcp"
}
- Campos clave que debes completar:
resource: el identificador HTTPS canónico de tu servidor MCP. ChatGPT envía este valor exacto como parámetro de consultaresourcedurante OAuth.authorization_servers: una o más URL base de emisores que apuntan a tu proveedor de identidad. ChatGPT probará cada una para encontrar los metadatos de OAuth.scopes_supported: lista opcional que ayuda a ChatGPT a explicar los permisos que le va a solicitar al usuario.- Los campos adicionales opcionales de RFC 9728, como
resource_documentation,resource_policy_urioresource_tos_uri, facilitan que los clientes y administradores comprendan tu configuración.
Cuando bloquees una solicitud porque no está autenticada, devuelve un desafío como este:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://your-mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
Ese único encabezado permite que ChatGPT descubra la URL de los metadatos aunque no la haya visto antes.
Publica metadatos de OAuth desde tu servidor de autorización
- Tu proveedor de identidad debe exponer uno de los documentos de descubrimiento en una ubicación conocida para que ChatGPT pueda leer su configuración:
- Metadatos de OAuth 2.0 en
https://auth.yourcompany.com/.well-known/oauth-authorization-server - Metadatos de OpenID Connect en
https://auth.yourcompany.com/.well-known/openid-configuration
- Metadatos de OAuth 2.0 en
- Cada documento responde tres preguntas clave para el host de OpenAI: a dónde enviar al usuario, cómo intercambiar códigos y cómo identificarse. Una respuesta típica tiene este aspecto:
{
"issuer": "https://auth.yourcompany.com",
"authorization_response_iss_parameter_supported": true,
"authorization_endpoint": "https://auth.yourcompany.com/oauth2/v1/authorize",
"token_endpoint": "https://auth.yourcompany.com/oauth2/v1/token",
"client_id_metadata_document_supported": true,
"token_endpoint_auth_methods_supported": ["none", "private_key_jwt"],
"registration_endpoint": "https://auth.yourcompany.com/oauth2/v1/register",
"code_challenge_methods_supported": ["S256"],
"scopes_supported": ["files:read", "files:write"]
}
- Campos que deben ser correctos:
issuer: el identificador canónico del servidor de autorización. Usa este valor exacto en la listaauthorization_serversde los metadatos del recurso protegido.authorization_response_iss_parameter_supported: establece su valor entruesolo cuando tu servidor de autorización devuelva un parámetroissen cada respuesta de autorización, incluidas las respuestas de error.authorization_endpoint,token_endpoint: las URL que ChatGPT necesita para ejecutar de principio a fin el flujo de código de autorización de OAuth con PKCE.client_id_metadata_document_supported: establece su valor entruecuando quieras que ChatGPT use CIMD para el registro de clientes. ChatGPT prioriza CIMD cuando está disponible, pero quien desarrolla el complemento puede elegir DCR cuando tanto CIMD como DCR están disponibles.token_endpoint_auth_methods_supported: incluye los métodos de autenticación del punto de acceso de tokens que acepta tu servidor de autorización. Esto se aplica a CIMD, DCR y los clientes OAuth predefinidos. Para CIMD, ChatGPT admitenonepara el intercambio de tokens de clientes públicos yprivate_key_jwtpara el intercambio de tokens mediante una aserción de cliente firmada. Otros clientes OAuth suelen usarnone,client_secret_postoclient_secret_basic.registration_endpoint: inclúyelo si admites el registro dinámico de clientes (DCR), que permite a ChatGPT crear y reutilizar unclient_iddedicado para la conexión con el servidor MCP.code_challenge_methods_supported: debe incluirS256. Los servidores MCP no son compatibles si los metadatos de su servidor de autorización omiten este campo o no anuncianS256, como exige la especificación de autorización de MCP.- Los campos opcionales siguen RFC 8414 / OpenID Discovery; incluye los que ayuden a tus administradores a configurar políticas.
Ámbitos de OIDC
- Si tu proveedor anuncia ámbitos de OIDC (por ejemplo,
openid,email,profile) enscopes_supportedde su documento.well-known/oauth-authorization-servero.well-known/openid-configuration, ChatGPT solicita esos ámbitos de forma predeterminada durante el flujo de OAuth. - Es posible que algunos proveedores de identidad no habiliten de forma predeterminada los ámbitos de OIDC que anuncian. Revisa la configuración de tu proveedor y asegúrate de que todos los ámbitos anunciados estén habilitados para el cliente OAuth, ya sea que use CIMD, se haya creado manualmente o se haya creado mediante DCR.
Admite restricciones de dominio del espacio de trabajo
Los espacios de trabajo de ChatGPT Enterprise pueden verificar la propiedad de los dominios de correo electrónico. Cuando un complemento vinculado mediante OAuth proporciona la dirección de correo electrónico verificada del usuario, ChatGPT puede usar el dominio del correo electrónico para impedir que esa identidad corporativa vincule el complemento en un espacio de trabajo personal o en otro espacio de trabajo ajeno a la organización.
Para admitir esta protección, configura tu servidor de autorización para que:
- Publique metadatos de descubrimiento de OpenID Connect.
- Anuncie y habilite los ámbitos
openidyemail. - Anuncie un punto de acceso UserInfo que devuelva la declaración
emaildel usuario yemail_verified: true.
También puedes devolver estas declaraciones en un token de ID durante el flujo de OAuth, pero el punto de acceso UserInfo es obligatorio para las restricciones de dominio del espacio de trabajo.
El espacio de trabajo de Empresas también debe verificar su dominio. Tu servidor de autorización proporciona la identidad del usuario que ChatGPT compara con los dominios verificados configurados para el espacio de trabajo; no verifica que el espacio de trabajo sea propietario de un dominio.
Conserva el contexto de inicio de sesión durante la reautorización
Cuando ChatGPT vuelve a autorizar una vinculación existente, incluso para solicitar ámbitos adicionales de OAuth, puede incluir el token de ID de OIDC anterior en la solicitud de autorización como parámetro estándar id_token_hint. Para que los usuarios puedan otorgar ámbitos adicionales sin iniciar sesión desde cero, configura tu servidor de autorización para que emita un token de ID durante el flujo de OAuth original y tenga en cuenta id_token_hint durante la autorización.
Esta optimización es opcional. La reautorización sigue funcionando cuando no hay un token de ID disponible o cuando tu servidor de autorización no utiliza esta indicación.
Protege los callbacks con la identificación del emisor
Los hosts de OpenAI usan la identificación del emisor de RFC 9207 para proteger los callbacks de OAuth contra ataques de confusión de servidores de autorización. Para permitir que ChatGPT y Codex usen una URI de redirección estable al crear un cliente OAuth que cumpla los requisitos:
- Establece
authorization_response_iss_parameter_supported: trueen los metadatos del servidor de autorización. - Usa exactamente el mismo identificador del emisor en el campo
issuerde los metadatos y en la listaauthorization_serversde los metadatos del recurso protegido. - Devuelve
issen todas las respuestas de autorización, tanto exitosas como de error. Su valor debe coincidir exactamente conissueren los metadatos; los clientes comparan las cadenas de forma exacta y no normalizan las barras finales, las rutas, los puertos ni las mayúsculas y minúsculas.
ChatGPT y Codex registran el valor issuer de los metadatos seleccionados antes de redirigir
al usuario y comprueban el iss devuelto antes de intercambiar el código
de autorización. Si el servidor anuncia la identificación del emisor pero omite iss o
devuelve un valor que no coincide, ChatGPT y Codex rechazan la respuesta. Estos requisitos
siguen las reglas de validación de respuestas
de autorización de MCP.
URL de redirección
Copia la URI exacta de redirección de producción que aparece en la página de administración del servidor MCP en la lista de permitidos de tu servidor de autorización.
- Si tu servidor de autorización no cumple con los requisitos de identificación del emisor
indicados anteriormente, ChatGPT usa la URI de redirección específica del ID de callback
https://chatgpt.com/connector/oauth/{callback_id}. - Si tu servidor de autorización cumple con esos requisitos, ChatGPT usa la
URI de redirección estable
https://chatgpt.com/connector_platform_oauth_redirect.
Los servidores MCP publicados antes de que ChatGPT incorporara las redirecciones específicas del ID de callback también siguen usando la URI de redirección estable.
Reproducir el parámetro resource a lo largo del flujo de OAuth
- Ten en cuenta que ChatGPT agrega
resource=https%3A%2F%2Fyour-mcp.example.comtanto a las solicitudes de autorización como a las de tokens. Esto vincula el token con los metadatos del recurso protegido que se muestran arriba. - Configura tu servidor de autorización para que copie ese valor en el token de acceso (normalmente en la declaración
aud), de modo que tu servidor MCP pueda verificar que el token se emitió exclusivamente para él. - Si llega un token sin la audiencia o los alcances esperados, recházalo y usa el desafío
WWW-Authenticatepara indicarle a ChatGPT que vuelva a realizar la autorización con los parámetros correctos.
Admitir el flujo de código de autorización
- ChatGPT, como cliente MCP, ejecuta el flujo de código de autorización con PKCE mediante el desafío de código
S256, para que un atacante no pueda reutilizar códigos de autorización interceptados. - Tu servidor de autorización debe publicar
code_challenge_methods_supportedconS256para que los clientes puedan confirmar la compatibilidad con PKCE a partir de los metadatos.
Flujo de OAuth
Si implementaste la especificación de autorización de MCP descrita anteriormente, el flujo de OAuth será el siguiente:
- ChatGPT consulta los metadatos del recurso protegido en tu servidor MCP.

- ChatGPT se identifica como el cliente OAuth. Cuando el servidor MCP usa CIMD, ChatGPT omite el registro dinámico de clientes y envía la URL de un documento CIMD como
client_id. Para los servidores de autorización que cumplen con los requisitos de identificación del emisor indicados anteriormente, ChatGPT usa la URL establehttps://chatgpt.com/oauth/client.json; para los demás servidores, usa la URL específica del ID de callbackhttps://chatgpt.com/oauth/{callback_id}/client.json. La página de administración del servidor MCP muestra el documento de metadatos del cliente y la URI de redirección exactos para el modo de callback de la conexión. Cuando el servidor MCP usa DCR, ChatGPT llama una vez alregistration_endpointde tu servidor de autorización para la conexión con el servidor MCP, recibe unclient_idgenerado y reutiliza ese cliente para la conexión.
Al usar CIMD, no hay un paso de registro del cliente. La siguiente pantalla muestra el flujo con DCR:

- Cuando el usuario invoca una herramienta por primera vez, el cliente de ChatGPT inicia el flujo de código de autorización de OAuth + PKCE. El usuario se autentica y da su consentimiento para los alcances solicitados.

- ChatGPT intercambia el código de autorización por un token de acceso y lo adjunta a las solicitudes MCP posteriores (
Authorization: Bearer <token>).

- Tu servidor verifica el token en cada solicitud (emisor, audiencia, vencimiento y alcances) antes de ejecutar la herramienta.
Registro de clientes
Usa documentos de metadatos del ID de cliente (CIMD) como método preferido de registro de clientes cuando tu servidor de autorización lo admita y el desarrollador del complemento lo elija. Con CIMD, ChatGPT usa la URL HTTPS de un documento de metadatos como su client_id. Tu servidor de autorización obtiene ese documento, valida los metadatos publicados del cliente y los identificadores de recursos de redirección, y trata la URL como la identidad estable de cliente de ChatGPT.
Si admites CIMD, establece client_id_metadata_document_supported: true en los metadatos de tu servidor de autorización. Esto permite que ChatGPT use una sola identidad estable de cliente para los servidores MCP que elijan CIMD. Tu servidor de autorización puede usar esa identidad para las listas de URI de redirección permitidas, los límites de solicitudes y otras políticas.
ChatGPT está adoptando la transición de CIMD propuesta en
MCP SEP-3149.
Su documento CIMD de producción publica
token_endpoint_auth_methods_supported como un arreglo de métodos que ChatGPT
puede usar, sin orden de preferencia. Durante la transición, también publica
el campo heredado en singular token_endpoint_auth_method como preferencia:
{
"token_endpoint_auth_methods_supported": ["none", "private_key_jwt"],
"token_endpoint_auth_method": "private_key_jwt"
}
El campo en plural refleja distintas perspectivas en los dos documentos: los metadatos del servidor de autorización enumeran los métodos que acepta tu punto de acceso de tokens, mientras que el documento CIMD de ChatGPT enumera los métodos que ChatGPT puede usar. ChatGPT selecciona un método de la intersección de esos conjuntos. Cuando la preferencia del campo heredado en singular está en la intersección, ChatGPT la usa para mantener la compatibilidad con los servidores de autorización que aún consideran vinculante el campo en singular. De lo contrario, ChatGPT puede usar otro método de la intersección.
Los servidores de autorización que lean el campo CIMD en plural deberían aceptar cualquier método
de la intersección, a menos que la política de seguridad local prohíba ese método para el
cliente. Deben rechazar los métodos que no estén en la intersección. La URL de client_id
se mantiene estable y no usa parámetros de consulta para seleccionar un documento
específico de un método.
Los métodos admitidos son:
none: usa este flujo de cliente público cuando tu punto de acceso de tokens admita el intercambio de códigos de autorización basado en PKCE sin autenticación del cliente. ChatGPT no almacena un secreto por cliente.private_key_jwt: usa este flujo de aserción firmada del cliente cuando tu punto de acceso de tokens requiera autenticación del cliente. ChatGPT publica una URL pública de JWKS en sus metadatos CIMD. El JWKS se sirve desde/oauth/jwks.jsonen el origen de los metadatos. ChatGPT firma las solicitudes de tokens en el servidor con una clave privada administrada y unkid; tu servidor de autorización verifica la aserción con el JWKS público.
DCR sigue siendo compatible. Si incluyes registration_endpoint, ChatGPT puede registrarse dinámicamente cuando el desarrollador del complemento elija DCR o CIMD no esté disponible. ChatGPT ejecuta DCR una vez por conexión con el servidor MCP y luego conserva y reutiliza el cliente OAuth registrado para esa conexión. DCR puede generar muchos clientes registrados en muchas conexiones independientes, por lo que CIMD suele ser más fácil de administrar a gran escala.
Mantén válidos el cliente OAuth registrado y cualquier secreto de cliente mientras la conexión con el servidor MCP esté en uso. Si tu servidor de autorización hace vencer, elimina o reemplaza cualquiera de las credenciales, los usuarios y revisores pueden recibir un error invalid_client al conectarse. Los tokens de acceso y de actualización pueden seguir venciendo o rotando con normalidad.
Identificación del cliente
Una pregunta frecuente es cómo puede tu servidor MCP confirmar que una solicitud realmente proviene de ChatGPT. ChatGPT presenta un certificado de cliente administrado por OpenAI al conectarse a servidores MCP, por lo que puedes verificar el cliente en la capa de transporte con mTLS. También puedes agregar a la lista de permitidos los rangos de IP de salida publicados de ChatGPT. ChatGPT no admite concesiones de OAuth entre máquinas, como credenciales de cliente, cuentas de servicio o aserciones JWT de portador, ni puede presentar claves de API personalizadas o certificados mTLS proporcionados por el cliente.
CIMD refuerza aún más la identificación del cliente al proporcionar a tu servidor de autorización una declaración estable de la identidad de ChatGPT alojada en HTTPS. Cuando uses private_key_jwt, verifica la aserción de cliente que ChatGPT envía al punto de acceso de tokens con el JWKS público publicado en los metadatos CIMD.
TLS mutuo (mTLS)
ChatGPT ahora presenta un certificado de cliente administrado por OpenAI al establecer conexiones TLS con servidores MCP. Si tu aplicación valida certificados de cliente, configúrala para que confíe en la cadena de certificados de OpenAI que se muestra a continuación.
Para validar el certificado de cliente al establecer la conexión TLS con tu servidor MCP:
- Verifica que haya un certificado de entidad final y que su cadena llegue a la CA intermedia de mTLS de OpenAI Connectors.
- Verifica que el certificado de entidad final sea válido para la autenticación del cliente.
- Verifica que el
dnsNamedel SAN del certificado de entidad final seamtls.prod.connectors.openai.com. - Evita fijar la huella digital de un certificado de entidad final; OpenAI puede rotar ese certificado y mantenerlo dentro de la cadena de CA publicada.
Usa mTLS para autenticar a ChatGPT como cliente MCP. Sigue usando OAuth 2.1 para autenticar al usuario final y autorizar el acceso a las herramientas.
Elegir un proveedor de identidad
La mayoría de los proveedores de identidad de OAuth 2.1 pueden cumplir con los requisitos de autorización de MCP si exponen un documento de descubrimiento, admiten CIMD con none o private_key_jwt, admiten DCR cuando sea necesario y reproducen el parámetro resource en los tokens emitidos. Da preferencia a los proveedores que admitan CIMD para el registro de clientes.
Te recomendamos enfáticamente que uses un proveedor de identidad existente y consolidado en lugar de implementar la autenticación desde cero por tu cuenta.
Aquí encontrarás instrucciones para algunos proveedores de identidad populares.
Auth0
Auth0 permite que los clientes MCP se conecten de forma segura a los servidores MCP al proporcionar descubrimiento de metadatos, registro con CIMD, seguridad de API e intercambio de tokens para llamadas a herramientas propias y de terceros.
- Guía para configurar Auth0 para la autorización de MCP
- Descripción general de la protección de servidores MCP con Auth0
- Guías de inicio rápido para proteger servidores MCP con Auth0
Ejemplo de proveedor alojado
- Guía del proveedor sobre la autorización de MCP
- Descripción general de la autorización de MCP
- Guía de autenticación para la interfaz de ChatGPT
Implementar la verificación de tokens
Cuando finaliza el flujo de OAuth, ChatGPT adjunta directamente el token de acceso que recibió a las solicitudes MCP posteriores (Authorization: Bearer …). Cuando una solicitud llega a tu servidor MCP, debes asumir que el token no es confiable y realizar por tu cuenta todas las comprobaciones del servidor de recursos: validación de la firma, coincidencia del emisor y la audiencia, vencimiento, consideraciones sobre ataques de repetición y aplicación de los alcances. Esa responsabilidad te corresponde a ti, no a ChatGPT.
En la práctica, deberías:
- Obtén las claves de firma publicadas por tu servidor de autorización (normalmente mediante JWKS) y verifica la firma del token y
iss. - Rechaza los tokens que hayan vencido o que aún no sean válidos (
exp/nbf). - Confirma que el token se haya emitido para tu servidor (
audo la declaraciónresource) y que contenga los alcances que marcaste como obligatorios. - Ejecuta las comprobaciones de políticas específicas del servidor y luego adjunta la identidad resuelta al contexto de la solicitud o devuelve un
401con un desafíoWWW-Authenticate.
Si la verificación falla, responde con 401 Unauthorized y un encabezado WWW-Authenticate que apunte a los metadatos de tu recurso protegido. Esto le indica al cliente que vuelva a ejecutar el flujo de OAuth.
Primitivas del SDK para la verificación de tokens
Los kits de desarrollo de software de MCP para Python y TypeScript incluyen funciones auxiliares para que no tengas que implementar esto desde cero.
Admitir varias cuentas
La compatibilidad con varias cuentas permite a los usuarios conectar más de una cuenta al mismo complemento, por ejemplo, una personal y otra de trabajo. OpenAI enruta cada llamada a herramientas con las credenciales autenticadas de la conexión seleccionada. Los usuarios pueden conectar varias cuentas sin una herramienta de perfil. Para ayudarlos a distinguir las conexiones y reconocer el mismo perfil después de una reconexión, proporciona una herramienta de perfil con autenticación que devuelva un ID estable y metadatos de visualización útiles.
Cómo funciona la compatibilidad con varias cuentas para los usuarios
Los usuarios pueden conectar cuentas adicionales desde la página de configuración del complemento. Todas las cuentas conectadas están disponibles para el modelo, que selecciona la cuenta o las cuentas pertinentes al invocar herramientas según la solicitud del usuario. Cada llamada a herramientas usa las credenciales y los permisos de la cuenta seleccionada.
Mejorar la identificación de las cuentas
Para ayudar a OpenAI a reconocer los perfiles conectados y mostrar etiquetas útiles:
- Proporciona una herramienta de perfil con autenticación que devuelva un ID opaco que identifique de forma única y estable el perfil representado por las credenciales de la solicitud. Esto permite a OpenAI reconocer el mismo perfil en sucesivas reconexiones y distinguirlo de otros perfiles. Un campo llamado
idsolo sirve para este propósito si su valor cumple esas garantías. - Designa la herramienta de perfil en los metadatos de MCP para que OpenAI pueda descubrir qué herramienta llamar para obtener información autenticada del perfil.
Cuando se necesita información del perfil, OpenAI descubre la herramienta designada en tiempo de ejecución, la llama con las credenciales de la conexión y valida la respuesta antes de usar los datos del perfil. Sin una herramienta de perfil, los usuarios pueden seguir conectando cuentas, pero las etiquetas de las cuentas, su reconocimiento o la detección de duplicados pueden ser menos confiables. Si declaras una herramienta de perfil, devuelve una identidad válida; una respuesta no válida puede impedir la conexión de la cuenta.
Definir una identidad de perfil estable
Un perfil identifica la identidad representada por las credenciales autenticadas de la solicitud. Tu servicio define qué perfiles se pueden conectar de forma independiente; este contrato no impone el modelo de organización ni de autorización de tu servicio.
Devuelve un ID de perfil opaco que sea único dentro de tu aplicación. El mismo perfil debe conservar su ID al actualizar el token y al volver a conectarse; los perfiles distintos deben tener ID distintos. OpenAI compara estos ID sin interpretar su contenido.
Usa un ID del proveedor existente, inmutable y opaco cuando identifique el perfil completo. De lo contrario, asigna un ID opaco una sola vez, guarda de forma persistente su asociación con ese perfil y recupera el mismo ID en solicitudes futuras. Mantén las relaciones internas dentro de tu servicio; no codifiques nombres, direcciones de correo electrónico ni relaciones organizativas en el ID devuelto.
Tu id debe:
- Ser una cadena que no esté vacía ni contenga solo espacios en blanco. Serializa los ID numéricos del proveedor como cadenas.
- Mantenerse igual para el mismo perfil al actualizar el token, volver a conectarse y ampliar los ámbitos.
- Ser distinto para cada perfil que pueda conectarse a través de la aplicación.
- Permanecer sin cambios cuando cambien el correo electrónico, el nombre o la etiqueta visible del perfil.
- No reasignarse nunca a un perfil diferente después de la eliminación.
No generes un ID nuevo por cada inicio de sesión, token, sesión o llamada a herramientas. Mantén el correo electrónico y los nombres editables en los metadatos de visualización: una dirección de correo electrónico que pueda cambiar o reasignarse no puede servir como ID de perfil estable. Para Google OIDC, usa el valor estable de sub en lugar de la declaración de correo electrónico; Google documenta que el correo electrónico puede cambiar, mientras que sub permanece sin cambios y nunca se reutiliza. Consulta la documentación de identidad de Google.
Conserva los ID de perfil existentes al actualizar tu integración. Un cambio de nombre visible, un token nuevo o una conexión nueva no deben crear una identidad de perfil nueva.
Implementar y declarar tu herramienta de perfil
Expón una herramienta con autenticación y de solo lectura que acepte un objeto de argumentos vacío y devuelva el perfil actual. La herramienta puede llamarse get_profile, whoami o tener otro nombre; sus metadatos la identifican como la herramienta de perfil para su descubrimiento en tiempo de ejecución. La respuesta debe cumplir los requisitos de identidad que se indican a continuación para que OpenAI pueda usarla correctamente.
- Determina la identidad a partir de las credenciales validadas de la solicitud.
- Haz que la operación sea de solo lectura y esté disponible con los permisos habituales de la conexión.
- Devuelve exactamente un perfil: el representado por las credenciales de la solicitud actual.
- No exijas que quien realiza la llamada proporcione un ID de usuario, un correo electrónico ni un selector de cuenta.
- Si falla la autenticación, devuelve el error de autenticación correspondiente en lugar de un ID de relleno o el perfil de otra cuenta.
La respuesta del perfil debe ajustarse a este JSON Schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"pattern": "\\S",
"description": "Opaque profile identifier, unique within this app and unchanged across token refresh, reconnection, and display-metadata changes. Never reassigned to another profile."
},
"name": {
"type": "string",
"description": "Display name for the authenticated profile."
},
"email": {
"type": "string",
"description": "Email address for display; not used as the profile identity."
},
"nickname": {
"type": "string",
"description": "A useful label that helps users distinguish connected profiles."
}
},
"required": ["id"],
"additionalProperties": false
}
La respuesta debe contener un campo id de tipo cadena que no esté vacío ni contenga solo espacios en blanco. Los campos de visualización son opcionales. Los metadatos de la herramienta indican a OpenAI dónde obtener la información del perfil; la respuesta identifica el perfil representado por las credenciales actuales.
La validación del esquema comprueba si una respuesta tiene la estructura y los tipos de campo necesarios para gestionar perfiles. Tu servicio también debe garantizar que los ID sean únicos y estables, y que el alcance de las credenciales sea correcto; ni los metadatos ni una validación exitosa del esquema demuestran esas propiedades de comportamiento.
Incluye name, email y/o nickname cuando estén disponibles para que los usuarios puedan distinguir los perfiles. Omite los valores opcionales que no estén disponibles; no los inventes ni agregues datos personales no relacionados. Coloca el contexto útil y legible para las personas en nickname, en lugar de incluirlo en el ID.
Marca la herramienta con _meta["openai/profile"]: true y publica el esquema de respuesta del perfil como su outputSchema. El marcador indica a OpenAI qué herramienta proporciona información del perfil; no habilita la función ni otorga elegibilidad para usarla. Si el marcador está ausente o es falso, la herramienta no está designada como fuente de información del perfil mediante este mecanismo. Las cadenas, los números y null no son valores válidos para el marcador.
{
"name": "get_profile",
"description": "Return the profile represented by this request's authenticated credentials. The opaque id is unique within this app and remains unchanged across token refresh, reconnection, and display-metadata changes.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"pattern": "\\S",
"description": "Opaque profile identifier, unique within this app and unchanged across token refresh, reconnection, and display-metadata changes. Never reassigned to another profile."
},
"name": {
"type": "string",
"description": "Display name for the authenticated profile."
},
"email": {
"type": "string",
"description": "Email address for display; not used as the profile identity."
},
"nickname": {
"type": "string",
"description": "A useful label that helps users distinguish connected profiles."
}
},
"required": ["id"],
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"securitySchemes": [
{
"type": "oauth2",
"scopes": []
}
],
"_meta": {
"openai/profile": true
}
}
Usa los ámbitos de OAuth reales de tu integración si el acceso al perfil los requiere. La declaración no implementa la autenticación; el servidor debe validar las credenciales y aplicar los permisos. Consulta Implementar la verificación de tokens y la referencia de herramientas.
Devuelve el perfil en structuredContent para que se pueda validar con outputSchema. Por compatibilidad, incluye también el mismo perfil serializado como JSON en un elemento de contenido de texto:
{
"content": [
{
"type": "text",
"text": "{\"id\":\"prf_8d7e4b19\",\"name\":\"Alex Chen\",\"email\":\"alex@example.com\",\"nickname\":\"Alex — Moonwaffle work\"}"
}
],
"structuredContent": {
"id": "prf_8d7e4b19",
"name": "Alex Chen",
"email": "alex@example.com",
"nickname": "Alex — Moonwaffle work"
},
"isError": false
}
Usa un único objeto JSON con los campos del perfil en el nivel superior.
¿Ya tienes una herramienta de perfil? Conserva su nombre, agrega la declaración de metadatos de perfil y devuelve la respuesta de perfil estándar. Si la respuesta existente tiene una estructura diferente, adáptala en tu servidor o expón una pequeña herramienta envolvente que se ajuste al esquema. El método de integración estándar usa la misma declaración y estructura de respuesta para todas las aplicaciones.
Ejemplo concreto: perfiles persistentes de Moonwaffle
Supongamos que Moonwaffle, un servicio ficticio, permite a Alex conectar dos perfiles de forma independiente. Moonwaffle almacena un ID opaco distinto para cada perfil. Las credenciales de la solicitud identifican uno de esos perfiles almacenados, y la herramienta de perfil devuelve su ID existente.
Ejemplo de perfiles almacenados. Las etiquetas pueden cambiar; los identificadores permanecen iguales:
Alex — Moonwaffle personal: prf_42a9c6e0
Alex — Moonwaffle work: prf_8d7e4b19
Estos ID de ejemplo no codifican etiquetas de perfil ni relaciones internas. Se almacenan de forma persistente una sola vez por perfil y se reutilizan al volver a conectarse, actualizar el token y cambiar el correo electrónico o el nombre visible.
Construye la respuesta a partir del perfil autenticado. Este ejemplo de JavaScript muestra la lógica de un manejador que puedes conectar a tu SDK de MCP. loadAuthenticatedProfile es el código de integración de tu aplicación: valida las credenciales de la solicitud, aplica sus permisos y recupera el ID persistente y los metadatos de visualización del perfil correspondiente. requestContext proviene del procesamiento de solicitudes de tu servidor; no es un argumento de la herramienta proporcionado por el modelo.
async function getProfile(requestContext) {
// Your auth/provider integration validates credentials and loads
// the existing profile. Auth failures use normal MCP auth handling.
const account = await loadAuthenticatedProfile(requestContext);
const id = account.profileId;
if (typeof id !== "string" || id.trim().length === 0) {
return {
isError: true,
content: [{ type: "text", text: "Profile identity unavailable." }],
};
}
// Return the persisted ID unchanged; do not generate an ID per call.
const profile = {
id,
...(typeof account.name === "string" ? { name: account.name } : {}),
...(typeof account.email === "string" ? { email: account.email } : {}),
...(typeof account.nickname === "string"
? { nickname: account.nickname }
: {}),
};
return {
isError: false,
structuredContent: profile,
content: [{ type: "text", text: JSON.stringify(profile) }],
};
}
Registra este manejador con la declaración de metadatos y los esquemas de entrada y salida anteriores. loadAuthenticatedProfile debe identificar el mismo perfil almacenado para credenciales equivalentes y después de una reconexión. No debe crear un ID de perfil nuevo por cada concesión de OAuth o sesión. Todas las demás herramientas deben usar las credenciales de la solicitud para aplicar los permisos de ese mismo perfil.
Verifica el comportamiento de la identidad:
| Prueba | Resultado esperado |
|---|---|
| Llamadas repetidas para el perfil de trabajo de Moonwaffle | prf_8d7e4b19 en cada llamada |
| El mismo perfil después de actualizar el token, volver a conectarse o ampliar un ámbito | prf_8d7e4b19 |
| El mismo perfil después de cambiar el correo electrónico o la etiqueta visible | prf_8d7e4b19; las etiquetas pueden cambiar |
| Perfil personal de Moonwaffle | prf_42a9c6e0, distinto del ID del perfil de trabajo |
| El ID persistente del perfil está ausente o en blanco | Un resultado de error; sin inventar una identidad ni recurrir a otro perfil |
La garantía de identidad debe mantenerse para todos los perfiles y ante cambios futuros en tu integración. Consérvala independientemente de los metadatos de visualización, el contenido de los tokens y los eventos del ciclo de vida de la conexión.
Pruebas y lanzamiento
- Pruebas locales: comienza con un tenant de desarrollo que emita tokens de corta duración para poder iterar rápidamente.
- Pruebas internas: una vez que funcione la autenticación, limita el acceso a personas de confianza que realicen pruebas antes del lanzamiento general. Puedes exigir la vinculación para herramientas específicas o para todo el servidor MCP.
- Rotación: planifica la revocación y renovación de tokens, así como los cambios de alcance. Tu servidor debe tratar las solicitudes con tokens ausentes u obsoletos como no autenticadas y devolver un mensaje de error útil.
- Depuración de OAuth: usa la configuración de autenticación de MCP Inspector para recorrer cada paso de OAuth y localizar dónde falla el flujo antes del lanzamiento.
Con la autenticación implementada, puedes ofrecer datos específicos de cada usuario y acciones de escritura a los usuarios de ChatGPT y Codex.
Activar la interfaz de autenticación
ChatGPT solo muestra su interfaz de vinculación mediante OAuth cuando tu servidor MCP indica que OAuth está disponible o es necesario.
Para activar el flujo de OAuth de una herramienta, se necesitan tanto metadatos (securitySchemes y el documento de metadatos del recurso) como errores en tiempo de ejecución que incluyan _meta["mcp/www_authenticate"]. Sin ambos elementos, ChatGPT no mostrará la interfaz de vinculación para esa herramienta.
-
Publica los metadatos del recurso. El servidor MCP debe exponer su configuración de OAuth en una URL de ubicación conocida, como
https://your-mcp.example.com/.well-known/oauth-protected-resource. -
Describe la política de autenticación de cada herramienta con
securitySchemes. DeclararsecuritySchemespara cada herramienta le indica a ChatGPT cuáles requieren OAuth y cuáles pueden ejecutarse de forma anónima. Mantén las declaraciones por herramienta incluso si todo el servidor usa la misma política; los valores predeterminados a nivel de servidor dificultan modificar herramientas individuales más adelante.Actualmente hay dos tipos de esquema disponibles, y puedes incluir más de uno para indicar que la autenticación es opcional:
noauth: la herramienta se puede invocar de forma anónima; ChatGPT puede ejecutarla de inmediato.oauth2: la herramienta necesita un token de acceso de OAuth 2.0; incluye los alcances que solicitarás para que la pantalla de consentimiento muestre información precisa.
Si omites el arreglo por completo, la herramienta hereda el valor predeterminado que anuncie el servidor. Declarar tanto
noauthcomooauth2le indica a ChatGPT que puede comenzar con llamadas anónimas, pero que la vinculación habilita funciones con privilegios. Independientemente de lo que le indiques al cliente, tu servidor debe verificar el token, los alcances y la audiencia en cada invocación.Ejemplo (acceso público + autenticación opcional): SDK de TypeScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; declare const server: McpServer; server.registerTool( "search", { title: "Public Search", description: "Search public documents.", inputSchema: { q: z.string(), }, outputSchema: {}, securitySchemes: [ { type: "noauth" }, { type: "oauth2", scopes: ["search.read"] }, ], }, async ({ q }) => { return { content: [{ type: "text", text: `Results for ${q}` }], structuredContent: {}, }; } );Ejemplo (autenticación obligatoria): SDK de TypeScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; declare const server: McpServer; server.registerTool( "create_doc", { title: "Create Document", description: "Make a new doc in your account.", inputSchema: { title: z.string(), }, outputSchema: {}, securitySchemes: [{ type: "oauth2", scopes: ["docs.write"] }], }, async ({ title }) => { return { content: [{ type: "text", text: `Created doc: ${title}` }], structuredContent: {}, }; } ); -
Comprueba los tokens dentro del manejador de la herramienta y emite
_meta["mcp/www_authenticate"]cuando quieras que ChatGPT active la interfaz de autenticación. Inspecciona el token y verifica el emisor, la audiencia, el vencimiento y los alcances. Si no hay un token válido, devuelve un resultado de error que incluya_meta["mcp/www_authenticate"]y asegúrate de que el valor contenga tanto el parámetroerrorcomo el parámetroerror_description. Esta carga útil deWWW-Authenticatees lo que realmente activa la interfaz de OAuth de la herramienta una vez implementados los pasos 1 y 2. Cuando un desafío solicita una nueva autorización, tu proveedor puede conservar el contexto de inicio de sesión existente del usuario durante ese flujo.Ejemplo
{ "jsonrpc": "2.0", "id": 4, "result": { "content": [ { "type": "text", "text": "Authentication required: no access token provided." } ], "_meta": { "mcp/www_authenticate": [ "'Bearer resource_metadata=\"https://your-mcp.example.com/.well-known/oauth-protected-resource\", error=\"insufficient_scope\", error_description=\"You need to login to continue\"'" ] }, "isError": true } }