Skip to main content
Glama
Beckett-Eiland

Agentic Travel Recommendations API

Agentic Travel Recommendations API

AI Concierge Proof of Concept — MCP Server


Related MCP server: expedia-travel-recommendations-mcp

Section A — Architecture & Trade-offs

Architecture Overview

The Agentic Travel Recommendations API is a TypeScript/Node.js service that exposes personalized travel recommendations to AI agents via the Model Context Protocol (MCP). The service sits between two upstream dependencies — a member data service and a partner configuration service — and a downstream AI agent such as Claude Code.

At runtime the flow works as follows: an AI agent connects to the MCP server and discovers available tools via the list_tools endpoint. The agent calls get_member_profile to retrieve a member's loyalty tier, travel history, and partner ID. It then calls get_recommendations, which fetches the member profile, retrieves the partner's configuration rules, loads the full recommendation catalog, and applies three sequential filters — category exclusions, loyalty tier eligibility, and recommendation cap — before returning an auditable response that includes both the filtered recommendations and the rules that were applied.

Both upstream services are mocked via static JSON files for this proof of concept. The mock structure mirrors what real API calls would look like, meaning the service layer can be swapped from file reads to HTTP calls without changing any business logic.

Design Trade-offs

Pre-populated catalog vs. LLM-generated recommendations

The recommendation pool is a static catalog rather than dynamically generated by a language model. An LLM-based approach might seem more "agentic" but would introduce significant reliability problems in a production context — generated hotel names and prices cannot be verified, category classification would be ambiguous making rule enforcement fragile, and outputs would be non-deterministic making the service untestable. A curated catalog ensures that category exclusions and recommendation caps are enforced against typed, validated data. The intelligence of the service lies in personalized selection and rule enforcement, not content generation.

Single partner per member

Each member is associated with exactly one partner, reflecting the reality that a member accessing the AI Concierge does so through a specific partner's branded portal. Supporting multiple partners per member would add complexity without demonstrating new behavior in the rule enforcement logic. In a production system this could be extended by passing an explicit partnerId alongside memberId in the request, allowing the caller to specify which partner context applies.

Handling Partner Configuration Changes

Because the partner configuration service is treated as read-only and loaded fresh on each request, configuration changes take effect immediately without requiring a service restart or cache invalidation. If a partner adds a new category exclusion or lowers their recommendation cap, the next request for any member under that partner will automatically reflect the updated rules. The only change required in this service would be adding the new category to the TravelCategory union type in types.ts if it is a category not previously defined — a one-line change. This design intentionally avoids caching partner config, accepting slightly higher read overhead in exchange for always-current rule enforcement.

Four-Week Delivery Plan

Ships first (Weeks 1–2):

  • MCP server with get_member_profile, get_recommendations, and list_members tools

  • Partner rule enforcement (category exclusions, recommendation cap, tier filtering)

  • Static catalog with typed data model

  • CLI demo and README documentation

Ships later (Weeks 3–4):

  • Replace file-based mocks with real HTTP calls to member data and partner config services

  • Add response caching for partner config with cache invalidation on config change events

  • Add support for multiple partner contexts per member

  • Add integration tests asserting rule enforcement across all partner configurations

  • Add logging and observability (structured logs per request with rulesApplied metadata)

  • Add pagination for recommendation results


Section B — Production Readiness & Incident Response

Incident Runbook Entry

Symptom: A member reports that the AI Concierge is showing cruise recommendations even though their partner's configuration excludes cruises.

Initial Diagnosis Steps:

  1. Identify the member ID and partner ID from the report. Check the member's profile via get_member_profile to confirm their partnerId is correct and matches the expected partner.

  2. Query the partner configuration service directly for that partnerId and verify that "cruise" is present in excludedCategories. If it is not present, the issue is in the partner config data itself — escalate to the partner configuration team as the config may have been accidentally modified or not yet propagated.

  3. If "cruise" is correctly in the partner config, check the recommendation catalog and confirm that the cruise offerings have "cruise" as their exact category value. A mismatch in casing or spelling — for example "Cruise" vs "cruise" — would cause the filter to silently pass cruise offers through.

  4. Check the version of the recommendation service that is currently deployed. If a recent deployment occurred, review the diff for any changes to the filtering logic in recommendationService.ts, particularly the category exclusion filter.

  5. Check service logs for the member's recent sessions to see the raw rulesApplied field in the response. If excludedCategories shows an empty array despite the partner config containing exclusions, the issue is in how partner config is being read or deserialized.

Resolution:

  • If the issue is a data mismatch in category strings, correct the catalog entry and redeploy

  • If the issue is in the partner config data, escalate to the partner config team with specific partnerId and expected vs actual values

  • If the issue is a code regression, roll back to the previous deployment and open a bug ticket with the specific commit that introduced the change

  • In all cases, verify the fix by calling get_recommendations for an affected member and confirming cruises no longer appear in the response before closing the incident

Prevention: Add an integration test that specifically asserts cruise recommendations never appear for partners with cruise exclusions configured. This test should run on every deployment.


Running the Demo

Prerequisites

  • Node.js 18+

  • npm

Installation

npm install

Run the full demo

npm run cli

Query a specific member

ts-node cli.ts WI001
ts-node cli.ts WI002
ts-node cli.ts WI003

Start the MCP server

npm run dev

Available MCP Tools

  • list_members — discover valid member IDs

  • get_member_profile — retrieve member profile by ID

  • get_recommendations — get partner-rule-enforced recommendations for a member

Available Tools

3 tools
get_member_profileA

Retrieves a member profile including loyalty tier, partner, and travel history. Use this to understand who the member is before making recommendations.

ParametersJSON Schema
NameRequiredDescriptionDefault
memberIdYesThe unique member ID (e.g. WI001)

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description must carry the full burden of behavioral disclosure. The verb 'Retrieves' implies a read-only operation, and the description lists the returned data, but it does not explicitly state side effects, error behavior (e.g., member not found), or any rate limits or authorization requirements. This is acceptable for a simple lookup but not fully transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences: the first fronts the core action and data scope, the second the usage context. It is concise, free of filler, and every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple—one parameter, no output schema, no annotations. The description adequately covers the purpose, the returned data fields, and the canonical use case. For such a low-complexity tool, this is complete enough for an AI agent to select and invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% description coverage for the sole parameter, memberId, including its type and an example format. The description adds no additional parameter-specific semantics, so it does not go beyond what the schema already provides. The score is at the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function using the verb 'Retrieves' and specifies the resource ('a member profile') and key data fields (loyalty tier, partner, travel history). It strongly differentiates from siblings: get_recommendations focuses on recommendations, and list_members lists members, while this tool retrieves a single member's profile.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly recommends when to use the tool: 'Use this to understand who the member is before making recommendations.' This provides clear contextual guidance. It does not, however, explicitly mention when not to use it or name alternative tools, leaving room for a more thorough comparison.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recommendationsA

Returns personalized travel recommendations for a member, filtered by partner rules including category exclusions and recommendation caps. Always call get_member_profile first.

ParametersJSON Schema
NameRequiredDescriptionDefault
memberIdYesThe unique member ID to generate recommendations for

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of disclosing behavior. It reveals that recommendations are filtered by partner rules including category exclusions and recommendation caps, and implies a dependency on get_member_profile. This adds meaningful context beyond the name, though it doesn't cover failure modes or exact return structure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences: the first states purpose and filters, the second gives a clear prerequisite. Both sentences are informative and free of fluff, making it maximally concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter read-only tool, the description covers the core behavior (returns recommendations), key filtering details, and a required dependency. It doesn't describe the response format or error conditions, but given the absence of an output schema and the tool's simplicity, it's reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully describes the memberId parameter (100% coverage). The description adds no additional parameter-specific details, so it neither enhances nor detracts from the schema's clarity. Baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns personalized travel recommendations for a member, with the specific verb 'returns' and resource 'travel recommendations'. It also mentions filtering by partner rules, which distinguishes it from sibling tools like get_member_profile and list_members.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly instructs to call get_member_profile first, providing a clear prerequisite and ordering. However, it does not explicitly mention when not to use this tool or alternatives, though the clear resource distinction and naming make the usage context strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_membersA

Returns all available members in the system. Use this to discover valid member IDs.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

There are no annotations, so the description must fully disclose behavior. It states the tool returns all available members, implying a read-only operation with no side effects. Yet it does not mention response shape, pagination, or any access constraints, leaving some behavioral ambiguity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences that are front-loaded—the first sentence states the core action, the second gives an explicit use case. No unnecessary words or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no parameters and no output schema, this description covers the core functionality and a known use case. It could expand on the return format, but the simplicity of the tool makes this adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema is empty (zero parameters) with 100% schema coverage. The description adds nothing about parameters, but since none exist, it is sufficient. Baseline score of 4 for zero parameters is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'Returns all available members in the system,' which is a specific action and resource. It distinguishes from sibling tools like get_member_profile and get_recommendations by focusing on the full member list rather than individual profiles or recommendations. The added note about discovering valid member IDs reinforces the tool's purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Use this to discover valid member IDs' gives a clear context for when to call this tool. However, it does not explicitly contrast with sibling tools or state when not to use it, such as 'if you need a single member's details, use get_member_profile instead.'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.4/5.0
Disambiguation5/5

Each tool serves a distinct purpose: list_members discovers valid IDs, get_member_profile provides detailed member context, and get_recommendations returns the actual recommendations. There is no overlap or ambiguity between them.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: list_members, get_member_profile, get_recommendations. The use of 'list' for collection retrieval and 'get' for single-item retrieval is a standard and predictable convention.

Tool Count5/5

With exactly 3 tools, the server is minimal but well-scoped. Each tool is necessary and supports the core workflow of discovering members, understanding their profile, and generating recommendations. This fits comfortably within the ideal 3-15 range.

Completeness5/5

The tool surface fully covers the recommendations domain: listing all members, fetching member profiles, and generating personalized recommendations. There are no obvious dead ends or missing operations for the stated purpose.

Maintenance

ActivitySlowing
ResponsivenessSyncing

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

Related MCP Servers

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/Beckett-Eiland/mcp-service-proof-of-concept'

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