Skip to main content
Glama
Varma904

Agentic Travel Recommendations Service

by Varma904

Servicio agéntico de recomendaciones de viajes

Este proyecto es una prueba de concepto en TypeScript y Node.js para un servicio de recomendaciones de viajes multiinquilino. Expone capacidades compartidas de recomendación a través de una API REST, un endpoint MCP de Streamable HTTP y una interfaz de línea de comandos.

Características principales

  • API REST para salud, perfiles de miembros y recomendaciones

  • Endpoint MCP de Streamable HTTP

  • Herramienta MCP: get_member_profile

  • Herramienta MCP: get_recommendations

  • Resolución autoritativa del inquilino derivada del miembro

  • Límites de recomendaciones específicos del socio

  • Exclusiones de categorías específicas del socio

  • Generación determinista de recomendaciones

  • Comportamiento de configuración del socio con cierre ante fallos

  • IDs de solicitud y registros JSON estructurados

  • Demostración mínima de CLI

  • Construcción Docker de varias etapas

  • Pruebas automatizadas

Arquitectura de un vistazo

REST / MCP / CLI
       |
       v
RecommendationService
       |
       v
MemberDataService
       |
       | member.partnerId
       v
PartnerConfigurationService
       |
       v
CandidateGenerator
       |
       v
RecommendationPolicy
       |
       | exclusions then cap
       v
Final Recommendations

Los llamadores proporcionan solo memberId; no seleccionan el partnerId autoritativo. El perfil del miembro determina la configuración del socio, y REST, MCP y CLI reutilizan la misma capa de negocio.

Inicio rápido

npm ci
npm run dev

El servicio está disponible por defecto en http://localhost:3000.

Comprobación de tipos

npm run typecheck
npm run typecheck:test
npm run typecheck:all

Pruebas

npm test

La base verificada actual es de 46 pruebas superadas en 6 archivos.

Compilación de producción

npm run build
npm start

API REST

GET /health
GET /api/members/:memberId
GET /api/recommendations/:memberId

Ejemplos de solicitudes:

curl http://localhost:3000/api/members/MEMBER-001
curl http://localhost:3000/api/recommendations/MEMBER-001

MCP

El servidor MCP se expone a través de:

POST /mcp

Proporciona estas herramientas:

  • get_member_profile

  • get_recommendations

Ambas herramientas aceptan solo el identificador del miembro:

{
  "memberId": "MEMBER-001"
}

La implementación utiliza el transporte Streamable HTTP del SDK oficial @modelcontextprotocol/sdk. El llamador no proporciona partnerId; este se resuelve a partir del perfil autoritativo del miembro.

CLI

npm run cli -- MEMBER-001

Miembros de demostración:

  • MEMBER-001BANK_A

  • MEMBER-002BANK_B

  • MEMBER-003CREDIT_UNION_C

Docker

docker build -t agentic-travel-recommendations .
docker run --rm -p 3000:3000 agentic-travel-recommendations

La imagen utiliza una compilación de varias etapas, un runtime de Node 24 y un usuario de runtime no root. El servidor HTTP gestiona las señales de apagado ordenado.

Sección A — Arquitectura y compensaciones

Resumen de la arquitectura

El servicio es una aplicación TypeScript y Node.js sin estado que expone el mismo flujo de trabajo de recomendaciones a través de REST, MCP de Streamable HTTP y una CLI. Cada transporte valida su entrada y delega en el RecommendationService compartido; los manejadores de transporte no implementan la política del socio por sí mismos.

El flujo autoritativo del inquilino es:

memberId
→ MemberDataService
→ MemberProfile.partnerId
→ PartnerConfigurationService
→ CandidateGenerator
→ RecommendationPolicy
→ final recommendations

Los llamadores proporcionan memberId y nunca seleccionan el partnerId autoritativo. El perfil del miembro devuelto por MemberDataService determina qué configuración del socio se recupera. Ambos servicios ascendentes también correlacionan la identidad incrustada en una respuesta con la identidad solicitada, y RecommendationService realiza una comprobación adicional de identidad del socio antes de la generación.

La generación de candidatos es intencionadamente independiente de la política del socio. El generador determinista produce primero candidatos brutos a partir del perfil del miembro; la capa de política genérica elimina después los candidatos en excludedCategories y aplica recommendationCap, en ese orden. Solo se devuelven las recomendaciones resultantes. El Servicio de Datos del Miembro y el Servicio de Configuración del Socio están simulados (mocked) para esta prueba de concepto, y el acceso a la configuración del socio es de solo lectura.

Compensaciones de diseño

Corrección frente a disponibilidad. Si la configuración autoritativa del socio falta, no está disponible, no es válida según el esquema o no coincide la identidad, la solicitud falla de forma segura (fail closed). El servicio no sustituye permisos por defecto ni devuelve recomendaciones sin restricciones. Esto puede reducir la disponibilidad durante un fallo ascendente, pero evita que las recomendaciones escapen a la política correcta del inquilino.

Configuración actual frente a caché. La primera versión recupera la configuración del socio para cada solicitud de recomendación en lugar de añadir infraestructura de caché. Esto mantiene el comportamiento simple y asegura que cada solicitud exitosa use la política actual. Acepta latencia y carga ascendentes adicionales; una caché de corta duración es apropiada más adelante solo si el rendimiento medido justifica la compensación de consistencia.

Generación determinista frente a un LLM externo. La generación de candidatos es reproducible, comprobable, sin coste y operativamente predecible. Esto limita la sofisticación de la personalización, pero hace que el comportamiento de la política y los resultados de evaluación sean fáciles de verificar. Un futuro LLM o componente de clasificación podría reemplazar la generación de candidatos sin cambiar la aplicación determinista de la política.

Gestión de cambios en la configuración del socio

El Servicio de Configuración del Socio es una dependencia de solo lectura. Si un socio cambia su límite de recomendaciones de ilimitado a 3, o añade cruise a excludedCategories, el servicio de recomendaciones no necesita ningún cambio de código ni ninguna rama específica por inquilino. La siguiente solicitud exitosa lee la configuración actual y la lógica de política genérica aplica los nuevos valores de exclusión y límite.

Mientras la configuración siga siendo compatible con el esquema existente, la aplicación no requiere una nueva implementación. Si se introduce caché de configuración más adelante, debe tener un TTL intencionadamente corto o una estrategia de invalidación fiable, porque una configuración obsoleta podría violar temporalmente la política actual del socio.

Sección B — Preparación para producción y respuesta ante incidentes

Entrada del runbook de incidentes

Escenario: Un miembro informa de que el AI Concierge mostró una recomendación de crucero aunque su socio excluye los cruceros.

  1. Identificar y correlacionar. Obtenga el ID de solicitud o correlación del informe cuando esté disponible y localice los registros estructurados correspondientes. Registre la operation, el memberId, el partnerId autoritativo una vez resuelto, el resultCode y el estado HTTP cuando corresponda. El historial de viajes y las cargas de recomendaciones no se registran intencionadamente, por lo que debe usar identificadores y metadatos de resultado para la correlación.

  2. Verificar el inquilino autoritativo. Recupere el miembro afectado a través de MemberDataService y confirme que el memberId solicitado es igual al member.memberId devuelto. Derive el inquilino solo a partir de member.partnerId. No confíe en un ID de socio proporcionado por un frontend, un llamador MCP, un parámetro de consulta o un informe de soporte.

  3. Verificar la configuración del socio. Recupere la configuración usando member.partnerId y confirme que configuration.partnerId === member.partnerId. Inspeccione excludedCategories y recommendationCap, y determine si cruise está excluido en la configuración autoritativa actual. La configuración faltante, no disponible, malformada o con identidad no coincidente debe hacer que el servicio falle de forma segura (fail closed) en lugar de usar valores por defecto permisivos.

  4. Reproducir el pipeline. Ejecute el miembro a través del mismo flujo de trabajo de recomendaciones. Un crucero en la salida bruta de CandidateGenerator no es en sí mismo un defecto porque la generación ignora deliberadamente la política del socio. Verifique que RecommendationPolicy procesa candidatos brutos → eliminar categorías excluidas → aplicar límite de recomendaciones → recomendaciones finales, y confirme que los cruceros están ausentes del resultado final.

  5. Aislar la ubicación del fallo. Si los cruceros aparecen en los candidatos brutos pero no en las recomendaciones finales, la política está operando correctamente. Investigue una respuesta de cliente obsoleta, una respuesta asociada al miembro equivocado, otro consumidor o endpoint que omita el flujo de trabajo esperado, o una diferencia entre el momento del informe y la configuración actual. Si un crucero sobrevive a RecommendationPolicy, inspeccione la comparación o normalización de categorías, el contenido e identidad de la configuración autoritativa, y los cambios o regresiones recientes de la política.

  6. Contener. Si no se puede establecer o reproducir de forma segura la política correcta del socio, falle de forma segura (fail closed) en lugar de devolver recomendaciones potencialmente no conformes. No intente modificar el Servicio de Configuración del Socio de solo lectura desde esta aplicación.

  7. Corregir y verificar. Corrija el defecto en la capa responsable y añada una prueba de regresión que reproduzca el fallo exacto. Ejecute:

    npm run typecheck:all
    npm test
    npm run build

    Verifique el socio afectado, al menos un inquilino no afectado, el comportamiento REST y el comportamiento MCP cuando corresponda.

  8. Seguimiento. Registre la causa raíz, el alcance del socio y miembro afectados, la ventana de impacto, la remediación, la cobertura de regresión y la acción preventiva.

Parte B2 — Pregunta de razonamiento requerida

Un asistente de codificación con IA podría plausiblemente producir una implementación que valide con Zod los registros ascendentes de miembros y socios pero que nunca correlacione las identidades devueltas con las identidades solicitadas. El código sería seguro en cuanto a tipos, las pruebas de validación de esquema y de camino feliz pasarían, y una revisión superficial vería una validación defensiva razonable. La falta de la invariante entre inquilinos seguiría creando un grave riesgo de política.

Por ejemplo, MEMBER-001 pertenece a BANK_A. RecommendationService solicita la configuración de BANK_A, pero un servicio ascendente con errores o mal enrutado devuelve una configuración de BANK_B completamente válida según el esquema, con un límite ilimitado y sin exclusiones de categorías. Zod acepta correctamente su forma, pero aplicar esa política a MEMBER-001 podría eludir las restricciones de BANK_A.

Detectaría esto con una prueba de regresión adversarial: solicitar BANK_A mientras un doble

Mantuve el RecommendationService compartido, el CandidateGenerator determinista, la RecommendationPolicy separada, la resolución de tenant derivada del miembro, el contrato de configuración de solo lectura y la lógica de negocio REST/MCP/CLI compartida. Esta estructura hace que la política de tenant sea comprobable de forma independiente y evita implementaciones de reglas específicas del transporte. También conservé intencionadamente la generación determinista en lugar de añadir una dependencia externa de LLM. La evaluación se centra en el diseño del servicio y la aplicación de políticas, y la salida reproducible es más fácil de probar, depurar y demostrar. Cada incremento se aceptó solo después de que su comportamiento coincidiera con los invariantes arquitectónicos y las comprobaciones se superaran.

Interacción 3 — Auditoría de producción y seguridad

Lo que pregunté

Una vez que la aplicación funcionó, le pedí a la IA que dejara de añadir funciones y auditará el repositorio desde las perspectivas de un ingeniero senior, un revisor de seguridad multi-tenant, un responsable de producción de guardia y un revisor de API REST/MCP.

Lo que proporcionó la IA

La auditoría reveló que las respuestas ascendentes válidas según el esquema no se correlacionaban originalmente con la identidad del miembro o socio solicitada. También descubrió que un JSON malformado podía fallar antes de que el middleware de ID de solicitud estableciera el contexto de la solicitud. Se sugirieron mejoras adicionales de menor prioridad.

Lo que mantuve, cambié o rechacé

Acepté ambos hallazgos de alto valor porque afectaban a la corrección del tenant y a las operaciones seguras. Para la correlación de identidad, la implementación ahora verifica que un memberId devuelto coincida con el miembro solicitado, que configuration.partnerId coincida con el member.partnerId autoritativo, y que RecommendationService repita la comprobación de identidad de configuración de forma defensiva. Las discrepancias fallan en modo cerrado, y las pruebas de regresión adversariales verifican que la generación de candidatos nunca comienza cuando no se puede establecer la configuración autoritativa.

Para el JSON malformado, el contexto de la solicitud y el ID de solicitud ahora se establecen antes del análisis. Los cuerpos no válidos reciben una respuesta estructurada 400 segura sin detalles del analizador, trazas de pila, rutas del sistema de archivos ni contenido bruto de la solicitud.

Diferí las ideas de menor prioridad, como las sesiones MCP persistentes, la infraestructura distribuida adicional y una observabilidad más avanzada, porque no eran necesarias para la prueba de concepto de cuatro semanas y aumentarían el alcance operativo. Evalué cada recomendación en función de los requisitos del encargo, la corrección del tenant, la capacidad de prueba, el riesgo operativo y el alcance de la entrega. El asistente ofreció opciones y ayuda con la implementación, pero yo revisé el razonamiento, seleccioné los cambios y los verifiqué mediante pruebas específicas y comprobaciones de extremo a extremo.

Primer paso de cuatro semanas

Lo que se publica primero

El objetivo de cuatro semanas es una primera prueba de concepto interna publicable. Demuestra el flujo de trabajo requerido con una aplicación segura de la política de tenant y los fundamentos operativos; no es una afirmación de que todas las capacidades necesarias para un despliegue amplio en producción estén completas.

Semana 1 — Fundamentos del servicio

  • Establecer la base del servicio TypeScript y Node.js.

  • Definir modelos de dominio, validación estricta de límites con Zod y errores tipados.

  • Añadir el contrato MemberDataService y la implementación mock.

  • Añadir el contrato de solo lectura PartnerConfigurationService y la implementación mock.

  • Establecer la resolución de tenant autoritativa derivada del miembro y la base inicial de pruebas unitarias.

Objetivo: Establecer límites seguros del servicio y la autoridad del tenant antes de implementar la lógica de recomendación.

Semana 2 — Flujo de trabajo de recomendación

  • Implementar el CandidateGenerator determinista independientemente de las reglas del socio.

  • Implementar RecommendationPolicy, incluidas las exclusiones de categorías y los límites de recomendaciones.

  • Aplicar el orden requerido: primero las exclusiones, luego el límite.

  • Añadir la orquestación de RecommendationService y el comportamiento de configuración con fallo cerrado.

  • Cubrir la política y la orquestación con pruebas unitarias específicas.

Objetivo: Demostrar que las reglas contractuales del socio son deterministas e independientes de la generación de candidatos.

Semana 3 — Interfaces y flujo de extremo a extremo

  • Exponer los endpoints REST y el endpoint MCP Streamable HTTP.

  • Proporcionar las herramientas MCP get_member_profile y get_recommendations.

  • Añadir la demostración CLI.

  • Enrutar REST, MCP y CLI a través de la capa de negocio compartida.

  • Añadir pruebas de integración REST/MCP y pruebas de anulación de tenant.

Objetivo: Demostrar el flujo de trabajo completo de recomendación a través de las interfaces requeridas por el encargo.

Semana 4 — Preparación para producción y entrega

  • Añadir ID de solicitud, campos de correlación, registro estructurado en JSON y manejo seguro de errores.

  • Gestionar el JSON malformado de forma segura e implementar el apagado elegante.

  • Añadir la compilación Docker de varias etapas y el tiempo de ejecución sin root.

  • Realizar el typecheck del código fuente de producción y de las pruebas por separado.

  • Realizar la auditoría de producción/seguridad y añadir pruebas adversariales de correlación de identidad.

  • Completar la verificación final de extremo a extremo y del contenedor.

  • Preparar el README, el runbook de incidentes y el vídeo de demostración.

Objetivo: Hacer que la prueba de concepto sea mantenible por el equipo que la posee en guardia.

Lo que viene después

El siguiente trabajo se pospone deliberadamente hasta después de la primera entrega de cuatro semanas:

  1. Integraciones reales con sistemas ascendentes. Sustituir las implementaciones mock de MemberDataService y PartnerConfigurationService por clientes REST reales de arrivia, preservando los contratos de servicio existentes y los invariantes de correlación de identidad.

  2. Integración con la autenticación y autorización existentes. Integrar con los mecanismos de identidad y pasarela existentes de arrivia en lugar de introducir una nueva plataforma de identidad. La autorización debe preservar la autoridad de tenant derivada del miembro.

  3. Resiliencia de red. Para las dependencias HTTP ascendentes reales, validar y configurar tiempos de espera de solicitud y conexión, reintentos limitados cuando las operaciones sean seguras de reintentar, y un comportamiento de error explícito. La incertidumbre en la configuración debe seguir fallando en modo cerrado.

  4. Validación del rendimiento. Ejecutar pruebas de carga y rendimiento realistas antes de optimizar. Considerar el almacenamiento en caché de corta duración de la configuración del socio solo si las mediciones lo justifican. Una política obsoleta es un riesgo de corrección, por lo que cualquier caché requiere una estrategia clara de frescura e invalidación.

  5. Inteligencia de recomendación. Potencialmente reemplazar o ampliar el CandidateGenerator determinista con un LLM, un modelo de clasificación o una personalización más rica. RecommendationPolicy debe seguir siendo determinista y estar fuera del modelo para que la salida generada no pueda anular las reglas del socio.

  6. Observabilidad en producción. Conectar los eventos estructurados existentes y los ID de correlación con las métricas, el rastreo, las alertas y las herramientas operativas aprobadas por arrivia.

  7. Evolución de MCP. Considerar el comportamiento de MCP con estado o reanudable solo cuando un requisito de producto concreto necesite estado entre solicitudes. La implementación actual de Streamable HTTP sin estado es intencional para este servicio.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Hotel booking MCP server. Search, book, and manage reservations across 250K+ properties worldwide.

  • AI marketplace — flights, tours, activities, transport & more via MCP. No auth required.

  • MCP server exposing the Backtest360 engine API as tools for AI agents.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Varma904/agentic-travel-recommendations'

If you have feedback or need assistance with the MCP directory API, please join our Discord server