Back to Browse

Salonrunner MCP Server

Developer ToolsUse Caution4.2MCP RegistryLocal
Free

Server data from the Official MCP Registry

Self-hosted MCP to find, book, and cancel salon appointments via SalonRunner.

About

Self-hosted MCP to find, book, and cancel salon appointments via SalonRunner.

Security Report

4.2
Use Caution4.2High Risk

This is a well-structured MCP server for SalonRunner appointment booking with thoughtful security design. The OAuth implementation is solid with stateless token design and encrypted credential storage. However, there are moderate concerns around undocumented API reliance, missing input validation on some parameters, and credential handling in error paths that warrant user awareness. Supply chain analysis found 4 known vulnerabilities in dependencies (0 critical, 3 high severity). Package verification found 1 issue.

7 files analyzed · 12 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

HTTP Network Access

Connects to external APIs or services over the internet.

env_vars

Check that this permission is expected for this type of plugin.

process_spawn

Check that this permission is expected for this type of plugin.

What You'll Need

Set these up before or after installing:

Your salon's numeric id (from your booking URL)Optional

Environment variable: SALONRUNNER_SALON_ID

Your SalonRunner client login (same as the booking site)Optional

Environment variable: SALONRUNNER_USERNAME

Your SalonRunner client passwordRequired

Environment variable: SALONRUNNER_PASSWORD

Set to 'true' to disable booking/cancelling (read-only)Optional

Environment variable: SALONRUNNER_READ_ONLY

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-topness-msft-salonrunner-mcp": {
      "env": {
        "SALONRUNNER_PASSWORD": "your-salonrunner-password-here",
        "SALONRUNNER_SALON_ID": "your-salonrunner-salon-id-here",
        "SALONRUNNER_USERNAME": "your-salonrunner-username-here",
        "SALONRUNNER_READ_ONLY": "your-salonrunner-read-only-here"
      },
      "args": [
        "-y",
        "salonrunner-mcp"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

salonrunner-mcp

An MCP server that lets an AI assistant find, book, and cancel salon appointments through your personal SalonRunner / Rosy Salon Software client account — the same booking site many salons use.

It's self-hosted: you deploy your own instance. Run it locally as a tool (Claude Desktop, Cursor, Copilot CLI) where credentials stay on your machine, or as a remote connector for claude.ai where you log in with your SalonRunner account on the connector's login screen.

⚠️ Unofficial, uses undocumented endpoints, personal use only. Read DISCLAIMER.md.

Tools

ToolWhat it does
list_servicesList bookable services (name, id, price)
list_providersList stylists; optionally only those who do a given service
find_availabilityOpen slots for a service over a date range (optionally one provider)
list_my_appointmentsYour upcoming appointments
book_appointmentBook a slot returned by find_availability
cancel_appointmentCancel by appointment id

How it works

list/find/book/cancel
        │
   this server ──login──► app.salonrunner.com  (session cookie)
        │      ──authv2─► customer JWT (30 min, auto-refreshed)
        │      ──reads──► app.rosysalonsoftware.com/api/v2  (Bearer JWT)
        └──────writes───► /customer/appointments/{book,cancel}.json  (cookie)

customerId is discovered from your account after login; corporateId is read from the JWT. Availability is computed from the provider's per-service duration and the salon's slot grid (SALONRUNNER_SLOT_MINUTES, default 15).

Configuration

There are two ways to run it, and they get their salon credentials differently:

  • Local (stdio): credentials come from the environment (.env).
  • Remote (HTTP, claude.ai): credentials are entered on the connector's login screen and encrypted into the token — the server needs no salon credentials in its environment.
VariableUsed byNotes
SALONRUNNER_SALON_IDstdio (+ optional HTTP)The id in your booking URL …/customer/login.htm?id=XXXXX. In HTTP mode it's optional — if set, it pre-fills the salon id on the connector's login screen (handy for single-salon deployments and re-auth)
SALONRUNNER_USERNAME / SALONRUNNER_PASSWORDstdioYour client login
SALONRUNNER_CUSTOMER_IDbothAuto-discovered; set only if discovery fails
SALONRUNNER_SLOT_MINUTESbothSalon booking granularity (default 15)
SALONRUNNER_READ_ONLYbothtrue disables book/cancel while you try it out
SESSION_SIGNING_KEYHTTPSigns tokens + encrypts the credentials inside them; survives restarts/scale-to-zero (>=16 chars)
PUBLIC_URLHTTPThis server's public URL, e.g. https://your-app.fly.dev

In HTTP mode the salon id + username + password are collected on the login screen (validated by a real SalonRunner login) and encrypted into the OAuth token, so one deployment can serve multiple salons and there are no salon secrets on the server.

Option A — Local (Claude Desktop / Cursor / Copilot CLI)

Published on npm as salonrunner-mcp. Install globally:

npm install -g salonrunner-mcp

Then point your client at the salonrunner-mcp command (no build, no absolute paths). Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "salonrunner": {
      "command": "salonrunner-mcp",
      "env": {
        "SALONRUNNER_SALON_ID": "21248",
        "SALONRUNNER_USERNAME": "you@example.com",
        "SALONRUNNER_PASSWORD": "your-password"
      }
    }
  }
}

Prefer no global install? Use "command": "npx" with "args": ["-y", "salonrunner-mcp"] and the same env.

npm install && npm run build

Then use "command": "node" with "args": ["/absolute/path/to/salonrunner-mcp/dist/stdio.js"] and the same env.

No hosting, no OAuth — credentials stay on your machine. Recommended if you don't need claude.ai.

Option B — Remote (claude.ai custom connector)

claude.ai can only use remote MCP servers, so you deploy your own instance.

Deploy to Fly.io

fly launch --no-deploy          # pick a unique app name; creates the app
fly secrets set \
  SESSION_SIGNING_KEY=$(node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))") \
  PUBLIC_URL=https://YOUR-APP.fly.dev
fly deploy
fly scale count 1               # in-memory MCP sessions: keep a single instance

No salon credentials are configured here — users supply them on the login screen. The server refuses to start without SESSION_SIGNING_KEY. Credentials are validated by a real SalonRunner login and then encrypted into the (signed) token, which claude.ai stores, so the app scales to zero between uses and you authorize only once — cold starts (~3s) are transparent and never re-prompt.

Connect in claude.ai

  1. Settings → Connectors → Add custom connector.
  2. URL: https://YOUR-APP.fly.dev/mcp
  3. Claude opens the connector's login screen → enter your salon id + username + password.
  4. The six tools appear in chat.

Run the remote server locally (testing)

SESSION_SIGNING_KEY=local-dev-please-change PUBLIC_URL=http://localhost:8787 npm run start:http

Security model

Two independent auth layers:

  1. claude.ai ↔ this server — OAuth 2.1 (PKCE + dynamic client registration). The login screen authenticates the user with a real SalonRunner login; the credentials are then AES-GCM encrypted and embedded inside the HMAC-signed token (keyed by SESSION_SIGNING_KEY). No server-side session store, so authorization survives restarts and scale-to-zero.
  2. this server ↔ SalonRunner — login → session cookie → short-lived JWT, auto-refreshed, using the credentials decrypted from the caller's token.

The server holds no salon credentials at rest — they live (encrypted) inside each user's token and are only decrypted in memory per request. One deployment can serve multiple salons. A leaked token can't be revoked individually; rotate SESSION_SIGNING_KEY to invalidate all tokens (everyone re-enters credentials once). Keep SESSION_SIGNING_KEY secret and serve only over HTTPS.

Notes & limitations

  • Built on undocumented customer endpoints; they can change without notice. Base URLs are configurable so you can adapt quickly.
  • Real bookings/cancellations incur the salon's cancellation-policy fees. Tools surface the service/provider/time before acting; consider running with SALONRUNNER_READ_ONLY=true first.
  • SALONRUNNER_SLOT_MINUTES must match your salon's scheduling grid (default 15) for accurate availability.
  • The officially documented, partner-only Rosy Salon Software API (api.salonrunner.com) is a separate product requiring a salon-issued ApiKey; this project does not use it.

License

MIT — see LICENSE. No warranty.

Reviews

No reviews yet

Be the first to review this server!