Skip to main content
Glama
matheusgalvao1

Travel Planner MCP Server

README.md
# Travel Planner MCP Server

Minimal TypeScript MCP server for a personal travel-planning agent.

Agent-visible tools:

- `search_flights` — real flight options from **Google Flights** (via SerpApi)
- `search_hotels` — real hotel/rental options from **Google Hotels** (via SerpApi)

Web search is intentionally excluded so it can be handled by your LLM provider's
built-in web/search tool. The intended flow:

```text
User
  -> LLM travel agent
    -> built-in web search for destination facts
    -> travel-planner.search_flights for real flight options
    -> travel-planner.search_hotels for real hotel options
  -> LLM compares tradeoffs and produces the recommendation
```

## Design

```text
Adapter (src/providers)    = talks to SerpApi
Normalizer (src/normalizers) = translates SerpApi response into our product shape
LLM                        = reasons over our product shape
```

A single SerpApi key powers both engines. The server is a thin wrapper: no
booking, payments, itineraries, ranking, or post-booking support — the LLM
composes the plan from the structured results.

## Install

```bash
npm install
```

## Run in mock mode (no API key needed)

```bash
npm run mock        # TRAVEL_MCP_MOCK=1, returns realistic mock data
```

## Develop / build (live)

```bash
cp .env.example .env   # set SERPAPI_API_KEY
npm run dev            # tsx, live
npm run build && npm start
```

## Test

```bash
npm test               # input validation, normalizers, provider errors, tool shapes
```

## MCP client config example

```json
{
  "mcpServers": {
    "travel-planner": {
      "command": "node",
      "args": ["/absolute/path/to/travel-planner-mcp/build/index.js"],
      "env": {
        "SERPAPI_API_KEY": "your_serpapi_key",
        "DEFAULT_CURRENCY": "BRL",
        "DEFAULT_MARKET": "BR",
        "DEFAULT_LOCALE": "pt-BR"
      }
    }
  }
}
```

Set `TRAVEL_MCP_MOCK=1` in `env` to run the client against mock data.

## Environment variables

| Variable | Required | Notes |
| --- | --- | --- |
| `SERPAPI_API_KEY` | live mode | SerpApi key for both engines |
| `SERPAPI_BASE_URL` | no | defaults to `https://serpapi.com/search.json` |
| `DEFAULT_CURRENCY` | no | e.g. `BRL`, `USD` |
| `DEFAULT_MARKET` | no | Google `gl` country code, e.g. `BR` |
| `DEFAULT_LOCALE` | no | Google `hl` language code, e.g. `pt-BR` |
| `REQUEST_TIMEOUT_MS` | no | supplier call timeout, default `15000` |
| `TRAVEL_MCP_MOCK` | no | `1` to use mock data instead of SerpApi |

## Notes

Supplier-specific request building is isolated in `src/providers/*`
(`serpapi.ts` is the shared client), and SerpApi → product-shape mapping lives in
`src/normalizers/*`. Flight/hotel result shapes are `FlightOption` / `HotelOption`.

TDQS

A3.7/5.0

Scored across 2 tools

Disambiguation5/5

Each tool targets a distinct domain (flights vs. hotels) with no overlap, making it clear which to use for each purpose.

Naming Consistency5/5

Both tools follow a consistent verb_noun pattern (search_flights, search_hotels), providing predictability and clarity.

Tool Count3/5

With only 2 tools, the server feels thin for a 'Travel Planner'—search alone is insufficient for planning beyond information retrieval.

Completeness2/5

The server only offers search functionality, lacking critical operations like booking, itinerary management, or destination recommendations, which are essential for a full travel planner.

Maintenance

ActivityInactive
ResponsivenessNo issues