webhotelier-mcp

webhotelier-mcp

A read-only MCP server that lets AI assistants query the WebHotelier REST API for live hotel data, including property info, room availability, rates, calendars, and offers via natural language tools.

Category
访问服务器

README

webhotelier-mcp

A read-only Model Context Protocol (MCP) server for the WebHotelier REST API.

It lets an AI assistant (Claude Code, Claude Desktop, or any MCP-compatible client) answer questions like these with live hotel data:

"Is there a double room at GOLDENSAND for Sep 3–5 for 2 adults, and at what price?" "Which days in August still have availability?" "What's the cheapest rate this weekend, and what's the cancellation policy?"

The assistant picks the right tool, the server calls WebHotelier, and the answer comes back grounded in real availability and real prices — not guesses.


Table of contents


How it works

MCP is an open protocol that gives language models a standard way to call external systems. The flow for every question:

┌────────────┐   JSON-RPC over stdio   ┌─────────────┐      HTTPS       ┌──────────────────────────┐
│ MCP client │ ──────────────────────▶ │  server.js  │ ───────────────▶ │ rest.reserve-online.net  │
│ (Claude)   │ ◀────────────────────── │  (this repo)│ ◀─────────────── │ (WebHotelier REST API)   │
└────────────┘    tool results         └─────────────┘   JSON payloads  └──────────────────────────┘
  1. On startup, the client launches node server.js as a subprocess and performs the MCP handshake over stdin/stdout.
  2. The server advertises its 8 tools, each with a name, a natural-language description, and a JSON Schema for its parameters. The model reads these to decide when and how to call each tool.
  3. When the model calls a tool, the server validates the arguments (zod), calls the WebHotelier endpoint with HTTP Basic Auth, slims the response (see Design decisions), and returns JSON text that lands in the model's context.
  4. Errors come back as readable results, not crashes — the model sees a message that tells it what to do next (e.g. "Unknown property code — call list_properties for valid codes.").

The tools

All eight tools are read-only. The server implements no write endpoint of any kind.

Tool What it answers Required params Optional params
list_properties Which hotels exist and their property codes. Local registry lookup — no API call. — —
get_property_info Hotel profile + full room catalog (room types, capacities, amenities). property —
get_availability Is there a room for these dates/party, and at what price. The workhorse. property, checkin checkout or nights, adults (default 2), children, infants, rooms
get_rates Rate plans and cancellation policies. property room
get_calendar Day-by-day availability over a date range. property, from, to adults, children
get_best_rate Cheapest available rate (BAR — Best Available Rate). property date, adults, children
get_offers Active special offers / packages. property —
get_reservations Booking search by property and check-in date range.* — property, from, to

All dates use YYYY-MM-DD. property is the WebHotelier property code (e.g. GOLDENSAND); the model is instructed to call list_properties first when it doesn't know a code.

* get_reservations requires a WebHotelier account with reservations privileges. Without them the API returns 403 NO_PRIVILEGES, and the tool degrades to a clear message — "The configured WebHotelier account does not have reservations access; all other tools work normally." If your credentials are later upgraded, the tool starts working with zero code changes.

Quickstart

Requires Node.js ≥ 20.

git clone <this repo>
cd webhotelier-mcp
npm install
cp .env.example .env    # then fill in WH_USERNAME / WH_PASSWORD
npm run smoke           # optional: verify your credentials against the live API

npm run smoke should end with SMOKE PASS.

Configuration

All configuration lives in .env (gitignored — credentials never enter the repo):

Variable Required Purpose
WH_USERNAME yes WebHotelier API username (HTTP Basic Auth)
WH_PASSWORD yes WebHotelier API password/key
HOTEL_REGISTRY_PATH no Absolute path to a JSON file backing list_properties (see below)

The hotel registry

list_properties reads a local JSON file so the model can discover valid property codes instead of guessing them. Shape:

{
  "hotels": {
    "my-hotel": {
      "id": "my-hotel",
      "name": "My Hotel",
      "webHotelierCode": "MYHOTEL",
      "rating": 4,
      "active": true
    }
  }
}

Only these five fields are ever exposed — anything else in the file is filtered out (and a unit test enforces that). Without a registry, list_properties explains it is not configured; every other tool still works if you already know your property codes.

Connecting a client

Claude Code

Add to your project's .mcp.json (or to ~/.claude.json for user-wide scope):

{
  "mcpServers": {
    "webhotelier": {
      "command": "node",
      "args": ["/absolute/path/to/webhotelier-mcp/server.js"]
    }
  }
}

Restart the session (MCP servers are launched at startup) and check with /mcp — you should see webhotelier with 8 tools.

Claude Desktop

Add the same entry under mcpServers in claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json), then restart the app.

Any other MCP client

Anything that speaks MCP over stdio can use this server — point it at node server.js with the repo as working directory or use absolute paths as above.

Architecture

webhotelier-mcp/
├── server.js           # entry point: McpServer + stdio transport
├── tools.js            # the 8 tool definitions (zod schema + thin handler each)
├── format.js           # response slimming before data reaches model context
├── registry.js         # hotel-registry loader with strict field whitelist
├── errors.js           # WebHotelier errors → actionable text for the model
├── env.js              # dotenv loading (must stay the FIRST import of server.js)
├── lib/
│   └── wh-client.cjs   # vendored WebHotelier REST client (CommonJS)
└── tests/
    ├── unit/           # offline unit tests (node:test, no framework deps)
    ├── fixtures/       # fake registry used by the privacy tests
    └── smoke.js        # live-API smoke test

Everything testable without a network — formatting, registry filtering, error mapping — is a pure module with unit tests. tools.js stays declarative: schema in, client call, slimmed JSON out.

lib/wh-client.cjs is a vendored, battle-tested HTTP client: Basic Auth, request timeouts, and a retry policy for transient failures (408/429/5xx and common network errors; backoff 500 ms → 1.5 s → 4.5 s, honoring Retry-After on 429). Permanent errors (400/401/403/404) are never retried.

Design decisions

Read-only by construction. The safety guarantee is structural, not a permission flag: no create/modify/cancel endpoint exists anywhere in the codebase, so no prompt or bug can reach one.

Errors are results, not crashes. A tool failure returns isError: true with text written for the model: what happened and what to do next. The server process never dies mid-session because one API call failed.

Responses are slimmed for context windows. WebHotelier payloads carry bulk that a language model doesn't need: a single property-info response can exceed 100 KB, largely photo URLs and HTML descriptions. format.js replaces photo arrays with photo_count and strips/truncates HTML descriptions — while passing every number (prices, allotments, capacities) through untouched. The model should never quote an altered price.

Registry privacy is tested, not promised. The registry loader whitelists five fields; a unit test feeds it a fixture full of fake sensitive data (emails, credential paths) and asserts none of it survives into the output.

stdout is sacred. stdio-transport MCP servers speak JSON-RPC on stdout. A single stray console.log corrupts the protocol stream — all logging here goes to console.error (stderr), which clients surface as server logs.

Credential loading is order-sensitive. The vendored client computes its Basic-Auth header at module load, so import "./env.js" must remain the first import in server.js — ESM executes imports in declaration order.

Development & testing

npm test          # offline unit tests (node:test — zero test-framework dependencies)
npm run smoke     # live smoke test: registry, property info, availability, 403 handling
npm run inspect   # MCP Inspector web UI — call tools manually, watch raw JSON-RPC

The MCP Inspector also has a CLI mode, useful for scripted checks:

npx @modelcontextprotocol/inspector --cli node server.js --method tools/list
npx @modelcontextprotocol/inspector --cli node server.js --method tools/call --tool-name list_properties

Troubleshooting

Symptom Cause & fix
Tools return "credentials rejected (401)" WH_USERNAME/WH_PASSWORD missing or wrong in .env. Run npm run smoke to verify.
get_reservations returns a permission message Your WebHotelier account lacks reservations privileges (403 NO_PRIVILEGES). Expected for API-only accounts; every other tool is unaffected.
list_properties says no registry configured Set HOTEL_REGISTRY_PATH in .env to a registry JSON (shape above), or skip it and use property codes directly.
Server doesn't appear in the client MCP servers launch at client startup — restart the session/app after editing the config. Check the path in args is absolute and correct.
"Unknown property code (404)" The property code doesn't exist on WebHotelier. Call list_properties, or double-check the code.
Contributing a change and output looks corrupted You logged to stdout. Use console.error — stdout belongs to the JSON-RPC stream.

推荐服务器

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 模型以安全和受控的方式获取实时的网络信息。

官方
精选