@betterstr/claude-mcp
v0.1.0
Published
BetterSTR MCP server — lets Claude (Desktop, Code, etc.) edit your guidebooks, manage map pins, read reservations, send SMS, and inspect WiFi through the BetterSTR User API.
Maintainers
Readme
BetterSTR MCP server
A Model Context Protocol server that exposes the BetterSTR User API as tools for Claude.
Once installed, you can ask Claude things like:
- "What check-ins do I have today?"
- "How many bookings did I get last month?"
- "Add a 'Parking' page to my Ohakune Retreat guidebook explaining the driveway fits 2 cars."
- "Generate a $30 NZD payment link for the reservation Sarah Jane has at 30c Snowmass."
…and Claude will call the appropriate API endpoints on your behalf.
What's included
| Tool | What it does |
|------|--------------|
| list_properties | List your active properties (with entry counts). |
| list_entries | List guidebook entries on a property (top-level or under a parent). |
| get_entry | Fetch one entry + its direct children. |
| create_entry | Add a new menu item or content entry. |
| update_entry | Edit any field on an entry (title, content, icon, parent, visibility, order). |
| delete_entry | Remove an entry and all of its descendants. |
| list_reservations | Filter by check-in date, booking date, status, or property. Includes total count. |
| get_reservation | Fetch one reservation (guest, dates, property summary, verbose fields). |
| generate_payment_link | Build a guest-paying URL for a reservation (requires Stripe Connect). |
| list_tags / get_tag | List your property tags / fetch one with its properties. |
| list_locations | List map locations (filter by scope, property, tag). |
| search_places | Search Google Places by text — Claude uses this to find a place_id + accurate coords. |
| get_place | Pull full Google Places details for confirmation before saving. |
| add_location | Add a map pin (scope=all/property/tag). |
| update_location | Edit any field on a pin (name, comments, coords, scope, place_id). Use this — not delete + add — for changes like "move from property X to tag Y". |
| delete_location | Remove a map pin. |
| send_sms | Send an SMS to the guest(s) of one or more reservations. Two-stage: returns a quote first (recipients, segments, total cost) and only sends when you echo the quote back. GSM-7 only. Cannot text arbitrary numbers — recipients always come from owned reservations. |
| list_wifi_controllers | Show your WiFi controllers with controller_type ('unifi_byod', 'unifi_hosted', 'omada_hosted') and the property each one serves. |
| get_wifi_status | Live status for one property: AP list with offline/online breakdown, WiFi vs wired client counts, per-SSID breakdown, and named list of unauthorised guests (with MAC + hostname). |
| list_wifi_clients | Full client list with filters: ap_mac, ssid, unauthorised, wired. Each client includes MAC, hostname (often very recognisable e.g. roborock-vacuum-a15), SSID, AP, last-seen age. |
| authorize_wifi_client | Grant a captive-portal guest device access for N minutes. Use for your own devices that landed on the guest network. |
| kick_wifi_client | Force-disconnect a client. Destructive — always re-confirm with the user. |
A guidebook entry is one item in the guide — a top-level menu, a submenu, or a leaf content card. Reservation-related tools are read-only; the writable resources are guidebook entries, tags, and locations. Payment links don't charge anyone — they just produce a URL the guest opens.
When you ask Claude to "add a location for [place] to [property/tag]", the MCP will:
- Search Google Places for the named place,
- Show you name, address, phone, website, coordinates, and a Google Maps link,
- Wait for you to confirm before calling
add_location.
1. Get API credentials
- Sign in at https://gb.betterstr.com/members/profile/.
- Scroll to API Credentials → New API Credentials.
- Name it (e.g. "Claude MCP"), confirm.
- Copy the
client_id(starts withbsc_) andclient_secret(starts withbss_). The secret is shown once — store it somewhere safe.
2. Install
Option A — npx (recommended)
No install step. Just add this block to your MCP host config:
{
"mcpServers": {
"betterstr": {
"command": "npx",
"args": ["-y", "@betterstr/claude-mcp"],
"env": {
"BETTERSTR_CLIENT_ID": "bsc_…",
"BETTERSTR_CLIENT_SECRET": "bss_…"
}
}
}
}npx will download the latest package (cached after the first run) and spawn the MCP on demand.
Option B — global install
npm install -g @betterstr/claude-mcpThen in your host config:
{
"mcpServers": {
"betterstr": {
"command": "betterstr-claude-mcp",
"env": {
"BETTERSTR_CLIENT_ID": "bsc_…",
"BETTERSTR_CLIENT_SECRET": "bss_…"
}
}
}
}Option C — from source (for development)
git clone https://gitlab.com/icepicknz/betterstr-claude-mcp.git
cd betterstr-claude-mcp
npm install
npm run buildPoint your host config at the built binary:
{
"mcpServers": {
"betterstr": {
"command": "node",
"args": ["/absolute/path/to/betterstr-claude-mcp/dist/index.js"],
"env": {
"BETTERSTR_CLIENT_ID": "bsc_…",
"BETTERSTR_CLIENT_SECRET": "bss_…"
}
}
}
}3. Wire it into Claude
Claude Desktop (macOS)
Edit ~/Library/Application Support/Claude/claude_desktop_config.json and add
the mcpServers block above. Restart Claude Desktop.
Claude Desktop (Windows)
Edit %APPDATA%\Claude\claude_desktop_config.json and add the same block.
Claude Code
claude mcp add betterstr -- npx -y @betterstr/claude-mcp \
--env BETTERSTR_CLIENT_ID=bsc_… \
--env BETTERSTR_CLIENT_SECRET=bss_…Or for a from-source install:
claude mcp add betterstr -- node /absolute/path/to/betterstr-claude-mcp/dist/index.js \
--env BETTERSTR_CLIENT_ID=bsc_… \
--env BETTERSTR_CLIENT_SECRET=bss_…Environment variables
| Var | Default | Notes |
|------------------------------|------------------------------------------|-------|
| BETTERSTR_CLIENT_ID | — | Required. From /members/profile/. |
| BETTERSTR_CLIENT_SECRET | — | Required. Shown once at creation. |
| BETTERSTR_API_URL | https://api.betterstr.com/user-api | Override for staging / local dev. |
Rate limits
The MCP itself is a thin pass-through, so the limits described in the User API README apply:
globalscope (everything except reservations): 30/min free, 120 + active_properties / min premium.reservationsscope (list_reservations,get_reservation,generate_payment_link): 5/min free, 60 + active_properties / min premium.
Hitting the limit returns an MCP tool error with the HTTP 429 details from the
API, including a retry_after value.
Local smoke test
With the API running locally and credentials in env:
npm install
npm run build
BETTERSTR_CLIENT_ID="bsc_…" \
BETTERSTR_CLIENT_SECRET="bss_…" \
BETTERSTR_API_URL="http://localhost:8000/api/user-api/index.php" \
node test/smoke.mjsThe test exercises the MCP wire protocol directly (no SDK on the client side) and runs through all the tools end-to-end.
Privacy
This server is a thin client over the BetterSTR User API. It does not
phone home, does not write anything other than guidebook pages, and only
makes HTTP calls when Claude invokes a tool. Your credentials live in your
local MCP host config and are sent only to BETTERSTR_API_URL.
Example things to ask Claude
These are the kinds of natural-language queries the MCP is built for. Claude will translate each into the appropriate tool calls (and ask you to confirm multi-step plans before writing).
Reservations & guests
- "What check-ins do I have today?"
- "Who's arriving at 30c Snowmass this weekend?"
- "How many bookings did I get last month, and what's the busiest property?"
- "Find reservation RC6SZG."
- "Look up Sarah Jane's booking — when is she checking in?"
- "Which of my cancelled reservations from this year had the highest cleaning fee?"
- "Show me upcoming check-outs at the Atiamuri property."
- "How many nights of bookings does Surfers Paradise have through June?"
Payment links (Stripe-connected accounts only)
- "Generate a $30 NZD payment link for Sarah Jane staying at 30c Snowmass."
- "Send Barry Murphy a $300 payment link for his Surfers Paradise booking in the original booking currency."
- "Create a $150 AUD link for reservation 5009312486 — keep the currency the guest was quoted."
Guidebook entries
- "Add a Wi-Fi entry to the 30c Snowmass guide — SSID
BeachHouse_Guest, passwordsurfsup2024." - "Add a Ski Hire section to 30c Snowmass pointing to https://tcb.co.nz."
- "Add a Ski Hire section under Book Activities on every Ohakune property, pointing to https://tcb.co.nz — no confirmation needed."
- "Rename the 'Parking' entry on 30d Snowmass to 'Parking & EV Charging'."
- "What entries do I have under 'Book Activities' on the 30c Snowmass property?"
- "Remove the 'Live Camera' section from all of my Ohakune guides."
- "Change the icon for Wi-Fi to fa-wifi on every property."
Map locations
- "Add Sky Tower to the Atiamuri property — link it to its Google place."
- "Add the local supermarket on every Ohakune guide (use the tag)."
- "Move the Sky Tower pin from the Atiamuri property to the Ohakune tag."
- "Rename my 'Petrol Station' pin to 'BP Ohakune' and add the phone number."
- "Which Australian pins do I have, and which ones are missing a website?"
- "Delete the 'cache test' Sky Tower pin — it's a leftover from earlier."
Tags & properties
- "List my tags and how many properties each one covers."
- "Which properties are in the Ohakune tag?"
- "Create a new 'Surf School Partners' tag."
- "How many active properties do I have?"
SMS to guests (charges your account)
The MCP always quotes the cost first and waits for your confirmation; you cannot text arbitrary numbers — every recipient is a reservation guest on your account.
- "SMS everyone currently staying in Ohakune: 'Power outage at the moment — power company contacted, updates to follow.'"
- "Send a check-in reminder to the bookings arriving tomorrow at 30c Snowmass."
- "Text reservation RC6SZG: 'Lock code is 4729.'"
- "How much would it cost to SMS everyone in the Ohakune tag with a 200-character pool-maintenance notice?"
Multi-segment (>160 chars) and past-checkout recipients always require an explicit second confirmation, even if you've said "no confirmations" earlier in the session.
WiFi (subscription required)
- "How many WiFi devices are connected to Hidden Hollow On The Pond?"
- "Give me a per-SSID breakdown for 30c Snowmass — and list any unauthorised guests with their device names."
- "Is any access point at the Atiamuri property offline?"
- "Show me the clients on the upstairs AP (mac aa:bb:cc:dd:ee:ff)."
- "Authorise the Roborock vacuum on the guest network — it's mine."
- "Kick the unknown laptop that's been sitting unauthorised on the guest network for two hours."
- "List my WiFi controllers and which property each one serves — and tell me if any are UniFi vs Omada."
Multi-step / batch jobs
These are where preflight matters most — Claude will narrate the plan first.
- "I have 15 cafes in a spreadsheet — let's walk through adding them all under the Ohakune tag. Look up each one with Google Places first and ask me to confirm."
- "Replace the Wi-Fi password on every Ohakune property with
newpassword 2026. Show me the affected entries first." - "Help me clean up duplicate map pins — find pins that share a place_id and tell me which to keep."
Skipping confirmation (use sparingly)
By default Claude confirms before writing. You can opt out per-instruction:
- "...without confirmation."
- "Just do it — no need to check with me."
- "Go ahead, no approval needed."
Or for an entire session:
- "Stop confirming each step until I tell you to."
Destructive operations (deletes, especially cascade deletes) will still ask, even with blanket consent — that's deliberate.
