agentic-travel-recs

agentic-travel-recs

Exposes tools for retrieving member profiles and personalized travel recommendations with multi-tenant partner rule enforcement, enabling AI agents to respect business constraints like caps and exclusions.

Category
访问服务器

README

Agentic Travel Recommendations Service

A multi-tenant travel recommendations service that exposes both a REST API and an MCP server, with partner-specific rule enforcement (recommendation caps, category exclusions). Built as an exploration of MCP server design and multi-tenant rule enforcement patterns for AI-agent-facing internal services.

Node TypeScript Tests License

What it does

An AI agent (e.g. a travel concierge embedded in a partner-branded portal) needs two things from this service:

  1. A member's profile — loyalty tier, past bookings, partner affiliation.
  2. Personalized travel recommendations that respect the partner's business rules.

Different partners have different rules. Some cap recommendations at 3 per session; others exclude entire categories like cruises. The service enforces those rules in a single code path so they can't drift between the REST and MCP interfaces.

Quick start

npm install
npm test          # 13 tests: rules engine + integration
npm run demo      # spawns the MCP server and walks 4 partner scenarios
npm run dev:api   # REST API on :3000
npm run dev:mcp   # MCP server on stdio

The demo is an actual MCP client that spawns the server as a subprocess and calls its tools the way an AI agent would.

Seeded scenarios

The mocks include four partners exercising every combination of rule shape:

Member Partner Loyalty Partner rules
M-1001 Bank A Gold No cap, no exclusions
M-1002 Credit Union B Platinum Excludes cruises
M-1003 Membership Org C Silver Cap of 3 recommendations
M-1004 Airline D Gold Cap of 5, excludes cars and cruises

Project structure

src/
  mcp/server.ts                    # MCP server, stdio transport, two tools
  api/server.ts                    # REST API (Express)
  api/routes/recommendations.ts
  services/
    recommendationsService.ts      # orchestrator — shared by REST & MCP
    memberDataService.ts           # client for the (mocked) member data upstream
    partnerConfigService.ts        # client for the (mocked) partner config upstream, 60s TTL cache
  rules/partnerRulesEngine.ts      # single source of truth for partner-rule enforcement
  mocks/                           # in-memory mocks of the two upstreams
  types/index.ts                   # shared domain types
  utils/logger.ts                  # pino JSON logger
cli/demo.ts                        # MCP client that spawns the server and walks the scenarios
tests/                             # vitest — unit tests for the rules engine + integration
docker/Dockerfile                  # multi-stage image; default CMD runs the REST API

Architecture

Four moving parts:

  1. AI agent speaks MCP.
  2. This service exposes two MCP tools (get_member_profile, get_recommendations) and an equivalent REST API for non-MCP callers and for debugging.
  3. Member data service (mocked) — returns member ID, loyalty tier, partner ID, and last five bookings.
  4. Partner configuration service (mocked, read-only) — returns per-partner rules.

Two design properties matter most:

  • REST and MCP share the same service layer. recommendationsService.ts is called from both api/routes/recommendations.ts and mcp/server.ts. Partner rules run in exactly one code path — it's structurally impossible to ship an MCP path that bypasses them.
  • Rules enforcement is a pure function. enforcePartnerRules(candidates, partnerConfig, requestedMax?) in src/rules/partnerRulesEngine.ts has no I/O and no side effects. Roughly 40 lines with a dedicated unit-test file, so partner-rule regressions can be caught in seconds.

Every response includes an appliedRules block reporting which categories were filtered and how many results were capped — so a downstream agent can explain to a user why cruises aren't showing up, and an on-call engineer can diagnose "empty result" cases without reading logs.

Design trade-offs

stdio MCP transport rather than Streamable HTTP.
Stdio has no public network surface — no auth, no rate limiting, no session management to design. The MCP server co-locates as a sidecar with the AI agent that consumes it. Streamable HTTP would be the upgrade path for remotely-hosted use; the tool contracts wouldn't change.

Rule-based candidate scoring, not ML.
The recommender uses a legible scoring function: baseline + historical-type affinity + tier boost − recent-destination penalty. Swapping in an ML model later would leave the rules engine, MCP tools, and REST contracts untouched. A broken model would silently degrade recommendations; a broken rules engine would violate a partner contract. Ship the trustworthy piece first.

60-second partner config cache.
Short enough that a partner rule change propagates within about a minute, long enough to reduce upstream load by roughly 99% on the hot path. A cache-bust endpoint could be added later for partners that need instant propagation.

Handling partner configuration changes

Partner config is read-only from this service's perspective, so a partner changing their cap or adding an exclusion happens entirely upstream. Within the 60-second TTL, the change is picked up on the next call. The rules engine reads it fresh, and the appliedRules block in the response reflects the new state.

The only case that requires a code change here is if a partner adds a new kind of rule (e.g. a time-of-day restriction). That would need a new field in the PartnerConfig type and a new step in enforcePartnerRules. A new instance of an existing rule shape needs no code change — that's what the four seeded partners demonstrate.

Production considerations

Things designed for the person on-call at 2 a.m.:

  • Every recommendation call logs one INFO line with { memberId, partnerId, returned, filteredCount, cappedCount }. One grep answers "did the rules run?"
  • The appliedRules block on every response means the same question can be answered by a curl, without logs.
  • The rules engine has 7 unit tests including a specific "order matters" test that fails if filter and cap are reversed.
  • Known error types map to stable HTTP status codes and structured MCP isError: true responses.

Things I'd add before running this in production:

  • Timeouts and one retry with backoff on upstream calls, plus a circuit breaker with a documented fallback behavior.
  • Per-partner dashboards for error rate and p99 latency; an alert if filteredCount suddenly spikes for a partner (usually the signal that someone shipped a bad config).
  • Load testing with realistic traffic mix to validate the cache TTL choice.
  • Streamable HTTP transport for MCP if remote hosting becomes a requirement.

About the build process

The initial scaffold — types, mocks, service layer skeleton, and the first pass at the MCP server — was AI-assisted. Everything after that (the Partner D onboarding to prove multi-tenant behavior, the integration test for it, the real readiness probe replacing the stub, and a cross-platform fix for a Windows path bug in the MCP entrypoint) was written by me. The Windows bug is the one I'd point out: the AI's original entrypoint check used import.meta.url === \file://${process.argv[1]}`, which silently fails on Windows because the two sides of the comparison use different path formats. Green unit tests didn't catch it because they never spawn the MCP server as a subprocess. I caught it by running the demo end-to-end, and fixed it by normalizing both sides through pathToFileURL`.

License

MIT — see LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选