Claude Guide · Hospitable

Connect Hospitable to Claude

Ask Claude about your Hospitable properties, reservations, and calendar availability in plain English. Bearer token auth, 10-minute setup, open-source MCP server.

10 minute setup Bearer token auth Claude Desktop or Claude Code
!
Plan requirement. Hospitable's public API is gated to the Host, Professional, or Mogul plans. If you're on the Essentials plan you'll need to upgrade before you can generate an access token. This is Hospitable's policy, not ours.

Cole Rubin at Conduit shipped Claude MCP guides for 8 PMSes. Hospitable (formerly Smartbnb), one of the fastest-growing US vacation rental platforms, was missing from his list. This guide fills that gap using the same 4-step format and the same @modelcontextprotocol/sdk pattern.

What you'll be able to ask Claude

Once connected, Claude can pull live data from your Hospitable account. Example queries:

"List all my Hospitable properties with their bedroom count and city."
"Which reservations are arriving in the next 7 days? Include the property name."
"Show me the full details on reservation 12345 including the guest and nightly rate."
"What's the calendar availability for property 789 for the next 30 days?"
"Which of my properties had the most bookings last month?"

Prerequisites

1

Generate a Hospitable Personal Access Token

Hospitable uses OAuth2 Bearer tokens. You'll generate a Personal Access Token (PAT) from the account settings. Only account owners can create PATs.

  1. Log in to my.hospitable.com.
  2. Click Apps in the sidebar (or Settings → Integrations, depending on your view).
  3. Open the Access tokens tab.
  4. Click + Add new.
  5. Give the token a name (e.g. "Claude MCP") and choose read permissions for this guide. You can give it write permissions too if you plan to extend the server to create/update reservations.
  6. Copy the token. Hospitable shows it only once. It looks like a long random string.

Note: Hospitable Personal Access Tokens expire after one year. Mark your calendar to rotate it before then. If you're building a multi-customer integration (not this guide), use OAuth2 instead of PATs.

2

Set up the Node.js project

Two dependencies: the MCP SDK and zod. Hospitable doesn't have an official Node SDK, so we'll make HTTP calls directly.

Terminal
mkdir hospitable-mcp
cd hospitable-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod

Add "type": "module" to package.json:

package.json
{
  "name": "hospitable-mcp",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "zod": "^3.22.0"
  }
}
3

Create the MCP server file

Save the following as index.js. The server exposes four tools: list-properties, list-reservations, get-reservation, and get-property-calendar.

index.js
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const TOKEN = process.env.HOSPITABLE_TOKEN;
const BASE_URL = "https://public.api.hospitable.com/v2";

if (!TOKEN) {
  console.error("Missing HOSPITABLE_TOKEN environment variable");
  process.exit(1);
}

async function hospitableGet(path, params = {}) {
  const url = new URL(`${BASE_URL}${path}`);
  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined && value !== null && value !== "") {
      url.searchParams.append(key, String(value));
    }
  }

  const response = await fetch(url.toString(), {
    method: "GET",
    headers: {
      Authorization: `Bearer ${TOKEN}`,
      Accept: "application/json",
      "User-Agent": "rapideye-hospitable-mcp/1.0",
    },
  });

  if (!response.ok) {
    const body = await response.text();
    throw new Error(`Hospitable API ${response.status}: ${body}`);
  }

  return response.json();
}

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

// Tool 1: List properties
server.tool(
  "list-properties",
  "List all properties on the Hospitable account. Returns property ID, name, address, bedroom/bathroom count, and status. Use this first to discover property IDs.",
  {
    page: z
      .number()
      .optional()
      .describe("Page number for pagination (default: 1)"),
    per_page: z
      .number()
      .optional()
      .describe("Results per page (default: 25, max: 100)"),
  },
  async ({ page, per_page }) => {
    const data = await hospitableGet("/properties", { page, per_page });
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
);

// Tool 2: List reservations with date filter and property include
server.tool(
  "list-reservations",
  "List reservations, optionally filtered by date range or property. Use include='property' to also return the associated property details in the response.",
  {
    start_date: z
      .string()
      .optional()
      .describe("Filter reservations with check-in on or after this date (YYYY-MM-DD)"),
    end_date: z
      .string()
      .optional()
      .describe("Filter reservations with check-in on or before this date (YYYY-MM-DD)"),
    property_id: z
      .string()
      .optional()
      .describe("Only return reservations for this property ID"),
    include: z
      .string()
      .optional()
      .describe("Comma-separated list of related resources to include (e.g. 'property,guest')"),
    page: z.number().optional(),
    per_page: z.number().optional(),
  },
  async ({ start_date, end_date, property_id, include, page, per_page }) => {
    const data = await hospitableGet("/reservations", {
      start_date,
      end_date,
      property_id,
      include,
      page,
      per_page,
    });
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
);

// Tool 3: Fetch one reservation
server.tool(
  "get-reservation",
  "Fetch a single reservation by ID. Returns full details including guest info, dates, nightly rate, and any notes.",
  {
    id: z.string().describe("Reservation ID"),
    include: z
      .string()
      .optional()
      .describe("Optional related resources to include (e.g. 'property,guest')"),
  },
  async ({ id, include }) => {
    const data = await hospitableGet(`/reservations/${id}`, { include });
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
);

// Tool 4: Property calendar
server.tool(
  "get-property-calendar",
  "Fetch the calendar (availability, pricing, min stay) for a specific property across a date range.",
  {
    property_id: z.string().describe("Hospitable property ID"),
    start_date: z.string().describe("Start date (YYYY-MM-DD)"),
    end_date: z.string().describe("End date (YYYY-MM-DD)"),
  },
  async ({ property_id, start_date, end_date }) => {
    const data = await hospitableGet(`/properties/${property_id}/calendar`, {
      start_date,
      end_date,
    });
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

To extend the server, copy the server.tool(...) pattern and point at any endpoint in the Hospitable v2 reference.

4

Register the server with Claude Desktop

Open your Claude Desktop config file:

macOS path
~/Library/Application Support/Claude/claude_desktop_config.json
Windows path
%APPDATA%\Claude\claude_desktop_config.json

Add the Hospitable entry:

claude_desktop_config.json
{
  "mcpServers": {
    "hospitable": {
      "command": "node",
      "args": ["/absolute/path/to/hospitable-mcp/index.js"],
      "env": {
        "HOSPITABLE_TOKEN": "your_personal_access_token_here"
      }
    }
  }
}

Replace the path and token with your real values. Then fully quit and reopen Claude Desktop.

Try your first query

Start with a simple read to confirm the connection:

"List my Hospitable properties and show them in a table with columns for name, address, bedrooms, and status."

Then try a harder query: "What reservations do I have checking in between April 15 and April 30? Include the property name for each." Claude will call list-reservations with include=property and format the result for you.

Troubleshooting

401 Unauthorized on every call

Your Personal Access Token is wrong, expired, or your account plan was downgraded to Essentials (which loses API access). Regenerate the token in my.hospitable.com → Apps → Access tokens.

Hospitable PATs expire after one year. If it's been about that long since you made it, rotate the token.

403 Forbidden on /v2/properties

Your Hospitable plan likely doesn't include public API access. The Essentials plan is excluded — you'll need to be on Host, Professional, or Mogul. Check your plan in Hospitable Settings → Billing.

Claude doesn't see any Hospitable tools

Claude Desktop only reads the config file at startup. Fully quit Claude (Cmd+Q on macOS, right-click tray icon → Quit on Windows) and reopen it. Closing the window is not enough.

Still broken? Check the logs: Help → Open Logs Folder. Look for JSON parse errors in the config or path-not-found errors for index.js.

"include=property" returns reservations without property data

Known quirk reported in the Hospitable community: the include parameter sometimes doesn't return the expected related resources on older v2 endpoints. If you hit this, make a second call with get-property-calendar or fetch the property directly with list-properties and filter client-side.

I want to post messages or modify reservations

The Hospitable API supports write operations including creating/updating reservations and sending messages. Generate your PAT with write permissions, then add a tool that uses fetch with method: "POST" or "PATCH" and a JSON body. Consult developer.hospitable.com for the exact schemas.

What's next

Guide 3 of the batch 1 series. If you run on OwnerRez instead of Hospitable, start with that guide. If you have smart locks, the Seam guide wraps 8+ lock brands with a single MCP connector.