Reserrva
Online bookings for appointment-based professionals. Your booking page and team calendar.
This listing identifies a third-party MCP server. MCPBundles is not affiliated with, sponsored by, or endorsed by the service or its operator unless stated on this page.
https://www.reserrva.app/enhttps://mcp.reserrva.app/mcpLast probed Nov 2, 2026 · mcp.reserrva.app
79tools discovered
Showing 25 of 79
Showing 25 of 79 tools from the public preview. Connect the server to inspect the full live tool list.
Recommend barbershops or tattoo studios
recommend_businessesThe first tool to call when someone wants to book ("resérvame un barbero", "find me a tattoo studio"): call it before search_businesses. It needs kind and a location. If you do not know where the user is, ask once — "¿en qué ciudad?" — and never again in the same conversation; do not guess a city. Pass city (the user's words, e.g. "Madrid") and, whenever you know them, the approximate lat/lng of that city or of the user, and country_code (ISO 3166-1 alpha-2): coordinates rank by distance and let
Description may be truncated on the public preview.
Add to workspace[
{
"name": "recommend_businesses",
"title": "Recommend barbershops or tattoo studios",
"annotations": {
"readOnlyHint": true
},
"description": "The first tool to call when someone wants to book (\"resérvame un barbero\", \"find me a tattoo studio\"): call it before search_businesses. It needs kind and a location. If you do not know where the user is, ask once — \"¿en qué ciudad?\" — and never again in the same conversation; do not guess a city. Pass city (the user's words, e.g. \"Madrid\") and, whenever you know them, the approximate lat/lng of that city or of the user, and country_code (ISO 3166-1 alpha-2): coordinates rank by distance and let an empty answer name the nearest covered cities. Returns { results, coverage_for_city, nearest_cities_with_kind }. results is already ranked (free within 48 h first, then nearest, then best rated): present the first 2–3, each with its name, next_slot_local (the business's local time with its UTC offset — say the time and the timezone, e.g. \"mañana a las 11:00 (hora de Madrid, UTC+02:00)\"), from_price_cents in currency and the rating when rating_count > 0. next_slot_offer is the exact service, professional, price and offer_fingerprint of that slot: when the user picks it, book it with book_as_guest (business_slug = slug, staff_id, service_id, starts_at = next_slot, offer_fingerprint) after asking for their name and phone, or with book_appointment if they are signed in; for any other service or time, use get_business and next_available_slots. Never invent a business, a time or a price that is not in this answer. When results is empty, say plainly that Reserrva is not in that city yet, name the cities in nearest_cities_with_kind (they are real and covered for this kind), and offer to let them know when it arrives: join_waitlist with their email and the city they asked for. coverage_for_city lists what Reserrva does have in the requested city (other kinds included). booking_url is the business's public page, for a user who prefers to book there.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs. Each result has mobile: boolean. mobile = true means the professional works a domicilio: there is no venue, the barber or artist comes to the customer's place within that city, so say \"comes to you\" instead of giving an address, and make sure the user is fine with a home visit before booking.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"kind"
],
"properties": {
"lat": {
"type": "number",
"maximum": 90,
"minimum": -90,
"description": "Approximate latitude of the city or the user. Pass with lng."
},
"lng": {
"type": "number",
"maximum": 180,
"minimum": -180
},
"city": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The city the user named, in their words."
},
"kind": {
"enum": [
"barbershop",
"tattoo_studio"
],
"type": "string"
},
"when": {
"type": "string",
"minLength": 1,
"description": "Earliest time the user can go. Defaults to now."
},
"limit": {
"type": "integer",
"maximum": 10,
"minimum": 1
},
"country_code": {
"type": "string",
"pattern": "^[A-Za-z]{2}$",
"description": "ISO 3166-1 alpha-2, e.g. ES"
}
}
}
},
{
"name": "list_coverage",
"title": "Where Reserrva has businesses",
"annotations": {
"readOnlyHint": true
},
"description": "Every city where Reserrva has active businesses, per kind: country_code, city, kind, active_count, and the city's lat/lng (centre of its shops). Pass kind to restrict it, and lat/lng or country_code to order it nearest / same country first (distance_m is then metres from the point). Use it to answer \"where do you work?\" or to tell a user which covered city is closest. recommend_businesses already includes the relevant part of this, so you rarely need both.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"lat": {
"type": "number",
"maximum": 90,
"minimum": -90
},
"lng": {
"type": "number",
"maximum": 180,
"minimum": -180
},
"kind": {
"enum": [
"barbershop",
"tattoo_studio"
],
"type": "string"
},
"country_code": {
"type": "string",
"pattern": "^[A-Za-z]{2}$",
"description": "ISO 3166-1 alpha-2, e.g. ES"
}
}
}
},
{
"name": "join_waitlist",
"title": "Get notified when Reserrva arrives in a city",
"annotations": {
"readOnlyHint": false
},
"description": "Add someone to Reserrva's waitlist for a city it does not cover yet, so they hear when it arrives. Offer it when recommend_businesses returns no results; only call it after the user has given you their email and agreed. Pass the city they asked for, country_code (ISO 3166-1 alpha-2) when you know it, kind, and locale (es or en, the language you are speaking with them). The answer is the same whether the address was already on the list or not — just confirm they will be told. Invalid email or city: invalid_input, ask again.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"email",
"city"
],
"properties": {
"city": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The city the user asked for, not a covered one."
},
"kind": {
"enum": [
"barbershop",
"tattoo_studio"
],
"type": "string"
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 160
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language you are speaking with the user."
},
"country_code": {
"type": "string",
"pattern": "^[A-Za-z]{2}$",
"description": "ISO 3166-1 alpha-2, e.g. ES"
}
}
}
},
{
"name": "search_businesses",
"title": "Search businesses and professionals",
"annotations": {
"readOnlyHint": true
},
"description": "Search Reserrva's bookable businesses exactly as the Explore page does (same filter, same order, demo and test shops excluded). query matches the business name, its tags, the names of its services, and the name or @handle (then a word of the bio) of its bookable professionals. A professional is returned on their business's row: professionals lists up to 3 matches, best first, each {id (the staff_id for available_slots), slug, display_name, avatar_url, match, handle}; match is \"name\" (the name matched), \"handle\" (only the Instagram handle matched; handle then holds it, without @) or \"bio\" (a word of the bio matched); handle is null unless match is \"handle\". professionals_total counts every match. A row the query matched only by itself, and every row of a search without query, has professionals: [] and professionals_total: 0. locale (es or en) sets the summary's language. city needs country_code (ISO 3166-1 alpha-2); lat/lng together sort by distance within radius_m (distance_m is then metres, otherwise null). Each row: slug, name, kind, city, at_home (the professional comes to the customer), rating, currency, timezone, the headline service with its start_price_cents and pricing mode, quote_only, and next_slot (the next opening, or null). Use it when the user names a shop, a person, a tag or a service (\"estudio que haga blackwork\"); to book, call recommend_businesses first — it ranks by availability. Use the returned slug with get_business. At most 25 rows.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"lat": {
"type": "number",
"maximum": 90,
"minimum": -90,
"description": "Pass with lng to sort by distance."
},
"lng": {
"type": "number",
"maximum": 180,
"minimum": -180
},
"city": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Pass with country_code."
},
"kind": {
"enum": [
"barbershop",
"tattoo_studio"
],
"type": "string"
},
"limit": {
"type": "integer",
"maximum": 25,
"minimum": 1
},
"query": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Free text: business name, tag, service name, or a professional's name or @handle."
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language you are speaking with the user, for the summary. Defaults to es."
},
"radius_m": {
"type": "integer",
"maximum": 100000,
"minimum": 100,
"description": "Search radius in metres, with lat/lng."
},
"country_code": {
"type": "string",
"pattern": "^[A-Za-z]{2}$",
"description": "ISO 3166-1 alpha-2, e.g. ES"
}
}
}
},
{
"name": "nearby_businesses",
"title": "Find businesses near a point",
"annotations": {
"readOnlyHint": true
},
"description": "Bookable businesses within radius_m metres of a point, nearest first, with the same rows and exclusions as search_businesses and reserrva.app/explore. Use this when the user gives a location rather than a name (\"near me\", \"close to Sol\") and you have coordinates; use search_businesses when they give words. distance_m is metres. At most 25 rows.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"lat",
"lng"
],
"properties": {
"lat": {
"type": "number",
"maximum": 90,
"minimum": -90
},
"lng": {
"type": "number",
"maximum": 180,
"minimum": -180
},
"kind": {
"enum": [
"barbershop",
"tattoo_studio"
],
"type": "string"
},
"limit": {
"type": "integer",
"maximum": 25,
"minimum": 1
},
"radius_m": {
"type": "integer",
"maximum": 100000,
"minimum": 100,
"description": "Search radius in metres."
}
}
}
},
{
"name": "get_business",
"title": "Get a business profile",
"annotations": {
"readOnlyHint": true
},
"description": "Everything public about one business, by slug: address and coordinates, timezone, currency, opening hours, booking policy (slot interval, minimum notice, maximum advance, cancellation window, whether bookings auto-confirm), the bookable staff with the service ids each one offers, the service catalog with prices and durations, portfolio and recent reviews. Returns null when no active business has that slug. Read this before quoting a price or a time: service.price_cents and service.duration_min are what a booking will snapshot. A service with requires_request = true or pricing_mode = 'quote' cannot be booked directly — use submit_booking_request instead. Each service also lists offers: per bookable professional, their price_cents, duration_min and offer_fingerprint — the exact offer a guest booking is checked against.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The business slug, as returned by search_businesses."
}
}
}
},
{
"name": "next_available_slots",
"title": "Find the next free appointments",
"annotations": {
"readOnlyHint": true
},
"description": "The earliest free slots for one service at one business, across every bookable professional (or one, with staff_id), scanning days days from from_date (default: today in the business timezone). This is the tool for \"who has a slot tomorrow?\" — one call instead of a loop over dates. Each row is one bookable start: staff_id, staff_name, slot_start, slot_end, and that professional's price_cents, duration_min and offer_fingerprint for the service. Show the user that price; pass slot_start straight to book_appointment, or slot_start and offer_fingerprint to book_as_guest. An empty list means nothing is free in that window, not that the business is closed. If the day the user wants is full, offer request_slot_alert for that day.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_id",
"service_id"
],
"properties": {
"days": {
"type": "integer",
"maximum": 30,
"minimum": 1
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Restrict to one professional. Omit to search the whole team."
},
"from_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day to scan. Defaults to today in the business timezone."
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "booking_days",
"title": "See which days can be booked",
"annotations": {
"readOnlyHint": true
},
"description": "One row per calendar day from from_date to to_date (a bounded range, see to_date) for one service at one business (business_slug), for one professional (staff_id) or anyone who offers the service. Days are counted in time_zone when you pass it (an IANA name, such as the user's), otherwise in the business timezone. Each row is { day, state }: open (someone can be booked that day, though every time may already be taken), closed (the business is closed), off (it opens, but that professional, or everyone who offers the service, is not working), past (over, or too late to book) or beyond (after the booking window). Use it to say which days are worth asking about — \"they are closed on Sundays\" — before calling next_available_slots or available_slots for the times; never present a day that is not open as bookable.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: invalid_input, invalid_range, range_too_long, business_not_found, service_not_found, staff_not_found.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_slug",
"service_id",
"from_date",
"to_date"
],
"properties": {
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language you are speaking with the user, for the summary. Defaults to es."
},
"to_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day, inclusive; the range holds at most 62 days."
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "One professional. Omit for anyone who offers the service."
},
"from_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day, YYYY-MM-DD in time_zone (or the business timezone)."
},
"time_zone": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "IANA time zone the days are counted in. Defaults to the business timezone."
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_slug": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
}
},
{
"name": "request_slot_alert",
"title": "Get an email if a slot opens on a full day",
"annotations": {
"readOnlyHint": false
},
"description": "When the day the user wants is full (next_available_slots or available_slots returned nothing for it), offer this: Reserrva emails them once if a cancellation frees a slot that day, with the free times and a booking link. Only call it after the user has given you their email and agreed. Pass business_slug, date (YYYY-MM-DD in the business timezone), service_id and staff_id when the user asked for one, and locale (es or en, the language you are speaking with them). The answer is the same whether they had already asked or not — confirm they will get one email if a slot opens. Past or out-of-range date or bad email: invalid_input. Too many alerts for one address today: rate_limited.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: invalid_input, business_not_found, staff_not_found, service_not_found, rate_limited.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_slug",
"date",
"email"
],
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 160
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language you are speaking with the user."
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Only this professional. Omit for anyone at the business."
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_slug": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
}
},
{
"name": "available_slots",
"title": "List one professional's free slots on a date",
"annotations": {
"readOnlyHint": true
},
"description": "Free slots for one professional and one service on a single date, honouring their schedule, their time off, the buffer after each appointment and the business's minimum notice and slot interval. Each row carries that professional's price_cents, duration_min and offer_fingerprint for the service. Use it when the user has already chosen the person and the day; use next_available_slots when they have not.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"staff_id",
"service_id",
"date"
],
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "book_appointment",
"title": "Book an appointment",
"annotations": {
"readOnlyHint": false
},
"description": "Book one slot for the signed-in Reserrva user. starts_at must be a slot_start returned by available_slots or next_available_slots for the same staff and service; anything else is rejected rather than rounded. The appointment snapshots the service name, price and duration at booking time, so later catalog edits never rewrite it. It comes back confirmed when the business auto-confirms and pending otherwise (see booking_policy.auto_confirm in get_business). The call is attributed to your OAuth client, and the business sees the appointment marked as booked via an agent. Confirm the business, professional, service, price and exact time with the user before calling: this creates a real commitment in someone's calendar.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, business_not_found, staff_not_found, service_not_found, service_requires_request, slot_unavailable, slot_taken, offer_changed, busy_refresh_required.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_id",
"staff_id",
"service_id",
"starts_at"
],
"properties": {
"notes": {
"type": "string",
"maxLength": 1000,
"description": "Free text the business will see."
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "A slot_start from available_slots or next_available_slots, unchanged."
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "my_appointments",
"title": "List the user's appointments",
"annotations": {
"readOnlyHint": true
},
"description": "The signed-in user's own appointments. scope is 'upcoming' (default: still to happen and not cancelled), 'past', or 'all'. Each row carries the business (name, city, address, timezone), the professional, the snapshotted service name and price_cents, the status, and cancellation_deadline — the instant after which cancel_appointment will refuse. Guest bookings made with book_as_guest are not here: they belong to a receipt, not to an account.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"scope": {
"enum": [
"upcoming",
"past",
"all"
],
"type": "string"
}
}
}
},
{
"name": "cancel_appointment",
"title": "Cancel an appointment",
"annotations": {
"readOnlyHint": false
},
"description": "Cancel one of the signed-in user's appointments and notify the business. Refused with too_late_to_cancel once the business's cancellation window has passed — my_appointments gives you cancellation_deadline, so check it and tell the user to phone the shop instead of retrying. reason is optional free text shown to the business.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, forbidden, too_late_to_cancel.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"appointment_id"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 300
},
"appointment_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "submit_booking_request",
"title": "Ask a studio for a quote",
"annotations": {
"readOnlyHint": false
},
"description": "Send a booking request for work that cannot be priced from the catalog — custom tattoos, and any service with requires_request = true or pricing_mode = 'quote'. Describe the piece in description; style, size_cm, body_placement, is_color and budget_cents (integer cents) are optional and help the artist quote. preferred_slots is a JSON array of ISO 8601 timestamps the user could attend. The studio answers with a price, a duration and, sometimes, a deposit; the user then picks a time with accept_booking_request. Reference images cannot be attached from here — point the user at the studio's page on reserrva.app for that.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, business_not_found, staff_not_found, service_not_found.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_id",
"description"
],
"properties": {
"style": {
"type": "string",
"maxLength": 120
},
"size_cm": {
"type": "string",
"maxLength": 40,
"description": "Free text, e.g. \"15x10\"."
},
"is_color": {
"type": "boolean"
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Ask for one artist. Omit to let the studio assign."
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"description": {
"type": "string",
"maxLength": 2000,
"minLength": 1,
"description": "What the user wants, in their own words."
},
"budget_cents": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Integer cents, never a decimal."
},
"body_placement": {
"type": "string",
"maxLength": 120
},
"preferred_slots": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"maxItems": 10,
"description": "Times the user could attend."
}
}
}
},
{
"name": "accept_booking_request",
"title": "Accept a quote and book it",
"annotations": {
"readOnlyHint": false
},
"description": "Accept a quote the studio sent for one of the user's booking requests and turn it into an appointment at starts_at. The quoted price and duration are what gets booked, so read them back to the user first. Refused with quote_expired past the quote's expiry and with request_not_acceptable when it has not been quoted yet or was already accepted. When the quote carries a deposit, the appointment stays pending until the user pays on reserrva.app — an agent cannot take money.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, forbidden, request_not_acceptable, quote_expired, slot_unavailable, slot_taken.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"request_id",
"starts_at"
],
"properties": {
"starts_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"request_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "book_as_guest",
"title": "Book without a Reserrva account",
"annotations": {
"readOnlyHint": false
},
"description": "Book a slot for someone who has no Reserrva account, exactly as the public booking page does: fixed-price services only, no online deposit, no quote services. Give business_slug, staff_id, service_id, a slot_start from available_slots or next_available_slots, the offer_fingerprint that came with the price you showed, the person's name and the contact the business asks for (get_business guest_contact): 'phone' (in person) a phone in E.164 form (+34600111222), 'email' (video calls) an email, 'both' both; the other one and notes are optional. Ask for them explicitly and repeat the business, service, price and time back before calling — this books a real chair. If the shop changed the price or duration since, the answer is offer_changed: read the slots again, show the new price and ask again — never retry with a fingerprint the user did not see. Generate booking_intent once per booking attempt (a random string) and send it again, with identical arguments, if a call fails or its answer is lost: the retry returns the same booking and the same receipt instead of a second booking. Omit it and one is generated and returned to you as booking_intent — keep it for the retry. The result contains a receipt: a secret that is the only way to see or cancel this booking afterwards (get_guest_booking, cancel_guest_booking). Show it to the user and tell them to keep it. Prefer book_appointment when the user is willing to sign in — that booking lives in their account.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: invalid_input, business_not_found, staff_not_found, service_not_found, service_requires_request, service_not_bookable_online, deposit_required, slot_unavailable, slot_taken, offer_changed, idempotency_conflict, receipt_invalid, too_many_bookings, rate_limited, busy_refresh_required.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_slug",
"staff_id",
"service_id",
"starts_at",
"offer_fingerprint",
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The person's name, as they want the shop to see it."
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 160,
"description": "Required when the business's guest_contact is 'email' or 'both' (video calls: the link and invitation go here)."
},
"notes": {
"type": "string",
"maxLength": 1000
},
"phone": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{6,14}$",
"description": "E.164. Required when the business's guest_contact is 'phone' (in person) or 'both'; optional for 'email'."
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "Language for the confirmation the shop sends. Defaults to es."
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "A slot_start from available_slots or next_available_slots, unchanged."
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_slug": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"booking_intent": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]+$",
"maxLength": 128,
"minLength": 16,
"description": "generate once per booking attempt and reuse on retry: a random string (letters, digits, - and _). Omit it and one is generated and returned."
},
"offer_fingerprint": {
"type": "string",
"pattern": "^[0-9a-f]{64}$",
"description": "the offer_fingerprint you showed the user for this service and professional; if the shop changed the price the booking is refused and you must show the new price"
}
}
}
},
{
"name": "get_guest_booking",
"title": "Look up a guest booking",
"annotations": {
"readOnlyHint": true
},
"description": "Read one guest booking back with the receipt returned by book_as_guest. Returns null for anything else — an unknown, expired or malformed receipt are deliberately indistinguishable, so do not guess and do not report a receipt as invalid in a way that helps someone probe. The receipt is the whole credential: never log it and never send it anywhere but back to the person who made the booking.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"receipt"
],
"properties": {
"receipt": {
"type": "string",
"maxLength": 128,
"minLength": 32
}
}
}
},
{
"name": "cancel_guest_booking",
"title": "Cancel a guest booking",
"annotations": {
"readOnlyHint": false
},
"description": "Cancel a guest booking with its receipt and notify the business. Subject to the same cancellation window as an account booking: past it the answer is too_late_to_cancel and the user has to phone the shop. reason is optional free text.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: receipt_invalid, too_late_to_cancel.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"receipt"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 300
},
"receipt": {
"type": "string",
"maxLength": 128,
"minLength": 32
}
}
}
},
{
"name": "business_booking_staff",
"title": "Read booking eligibility",
"annotations": {
"readOnlyHint": true
},
"description": "Business members only. Returns staff ids currently permitted to receive new bookings, including plan expiry and grace. Does not change configuration or existing appointments.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_id"
],
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "business_plan",
"title": "Read the effective plan",
"annotations": {
"readOnlyHint": true
},
"description": "Returns effective plan, billing authority, trial deadline, bookable seats, reservations and excess. Solo is free, Team permits two professionals, Business permits unlimited professionals.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, business_not_found, invalid_input, trial_unavailable, plan_choice_not_pending, invite_invalid.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "start_business_trial",
"title": "Start the optional Business trial",
"annotations": {
"readOnlyHint": false
},
"description": "Owner only. Explicit once-only local trial, no card and no Stripe subscription. Ask the owner before starting.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, business_not_found, invalid_input, trial_unavailable, plan_choice_not_pending, invite_invalid.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "end_business_trial",
"title": "End the local trial",
"annotations": {
"readOnlyHint": false
},
"description": "Owner only. End a local trial and continue on Solo. Never cancels a paid subscription or changes existing appointments.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, business_not_found, invalid_input, trial_unavailable, plan_choice_not_pending, invite_invalid.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "keep_bookable_staff",
"title": "Choose bookable professionals",
"annotations": {
"readOnlyHint": false
},
"description": "Owner only. When over capacity, choose the specified staff ids, including ids from pending invitations. During team grace, save the choice for the returned effective_at deadline; everyone eligible keeps booking until then. After grace, apply immediately. Existing appointments and history remain intact.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, business_not_found, invalid_input, trial_unavailable, plan_choice_not_pending, invite_invalid.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"keep"
],
"properties": {
"keep": {
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"minItems": 1
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "revoke_staff_invite",
"title": "Revoke a team invitation",
"annotations": {
"readOnlyHint": false
},
"description": "Atomically revoke a pending invitation and release its reserved seat.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, business_not_found, invalid_input, trial_unavailable, plan_choice_not_pending, invite_invalid.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"invite_id"
],
"properties": {
"invite_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "my_agenda",
"title": "Read the shop's agenda",
"annotations": {
"readOnlyHint": true
},
"description": "The agenda of the user's business, as the panel shows it: every appointment (status, service, price_cents, customer name and phone, professional, local_start/local_end in the business timezone) and every blocked range (time_off) between date and to_date inclusive (default: today; at most 31 days). staff_id narrows it to one professional. For a professional's own grant it is always their own column plus shop-wide blocks. Use it before moving, cancelling or blocking anything, and to answer \"¿qué tengo mañana?\".\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day. Defaults to today at the business."
},
"to_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day, inclusive. Defaults to date."
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "list_time_off",
"title": "List blocked time",
"annotations": {
"readOnlyHint": true
},
"description": "Every blocked range between date and to_date inclusive (default today, at most 31 days), for the whole shop or staff_id, with local_start/local_end in the business timezone, reason and series_id. Use its ids with unblock_time.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day. Defaults to today at the business."
},
"to_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day, inclusive. Defaults to date."
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "create_appointment",
"title": "Add an appointment by hand",
"annotations": {
"readOnlyHint": false
},
"description": "Create an appointment the business took itself (phone, walk-in, WhatsApp): staff_id, service_id (a fixed-price active service), starts_at and the customer's name; customer_id (from search_customers) books it for that existing client, otherwise phone (E.164) links it to the client with that number, ignoring formatting. It is confirmed at once and snapshots the service's current price and duration. Opening hours are not enforced (the shop may book outside them) but overlaps are: slot_taken when the professional already has something then.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_customer, staff_not_found, service_not_found, slot_taken.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"staff_id",
"service_id",
"starts_at",
"customer_name"
],
"properties": {
"phone": {
"type": "string",
"pattern": "^\\+[1-9][0-9]{6,14}$"
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"customer_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "An existing client from search_customers; the appointment is booked for them."
},
"customer_name": {
"type": "string",
"maxLength": 120,
"minLength": 1
}
}
}
},
{
"name": "update_appointment",
"title": "Move or reassign an appointment",
"annotations": {
"readOnlyHint": false
},
"description": "Move a pending or confirmed appointment to starts_at, and/or give it to staff_id (who must offer the service). The snapshotted service, price and duration never change. slot_taken when the new time overlaps something else; appointment_closed when it is already completed, cancelled or a no-show. The customer is not messaged by this tool: tell the user to let them know.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, appointment_closed, staff_not_found, service_not_found, slot_taken.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"appointment_id"
],
"properties": {
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"appointment_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "set_appointment_status",
"title": "Mark an appointment done, no-show or cancelled",
"annotations": {
"readOnlyHint": false
},
"description": "status = completed after the visit (it then counts as revenue in business_stats), no_show when the customer did not come, or cancelled (reason optional, ≤ 300 chars; a customer with an account is notified). completed and no_show only once the appointment has started: appointment_not_started before. status = confirmed takes a completed or no_show back on the business-local day it was set (undo_expired after; appointment_reviewed once the customer reviewed it). Automatic completions can be undone after midnight too; undo prevents another automatic completion until rescheduled. Open visits complete automatically after the reserved end (including cleanup buffer), except pending deposits. Otherwise only pending or confirmed appointments can change: appointment_closed.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, appointment_closed, appointment_not_started, undo_expired, appointment_reviewed, slot_taken.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"appointment_id",
"status"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 300,
"description": "Only for cancelled; shown to the customer."
},
"status": {
"enum": [
"completed",
"no_show",
"cancelled",
"confirmed"
],
"type": "string",
"description": "confirmed undoes a completed/no_show set today (business-local)."
},
"appointment_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "block_time",
"title": "Block time in the agenda",
"annotations": {
"readOnlyHint": false
},
"description": "Block starts_at–ends_at (at most 24 h; lunch, a late start, a closed afternoon) for staff_id, or for the whole shop when staff_id is omitted by an owner/admin. A professional's own grant always blocks their own column. weeks (1–8) repeats it on the same weekday at the same local time; reason is an optional label (≤ 60 chars, e.g. \"Comida\"). Online booking stops offering those times at once. Appointments already inside the range are kept and returned in conflicts — tell the user about them; never cancel them unless they ask.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, business_not_found, staff_not_found, invalid_range, range_too_long, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"starts_at",
"ends_at"
],
"properties": {
"weeks": {
"type": "integer",
"maximum": 8,
"minimum": 1,
"description": "Repeat on the same weekday and local time for this many weeks (1 = once)."
},
"reason": {
"type": "string",
"maxLength": 60,
"description": "Short label, e.g. \"Comida\"."
},
"ends_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit to block the whole shop (owner/admin). A professional's grant always blocks their own column."
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "unblock_time",
"title": "Remove blocked time",
"annotations": {
"readOnlyHint": false
},
"description": "Remove the block with time_off_id (from my_agenda or list_time_off). scope = series removes every week of a repeated block (same series_id); one (default) only that one. A professional removes only their own blocks.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"time_off_id"
],
"properties": {
"scope": {
"enum": [
"one",
"series"
],
"type": "string"
},
"time_off_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "list_staff",
"title": "List the team",
"annotations": {
"readOnlyHint": true
},
"description": "The team: id, display_name, is_active, is_bookable (shown on the booking page), has_account and role when they signed in, invite_pending, and schedule — their weekly hours as rows { weekday 0–6 (0 = Sunday), starts_at, ends_at } local to the business.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "upsert_staff",
"title": "Add or edit a professional",
"annotations": {
"readOnlyHint": false
},
"description": "Without staff_id: add a professional (display_name required) who starts on the shop's opening hours; they need no Reserrva account (use invite_staff to give them one). With staff_id: change only the fields you pass — display_name, is_bookable (offered on the booking page), is_active (false hides them everywhere), bio, instagram. max_staff_reached when the plan has no seat left. staff_invite_pending when making bookable someone invited who has not accepted yet: they become bookable when they accept the invitation.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, staff_not_found, max_staff_reached, staff_invite_pending.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"bio": {
"anyOf": [
{
"type": "string",
"maxLength": 1000
},
{
"type": "null"
}
]
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit to add a new professional."
},
"instagram": {
"anyOf": [
{
"type": "string",
"maxLength": 100
},
{
"type": "null"
}
]
},
"is_active": {
"type": "boolean"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"is_bookable": {
"type": "boolean"
},
"display_name": {
"type": "string",
"maxLength": 80,
"minLength": 1
}
}
}
},
{
"name": "set_staff_schedule",
"title": "Set a professional's weekly hours",
"annotations": {
"readOnlyHint": false
},
"description": "Replace staff_id's whole week with rows [{ weekday 0–6 (0 = Sunday), starts_at \"HH:MM\", ends_at \"HH:MM\" }], local to the business; up to two ranges a day (split shift), no overlaps. A day with no row is a day off; an empty list means no hours at all. For one-off absences use block_time instead.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, staff_not_found, hours_overlap.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"staff_id",
"rows"
],
"properties": {
"rows": {
"type": "array",
"items": {
"type": "object",
"required": [
"weekday",
"starts_at",
"ends_at"
],
"properties": {
"ends_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"weekday": {
"type": "integer",
"maximum": 6,
"minimum": 0,
"description": "0 = Sunday … 6 = Saturday"
},
"starts_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
}
}
},
"maxItems": 14
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "invite_staff",
"title": "Invite someone to the team",
"annotations": {
"readOnlyHint": false
},
"description": "Invite email to join the business as staff (default) or admin; is_bookable (default true) says whether they take bookings. Returns invite_url, a private link valid until expires_at — give it to the user to send (this tool sends no email). Inviting an owner is done in the panel, not by an agent. invite_already_member when that address is already on the team.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, invite_invalid, invite_already_member, max_staff_reached.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"email"
],
"properties": {
"role": {
"enum": [
"staff",
"admin"
],
"type": "string"
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 254
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "Language of the invitation page. Defaults to es."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"is_bookable": {
"type": "boolean"
}
}
}
},
{
"name": "list_services",
"title": "List the service catalog",
"annotations": {
"readOnlyHint": true
},
"description": "The catalog as the panel sees it, inactive services included: id, name, pricing_mode (fixed, from = \"desde\", quote = priced per request), price_cents, duration_min, buffer_after_min (cleanup time after), requires_request, deposit_cents, is_active and category.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "upsert_service",
"title": "Add or edit a service",
"annotations": {
"readOnlyHint": false
},
"description": "Without service_id: create a service (name and duration_min required; pricing_mode defaults to fixed, which needs price_cents). With service_id: change only the fields you pass. price_cents is integer minor units of the business currency (1500 = 15,00 €); pricing_mode quote needs no price and may set requires_request and deposit_cents (deposits need online payments on the business's plan: feature_locked otherwise). category is a name (created if new; null clears it). Past appointments keep the price they were booked at.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, service_not_found, feature_locked.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"category": {
"anyOf": [
{
"type": "string",
"maxLength": 80
},
{
"type": "null"
}
]
},
"is_active": {
"type": "boolean"
},
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit to create a new service."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 1000
},
{
"type": "null"
}
]
},
"price_cents": {
"anyOf": [
{
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Integer minor units of the business currency."
},
"duration_min": {
"type": "integer",
"maximum": 720,
"minimum": 1
},
"pricing_mode": {
"enum": [
"fixed",
"from",
"quote"
],
"type": "string"
},
"deposit_cents": {
"anyOf": [
{
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
{
"type": "null"
}
]
},
"buffer_after_min": {
"type": "integer",
"maximum": 120,
"minimum": 0
},
"requires_request": {
"type": "boolean"
}
}
}
},
{
"name": "remove_service",
"title": "Remove a service",
"annotations": {
"readOnlyHint": false
},
"description": "Remove service_id from the catalog. When it still has upcoming bookings it is deactivated instead (deactivated: true): those appointments stay, nobody can book it again. service_busy means a booking is being made right now: try again.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, service_not_found, service_busy.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"service_id"
],
"properties": {
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "close_business",
"title": "Close the business",
"annotations": {
"readOnlyHint": false
},
"description": "Permanently stop new bookings for this business while retaining appointments, customers, membership and billing history. Only its owner can close it. Requires explicit user confirmation (confirm=true), no pending or ongoing appointments, no unresolved requests, and no live billing or unsettled payments. This does not cancel subscriptions or refund payments; resolve those first. Closure cannot be undone with resume_public_page.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, business_not_found, business_has_upcoming_appointments, business_has_open_requests, business_has_upcoming_reservations, business_has_active_billing, business_has_pending_payments, retry_transaction.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"confirm"
],
"properties": {
"confirm": {
"type": "boolean",
"const": true
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "get_business_settings",
"title": "Read the business settings",
"annotations": {
"readOnlyHint": true
},
"description": "Everything on the Ajustes page: name, slug, status (active = public page on, paused = off), phone, whatsapp, instagram, description, service_mode (venue or mobile), address, city, timezone, currency, show_prices, phone_public, explore_opt_in (listed in Explore and in search_businesses/nearby_businesses once the shop has a bookable professional with an active service), the booking policy (slot_interval_min, min_notice_min, max_advance_days, cancellation_window_min) and hours [{ weekday, opens_at, closes_at }].\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "update_business",
"title": "Change the business settings",
"annotations": {
"readOnlyHint": false
},
"description": "Apply patch, an object with only the keys to change: name, phone, phone_public (false hides the phone from the public page, receipts and listings), whatsapp, instagram, description, show_prices, explore_opt_in, slot_interval_min, min_notice_min, max_advance_days, cancellation_window_min, slug (changes the public link; the old one redirects), service_mode, address, area, city, venue, notifications. Every value is re-checked: invalid_input names no field, so change one thing at a time when unsure. slug_taken when another business has that link.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, slug_taken.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"patch"
],
"properties": {
"patch": {
"type": "object",
"description": "Only the keys to change; see the description.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "set_business_hours",
"title": "Set the opening hours",
"annotations": {
"readOnlyHint": false
},
"description": "Replace the week with rows [{ weekday 0–6 (0 = Sunday), opens_at \"HH:MM\", closes_at \"HH:MM\" }] local to the business; up to two ranges a day, on the booking grid (slot_interval_min). A day with no row is closed. Professionals whose hours were exactly the old week follow the new one (staff_following); the rest keep theirs. To set one day, read get_business_settings first and send the whole week back with that day changed.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input, hours_empty, hours_overlap, hours_off_grid.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rows"
],
"properties": {
"rows": {
"type": "array",
"items": {
"type": "object",
"required": [
"weekday",
"opens_at",
"closes_at"
],
"properties": {
"weekday": {
"type": "integer",
"maximum": 6,
"minimum": 0,
"description": "0 = Sunday … 6 = Saturday"
},
"opens_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"closes_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
}
}
},
"maxItems": 14,
"minItems": 1
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "pause_public_page",
"title": "Pause online booking",
"annotations": {
"readOnlyHint": false
},
"description": "Set the business to paused: its public page and every agent stop offering it, existing appointments are untouched. Undo with resume_public_page.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "resume_public_page",
"title": "Resume online booking",
"annotations": {
"readOnlyHint": false
},
"description": "Set a paused business back to active, so customers and agents can book it again.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "list_requests",
"title": "List quote requests (studios)",
"annotations": {
"readOnlyHint": true
},
"description": "Booking requests customers sent (tattoo ideas and quote-only services), newest first. tab: new (waiting for a quote, default), quoted (quote sent and not expired), accepted (the customer said yes, or it became an appointment), closed (declined, expired, cancelled). Each has the description, style, size_cm, body_placement, is_color, budget_cents, preferred_slots, how many reference images were attached, and the quote once sent.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"tab": {
"enum": [
"new",
"quoted",
"accepted",
"closed"
],
"type": "string"
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "quote_request",
"title": "Send a quote",
"annotations": {
"readOnlyHint": false
},
"description": "Quote request_id: price_cents and duration_min (whole minutes), deposit_cents (≤ price, default 0; needs online payments on the plan), an optional note, the artist (staff_id) and expires_at, when the quote stops being valid (default: 7 days from now). The customer is notified in the app and accepts it themselves; the panel also emails them, this tool does not.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, request_not_quotable, invalid_quote, staff_not_found, feature_locked.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"request_id",
"price_cents",
"duration_min"
],
"properties": {
"note": {
"type": "string",
"maxLength": 300
},
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"expires_at": {
"type": "string",
"minLength": 1,
"description": "When the quote stops being valid. Defaults to 7 days from now."
},
"request_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"price_cents": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
"duration_min": {
"type": "integer",
"maximum": 720,
"minimum": 1
},
"deposit_cents": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
}
}
}
},
{
"name": "accept_request",
"title": "Book an accepted request",
"annotations": {
"readOnlyHint": false
},
"description": "Schedule request_id at starts_at with the assigned artist (or staff_id). Works on a request the customer accepted, or a pending one with a fixed price. starts_at must be free for that artist and the quoted duration: slot_unavailable otherwise — read my_agenda first.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, forbidden, request_not_acceptable, quote_expired, business_not_found, staff_not_found, slot_unavailable, slot_taken.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"request_id",
"starts_at"
],
"properties": {
"staff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"request_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "decline_request",
"title": "Decline a request",
"annotations": {
"readOnlyHint": false
},
"description": "Decline request_id (reason optional, ≤ 300 chars, shown to the customer). request_closed when it was already closed.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, request_closed, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"request_id"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 300
},
"request_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "search_customers",
"title": "Search the client list",
"annotations": {
"readOnlyHint": true
},
"description": "Search the client list (query matches name, phone or email; omit it for everyone), most recent visit first, limit ≤ 100 with offset for the next page. Each row has total_appointments, no_show_count, last_visit_at and the private notes. This is personal data: only read it out for the business's own purposes.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"query": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "customer_history",
"title": "A client's history",
"annotations": {
"readOnlyHint": true
},
"description": "customer_id's contact, notes, counts and their latest appointments (limit ≤ 100), newest first, with service, price_cents, status and professional.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"customer_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"customer_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "set_customer_notes",
"title": "Write a client's private notes",
"annotations": {
"readOnlyHint": false
},
"description": "Replace customer_id's private notes (≤ 2000 chars; empty clears them). The client never sees them. Read customer_history first so nothing is lost.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"customer_id",
"notes"
],
"properties": {
"notes": {
"type": "string",
"maxLength": 2000
},
"customer_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "business_stats",
"title": "Business numbers",
"annotations": {
"readOnlyHint": true
},
"description": "The Estadísticas page for from–to (dates in the business timezone, default today; at most the range the RPC allows): summary (appointments, completed, revenue_cents from completed ones, no_shows and what they cost, cancelled, unmarked_past), per professional, busiest hours, booking sources, new vs returning and at-risk clients, requests for studios, and series — one row per day with revenue_cents, completed, booked, cancelled, no_shows. Revenue counts completed appointments only: suggest set_appointment_status for unmarked_past ones.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"to": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Inclusive. Defaults to from."
},
"from": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Defaults to today at the business."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "get_restaurant",
"title": "Look at a restaurant",
"annotations": {
"readOnlyHint": true
},
"description": "The public reservation profile of a restaurant by slug: timezone, phone and whatsapp (for groups above online_max_party), online_max_party, min_notice_min, max_advance_days, cancellation_window_min, response_deadline_min (how long the restaurant has to answer), arrival_interval_min, seating_duration_min and the areas guests can choose (id, name, max_party). null when the slug is not a restaurant taking online requests. Area names are the restaurant's own words: never translate them.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The restaurant's slug."
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language you are speaking with the user, for the summary. Defaults to es."
}
}
}
},
{
"name": "restaurant_availability",
"title": "Find a time at a restaurant",
"annotations": {
"readOnlyHint": true
},
"description": "Arrival times of one service date (YYYY-MM-DD in the restaurant's timezone) for party_size guests: each slot has starts_at, available and area_ids (the areas that seat the whole party then). Pass area_id for one area; omit it for \"no preference\" (any single area that fits the whole party: spare tables are never added up across areas). A service may run past midnight: its late slots belong to the date asked for. Availability is advisory: the restaurant still accepts or declines each request.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: invalid_input, party_too_large, area_not_found.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_slug",
"date",
"party_size"
],
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "The service date, YYYY-MM-DD in the restaurant's timezone."
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language you are speaking with the user, for the summary. Defaults to es."
},
"area_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "One area from get_restaurant. Omit for no preference."
},
"party_size": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"business_slug": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
}
}
},
{
"name": "request_reservation",
"title": "Request a restaurant reservation",
"annotations": {
"readOnlyHint": false
},
"description": "Sends a reservation request for the signed-in user: business_slug, party_size, starts_at (a starts_at from restaurant_availability, unchanged), area_id (null or omitted = no preference), the name and E.164 phone the restaurant will see, optional notes and locale. The answer is the request with status pending: nothing is held until the restaurant accepts, and it expires at respond_by if they do not answer. Say exactly that; never call it confirmed. Read the restaurant, party, date, time (with the timezone) and area back to the user first. booking_intent is required: generate a random string once, before the first call, keep it, and send the same one on every retry (including after a lost or failed answer): the same request comes back instead of a second one.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, invalid_input, business_not_found, party_too_large, area_not_found, area_closed, outside_hours, slot_unavailable, tables_unavailable, pacing_full, rate_limited, too_many_bookings, idempotency_conflict, receipt_invalid, retry_transaction.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"business_slug",
"party_size",
"starts_at",
"name",
"phone",
"booking_intent"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The name the restaurant will see."
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 160
},
"notes": {
"type": "string",
"maxLength": 1000,
"description": "Free text for the restaurant (e.g. a high chair)."
},
"phone": {
"type": "string",
"pattern": "^\\+[1-9]\\d{6,14}$"
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language the restaurant should use with the guest. Defaults to es."
},
"area_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
],
"description": "The area the user chose; null or omitted = no preference."
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "A starts_at from restaurant_availability, unchanged."
},
"party_size": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"business_slug": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"booking_intent": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]+$",
"maxLength": 128,
"minLength": 16,
"description": "required: a random string (letters, digits, - and _) you generate once before the first call and keep; send the same one on every retry."
}
}
}
},
{
"name": "my_reservations",
"title": "The user's restaurant reservations",
"annotations": {
"readOnlyHint": true
},
"description": "The signed-in user's own reservation requests and reservations, oldest first: status (pending, confirmed, declined, expired, cancelled), party_size, starts_at, service_date, area, respond_by while pending, cancellable and cancellable_until, and the restaurant's name, phone and timezone. scope: upcoming (default), past or all.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"scope": {
"enum": [
"upcoming",
"past",
"all"
],
"type": "string"
}
}
}
},
{
"name": "cancel_my_reservation",
"title": "Cancel the user's restaurant reservation",
"annotations": {
"readOnlyHint": false
},
"description": "Cancels one of the user's own reservations: a pending request at any time before its deadline, a confirmed reservation until cancellation_window_min before arrival. Later than that the answer is too_late_to_cancel: the user has to call the restaurant. Confirm with the user first.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, reservation_not_found, too_late_to_cancel, reservation_closed, retry_transaction.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 300
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "list_reservations",
"title": "Read the restaurant's reservations",
"annotations": {
"readOnlyHint": true
},
"description": "Reservations of service dates from–to (YYYY-MM-DD in the restaurant's timezone, at most 31 days; to defaults to from), every status. Each row: id, status (pending past its deadline reads expired; a confirmed one whose time is over reads completed: attendance is automatic), attendance (not_arrived, seated, departed = left early, no_show), source, party_size, tables_needed and table_use (the tables of each size it uses, [{seats, count}]), area_id, requested_area_id (the guest's binding choice, null = no preference), starts_at, ends_at, seating_duration_min, hold_to (when its tables free: the planned or extended end), service_date, contact name/phone, guest notes, private_note, expires_at, and flags: at_risk (a later party whose tables an extension or an undone no-show is holding), extended, no_show_allowed, in_hours, open_tasks. areas lists each area's tables. Personal data: use it for the restaurant only.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First service date. Defaults to today at the restaurant."
},
"to_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last service date, inclusive. Defaults to date."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "get_restaurant_setup",
"title": "Read the restaurant's setup",
"annotations": {
"readOnlyHint": true
},
"description": "Everything that shapes availability: settings (default seating duration, arrival interval, last arrival, online maximum party, notice, booking window, cancellation window, response deadline, no-show grace, receipt retention), areas (tables as rows of seats × count, one or several sizes, with capacity: tables, seats, largest party; joining_rule keeps_seats or loses_two, max_join, setup_min, arrival_pacing_guests, online, status), weekly hours (a window may close the next day and may set its own seating_duration_min, the meal length of that service) and special days.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "accept_reservation_request",
"title": "Accept a reservation request",
"annotations": {
"readOnlyHint": false
},
"description": "Accepts a pending request (reservation_id from list_reservations). A guest who chose an area keeps it (area_binding if you name another); a no-preference request needs area_id (area_required). Refused when the tables or the arrival pacing no longer fit or the deadline passed (request_expired). The guest is not messaged by Reserrva: a contact task opens in the panel.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, area_not_found, area_closed, party_too_large, tables_unavailable, pacing_full, business_closed, business_not_found, reservation_not_found, reservation_closed, request_expired, area_required, area_binding, outside_hours, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"area_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Required for a no-preference request; a guest-chosen area cannot be changed."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "decline_reservation_request",
"title": "Decline a reservation request",
"annotations": {
"readOnlyHint": false
},
"description": "Declines a pending request. Terminal: a declined request cannot be accepted later. Confirm with the user first.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, reservation_closed, request_expired, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "create_manual_reservation",
"title": "Add a phone booking or walk-in",
"annotations": {
"readOnlyHint": false
},
"description": "Adds a confirmed reservation: area_id, party_size, starts_at, source (phone, walk_in or other), contact_name (optional for a walk-in), optional contact_phone, contact_email, notes, private_note, locale, and seated: true to mark a walk-in at the table. The meal length is that service's (else the restaurant default); the tables free themselves at its end. Capacity, join limit and pacing are checked like any request; a time outside service hours is allowed and comes back with warnings: [\"outside_hours\"].\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, area_not_found, area_closed, party_too_large, tables_unavailable, pacing_full, business_closed, business_not_found, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"area_id",
"party_size",
"starts_at",
"source"
],
"properties": {
"notes": {
"type": "string",
"maxLength": 1000
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string"
},
"seated": {
"type": "boolean",
"description": "A walk-in sitting down now."
},
"source": {
"enum": [
"phone",
"walk_in",
"other"
],
"type": "string"
},
"area_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"party_size": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"contact_name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Required except for a walk-in."
},
"private_note": {
"type": "string",
"maxLength": 2000
},
"contact_email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 160
},
"contact_phone": {
"type": "string",
"pattern": "^\\+[1-9]\\d{6,14}$"
}
}
}
},
{
"name": "update_reservation",
"title": "Move or resize a reservation",
"annotations": {
"readOnlyHint": false
},
"description": "Moves a confirmed, not-yet-seated reservation (starts_at, area_id; a new time takes that service's meal length) or changes its party_size, re-checked against capacity and pacing with its old place released. A guest with a phone gets a contact task. Refused for arrived parties (attendance_invalid).\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, area_not_found, area_closed, party_too_large, tables_unavailable, pacing_full, business_closed, business_not_found, reservation_not_found, reservation_closed, attendance_invalid, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"area_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"minLength": 1,
"description": "ISO 8601 with an explicit UTC offset, e.g. 2026-09-23T11:00:00+02:00"
},
"party_size": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "extend_reservation",
"title": "A party is still at the table",
"annotations": {
"readOnlyHint": false
},
"description": "Tables free themselves at the planned end with nothing recorded. When a party is still there, pass until (later than the planned end and than now). It is recorded even when it overlaps later bookings: at_risk lists them (each with a phone gets a contact task), conflict says whether the tables are short, and new bookings that would worsen it are refused. The same until again is a no-op (safe to retry); an earlier one than the current end is refused with extension_shortening.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, reservation_closed, attendance_invalid, invalid_input, extension_shortening.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id",
"until"
],
"properties": {
"until": {
"type": "string",
"minLength": 1,
"description": "The new end: later than the planned end and than now."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "record_reservation_departure",
"title": "A party left early",
"annotations": {
"readOnlyHint": false
},
"description": "at is when they left (default now, never in the future, after arrival, before the end). The tables are free from then.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, reservation_closed, attendance_invalid, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"at": {
"type": "string",
"minLength": 1,
"description": "When they left. Defaults to now."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "record_reservation_no_show",
"title": "Record a no-show",
"annotations": {
"readOnlyHint": false
},
"description": "Only from no_show_grace_min after the planned arrival and before the planned end (no_show_too_early before). Undo with undo_reservation_no_show.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, reservation_closed, attendance_invalid, no_show_too_early.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "undo_reservation_no_show",
"title": "Undo a no-show",
"annotations": {
"readOnlyHint": false
},
"description": "Re-admits the planned hold. A conflict with bookings made meanwhile is recorded: at_risk lists them, with contact tasks.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, reservation_closed, attendance_invalid.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "set_reservation_seated",
"title": "Mark a party at the table",
"annotations": {
"readOnlyHint": false
},
"description": "Optional: capacity never depends on it. A seated party can no longer be cancelled; it ends at its time, or by left early.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, reservation_closed, attendance_invalid, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id",
"seated"
],
"properties": {
"seated": {
"type": "boolean",
"description": "false removes the marker."
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "cancel_reservation",
"title": "Cancel a reservation for the restaurant",
"annotations": {
"readOnlyHint": false
},
"description": "Cancels a confirmed reservation before the party is at the table and before it has completed (a seated party ends at its time, or with record_reservation_departure). reason is optional free text for the restaurant's records. The guest is not messaged by Reserrva: a contact task opens. Confirm with the user first.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, reservation_closed, attendance_invalid, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 300
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "set_reservation_private_note",
"title": "Write a reservation's private note",
"annotations": {
"readOnlyHint": false
},
"description": "Replaces the private note (empty clears it). The guest never sees it. Read list_reservations first so nothing is lost.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, reservation_not_found, invalid_input.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"reservation_id",
"note"
],
"properties": {
"note": {
"type": "string",
"maxLength": 2000
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
}
}
},
{
"name": "list_reservation_contact_tasks",
"title": "Read the guests to contact",
"annotations": {
"readOnlyHint": true
},
"description": "Contact tasks (open ones by default; open_only: false for all): kind (accepted, declined, expired, cancelled, changed, at_risk), structured data, the reservation and its contact. Reserrva sends no message: someone at the restaurant contacts the guest and marks the task done in the panel (agents cannot).\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"open_only": {
"type": "boolean"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "update_restaurant_settings",
"title": "Change restaurant settings",
"annotations": {
"readOnlyHint": false
},
"description": "Changes any of: seating_duration_min (the default meal length; a service window may set its own), arrival_interval_min, last_arrival (HH:MM), online_max_party, min_notice_min, max_advance_days, cancellation_window_min, response_deadline_min, no_show_grace_min, receipt_ttl_days, receipt_links_max. Existing reservations keep their own terms. A change that would push a confirmed arrival out of hours is refused with reservations_affected and the ids: move or cancel those first.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, invalid_input, reservations_affected.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"changes"
],
"properties": {
"changes": {
"type": "object",
"properties": {
"last_arrival": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"min_notice_min": {
"type": "integer",
"maximum": 10080,
"minimum": 0
},
"max_advance_days": {
"type": "integer",
"maximum": 365,
"minimum": 1
},
"online_max_party": {
"type": "integer",
"maximum": 50,
"minimum": 1
},
"receipt_ttl_days": {
"type": "integer",
"maximum": 365,
"minimum": 1
},
"no_show_grace_min": {
"type": "integer",
"maximum": 240,
"minimum": 0
},
"receipt_links_max": {
"type": "integer",
"maximum": 10,
"minimum": 1
},
"arrival_interval_min": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991
},
"seating_duration_min": {
"type": "integer",
"maximum": 480,
"minimum": 15
},
"response_deadline_min": {
"type": "integer",
"maximum": 10080,
"minimum": 5
},
"cancellation_window_min": {
"type": "integer",
"maximum": 10080,
"minimum": 0
}
},
"description": "Only the settings to change.",
"additionalProperties": false
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "upsert_restaurant_area",
"title": "Create or edit an area",
"annotations": {
"readOnlyHint": false
},
"description": "id (omit to create), name (the restaurant's own words), tables: 1 to 6 rows {seats, count}, each size once (e.g. a terrace with 2×2, 4×4 and 1×6), joining_rule (loses_two: each join loses two seats, so a 4 and a 6 joined seat 8, 4/6/8 at 4-seat tables, a 2-seat table is only used alone; keeps_seats: seats add up, 4/8/12), max_join (most tables in one group, any sizes; default: all tables), setup_min (preparation before a joined party), arrival_pacing_guests (guests per arrival interval, null = none), online, sort_order. The answer's capacity gives tables, seats and the largest party. A change that would no longer fit a current or future reservation is refused with reservations_affected and the ids; more than 6 sizes is table_sizes_unsupported.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, invalid_input, area_not_found, area_name_taken, table_sizes_unsupported, reservations_affected.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"area"
],
"properties": {
"area": {
"type": "object",
"required": [
"name",
"tables"
],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"online": {
"type": "boolean"
},
"tables": {
"type": "array",
"items": {
"type": "object",
"required": [
"seats",
"count"
],
"properties": {
"count": {
"type": "integer",
"maximum": 500,
"minimum": 1
},
"seats": {
"type": "integer",
"maximum": 30,
"minimum": 1
}
},
"additionalProperties": false
},
"maxItems": 6,
"minItems": 1
},
"max_join": {
"type": "integer",
"maximum": 500,
"minimum": 1
},
"setup_min": {
"type": "integer",
"maximum": 120,
"minimum": 0
},
"sort_order": {
"type": "integer",
"maximum": 1000,
"minimum": 0
},
"joining_rule": {
"enum": [
"keeps_seats",
"loses_two"
],
"type": "string"
},
"arrival_pacing_guests": {
"anyOf": [
{
"type": "integer",
"maximum": 500,
"minimum": 1
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "set_restaurant_area_status",
"title": "Close, reopen or retire an area",
"annotations": {
"readOnlyHint": false
},
"description": "status open, closed or retired. Closing or retiring is refused with reservations_affected while reservations hold its tables now or later.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, invalid_input, area_not_found, reservations_affected.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"area_id",
"status"
],
"properties": {
"status": {
"enum": [
"open",
"closed",
"retired"
],
"type": "string"
},
"area_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "set_restaurant_hours",
"title": "Set the weekly service hours",
"annotations": {
"readOnlyHint": false
},
"description": "rows: [{weekday 0–6 (0 = Sunday), opens_at, closes_at (HH:MM), closes_next_day (closing after midnight), last_arrival, seating_duration_min (this service's meal length; omit for the restaurant default)}] replaces the whole week. Windows of a day may not overlap. Refused with reservations_affected when a confirmed arrival would fall outside the new hours.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, invalid_input, hours_overlap, reservations_affected.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rows"
],
"properties": {
"rows": {
"type": "array",
"items": {
"type": "object",
"required": [
"weekday",
"opens_at",
"closes_at"
],
"properties": {
"weekday": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"opens_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"closes_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"last_arrival": {
"anyOf": [
{
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
{
"type": "null"
}
]
},
"closes_next_day": {
"type": "boolean"
},
"seating_duration_min": {
"anyOf": [
{
"type": "integer",
"maximum": 480,
"minimum": 15
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "set_restaurant_special_day",
"title": "Set a special day",
"annotations": {
"readOnlyHint": false
},
"description": "date (YYYY-MM-DD, today or later) and windows: null removes the exception, [] closes the day, otherwise up to three windows like set_restaurant_hours without weekday. Refused with reservations_affected when a confirmed arrival would fall outside.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, invalid_input, hours_overlap, reservations_affected.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"date",
"windows"
],
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"windows": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"opens_at",
"closes_at"
],
"properties": {
"opens_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"closes_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"last_arrival": {
"anyOf": [
{
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
{
"type": "null"
}
]
},
"closes_next_day": {
"type": "boolean"
},
"seating_duration_min": {
"anyOf": [
{
"type": "integer",
"maximum": 480,
"minimum": 15
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"maxItems": 3
},
{
"type": "null"
}
]
},
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "create_business",
"title": "Create the user's business",
"annotations": {
"readOnlyHint": false
},
"description": "Creates the signed-in user's business; one per account (calling again returns the first one with created: false). Ask the user for every value, never invent one, and read them back before calling. A restaurant (profession restaurant): name, country_code (ISO alpha-2), phone (E.164, the number that takes reservations), whatsapp (E.164 or null; usually the same number), phone_public (false = the phone is not shown on the page), address (street and number), optional city, locale (es or en). It starts as a private draft. Then, in separate calls: set_restaurant_hours (the meals and arrival times), upsert_restaurant_area (each area with the tables the user describes; there are no default tables), optionally update_restaurant_settings and set_restaurant_special_day, then get_restaurant_readiness, and publish_restaurant once the user agrees. Any other profession (barber, tattoo_artist, hairdresser, beauty_salon, nails, doctor, dentist, psychologist, physiotherapist, consultant, software_engineer, coach, photographer, other): name, country_code, phone and/or email (the profession decides which is required), service_mode (venue with address, mobile with area.city, remote with neither), hours (weekly rows: weekday 0 = Sunday, opens_at, closes_at), staff_name and bookable (the user as a professional), services (name, duration_min, pricing_mode and price_cents: fixed = a set price in cents, 0 = free, the default; from = a starting price, shown as \"from\" and arranged with the business, not booked online; quote = no price, the customer asks and the business replies with one, omit price_cents), locale; it is public at once. A quote service needs the Business trial: send trial true only when the user agrees to start it (no card), otherwise the answer is feature_locked; ask whether to start the trial or to give those services a price. Teammates are invited afterwards (invite_staff). The answer carries business_id and slug.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, forbidden, agent_not_allowed, invalid_input, phone_required, email_required, already_member, hours_overlap, hours_empty, hours_off_grid, max_staff_reached, slug_unavailable, trial_unavailable, feature_locked.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"profession",
"name",
"country_code",
"locale"
],
"properties": {
"area": {
"type": "object",
"required": [
"city",
"lat",
"lng"
],
"properties": {
"lat": {
"type": [
"number",
"null"
]
},
"lng": {
"type": [
"number",
"null"
]
},
"city": {
"type": "string",
"maxLength": 120,
"minLength": 1
}
},
"description": "Mobile professionals: the city they cover."
},
"city": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 2,
"description": "The business name, as the user says it."
},
"email": {
"anyOf": [
{
"type": "string",
"maxLength": 254
},
{
"type": "null"
}
],
"description": "Contact email (required for remote professions)."
},
"hours": {
"type": "array",
"items": {
"type": "object",
"required": [
"weekday",
"opens_at",
"closes_at"
],
"properties": {
"weekday": {
"type": "integer",
"maximum": 6,
"minimum": 0,
"description": "0 = Sunday … 6 = Saturday"
},
"opens_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
},
"closes_at": {
"type": "string",
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
}
}
},
"description": "Not for restaurants (use set_restaurant_hours)."
},
"phone": {
"type": [
"string",
"null"
],
"description": "E.164. Restaurants: the number that takes reservations (required)."
},
"trial": {
"type": "boolean",
"description": "Start the Business trial (no card). Only when the user asks for it; required for quote services."
},
"locale": {
"enum": [
"es",
"en"
],
"type": "string",
"description": "The language the user speaks with you: the business's notices and summaries use it."
},
"address": {
"type": "string",
"maxLength": 300,
"description": "Street and number (venue)."
},
"bookable": {
"type": "boolean",
"description": "Not for restaurants: whether the user takes appointments themself."
},
"services": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"duration_min"
],
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"price_cents": {
"anyOf": [
{
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Required for fixed and from; omit (or null) for quote."
},
"duration_min": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1
},
"pricing_mode": {
"enum": [
"fixed",
"from",
"quote"
],
"type": "string",
"description": "fixed (default): a set price, 0 = free. from: a starting price, not booked online. quote: no price; the customer asks for one (needs trial true)."
}
}
},
"description": "Not for restaurants."
},
"timezone": {
"type": "string",
"maxLength": 64,
"description": "IANA zone; defaults to the country's."
},
"whatsapp": {
"type": [
"string",
"null"
],
"description": "Restaurants: E.164 WhatsApp number, usually the same as phone; null when there is none."
},
"profession": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "A catalogue id: restaurant, barber, tattoo_artist, hairdresser, beauty_salon, nails, doctor, dentist, psychologist, physiotherapist, consultant, software_engineer, coach, photographer or other."
},
"staff_name": {
"type": "string",
"maxLength": 80,
"description": "Not for restaurants."
},
"country_code": {
"type": "string",
"pattern": "^[A-Za-z]{2}$",
"description": "ISO 3166-1 alpha-2, e.g. ES"
},
"phone_public": {
"type": "boolean",
"description": "Restaurants: show the phone on the public page (default false)."
},
"service_mode": {
"enum": [
"venue",
"mobile",
"remote"
],
"type": "string",
"description": "Not for restaurants (always venue)."
},
"explore_opt_in": {
"type": "boolean",
"description": "Not for restaurants: list the business in Reserrva's Explore."
}
}
}
},
{
"name": "get_restaurant_readiness",
"title": "Check what a new restaurant still needs",
"annotations": {
"readOnlyHint": true
},
"description": "A restaurant created with create_business is a draft: no public page and no online requests until publish_restaurant. Answers status (draft, active, paused), published, admits_online, ready and missing — service_hours (call set_restaurant_hours) and online_area (call upsert_restaurant_area with its tables and online true). Call it before publish_restaurant and tell the user what is left in plain words. On a published restaurant a missing item is a setup gap, not proof that nothing can be booked (special days still offer their own times): use restaurant_availability to know what guests see.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
},
{
"name": "publish_restaurant",
"title": "Publish a restaurant",
"annotations": {
"readOnlyHint": false
},
"description": "Publishes a draft restaurant once it has weekly service hours and an open online area with tables; refused with restaurant_not_ready otherwise (get_restaurant_readiness says what is missing). Already published: answers the current checklist and changes nothing. Afterwards guests book on the restaurant's page and every request waits for the restaurant to accept it. Confirm with the user before publishing: their page becomes public.\n\nOn failure the tool returns isError with one of these stable codes; show the user what it means, never the raw code: not_authenticated, agent_not_allowed, forbidden, booking_mode_mismatch, retry_transaction, restaurant_not_ready, business_closed.\n\nUnits: money is an integer number of cents in the business currency (ISO 4217, from the business profile) — never a decimal. Timestamps are ISO 8601 with an explicit UTC offset (e.g. 2026-09-23T11:00:00+02:00). Dates are YYYY-MM-DD in the business timezone (IANA name, from the business profile); opening hours and slots are local to that timezone, so always show the user a time together with the business timezone when it differs from theirs. Durations are whole minutes. Ids are UUIDs.\n\nOwner tool: it acts on a business the signed-in user owns or runs, and needs their business:manage permission for this app. business_id is optional when the user has granted exactly one business; otherwise pass one from the error message. Read back what you are about to change (who, what, when, how much) before any write: this is someone's real shop.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"business_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Omit when the user manages exactly one business."
}
}
}
}
]Get your MCP into directories
A working endpoint is step one. Directory coverage is the coordinated launch across ChatGPT, Claude, Cursor, the MCP Registry, and community indexes.
Directory coverage for brandsOnline bookings for appointment-based professionals. Your booking page and team calendar.
Use the MCP endpoint listed on this page in your MCP client configuration. One-click install pills support Claude, Cursor, VS Code, and other hosts. Copy the remote MCP URL if your client needs a manual entry.
Request removal if you do not want Reserrva listed here, or claim the listing if you want to manage it on MCPBundles.
This server appears in the MCPBundles directory. Verify you operate it to take over the listing — name, description, logo, contact email, and skill content. We email a 6-digit code to a maintainer address your server publishes in /.well-known/security.txt or /.well-known/mcpbundles.json. Free, takes about a minute.
MCPBundles publishes this directory for MCP discovery. Except where we host or operate an offering, third-party services run under their own terms. Product and company names on this page are used in a descriptive, identifying way (including under nominative fair use where applicable); they remain the property of their owners. Nothing here grants you rights in those marks, and nothing here is an offer to sell a third party's services. Terms · Request removal
Other MCP servers in this category from the directory index
Previewing 25 of 79 tools
MCPBundles probed 79 tools on the live server. The tool list on this page reflects what was discovered at the last refresh — connect your client to see the full set available to your session.
No provider sign-in was required during MCPBundles' probe. Your client may still need MCPBundles credentials depending on how you connect.
Request removal from the MCPBundles directory. We stop publishing this listing on mcpbundles.com.
MCPBundles is an independent platform built on the open Model Context Protocol standard. MCPBundles is not affiliated with, sponsored by, or endorsed by Anthropic PBC.