MCP: scopes y tokens
Cómo delimitar qué herramientas del servidor MCP puede usar cada token mediante scopes.
El servidor MCP de HotelDataHub (POST /mcp) expone herramientas ("tools") agrupadas
por dominio (documentación, logs, contactos, movimientos, clientes, hoteles, segmentos
y fidelización). Cada token puede limitarse a un subconjunto de esas herramientas
mediante scopes, de forma que, por ejemplo, una persona pueda tener acceso solo a la
documentación y los logs, y otra solo a los contactos.
Tabla de contenidos¶
- Cómo funciona
- Catálogo de scopes
- Qué herramienta requiere qué scope
- Crear un token con scopes
- Aplicaciones internas (acceso a todos los customers)
- Comportamiento al usar el token
- Usuarios internos (JWT)
Cómo funciona¶
La identidad detrás de un token (tanto un API key como un token OAuth2) es una Customer OAuth Application. Esa aplicación lleva una lista de scopes concedidos. La autorización se aplica en dos momentos:
tools/list— el token solo "ve" las herramientas para las que tiene scope. Las demás no aparecen, de modo que el agente no intenta usarlas.tools/call— antes de ejecutar una herramienta se vuelve a comprobar el scope. Si falta, la llamada devuelve un error:{"error": "Permiso denegado: se requiere el scope 'contacts:read'"}.
Catálogo de scopes¶
Los scopes siguen la convención dominio:acción (read para lectura, write para
creación/modificación):
| Scope | Permite |
|---|---|
docs:read |
Buscar en la documentación |
logs:read |
Consultar logs de la API HDH, peticiones push y eventos internos (Elasticsearch) |
contacts:read |
Leer contactos |
contacts:write |
Crear/modificar contactos |
movements:read |
Leer movimientos (reservas) |
movements:write |
Crear/modificar movimientos |
customers:read |
Leer clientes (cadenas), hoteles y conexiones |
hotels:read |
Leer hoteles de Fideltour |
segments:read |
Leer segmentos/audiencias |
loyalty:read |
Leer información de fidelización |
Los scopes de escritura de dominios que aún no tienen herramienta de escritura (
customers:write,hotels:write,segments:write,loyalty:write) existen en el catálogo para el futuro, pero hoy no habilitan ninguna herramienta.
Qué herramienta requiere qué scope¶
El scope de cada herramienta se deduce de su dominio y de si lee o escribe. Ejemplos:
| Herramienta | Scope |
|---|---|
search_documentation |
docs:read |
list_api_users, search_api_requests, get_api_request_body |
logs:read |
search_push_requests, get_push_request_body, list_loggable_integrations |
logs:read |
search_integration_events, search_internal_logs, search_logs |
logs:read |
search_contact_by_email, list_contacts, … |
contacts:read |
create_contact |
contacts:write |
list_movements, search_movement_by_localizer, … |
movements:read |
create_movement |
movements:write |
list_customers, get_customer_summary, list_connections, … |
customers:read |
list_hotels, get_hotel |
hotels:read |
list_segments, get_segment, get_segment_contacts |
segments:read |
list_operations, list_products, list_levels, … |
loyalty:read |
Crear un token con scopes¶
Desde el admin de Django (Customer OAuth Applications):
- Crea (o edita) una aplicación, asígnale un
usery uncustomer(cadena) para limitar los datos a ese cliente. Si la aplicación es para procesos internos de Fideltour y debe poder consultar cualquier cadena, deja elcustomervacío y marca Internal application (ver Aplicaciones internas). - En la sección Scopes, marca las casillas que correspondan. Para un token de
"documentación y logs", marca solo
docs:readylogs:read. - Guarda. Las credenciales
client_id/client_secretson el token.
Aplicaciones internas (acceso a todos los customers)¶
Una Customer OAuth Application normal queda ligada a una única cadena: sus tokens solo
pueden consultar datos del customer asignado. Para procesos internos de Fideltour que
necesitan preguntar por cualquier cadena existe el flag Internal application
(is_internal):
- Se marca en el admin, en la misma pantalla de la aplicación, dejando el campo
customervacío (son mutuamente excluyentes: el admin no permite guardar una app interna con customer asignado). - El token resultante (tanto por API key como por OAuth2) puede pasar cualquier
customer_codea las herramientas del MCP, ylist_customers/search_customerdevuelven todas las cadenas. - Los scopes siguen aplicando igual: una app interna con solo
contacts:readno puede usar herramientas de otros dominios.
Una aplicación sin customer y sin is_internal queda bloqueada: no puede acceder a
los datos de ninguna cadena (las herramientas devuelven Not authorized). Esto evita
que una app creada por error sin customer obtenga acceso global.
Comportamiento al usar el token¶
Con un API key (client_id:client_secret), listar herramientas:
curl -s -X POST https://<host>/mcp \
-H "X-API-Key: <client_id>:<client_secret>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Un token con ["docs:read","logs:read"] solo verá search_documentation y las
herramientas de logs (más las herramientas genéricas sin scope). Si intenta llamar a
search_contact_by_email, recibirá un error de permiso.
Usuarios internos (JWT)¶
Los usuarios autenticados por JWT (staff interno) no tienen aplicación asociada y, por tanto, no están limitados por scopes: siguen viendo y pudiendo usar todas las herramientas. Los scopes solo afectan a clientes externos vía API key u OAuth2.