MCP: búsqueda de logs

Herramientas del servidor MCP para consultar los tres tipos de logs que HDH guarda en Elasticsearch.

HotelDataHub registra en Elasticsearch tres familias de índices distintas, cada una con un propósito y un contenido diferentes. El servidor MCP (POST /mcp) expone una herramienta especializada por cada una, más una herramienta unificadora para cuando no se sabe en qué índice está el dato. Todas requieren el scope logs:read y devuelven únicamente datos del cliente (customer) indicado.

Tabla de contenidos

Las tres aplicaciones de Elasticsearch

Aplicación Índices Qué contiene Cuándo usarla
HTTP backend_api_{año}_{mes}_{prefijo} Peticiones/respuestas HTTP crudas que recibe HDH, tanto de la API autenticada como de integraciones push. Ver el tráfico HTTP literal: ruta, método, código de estado y, bajo demanda, cuerpo.
Integraciones integration_log_{año}_{mes}_{source} Cada entrada recibida de una integración PMS/BE (booking, huésped, evento…) tal y como llegó, con su payload original en data, antes de normalizarse. "¿Qué nos mandó el PMS X?", auditar lo recibido, depurar una reserva.
Interna hdh_log_{año}_{mes} Eventos internos del propio HDH (locks de movimiento fallidos, contacto no encontrado, warnings/errores de procesamiento). No son datos de negocio. Diagnosticar por qué algo no se procesó.

El scoping por cliente difiere: el tráfico autenticado de la API se acota por apiuser_id y se contrasta con el customer_id; el tráfico push, que puede no estar autenticado, se acota por la URL de la petición. Las aplicaciones de integraciones e interna se acotan por el campo customer_id del documento. Los eventos internos globales (sin customer_id) nunca se devuelven a través del MCP.

Elegir entre tráfico de API y tráfico push

Company.use_api indica el flujo recomendado, pero es una señal orientativa: la existencia del ApiUser y de documentos en Elasticsearch es la fuente de verdad.

  1. Ejecuta list_api_users(customer_code, company_name) para localizar la empresa.
  2. Si company.use_api es true, usa search_api_requests y después, solo si hace falta, get_api_request_body.
  3. Si company.use_api es false, usa list_loggable_integrations, search_push_requests y get_push_request_body.
  4. Si el flag no coincide con el caso investigado, no bloquea una búsqueda explícita: un ApiUser perteneciente al customer todavía puede consultarse por su ID.

Ejemplo para investigar «las peticiones recibidas por la API HDH»:

list_api_users(customer_code="CHAIN01")
search_api_requests(customer_code="CHAIN01", apiuser_id=123, days=7)
get_api_request_body(customer_code="CHAIN01", apiuser_id=123,
                     request_id="abc123", index="backend_api_2026_8_contacts")

Ejemplo para una «integración con Paraty» cuando todavía no se sabe cómo envía los datos:

list_api_users(customer_code="CHAIN01", company_name="Paraty")

Si el resultado contiene un usuario y company.use_api=true, continúa con search_api_requests. Si no hay usuario o use_api=false, consulta las integraciones push con list_loggable_integrations y search_push_requests.

Herramientas disponibles

Parámetros comunes de rango de fechas en todas ellas: si no se indican from_date/to_date (formato YYYY-MM-DD, inclusivos) se consultan los últimos days días (por defecto 7). El tamaño máximo de resultados es 50 (size, por defecto 20), siempre de más reciente a más antiguo.

list_api_users

Lista los ApiUser del customer. Acepta company_name como filtro parcial sin distinguir mayúsculas/minúsculas y active_only (por defecto true). Devuelve:

  • ID y username del ApiUser.
  • Estado, última conexión y nombres de sus permisos.
  • ID, código y nombre del customer.
  • ID, nombre y use_api de la company.

No devuelve contraseñas, hashes, tokens ni flags internos de normalización.

search_api_requests

Busca el tráfico autenticado de un ApiUser en todos los índices mensuales backend_api_* del rango. Antes de consultar valida que el usuario pertenece al customer_code. El filtro de path solo acota documentos; no se usa para deducir el índice, por lo que rutas como /api/v1/contacts/ se buscan correctamente.

Parámetro Descripción
customer_code Código de la cadena. Obligatorio.
apiuser_id ID obtenido con list_api_users. Obligatorio.
path_contains Fragmento opcional de la ruta.
method Método HTTP opcional, por ejemplo GET o POST.
status_code Estado HTTP opcional, por ejemplo 200, 400 o 500.
days, from_date, to_date, size Rango inclusivo y tamaño; últimos 7 días y máximo 50 resultados.

Cada resultado incluye path, method, status_code, @timestamp, host, customer_id, company_id, apiuser_id, _id e _index. No incluye cuerpos, respuestas ni cabeceras, para evitar exponer credenciales o datos personales en listados.

get_api_request_body

Recupera el cuerpo de una única petición localizada con search_api_requests. Requiere el request_id y el index exactos devueltos por la búsqueda. Solo acepta índices backend_api_* y vuelve a validar que el documento pertenece al ApiUser, customer y company indicados. Si el cuerpo es JSON, lo devuelve indentado; también incluye ruta, método, estado y timestamp.

search_push_requests (aplicación HTTP)

Busca peticiones push (webhooks) recibidas de un PMS/Booking Engine para los hoteles del cliente. Devuelve solo metadata; el cuerpo completo se obtiene con get_push_request_body. Requiere el nombre de la integration (su configuración de Elastic vive en el frontmatter de la documentación de cada integración). Usa list_loggable_integrations para descubrir qué integraciones son consultables y a qué hoteles corresponden.

search_integration_events (aplicación de integraciones)

Busca las entradas crudas registradas por cada integración para un cliente.

Parámetro Descripción
customer_code Código de la cadena en Fideltour (p. ej. CHAIN01). Obligatorio.
source Nombre corto de la integración (sufijo del índice), p. ej. sihot, opera, cloudbeds, winhotelv2. Si se omite, busca en todos los sources del cliente.
company_id, connection_id, place_id Filtros opcionales por empresa, conexión u hotel.
event_type Tipo de evento (booking, guest, event, roomstay, loyalty_member…).
status received, processed o error.
days, from_date, to_date, size Rango y tamaño (ver arriba).

Respuesta:

{
  "customer_code": "CHAIN01",
  "count": 2,
  "sources_found": ["sihot"],
  "events": [
    {
      "@timestamp": "2026-06-22T08:14:03Z",
      "source": "sihot",
      "status": "received",
      "event_type": "booking",
      "company_id": 15,
      "company": "Sihot",
      "customer_id": 314,
      "customer": "Cadena Demo",
      "place_id": 42,
      "place": "Hotel Demo",
      "connection_id": 1234,
      "data": "{...payload original de la integración...}",
      "_id": "abc123",
      "_index": "integration_log_2026_06_sihot"
    }
  ]
}

El campo sources_found lista los sources presentes en los resultados, útil cuando se busca sin especificar source.

search_internal_logs (aplicación interna)

Busca eventos internos del sistema HDH para un cliente.

Parámetro Descripción
customer_code Código de la cadena. Obligatorio.
log_type Identificador del evento, p. ej. movement_lock_failed, contact_not_found.
level warning, error o info.
company_id, connection_id Filtros opcionales.
days, from_date, to_date, size Rango y tamaño.

Respuesta:

{
  "customer_code": "CHAIN01",
  "count": 1,
  "logs": [
    {
      "@timestamp": "2026-06-22T08:10:00Z",
      "log_type": "movement_lock_failed",
      "level": "warning",
      "company_id": 15,
      "company": "Sihot",
      "customer_id": 314,
      "connection_id": 1234,
      "place_id": 42,
      "data": "{...detalles del evento...}",
      "_id": "def456",
      "_index": "hdh_log_2026_06"
    }
  ]
}

search_logs (búsqueda unificada)

Cuando no se sabe en qué aplicación está el dato, search_logs lanza la consulta a las tres y combina los resultados, etiquetando cada uno con el campo application (http, integration o internal).

Parámetro Descripción
customer_code Código de la cadena. Obligatorio.
applications Subconjunto de ["http", "integration", "internal"]. Por defecto, las tres.
source Filtro de la app de integraciones (nombre corto).
integration Nombre de la integración para la app HTTP (p. ej. Sihot).
event_type, status Filtros de la app de integraciones.
level, log_type Filtros de la app interna.
status_code, method Filtros de la app HTTP.
days, from_date, to_date, size Rango y tamaño del resultado combinado.

Coste de la app HTTP: resolver la aplicación HTTP requiere conocer la integración. Si se indica integration, solo busca en esa; si no, busca en todas las integraciones consultables del cliente con un límite reducido por integración, lo que puede ser lento. Excluye "http" de applications para saltarla, o indica integration para acotar.

Respuesta:

{
  "customer_code": "CHAIN01",
  "counts": {"http": 0, "integration": 2, "internal": 1},
  "count": 3,
  "results": [
    {"application": "integration", "@timestamp": "2026-06-22T08:14:03Z", "...": "..."},
    {"application": "internal", "@timestamp": "2026-06-22T08:10:00Z", "...": "..."}
  ],
  "notes": ["http: ..."]
}

El campo notes recoge avisos de diagnóstico (por ejemplo, por qué se omitió o acotó una aplicación).

Nota RGPD

El payload original de las integraciones (data en search_integration_events y en los resultados integration de search_logs) contiene datos personales del huésped, igual que los cuerpos de get_push_request_body y get_api_request_body. Consulta los cuerpos solo de forma individual, cuando sean necesarios, y no los expongas más allá de lo solicitado.