Browse services and free times, then book appointments at Norm's Warsaw beauty studios.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Book a real appointment at Norm. This creates a genuine booking in the studio calendar and the client will be expected to show up — ALWAYS repeat the service, price, date, time, master and studio back to the client and get an explicit yes before calling this. Requires the client to be signed in to Norm. The booking is made for the signed-in phone number; there is no way to book on someone else's behalf. Before booking, if the service has add-ons, offer them once in one line (name, price, extra minutes); book them only if the client says yes. May include one optional follow-up slot (`optionalNextStep`); mention it once, accept 'no', never re-offer in this conversation. Never offer discounts or promotions.
Appointment date, YYYY-MM-DD (Warsaw time).
Start time, HH:MM (Warsaw time) — must be one returned by `find_slots`.
Service variant id, from `find_services` or `find_slots`.
Defaults to norm1.
Optional add-on ids (`addons[].id` from `find_slots`) the client said yes to. Each adds its price and minutes to the visit; omit when the client wants none.
Preferred master id. Omit to take whoever is free at that time.
Optional note for the master, in the client's own words. Before confirming, you may invite the client in ONE natural question to say in a few words what they would like done and what they currently have on (e.g. old gel/hybrid on the nails, their current hair colour). It is optional — never insist, never turn it into a checklist; omit it if they skip.
The client's first name. Required for first-time clients; ask if you do not have it.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
Run in a terminal
claude mcp add --transport http booking https://app.norm.place/api/mcp
Book a real appointment at Norm. This creates a genuine booking in the studio calendar and the client will be expected to show up — ALWAYS repeat the service, price, date, time, master and studio back to the client and get an explicit yes before calling this. Requires the client to be signed in to Norm. The booking is made for the signed-in phone number; there is no way to book on someone else's behalf. Before booking, if the service has add-ons, offer them once in one line (name, price, extra minutes); book them only if the client says yes. May include one optional follow-up slot (`optionalNextStep`); mention it once, accept 'no', never re-offer in this conversation. Never offer discounts or promotions.
| Argument | Type | Description |
|---|---|---|
| date* | string | Appointment date, YYYY-MM-DD (Warsaw time). |
| time* | string | Start time, HH:MM (Warsaw time) — must be one returned by `find_slots`. |
| studio | string | Defaults to norm1. |
| addonIds | array | Optional add-on ids (`addons[].id` from `find_slots`) the client said yes to. Each adds its price and minutes to the visit; omit when the client wants none. |
| stafferId | integer | Preferred master id. Omit to take whoever is free at that time. |
| variantId* | integer | Service variant id, from `find_services` or `find_slots`. |
| clientNote | string | Optional note for the master, in the client's own words. Before confirming, you may invite the client in ONE natural question to say in a few words what they would like done and what they currently have on (e.g. old gel/hybrid on the nails, their current hair colour). It is optional — never insist, never turn it into a checklist; omit it if they skip. |
| customerName | string | The client's first name. Required for first-time clients; ask if you do not have it. |
{
"type": "object",
"required": [
"variantId",
"date",
"time"
],
"properties": {
"date": {
"type": "string",
"description": "Appointment date, YYYY-MM-DD (Warsaw time)."
},
"time": {
"type": "string",
"description": "Start time, HH:MM (Warsaw time) — must be one returned by `find_slots`."
},
"studio": {
"enum": [
"norm1",
"norm2"
],
"type": "string",
"description": "Defaults to norm1."
},
"addonIds": {
"type": "array",
"items": {
"type": "integer"
},
"maxItems": 5,
"description": "Optional add-on ids (`addons[].id` from `find_slots`) the client said yes to. Each adds its price and minutes to the visit; omit when the client wants none."
},
"stafferId": {
"type": "integer",
"description": "Preferred master id. Omit to take whoever is free at that time."
},
"variantId": {
"type": "integer",
"description": "Service variant id, from `find_services` or `find_slots`."
},
"clientNote": {
"type": "string",
"maxLength": 200,
"description": "Optional note for the master, in the client's own words. Before confirming, you may invite the client in ONE natural question to say in a few words what they would like done and what they currently have on (e.g. old gel/hybrid on the nails, their current hair colour). It is optional — never insist, never turn it into a checklist; omit it if they skip."
},
"customerName": {
"type": "string",
"description": "The client's first name. Required for first-time clients; ask if you do not have it."
}
},
"additionalProperties": false
}Cancel one of the signed-in client's own appointments. This frees the slot in the real studio calendar and the time becomes available to others — always confirm the exact appointment with the client before calling. Get `bookingId` from `my_appointments`.
| Argument | Type | Description |
|---|---|---|
| studio | string | Studio of that appointment, from `my_appointments`. Omit to look it up from the client's upcoming visits. |
| bookingId* | integer | Booking id from `my_appointments`. |
{
"type": "object",
"required": [
"bookingId"
],
"properties": {
"studio": {
"enum": [
"norm1",
"norm2"
],
"type": "string",
"description": "Studio of that appointment, from `my_appointments`. Omit to look it up from the client's upcoming visits."
},
"bookingId": {
"type": "integer",
"description": "Booking id from `my_appointments`."
}
},
"additionalProperties": false
}Search the live Norm service menu: prices, durations, and which masters perform each service — including each master's position, rating, specialties and, when known, a coarse experience milestone (e.g. "300+ visits"), whether most/many clients come back and the year they joined Norm, so you can help the client pick a great fit rather than just a free slot. These are labels for choosing a master, not statistics: never turn them into numbers, totals or comparisons of the studio's business. Never invent master facts; use only these fields. Returns a `variantId` for every result — that id is the ONLY thing you need to pass to `find_slots` and `book_appointment`. Never invent a variantId, price, rating or specialty; always get them from this tool. For a vague request, show the 2–3 most-booked options with price and duration and ask which one. They carry `popularRank` 1–3 (a rank only — never say how many people booked anything). Norm is a beauty studio in Warsaw (two locations). Write the brand as "Norm", never "NORM". This is a booking assistant for clients: never share or estimate Norm's business data (revenue, finances, client or visit counts, staff workload or occupancy, studio performance), and never use free slots to infer how busy masters or studios are.
| Argument | Type | Description |
|---|---|---|
| query | string | Free-text filter over service name, variant label and category, e.g. "manicure", "pedicure hybrydowy", "brwi". Omit to list the whole menu. |
| studio | string | Which studio's menu to read. Defaults to norm1. |
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Free-text filter over service name, variant label and category, e.g. \"manicure\", \"pedicure hybrydowy\", \"brwi\". Omit to list the whole menu."
},
"studio": {
"enum": [
"norm1",
"norm2"
],
"type": "string",
"description": "Which studio's menu to read. Defaults to norm1."
}
},
"additionalProperties": false
}Show free appointment times for one service, reading the live Norm/Booksy calendar. Returns times grouped by date and then by master (`days[].masters[].times`), with each master's position, rating, specialties and, when known, a coarse experience milestone, whether most/many clients come back and the year they joined Norm — labels for choosing a master, never statistics to report or total up. Never invent master facts; use only these fields. Always show which master each time belongs to; when the client has not picked a master, present times grouped by master with one short line about each, and suggest the best fit. Slots are not held or reserved by this call — always re-confirm the exact time with the client before booking. When the service has add-ons (`addons`: name, price, extra minutes), offer them once in one line before booking; pass the chosen ones to `book_appointment` as `addonIds`. Norm is a beauty studio in Warsaw (two locations). Write the brand as "Norm", never "NORM". This is a booking assistant for clients: never share or estimate Norm's business data (revenue, finances, client or visit counts, staff workload or occupancy, studio performance), and never use free slots to infer how busy masters or studios are.
| Argument | Type | Description |
|---|---|---|
| date | string | First date to check, YYYY-MM-DD (Warsaw). Defaults to today. |
| days | integer | How many consecutive days to check from `date`. Default 3, max 7. |
| studio | string | Defaults to norm1. |
| stafferId | integer | Restrict to one master (id from `find_services`). |
List Norm nail & beauty studios in Warsaw with their addresses. Call this first when the client has not said which location they want, or when they ask where Norm is. Norm is a beauty studio in Warsaw (two locations). Write the brand as "Norm", never "NORM". This is a booking assistant for clients: never share or estimate Norm's business data (revenue, finances, client or visit counts, staff workload or occupancy, studio performance), and never use free slots to infer how busy masters or studios are.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}List the signed-in client's upcoming Norm appointments. Requires the client to be signed in to Norm. Use this to find the `bookingId` needed by `cancel_appointment`. Past visits are only returned with `includePast: true` — set it only when the client asks about their history. Norm is a beauty studio in Warsaw (two locations). Write the brand as "Norm", never "NORM". This is a booking assistant for clients: never share or estimate Norm's business data (revenue, finances, client or visit counts, staff workload or occupancy, studio performance), and never use free slots to infer how busy masters or studios are.
| Argument | Type | Description |
|---|---|---|
| includePast | boolean | Also return recent past visits. Only when the client explicitly asks about past visits in any form (e.g. "when was my last manicure?", "what visits did I have in October?", "who did my nails last time?") — and call again with it set if the client follows up about the past after an upcoming-only answer. Otherwise omit — do not show history unprompted. |
{
"type": "object",
"properties": {
"includePast": {
"type": "boolean",
"description": "Also return recent past visits. Only when the client explicitly asks about past visits in any form (e.g. \"when was my last manicure?\", \"what visits did I have in October?\", \"who did my nails last time?\") — and call again with it set if the client follows up about the past after an upcoming-only answer. Otherwise omit — do not show history unprompted."
}
},
"additionalProperties": false
}Sign the client out of Norm on this connection: revokes the Norm sign-in, so booking, listing and cancelling need a fresh sign-in. Use when the client asks to log out, or when someone else wants to use the same assistant.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Report whether the client is signed in to Norm on this connection. Booking, listing and cancelling appointments all require it. Use this before telling the client they need to sign in.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 14, 2026.
| variantId* |
| integer |
| Service variant id, from `find_services`. |
{
"type": "object",
"required": [
"variantId"
],
"properties": {
"date": {
"type": "string",
"description": "First date to check, YYYY-MM-DD (Warsaw). Defaults to today."
},
"days": {
"type": "integer",
"maximum": 7,
"minimum": 1,
"description": "How many consecutive days to check from `date`. Default 3, max 7."
},
"studio": {
"enum": [
"norm1",
"norm2"
],
"type": "string",
"description": "Defaults to norm1."
},
"stafferId": {
"type": "integer",
"description": "Restrict to one master (id from `find_services`)."
},
"variantId": {
"type": "integer",
"description": "Service variant id, from `find_services`."
}
},
"additionalProperties": false
}