Skip to main content
Glama

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

Tool

What it does

list_services

List bookable services (name, id, price)

list_providers

List stylists; optionally only those who do a given service

find_availability

Open slots for a service over a date range (optionally one provider)

list_my_appointments

Your upcoming appointments

book_appointment

Book a slot returned by find_availability

cancel_appointment

Cancel by appointment id

Related MCP server: Zenoti MCP Server

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.

Variable

Used by

Notes

SALONRUNNER_SALON_ID

stdio (+ 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_PASSWORD

stdio

Your client login

SALONRUNNER_CUSTOMER_ID

both

Auto-discovered; set only if discovery fails

SALONRUNNER_SLOT_MINUTES

both

Salon booking granularity (default 15)

SALONRUNNER_READ_ONLY

both

true disables book/cancel while you try it out

SESSION_SIGNING_KEY

HTTP

Signs tokens + encrypts the credentials inside them; survives restarts/scale-to-zero (>=16 chars)

PUBLIC_URL

HTTP

This 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.

Available Tools

6 tools
book_appointmentBook an appointmentA

Book an appointment. startTime must be a value returned by find_availability ('YYYY-MM-DD HH:MM:SS'). End time is computed from the provider's service duration. This creates a REAL booking subject to the salon's cancellation policy.

ParametersJSON Schema
NameRequiredDescriptionDefault
serviceIdYes
startTimeYes'YYYY-MM-DD HH:MM:SS' from find_availability
providerIdYesProvider id from find_availability

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries burden. Discloses that booking is real and subject to cancellation policy. Could add details about side effects or authorization needs, but adequate for basic transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each informative. No redundant text. Front-loaded with action and key constraint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Well-covered for a simple 3-param creation tool. Explains dependency on find_availability and real booking status. Missing output description but acceptable without output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage 67% with startTime and providerId described. Description adds format and dependency for startTime but not for serviceId or providerId beyond schema. Baseline 3 with marginal value added.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Book an appointment' with specific verb and resource. Distinguishes from siblings like cancel_appointment and find_availability by noting that startTime comes from find_availability.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context: startTime must be from find_availability, end time computed automatically, creates real booking subject to cancellation policy. Does not explicitly exclude alternatives but implies prerequisite sequencing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_appointmentCancel an appointmentA

Cancel an existing appointment by appointmentId (from list_my_appointments). Cancellation fees may apply per the salon's policy.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonYesReason for cancellation
appointmentIdYes

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must disclose behaviors. It warns about cancellation fees but does not mention other side effects (e.g., refunds, reversibility, notifications). Adequate but minimal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no wasted words. Front-loaded with main action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema; description does not explain return values or confirmation behavior. Lacks information on success/error handling. Adequate for simple tool but incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Adds context to appointmentId by linking it to list_my_appointments. Reason parameter is already described in schema; description does not add further value. Overall, useful beyond schema for one of two parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states action (cancel), object (appointment), and method (by appointmentId from list_my_appointments). Distinct from sibling tools like book_appointment or find_availability.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies when to use: after obtaining appointmentId from list_my_appointments. Mentions cancellation fees as a consideration but does not explicitly state when not to use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_availabilityFind availabilityA

Find open appointment slots for a service in a date range (inclusive). Dates are YYYY-MM-DD. Optionally restrict to one providerId. Returns startable times with the matching provider.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd date YYYY-MM-DD (inclusive)
fromYesStart date YYYY-MM-DD
limitNoMax slots to return (default 50)
serviceIdYesService id from list_services
providerIdNoRestrict to this provider id

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must convey behavioral traits. It discloses that dates are inclusive and in YYYY-MM-DD format, and that the tool returns 'startable times with the matching provider.' However, it omits details about pagination (despite a limit parameter), default behavior, and what happens when no slots are found. The transparency is adequate but not thorough.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences that front-load the core purpose. The first sentence covers the main action and date format, while the second adds optional restriction and return type. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 5 parameters (3 required) and no output schema or annotations, the description covers the essential purpose and return type. However, it lacks details about the output format (structure of 'startable times'), default limit behavior, and error conditions. An agent might need to infer these from context, making it slightly incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% coverage with descriptions for all parameters. The description adds value by clarifying that the date range is inclusive and specifying the date format, but does not significantly extend beyond the schema. The baseline score of 3 is appropriate given the high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool finds open appointment slots for a service within a date range, distinguishing it from sibling tools like book_appointment, cancel_appointment, list_my_appointments, list_providers, and list_services. The verb 'find' and the resource 'availability' are specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool: to find open slots for a service in a date range, with an optional providerId restriction. While it does not explicitly state when not to use it, the context of sibling tools implies alternatives for other tasks (e.g., booking or listing appointments). This is sufficient for an AI agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_my_appointmentsList my appointmentsA

List the signed-in client's upcoming (non-cancelled) appointments.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description provides transparency on the behavioral constraint of listing only upcoming, non-cancelled appointments. It also implies the need for authentication ('signed-in client'). No mention of pagination or error cases, but given simplicity, it's adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no filler. Every word adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and no output schema, the description is mostly complete. It doesn't define 'upcoming' time range, but the simple nature and sibling tools provide enough context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Tool has zero parameters with 100% schema coverage. Baseline for 0 params is 4. Description adds no parameter details but none are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'list' and the resource 'appointments', with specific constraints: 'signed-in client's upcoming (non-cancelled)'. This distinguishes it from sibling tools like 'find_availability' and 'list_providers'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use (to see one's own appointments) but lacks explicit guidance on when not to use or alternatives. For example, no mention that cancelled appointments are excluded, which is a key differentiator.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_providersList providersA

List stylists/providers who take online bookings. Optionally filter to those who perform a given serviceId.

ParametersJSON Schema
NameRequiredDescriptionDefault
serviceIdNoOnly providers who perform this service

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description bears full responsibility. It adds context that the list is limited to those who take online bookings, which is a behavioral trait. However, it does not disclose other potential traits like pagination, ordering, or whether the list is real-time or cached.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences with no fluff. It front-loads the main action and includes the filter as secondary. Every word adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one optional parameter, no output schema), the description covers the essential purpose and filter. It could be more complete by mentioning ordering or pagination, but for a list tool with common expectations, it is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the schema already explains the parameter. The description merely reiterates that the filter is for providers who perform the given serviceId, adding no new meaning beyond the schema. Baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('List'), the resource ('stylists/providers'), and the context ('who take online bookings'). It distinguishes from sibling tools like 'list_services' by specifying providers. The optional filter by serviceId is also mentioned, adding precision.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

While the description does not explicitly state when or when not to use this tool, the purpose is clear enough to distinguish from siblings (e.g., 'book_appointment' is for booking, not listing). The context implies use when you need a list of providers, especially with optional filtering.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_servicesList servicesA

List bookable services offered by the salon (name, id, price, base duration).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It implies a read-only operation but does not explicitly ensure no side effects or authorization needs. Adequate for a simple list tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the action and output fields, no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with no input parameters and no output schema, the description is complete: it specifies the action and the fields returned.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist. With 0 parameters and 100% schema coverage, baseline is 4. The description adds no parameter info because none are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists bookable services with name, id, price, base duration. It is distinct from sibling tools like book_appointment or list_providers.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for retrieving service information, but does not explicitly exclude when not to use or mention alternatives. However, the context is clear given sibling tool names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.2.0
    • First observedbook_appointment
    • First observedcancel_appointment
    • First observedfind_availability
    • First observedlist_my_appointments
    • First observedlist_providers
    • First observedlist_services

TDQS

A4.3/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a unique purpose: booking, canceling, finding availability, listing appointments, providers, and services. No overlap or ambiguity.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern in snake_case (e.g., book_appointment, list_services). The pattern is uniform and predictable.

Tool Count5/5

With 6 tools, the set is well-scoped for a salon booking MCP. It covers browsing and booking without being overly large or minimal.

Completeness5/5

The surface covers the full client-side booking lifecycle: browsing services and providers, checking availability, booking, listing appointments, and canceling. No obvious gaps.

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for Mindbody, enabling AI agents to fetch client info, query class schedules, book classes/appointments (env-gated), and process checkout (payment-gated).
    5
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    MCP server that exposes meetergo's scheduling and CRM API as tools for AI assistants, enabling Proton Calendar-backed booking management and contact operations without Google Workspace.
    37
    BSD 3-Clause
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes SMB business data as tools for AI agents, enabling retrieval of business profiles, services, availability, and reviews.
    -