Confused? Book a call with Sam
MCP Guide

Connect Hostaway to Claude

Run a small local server so Claude can read your Hostaway listings, reservations, calendar, and tasks, and answer questions about them in plain English. Free, working code, about twenty minutes.

~20 minutes Read-only by default Updated June 2026
Hand it to Claude Code

To connect Hostaway to Claude, you run a small MCP server: a lightweight program on your own machine that wraps the Hostaway Public API and exposes it to Claude as a set of tools. Once it's connected, Claude can read your listings, reservations, calendar, tasks, and guest conversations and answer questions about them, with no dashboards or exports.

MCP (the Model Context Protocol) is an open standard from Anthropic that lets AI assistants talk to outside systems. There is no official Hostaway MCP server as of June 2026, so this guide builds a focused, read-only one. You don't need to be a Hostaway Marketplace partner; the Public API uses self-serve credentials you generate yourself.

What you can ask once it's connected

Before you start

Three things: a Hostaway account with Public API access (any plan that shows Settings → Hostaway API), Node.js 18 or newer (20+ recommended; check with node --version), and either Claude Desktop or Claude Code.

1

Get your API credentials

In the Hostaway dashboard, open Settings → Hostaway API. Your Account ID is shown there (this is your OAuth client_id). Click Create to generate an API key (your client_secret).

Copy the API key right away. Hostaway shows it once. If you lose it, just create a new one. According to Hostaway's Public API documentation, these credentials use the OAuth 2.0 client-credentials grant.
2

Scaffold the project

Make a folder and install the two dependencies, the official MCP SDK and zod (used to describe each tool's inputs). No build step, no TypeScript compiler.

terminal
mkdir hostaway-mcp && cd hostaway-mcp
npm init -y
npm pkg set type="module"
npm install @modelcontextprotocol/sdk zod
3

Write the server

Save this as index.js. It mints a Hostaway access token once (tokens last about 24 months), caches it, and exposes six read-only tools. That's the whole file.

index.js
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const API_BASE = "https://api.hostaway.com/v1";
const ACCOUNT_ID = process.env.HOSTAWAY_ACCOUNT_ID;
const API_KEY = process.env.HOSTAWAY_API_KEY;

if (!ACCOUNT_ID || !API_KEY) {
  console.error("Set HOSTAWAY_ACCOUNT_ID and HOSTAWAY_API_KEY first.");
  process.exit(1);
}

// Tokens last ~24 months. Mint one on first use and keep it in memory.
let token = null;

async function getToken() {
  if (token) return token;
  const res = await fetch(`${API_BASE}/accessTokens`, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      grant_type: "client_credentials",
      client_id: ACCOUNT_ID,
      client_secret: API_KEY,
      scope: "general",
    }),
  });
  if (!res.ok) throw new Error(`Token request failed (${res.status})`);
  token = (await res.json()).access_token;
  return token;
}

// Authenticated GET; unwraps Hostaway's { result: ... } envelope.
async function get(path) {
  const res = await fetch(`${API_BASE}${path}`, {
    headers: { Authorization: `Bearer ${await getToken()}` },
  });
  if (!res.ok) throw new Error(`Hostaway ${res.status}: ${await res.text()}`);
  return (await res.json()).result ?? null;
}

function json(data) {
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}

const server = new McpServer({ name: "hostaway", version: "1.0.0" });

server.registerTool(
  "list_listings",
  {
    description: "List the properties (listings) in the Hostaway account.",
    inputSchema: { limit: z.number().optional().describe("Max rows, default 100") },
  },
  async ({ limit }) => {
    const q = new URLSearchParams({ limit: String(limit ?? 100) });
    return json(await get(`/listings?${q}`));
  }
);

server.registerTool(
  "list_reservations",
  {
    description: "List reservations, optionally within an arrival date range.",
    inputSchema: {
      arrivalStartDate: z.string().optional().describe("Earliest arrival, YYYY-MM-DD"),
      arrivalEndDate: z.string().optional().describe("Latest arrival, YYYY-MM-DD"),
      limit: z.number().optional().describe("Max rows, default 100"),
    },
  },
  async ({ arrivalStartDate, arrivalEndDate, limit }) => {
    const q = new URLSearchParams({ limit: String(limit ?? 100) });
    if (arrivalStartDate) q.set("arrivalStartDate", arrivalStartDate);
    if (arrivalEndDate) q.set("arrivalEndDate", arrivalEndDate);
    return json(await get(`/reservations?${q}`));
  }
);

server.registerTool(
  "get_calendar",
  {
    description: "Get the availability calendar for one listing over a date range.",
    inputSchema: {
      listingId: z.number().describe("Hostaway listing id"),
      startDate: z.string().describe("YYYY-MM-DD"),
      endDate: z.string().describe("YYYY-MM-DD"),
    },
  },
  async ({ listingId, startDate, endDate }) => {
    const q = new URLSearchParams({ startDate, endDate });
    return json(await get(`/listings/${listingId}/calendar?${q}`));
  }
);

server.registerTool(
  "list_tasks",
  {
    description: "List tasks (cleaning, maintenance, inspections) from Hostaway.",
    inputSchema: { limit: z.number().optional().describe("Max rows, default 100") },
  },
  async ({ limit }) => {
    const q = new URLSearchParams({ limit: String(limit ?? 100) });
    return json(await get(`/tasks?${q}`));
  }
);

server.registerTool(
  "list_conversations",
  {
    description: "List recent guest conversations.",
    inputSchema: { limit: z.number().optional().describe("Max rows, default 100") },
  },
  async ({ limit }) => {
    const q = new URLSearchParams({ limit: String(limit ?? 100) });
    return json(await get(`/conversations?${q}`));
  }
);

server.registerTool(
  "get_messages",
  {
    description: "Read the messages in one guest conversation.",
    inputSchema: { conversationId: z.number().describe("Conversation id") },
  },
  async ({ conversationId }) => json(await get(`/conversations/${conversationId}/messages`))
);

const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Hostaway MCP server running on stdio");
Large portfolio? Each list tool returns up to limit rows (default 100). If you run 100+ units and ask Claude to total a full month, tell it to raise the limit or narrow the range, otherwise it totals only the first 100 rows. Hostaway also supports an offset parameter for full pagination.
4

Connect it to Claude

Point Claude at the server and pass your two credentials.

Claude Desktop

Add a hostaway entry to your config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %AppData%\Claude\claude_desktop_config.json on Windows), then fully quit and reopen the app.

claude_desktop_config.json
{
  "mcpServers": {
    "hostaway": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/hostaway-mcp/index.js"],
      "env": {
        "HOSTAWAY_ACCOUNT_ID": "your-account-id",
        "HOSTAWAY_API_KEY": "your-api-key"
      }
    }
  }
}
Claude Code

One command from your terminal. Everything after -- is what launches the server.

terminal
claude mcp add \
  --env HOSTAWAY_ACCOUNT_ID=your-account-id \
  --env HOSTAWAY_API_KEY=your-api-key \
  --transport stdio hostaway \
  -- node /ABSOLUTE/PATH/TO/hostaway-mcp/index.js

Confirm with claude mcp list. Add --scope user to make it available in every project.

5

Ask away

Start a new conversation. Claude asks permission the first time it calls a tool, approve it, and you're set.

try these
What reservations arrive in the next 7 days? Group them by listing.

Which of my listings has the most open nights this month?

Pull the open tasks and tell me which properties have more than one.

Prefer to skip the typing?

Paste this into Claude Code (or any coding agent) and it will build, install, and wire up the server for you. Then come back to step 1 for your credentials.

prompt for Claude Code
Build a local MCP server (Node.js, ESM, @modelcontextprotocol/sdk and zod)
that wraps the Hostaway Public API. Read HOSTAWAY_ACCOUNT_ID and
HOSTAWAY_API_KEY from the environment. Mint an OAuth token by POSTing to
https://api.hostaway.com/v1/accessTokens (grant_type=client_credentials,
scope=general, x-www-form-urlencoded) and cache it. Add an authenticated GET
helper that returns the response's `result`. Register these read-only tools,
default limit 100, built with URLSearchParams: list_listings(limit?),
list_reservations(arrivalStartDate?, arrivalEndDate?, limit?),
get_calendar(listingId, startDate, endDate), list_tasks(limit?),
list_conversations(limit?), get_messages(conversationId). Use
StdioServerTransport; log startup to stderr. Then make a package.json
(type: module), install the deps, and show me the claude mcp add command,
the claude_desktop_config.json block, and three prompts to try.

Good to know

One Hostaway connection we already built: your turnover photos. This server gives you conversational access to reservations and tasks. RapidEye connects to Hostaway for the inspection photos your cleaners upload after every turnover, reading them automatically and flagging damage and missed cleaning before the next guest checks in.

FAQ

Does Hostaway have an official MCP server?

Not as of June 2026. Hostaway publishes a Public API but no first-party MCP server. Build a focused one yourself (this guide), or use a no-code bridge like Zapier MCP. No partner approval is needed for the Public API.

Is it safe to connect my real account?

The server here is read-only, so Claude can look but not touch. Your credentials stay on your machine and Claude asks before every tool call.

Do I need to pay for API access or a partner program?

The Public API uses self-serve credentials on API-enabled plans, generated under Settings → Hostaway API. The Marketplace partner program is separate, only for publishing an integration for other customers.

Can I do this with Guesty, OwnerRez, or Lodgify too?

Yes. The structure is identical for any PMS with a public REST API; only the auth step changes. See our OwnerRez and Hospitable guides for worked examples.

Sources

Independent integration guide. RapidEye is not affiliated with or endorsed by Hostaway or Anthropic. API behavior and dashboard menus can change; confirm specifics against the official docs above. Last reviewed June 14, 2026.