A Model Context Protocol (MCP) server that provides intelligent access to the Zenoti spa/wellness management API. Designed for AI agents to efficiently manage appointments, guests, services, and billing workflows.
- Complete Service Booking: Single tool handles the entire 4-step booking flow
- Guest Lifecycle Management: Create, search, update guests with smart defaults
- Appointment Management: Check-in, status updates, and progress tracking
- Invoice & Payment: Retrieve, confirm, and close invoices with proper error handling
- Forms & Feedback: List forms, retrieve data, and submit feedback
- Context-Efficient Responses: Returns only essential information by default
- Smart Error Messages: Guides agents toward correct usage patterns
- Workflow Consolidation: Combines related operations into single tools
- Human-Readable Outputs: Uses names over IDs, dates in readable format
- Clone the repository:
git clone https://github.com/yourusername/zenoti-mcp-server.git
cd zenoti-mcp-server- Install dependencies:
npm install- Configure environment variables:
cp .env.example .env
# Edit .env with your Zenoti API credentials- Build the server:
npm run buildZENOTI_API_KEY: Your Zenoti API key (required)ZENOTI_API_URL: Zenoti API base URL (default: https://api.zenoti.com)ZENOTI_CENTER_ID: Default center ID for operationsZENOTI_ORG_ID: Your organization ID
- Log into Zenoti Admin
- Navigate to: Admin > Setup > Apps (organization level)
- Create a new backend app
- Assign necessary module permissions (avoid global permissions)
- Copy the API key (valid for 1 year)
# Development mode with auto-reload
npm run dev
# Production mode
npm start
# Test the server with example client
npm testAdd to your Claude Desktop configuration (claude_desktop_config.json):
{
"mcpServers": {
"zenoti": {
"command": "node",
"args": ["/path/to/zenoti-mcp-server/dist/index.js"],
"env": {
"ZENOTI_API_KEY": "your_api_key",
"ZENOTI_API_URL": "https://api.zenoti.com",
"ZENOTI_CENTER_ID": "your_center_id"
}
}
}
}Complete 4-step service booking workflow in a single tool.
Parameters:
guest_id(required): Guest ID or search queryservice_id(required): Service ID or namedate(required): Appointment date (YYYY-MM-DD)time(optional): Preferred time (HH:MM)therapist_id(optional): Therapist ID or namenotes(optional): Booking notespay_later(optional): Skip payment (default: true)
Example:
{
"guest_id": "john.doe@email.com",
"service_id": "Deep Tissue Massage",
"date": "2025-11-15",
"time": "14:00"
}Search for guests by name, email, or phone.
Parameters:
query(required): Search querylimit(optional): Max results (default: 10)
Create a new guest profile.
Parameters:
first_name(required)last_name(required)email(optional)phone(optional)gender(optional)date_of_birth(optional)
List appointments with filters.
Parameters:
start_date(required): Start date (YYYY-MM-DD)end_date(optional): End date (default: start_date)status(optional): Filter by statusguest_id(optional): Filter by guestlimit(optional): Max results (default: 50)
Check in a guest for their appointment.
Parameters:
appointment_id(required): Appointment or group ID
Update appointment status (confirm, cancel, no-show).
Parameters:
appointment_id(required)status(required): "confirmed", "cancelled", "no_show"reason(optional): Cancellation reason
Retrieve invoice details.
Parameters:
invoice_id(required)include_details(optional): Include line items (default: true)
Process payment and close invoice.
Parameters:
invoice_id(required)payment_method(optional): Payment typeamount(optional): Payment amount
Get forms for an appointment.
Parameters:
appointment_id(required)
Submit guest feedback for appointment.
Parameters:
appointment_id(required)rating(required): 1-5 or 1-10comments(optional)
The server provides actionable error messages to guide agents:
{
"error": "No available slots found",
"suggestion": "Try a different date or remove therapist preference",
"alternatives": ["2025-11-16", "2025-11-17"]
}The server implements intelligent rate limiting:
- Automatic retry with exponential backoff
- Rate limit status in responses
- Suggestions for reducing API calls
zenoti-mcp-server/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── zenoti-client.ts # Zenoti API client
│ ├── tools/ # Tool implementations
│ │ ├── booking.ts # Service booking tools
│ │ ├── guests.ts # Guest management tools
│ │ ├── appointments.ts # Appointment tools
│ │ └── invoices.ts # Invoice tools
│ ├── utils/ # Shared utilities
│ │ ├── errors.ts # Error handling
│ │ ├── formatters.ts # Response formatting
│ │ └── validators.ts # Input validation
│ └── test-client.ts # Test client
├── package.json
├── tsconfig.json
└── README.md
Run the test client to verify functionality:
npm testThe test client demonstrates:
- Service booking workflow
- Guest search and creation
- Appointment management
- Error handling
- Use search before create: Always search for existing guests before creating
- Handle partial matches: Guest search returns fuzzy matches
- Respect rate limits: Use suggested delays between requests
- Check availability first: Query slots before attempting bookings
- Use human-readable inputs: Names work as well as IDs
- Environment-specific apps: Create separate Zenoti apps for dev/staging/prod
- Minimal permissions: Grant only necessary module permissions
- Token refresh: Implement token refresh for long-running sessions
- Error logging: Monitor failed requests for API issues
- Webhook integration: Consider webhooks for real-time updates
-
API Key Authorization Denied (Error 602)
- Verify API key is correct and not expired
- Check app has necessary permissions in Zenoti
- Ensure using correct center_id
-
No Available Slots
- Check service is bookable online
- Verify therapist works on requested date
- Try without therapist preference
-
Guest Not Found
- Search uses fuzzy matching
- Try partial name or email
- Check guest exists in correct center
MIT License - See LICENSE file for details
For issues or questions:
- GitHub Issues: zenoti-mcp-server/issues
- Zenoti API Docs: docs.zenoti.com
- MCP Protocol: modelcontextprotocol.io