MCP configuration tools
The tools behind the configuration door /mcpconfig: the ones an environment is set up with. Products and prices, the front end and the theme, e-mail templates and the booking workflow. A key with scope config opens this door; how to connect is described in Connecting an AI agent to the MCP server. The daily work sits behind a different door — see MCP operations tools.
Plan and apply are two tools
Every writing act here consists of two tools: ..._plan shows what would change and writes nothing, ..._apply carries it out. That is not a formality but the heart of how this door is used safely: you show a plan to somebody who says yes to it, and only then is anything written. They each have their own right, so you can let somebody look without letting them change.
An _apply that finds nothing to change is a success, not an error: if the value already was what was asked for, the answer says nothing changed. A client that lost its answer can therefore simply try again.
Two locks, plus the production lock
Before anything is written here, two locks must be open: one set by the supplier for the whole environment, and one set by the license holder. If either is closed, even the plan is refused — otherwise the door you cannot open would still describe in full detail what is behind it.
On top of that, the heaviest tools face a third condition: on a production environment they do not run at all. Those are the tools with level 2 in the table below — the statuses and the automatic status transitions. Changing those decides which e-mail goes out at which status change, and at the next job run that is real post to real customers. Changing theme CSS is allowed on production: that is visible and reversible.
The tools
| Tools | Read/write | Level | Description |
|---|---|---|---|
| env_describe / config_diff_vs_baseline / recent_changes | read | - | What this environment is, what differs from a fresh installation, and what changed recently |
| object_explain / pricing_explain / availability_why_not_bookable | read | - | An explanation of one product: its settings, how the price is built up, and why it is not bookable on a date |
| object_create / object_update / object_set_periods / object_set_extras / object_set_participants | write | 1 | Create and change products, with their periods, extra options and participant types, and the booking settings: participant limits, buffer times and how far ahead people can book |
| object_copy | write | 1 | Copy a product into a new, immediately bookable product: calendar, prices, opening hours, options, questions, participants, resources and status mails come along. The copy starts switched off and can be linked to a location straight away |
| object_set_opening_hours | write | 1 | Opening hours in groups (for example default and summer): per weekday from–till, and open, closed or on request |
| object_set_price_schemas | write | 1 | The prices per period, in groups: per weekday and time window the price, the price type and the VAT |
| object_set_calendar | write | 1 | The calendar: which price group and which opening-hours group apply on which dates. A date without a calendar row cannot be booked |
| object_set_questions | write | 1 | Booking questions with type, required and answer options. The structure applies in every language |
| object_set_resources | write | 1 | Which resources a product occupies (room, layout, staff member, equipment) and how |
| object_set_attributes | write | 1 | Address, GPS location and the custom fields of a product, such as type of room or capacity. The plan shows what your environment calls each custom field |
| resource_describe / resource_create / resource_update | read/write | 1 | Manage resources: rooms, staff, layouts and equipment, with amount and buffer times |
| vat_describe | read | - | The VAT rates of the environment, and which rate is the default |
| franchise_describe / franchise_create / franchise_update | read/write | 1 | Manage locations (branches): name and address, and how many locations your licence allows |
| franchise_set_objects | write | 1 | Which products a location sells |
| product_set_active | write | 1 | Switch a product on or off |
| combi_create / combi_update | write | 1 | Compose packages |
| combi_copy | write | 1 | Copy a package, with its parts, options, prices, calendar and status mails. The copy starts switched off |
| combi_set_parts | write | 1 | The parts of a package, in order: which products and periods it books, and whether a part is optional |
| combi_set_extras | write | 1 | The options of a package |
| combi_set_price_schemas / combi_set_calendar | write | 1 | The prices and the calendar of a package |
| theme_describe / theme_set_variables / theme_set_css / theme_set_logo / theme_rebuild | read/write | 1 | The front-end theme: colours and variables, own CSS, logo, and recompiling |
| theme_patch_css | write | 1 | Change part of the own CSS: a colour, a rule or a named block, without sending the whole stylesheet again |
| media_upload_link | write | 1 | A one-time upload link to the media library, for a logo, stylesheet or font |
| media_fetch | write | 1 | Fetch a file from your own website into the media library |
| brand_set_logo | write | 1 | The corporate logo |
| content_block_describe / content_block_create / content_block_update | read/write | 1 | The blocks a front-end page is built from |
| content_block_delete | write | 1 | Delete a block. Refused while it is still used somewhere: on a page, in a theme, in another block or in a form |
| content_block_patch | write | 1 | Change part of a block field, for example one filter in the script of the search-and-book page, without sending the whole field again |
| menu_describe_items / menu_set_items | read/write | 1 | The items of a menu as a list: order, dropdowns, the page an item leads to and the label per language |
| page_describe / page_create / page_update | read/write | 1 | Content pages in the front end |
| page_list / page_check_links | read | - | All content pages, and which internal links in menus, content blocks and the homepage lead nowhere |
| page_delete | write | 1 | Delete a page. Refused when another language version points to it, unless you have that link cleaned up at the same time |
| theme_set_menu | write | 1 | Which menu the header of a theme shows, per language |
| homepage_set | write | 1 | Which page the front end opens when a visitor arrives at the base address |
| template_describe / template_create / template_update / template_section_set | read/write | 1 | E-mail and pdf templates and their header, footer and css parts |
| template_delete | write | 1 | Delete a template. Refused as long as it is still used somewhere; the answer says where. An active template is only deleted when you ask to deactivate it first |
| workflow_describe | read | - | The whole booking workflow in one answer: statuses, manual and automatic transitions, and which template belongs to which transition — including checks on templates nothing points at any more |
| status_set | write | 2 | Change a booking status: whether it occupies a place, and where somebody may move a booking to by hand |
| status_create | write | 1 | A new booking status (the code is digits only), with the same settings as status_set. A new status occupies a place by default, as on the screen |
| auto_set / auto_delete | write | 2 | Automatic status transitions: from which status to which, at what moment, and which e-mail or sms goes with it |
| status_override_set / status_override_delete | write | 2 | Which e-mail or text message goes out on a status change of one product or package. Removing a row silences that transition: nothing falls back to a default |
| payment_schedule_describe / payment_schedule_set / payment_schedule_delete | read/write | 2 | Payment schedules: the instalments, their texts and which product or package they apply to. Removing one is refused while an automation is waiting for it |
| user_profile_describe / user_profile_create / user_profile_update | read/write | 1 | User profiles: the discount for a group of customers (fixed amount or percentage), and which customer status assigns the profile |
| user_profile_set_objects | write | 1 | Which products a profile applies to, and with that which products customers with that profile see in the front end |
| customer_status_describe / customer_status_create | read/write | 1 | Customer statuses: may book, may pay by invoice, which statuses a customer may move to, the profile the status assigns, and the colours |
| customer_status_update | write | 2 | Change an existing customer status. That applies at once to every customer already in that status |
| telnyx_diagnose | read | - | Diagnosis of the phone assistant at Telnyx: which MCP tools it may use and whether it called them in recent conversations |
| language_list | read | - | The languages of the environment (active, default) and which parts are translatable |
| language_activate | write | 1 | Switch a front-end language on or off; the plan counts what is still empty in that language |
| language_missing_report | read | - | Per part, the texts that are filled in the source language but not yet in the new one, with the source text included |
| translation_get / translation_set | read/write | 1 | Read and store translations, up to 50 at a time, across all translatable parts |
Making a product bookable
A product can only be booked once it has periods, opening hours, prices and a calendar. The quickest way is copying: object_copy creates a new product as a copy of an existing one, with everything attached, and starts it switched off. You then change what is different and switch it on with product_set_active.
Starting from scratch, the order is:
object_create: the product itself.object_set_periods: how long it is booked, for example an hour, a half day or a day.object_set_opening_hours: when it is open, in one or more groups.object_set_price_schemas: the prices per period, in one or more groups.object_set_calendar: which price group and opening-hours group apply on which dates.- Where needed
object_set_extras,object_set_participants,object_set_questions,object_set_resourcesandobject_set_attributes. product_set_active: switch it on.availability_why_not_bookabletells you why a product cannot be booked on a date yet.
A number of things are guarded along the way:
- Every list is complete. You send all periods, opening hours or options that should exist afterwards. Anything not in the list is removed. Existing rows are updated and keep their number.
- A calendar row may only name groups that exist, and a group the calendar still uses cannot be removed. To switch price groups, add the new group first, switch the calendar and only then leave out the old group.
- Overlapping times on one day and overlapping calendar rows are refused before anything is stored.
- Write times as
hh:mm.24:00is midnight,26:00is 02:00 the next day. - Questions exist per language. The structure (type, required, order and the answer options) applies in every language. Translate the question text and the answer labels with
translation_set. A question you leave out is removed in every language. - A GPS location is stored to about seven digits: 51.578721 becomes 51.57872, accurate to about one metre.
- A product, package or location of another licence does not exist for these tools.
A package is set up the same way: combi_create or combi_copy, then combi_set_parts (which products and periods it books), combi_set_extras, combi_set_price_schemas and combi_set_calendar. combi_update switches it on, but only once it has parts.
Multiple locations
If you sell at more than one location, set up a branch per location and link the products that can be booked there. The search-and-book page can then filter by location.
franchise_describeshows the existing locations, and how many locations your licence allows.franchise_createcreates a location with name and address. Set the name in other languages withtranslation_set.franchise_set_objectslinks the products.object_copycan also link a new product to a location straight away.content_block_patchchanges the search-and-book page, for example to add a location filter, without sending the whole script again. If the script was changed in the admin in the meantime, the change is refused and the assistant reads it again.
- Your licence determines how many locations you can create. At the maximum a new location is refused; raising the maximum is a change to your licence.
- Existing bookings keep their location. If they should move to the location the product now belongs to, ask for that explicitly.
- The name of a location must be unique. Two locations with the same name cannot be told apart by a visitor.
Furnishing the front end
A front end consists of content blocks, pages that show those blocks, a menu, a theme and a homepage. With the tools this goes in the following order: create and fill blocks (content_block_create, content_block_update), turn them into pages (page_create), fill the menu (menu_set_items), link the menu to the theme (theme_set_menu) and choose the homepage (homepage_set). Finally, page_check_links shows whether any links still lead nowhere.
Along the way a number of things are guarded, so that a mistake does not only show up for the visitor:
- The content of a content block is checked before it is saved, the same way as in the editor. Text that would break the page, such as a stray curly brace or an
{if}without{/if}, is refused. Put JavaScript and CSS with curly braces between{literal}and{/literal}. - The menu in the header is chosen per language, and a language without a menu does not fall back to another language. The plan of
theme_set_menunames every active language that has no menu afterwards. - A menu set up for one language only needs labels in that language. A menu for all languages needs a label in every active language.
- The homepage is one setting for all languages. When a visitor switches language, the front end follows the linked language version of that page. The plan of
homepage_setwarns about every active language in which the page has no version. - The link check only looks at links a visitor clicks. JavaScript does not count, even when it contains something like
location.href.
Supplying a logo and house style
Do not paste a logo or a complete stylesheet into the conversation with your assistant. That is slow, and one wrong character makes the file unusable. The file goes into the media library of your environment first, and the assistant then refers to it.
- Supply the file. Ask the assistant for an upload link (
media_upload_link). Open the link, choose the file and click Upload. If the logo is already on your own website, the assistant can also fetch it itself (media_fetch). - Have it used. The assistant then sets the file as the logo (
brand_set_logoortheme_set_logo) or as the stylesheet of the theme (theme_set_css). You do not have to paste anything into the admin.
Example: "Use the logo I am uploading now on our site and in the confirmation e-mail, and make the buttons dark green." The assistant creates an upload link, sets the logo after your upload, and changes only the button colour with theme_patch_css. The rest of the stylesheet is left untouched.
- An upload link works once and is valid for 15 minutes by default. If a file is refused, for example because it is not an image, the link stays usable.
- Allowed: images (png, jpg, gif, webp, svg, ico), stylesheets (css) and fonts (woff, woff2, ttf, otf), up to 5 MB. The file type is determined from the content, not from the name.
- Fetching only works from your licence's own domains: the domains in the setting CORS - Allowed domains.
- These tools need the right
menu_config_manage_media(manage media), and the locks above must be open. - For a small change,
theme_patch_cssfirst checks that the stylesheet is still the one the assistant read. If it was changed in the admin in the meantime, the change is refused and the assistant reads it again.
Customer profiles and customer statuses
A user profile gives a group of customers a price of their own: a fixed amount or a percentage discount. A profile also decides which products those customers see in the front end. A customer status records what a customer may do, such as booking or paying by invoice, and can give the customer a profile. For example: regular customers 10% discount, non-profits 25%, and a blacklist that may no longer book.
user_profile_create: the profile with the discount. A percentage can apply to the price before or after other discounts, with or without options.user_profile_set_objects: which products the profile applies to.customer_status_create: the customer status, with what the customer may do and the profile the status assigns.customer_status_describeshows the existing statuses.
Along the way a number of things are guarded:
- A profile without linked products applies to all products. Link products to it and customers with that profile see only those products. The plan of
user_profile_set_objectswarns in both cases. - A customer only gets the profile of their status at the next status change. If they have no login yet but do have an e-mail address, they get a login without a password at that moment. The plan says so.
- Changing an existing customer status (
customer_status_update) has level 2: it is not run on a production environment. May book and may pay by invoice change at once for every customer already in that status. A new status affects nobody yet. - If a customer status is still on the system default, the first change makes a copy of its own for your licence, just like the screen does.
- The name of a customer status is set in the current language. Other languages are filled with
translation_set.
The profiles need the right menu_object_userprofile, the customer statuses menu_config_status_customer.
Adding a language
Switching a front-end language on copies nothing. Everything that has no text in that language yet stays empty in the front end: product names, options, statuses, field labels, content blocks, the menu and the pages. Almost nothing falls back to the default language. The language tools turn that manual work into one structured job:
language_activate_planshows how many texts are still empty per part. Only after approval doeslanguage_activate_applyswitch the language on.language_missing_reportgives the work queue: per part, which texts are missing, with the source text included.- The agent translates and
translation_set_planshows per text what would change.translation_set_applystores it.
Three things are always guarded. A text that is already filled is not overwritten unless that is explicitly asked for. Codes such as {NAME} or ##OWNER_ID## and the HTML markup of a text must come back exactly the same after translating. And a text may not be longer than its field allows. A content page in a new language needs its own url; it is not taken over from the original page.
E-mail and pdf templates are not covered here: those are separate documents per language, made with the template tools.
All these tools need the right menu_config_language, plus the right of the screen where the text is normally edited. Someone who may not change the products cannot translate them through AI either.
You ask for the exact, always current list with all input fields using the standard MCP method tools/list on the door itself. What you get back depends on your rights, so a shorter list than this usually means a right is missing.
Which rights each tool needs is described right by right on AI configuration tool rights.
BETA. This door is new and still being developed. Tool names, input fields and levels may change between releases without a transition period. Use the plan variant before applying anything, and do not yet build a production integration on it that is not allowed to break.


