MCP App Store
by KeenEthics

Overview

Laioutr is the agentic frontend management platform that combines Studio (visual editor), Frontend (performance layer), Orchestr (backend integrations), and Laioutr Cloud (hosting) into a single platform. Developers no longer need to manually maintain integrations, while marketing and content teams can independently design pages, launch campaigns, and manage content via a unified interface - without requiring an engineering ticket for every adjustment.

Tools

collections_create_entry

ChatGPT
Create an empty draft entry of a collection, seeded with the type's defaults when its schema can be read, and return its id. A new entry is never open, so this writes the draft row. When to use: Use to add an entry, then fill it with collections_set_fields. Pass an idempotencyKey when you may retry. When NOT to use: Don't use to copy an entry or to set values — create, then write with collections_set_fields. To publish it, use collections_publish_entries. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","entityType":"BlogPost"} Response: { entryId, revision }. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing); COLLECTION_NOT_FOUND (the storefront does not declare the type; detail.refresh.tool names collections_list_collections); PROJECT_LOCKED (a restore or migration holds the project). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_get_entry

ChatGPT
Return one entry: each component in the authoring view (the shape the write tools take), its links, its validation issues and its state. Reads the live form when a person has the entry open. Reading a live entry also shows you among the entry's participants. When to use: Use to read an entry before editing it, and to find the list item ids that collections_edit_array_items and collections_remove_array_items address. Pass components for the ones a large entry listed in omitted. When NOT to use: Don't use to read one value — use collections_get_field. Don't use to find entries — use collections_list_entries. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","entryId":"a1b2c3d4e5f6g7h8j9k0"} Response: { entryId, entityType, revision, status, live, data: { <component>: value }, links: { <token>: entryId[] }, issues, omitted? } — about 100 KB at most. issues belong to the data returned: for a live entry, its live form. live: true means a person has the entry open; publication is status. A component without a stored value is left out of data, also when components names it. Components are added in order; once one does not fit, it and every later one go to omitted: Array<{ component, bytes }>: read them with components, and a single component above the cap field by field with collections_get_field. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing); ENTRY_NOT_FOUND; COLLECTION_NOT_FOUND (the storefront no longer declares the entry's type; detail.refresh.tool names collections_list_collections); SCHEMA_UNAVAILABLE; INVALID_INPUT for an unknown component (detail.available). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_get_field

ChatGPT
Return one value of an entry, addressed by at + keyPath exactly as a collections_set_fields write item addresses it. A localized field comes back as its { locale: value } map, which values accepts as it is. When to use: Use to read the current value before a collections_set_fields write, or to read a component too large for collections_get_entry. When NOT to use: Don't use to read a whole entry — use collections_get_entry. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","at":{"entryId":"a1b2c3d4e5f6g7h8j9k0","component":"content"},"keyPath":["title"]} Response: { value, live } — usually under 1 KB. value is null when nothing is stored there. live: true: a person has the entry open, and the value is read from their live form. Reading a live entry also shows you among the entry's participants. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing); ENTRY_NOT_FOUND; COLLECTION_NOT_FOUND (the storefront no longer declares the entry's type; detail.refresh.tool names collections_list_collections); SCHEMA_UNAVAILABLE; ARRAY_ITEM_NOT_FOUND; INVALID_INPUT for an unknown component or field (detail.reason). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_get_schema

ChatGPT
Return the field model of one collection: per component its fields (kind, localized, required, constraints, options, union variants and their discriminator, list items), plus the link tokens that start at the type. When to use: Use before writing, to learn the field names for a keyPath, which fields are localized, and the token for collections_set_links. Pass components to read only some. When NOT to use: Don't use to read an entry's values — use collections_get_entry or collections_get_field. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","entityType":"BlogPost"} Response: { entityType, fingerprint, slug?, requiredComponents, components: Array<{ name, title?, fields }>, links: Array<{ token, label, target, type }>, stale? } — 2–15 KB. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing); COLLECTION_NOT_FOUND (the storefront does not declare the type; detail.refresh.tool names collections_list_collections); SCHEMA_UNAVAILABLE (the storefront could not be read; retry); INVALID_INPUT for an unknown component (detail.available). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_list_collections

ChatGPT
List the project's content collections — each an entity type with its components — and the project locales with their fallbacks. When to use: Use first, to find an entityType for the other collections_* tools and the locale codes a localized field takes. When NOT to use: Don't use to read a collection's fields or link tokens — use collections_get_schema. Don't use to list entries — use collections_list_entries. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g"} Response: { collections: Array<{ entityType, components, slug?, app? }>, locales: Array<{ code, name, fallbacks }>, reachable, staleSince? } — under 2 KB. reachable: false means the storefront could not be read: the list is the last known one (staleSince) or empty. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_list_entries

ChatGPT
List the entries of one collection, a page at a time. Search them by label with query, or filter them by exact field values with where (for example a SKU): each condition names a field by component + keyPath and gives its value in equals, with locale for a localized field. where reads the saved draft, so an entry a person has open is matched on its last save. When to use: Use to find an entryId, and before creating an entry, to find one that already has the same key value. Page with limit (1–50, default 20) and offset. When NOT to use: Don't use to read an entry's values — use collections_get_entry. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","entityType":"ProductVariant","where":[{"component":"base","keyPath":["sku"],"equals":"SKU-1001"}]} Response: { entries: Array<{ entryId, label, status, valid, issueCount, live, updatedAt }>, total } — about 150 B per row. live: true: a person has the entry open. total counts the matching entries; with query it is the rows returned, since a query returns the best limit matches. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing); for a where condition that does not fit the field model, the codes of collections_set_fields with detail.itemIndex (INVALID_INPUT for an unknown component or field or a value of the wrong type, MISSING_LOCALES / INVALID_LOCALES); with where, also COLLECTION_NOT_FOUND and SCHEMA_UNAVAILABLE; INVALID_INPUT with detail.reason: "WHERE_WITH_QUERY" for where together with query. Only text, number, boolean and enum fields can be filtered. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_publish_entries

ChatGPT
Publish 1–50 entries to the live storefront, one after another in the given order. Each entry is checked against the deployed storefront's schema and publishes or fails on its own: the call is not atomic. An entry a person has open is published with the changes in their form. When to use: Use when the person asks to publish, after the entries are complete. Publish link targets (variants, categories) before the entries that link to them, and check issues with collections_get_entry first. When NOT to use: Don't use to save a draft — every write already saves it. Unpublishing and deleting entries are not available here. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","entryIds":["a1b2c3d4e5f6g7h8j9k0"]} Response: { results: Array<{ entryId, published: { revision, publishedAt } } | { entryId, error: { code, message, detail? } }> } — one element per entry, in order. A publish replaces what the storefront shows for the entry. Per-entry codes: PUBLISH_REJECTED (the draft has blocking issues, listed in detail.issues); ENTRY_NOT_FOUND; ENTRY_BUSY (retry after detail.retryAfterMs); ENTRY_UNSAVED (the open form's latest changes are not saved yet: retry when detail.retryable is true, otherwise ask the person to reopen the entry); COLLECTION_NOT_FOUND (the storefront no longer declares the entry's type; detail.refresh.tool names collections_list_collections); SCHEMA_UNAVAILABLE; PROJECT_LOCKED. Errors of the whole call: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_remove_array_items

ChatGPT
Remove 1–50 items of list fields on ONE entry in one atomic call. The items and their content are removed from the entry. When to use: Use to delete list items. Item ids are in collections_get_entry ([{ id, value }]). When NOT to use: Don't use to reorder — use collections_edit_array_items. Deleting a whole entry is not available here. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","entryId":"a1b2c3d4e5f6g7h8j9k0","removals":[{"component":"content","keyPath":["faq"],"arrayItemId":"k3m9p2"}]} Response: { results, revision, issues, live, pulled } — each result is {}. The write changes only this project's draft, never the storefront. results has one element per batch item, in order; revision is the draft revision; issues are the entry's validation issues after the write. live: true: the entry is open in this project's Cockpit editor, and the write also went into that open editor. pulled: false: the write is in the open editor, but the draft row is not updated yet; the next save of the entry writes it, so do not repeat the write. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing); ENTRY_NOT_FOUND; COLLECTION_NOT_FOUND (the storefront no longer declares the entry's type; detail.refresh.tool names collections_list_collections); ENTRY_BUSY (the entry is being opened or closed: retry after detail.retryAfterMs. It also comes back when an open entry's live copy is lost, before or after the write reached it: nothing of the call is kept, so retry; the retry succeeds once the person leaves the entry, and then writes the draft row); ENTRY_TOO_LARGE; PROJECT_LOCKED (a restore or migration holds the project); SCHEMA_UNAVAILABLE. The batch is written whole or not at all: an invalid item fails the call with detail.itemIndex (0-based), and INVALID_INPUT carries the cause in detail.reason. Also ARRAY_ITEM_NOT_FOUND. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_set_fields

ChatGPT
Write 1–50 values on ONE entry in one atomic call. Each write item addresses a value with component + keyPath and carries value (with locales for a localized field), or values (a { locale: value } map; only the listed locales change, a null entry clears that locale); variant switches a union. null clears. When the entry is open in the project's Cockpit editor, the values appear there at once. When to use: Use to fill in or change field values. Read the field model with collections_get_schema and the current value with collections_get_field. Batch the writes for one entry into one call. For a media field, write item.media from media_list_assets or media_import_from_url. When NOT to use: Don't use to change a list that holds items — use collections_edit_array_items and collections_remove_array_items; a list with no items takes [] or [{ value }, …], and a null is refused on a list that holds items and on an object that contains one. Don't use for links — use collections_set_links. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","entryId":"a1b2c3d4e5f6g7h8j9k0","writes":[{"component":"content","keyPath":["title"],"value":"Winter sale","locales":["en"]},{"component":"content","keyPath":["teaser"],"values":{"en":"Up to 30% off","de":"Bis zu 30% Rabatt"}}]} Response: { results: Array<{ writtenLocales }>, revision, issues, live, pulled } — The write changes only this project's draft, never the storefront. results has one element per batch item, in order; revision is the draft revision; issues are the entry's validation issues after the write. live: true: the entry is open in this project's Cockpit editor, and the write also went into that open editor. pulled: false: the write is in the open editor, but the draft row is not updated yet; the next save of the entry writes it, so do not repeat the write. Errors: MCP_NOT_ENABLED, FORBIDDEN, PROJECT_NOT_FOUND, CMS_NOT_ENABLED (the project has no content editing); ENTRY_NOT_FOUND; COLLECTION_NOT_FOUND (the storefront no longer declares the entry's type; detail.refresh.tool names collections_list_collections); ENTRY_BUSY (the entry is being opened or closed: retry after detail.retryAfterMs. It also comes back when an open entry's live copy is lost, before or after the write reached it: nothing of the call is kept, so retry; the retry succeeds once the person leaves the entry, and then writes the draft row); ENTRY_TOO_LARGE; PROJECT_LOCKED (a restore or migration holds the project); SCHEMA_UNAVAILABLE. The batch is written whole or not at all: an invalid item fails the call with detail.itemIndex (0-based), and INVALID_INPUT carries the cause in detail.reason. Also MISSING_LOCALES / INVALID_LOCALES (detail.allowed), ARRAY_ITEM_NOT_FOUND. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

distributr_create_feed

ChatGPT
Creates a product feed for one channel and market of an environment. marketId must be a market id and channel a channel id, both exactly as distributr_feed_options returns them — never a name or a label. Give it a short name and a file name without extension. It starts with the channel's standard mapping and is not run: the customer runs it from the feed's page. Its result carries readiness: a new feed usually cannot run yet (it has no storefront address, or its product links cannot be built), so tell the customer each problem with its fix instead of telling them to run it. Pass the projectId from project_list; the call acts only inside that project.

distributr_feed_health

ChatGPT
How each feed of one environment has been running lately: its newest run and what succeeded or failed over the last days. Pass the projectId from project_list; the call acts only inside that project.

distributr_feed_options

ChatGPT
Lists what a new product feed can be made for in one environment: its markets (id, name) and the channels feeds are written for (id, label — Google Merchant Center, Meta, idealo, …). Call it before distributr_create_feed to pick the market and the channel id. Pass the projectId from project_list; the call acts only inside that project.

distributr_feed_readiness

ChatGPT
Says whether one feed can run and publish a usable file, and if not, each problem with how to fix it: no storefront address, a storefront that cannot be read, product links that cannot be built, or required columns without a source. Call it before telling a customer to run a feed, whenever they ask whether a feed is ready or why it does not work, and after changing a feed. Never tell them to run a feed it reports problems for; say the problems and their fixes instead, or offer to set the storefront address or the product link pattern for them. Pass the projectId from project_list; the call acts only inside that project.

distributr_get_feed

ChatGPT
Reads one feed: its channel, market, schedule, selection rules, field mapping (the columns of the file and where each value comes from) and public address. Pass the projectId from project_list; the call acts only inside that project.

distributr_list_feeds

ChatGPT
Lists the product feeds of one environment, each with its channel, market, file name, public address, when it was last published and whether a run is going on now. Pass the projectId from project_list; the call acts only inside that project.

distributr_list_runs

ChatGPT
Lists a feed's latest runs: when each started and ended, whether it succeeded, how many products it wrote, and the error a failed run stopped on. Read this when a customer reports that a feed failed. Pass the projectId from project_list; the call acts only inside that project.

distributr_source_fields

ChatGPT
Lists the product fields the feed's storefront actually returns, to choose sources from when mapping a column. Asks the storefront, so it can take a few seconds or say why it could not. Pass the projectId from project_list; the call acts only inside that project.

distributr_update_feed

ChatGPT
Changes a feed: its name, schedule, whether it is on, its storefront address (sourceEndpoint, the storefront's public URL), its product link pattern (rules.productUrlPattern, such as https://shop.example.com/p/{slug}, sent with the feed's other rules), selection rules, or its mapping — the list of columns, each with a header, a source field and a transform. To add a custom column such as a price, read the feed first, then send the whole mapping with the new column added; columns left out are removed. Pass the projectId from project_list; the call acts only inside that project.

feedback_file_report

ChatGPT
Files a report to Laioutr support as the customer, from what they told you — once they asked or agreed to send it. The card they confirm is their agreement: propose it straight away and never ask for agreement in words first, and never say it is filed before it ran. kind: bug for something broken (then also stepsToReproduce, expectedResult, ordersBlocked, ongoing, workaround), help for a question, idea for a wish. severity: s1 when a live shop cannot sell, s2 when an important feature is broken, s3 for a smaller problem, s4 for a question or an idea. Write a short title and, in body, what happens in their words. pagePath, screenshot and clientContext may be null. Support triages it and answers in the report. Pass the projectId from project_list; the call acts only inside that project.

feedback_get_report

ChatGPT
Reads one of the customer's reports: its status, and the replies support or Ask Larry wrote in it. Pass the projectId from project_list; the call acts only inside that project.

feedback_list_reports

ChatGPT
Lists the customer's reports for this project, as their Reports page shows them: how many are open and closed, and each with its title, kind, severity, status, whether support answered, and when it was sent and last changed — not its text. Closed reports older than a few weeks come only with includeOldClosed: true. Use it to answer how many reports are open, what happened to one, or which one they mean; then read one with feedback_get_report. It does not say who closed a report. Pass the projectId from project_list; the call acts only inside that project.

media_import_from_url

ChatGPT
Fetch one file from a public https URL on port 443 and store a copy in one of the project's media libraries. Returns the new library item. The library must take staged uploads (capabilities.upload.transfer is staged in studio_get_capabilities → mediaLibraries); it also sets the accepted types (capabilities.upload.accept) and the size limit in bytes (capabilities.upload.maxFileSize). When to use: Use when content needs an image, video or document that is not in the library yet — for example a URL from a CSV. Import each distinct URL once and reuse the returned item: every call without a repeated idempotencyKey makes a new asset. Write the item into a field as the studio_get_data_model primer describes; never store the source URL as a plain-URL source (provider: 'raw' or 'none') when a library can import. When NOT to use: Don't use for a file that is already in the library — find it with media_list_assets. After reason timeout or processing_failed, or an upload_failed whose message starts with At finalize:, the file can still be in the library: check with media_list_assets before you try again. The call stops after 45 s. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","library":"@laioutr-app/cms","url":"https://images.example.com/summer/banner.jpg"} Response: The item: a media item { kind?: "media", media, previewUrl?, fileName?, externalId?, … }, or a file item { kind: "file", file: { url, mimeType, size? }, … } for a document such as a PDF. About 1 KB. A failed import returns MEDIA_IMPORT_FAILED with detail.reason: source_unavailable (the URL failed, or is not a public https URL on port 443), unsupported_type (also when the library takes the type in general but not in this project, for example video without the video CDN), too_large, upload_failed, processing_failed or timeout. CAPABILITY_UNSUPPORTED means the frontend is too old or the library takes no staged uploads. INVALID_INPUT for folderId on a library without folders. Also FRONTEND_UNREACHABLE (the storefront did not answer; after an upload started, check with media_list_assets before retrying) and LIBRARY_NOT_FOUND. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

media_list_assets

ChatGPT
List or search the assets in one of the project's media libraries, one page at a time, with the subfolders of the folder you list. Library ids and what each library can do (capabilities.search, capabilities.folders) come from studio_get_capabilities → mediaLibraries. When to use: Use before you import a file, to reuse an asset that is already in the library. Use after a media_import_from_url that failed with reason timeout: the file can still have arrived. Write an item into a field as the studio_get_data_model primer describes. When NOT to use: Don't use to add a file — use media_import_from_url. Don't pass term to a library whose capabilities.search is false, or folderId to one whose capabilities.folders is false. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","library":"@laioutr-app/cms","term":"banner","type":["image"]} Response: { items, folders?, nextCursor?, total? } as the library returns it. Each item is a media item { kind?: "media", media, previewUrl?, fileName?, externalId?, file?, tags? } or a file item { kind: "file", file: { url, mimeType, size? }, … }; only a file item always has kind. folders comes on the first page only; nextCursor is absent on the last page. About 1 KB per item. An unknown folderId can give an empty page. LIBRARY_NOT_FOUND names the libraries the project has. Requires a reachable frontend: FRONTEND_UNREACHABLE only when the storefront does not answer. INVALID_INPUT when the library refuses the request (for example an unknown cursor, term on a library that cannot search, or folderId on a library without folders). MEDIA_LIBRARY_FAILED when the library fails: retry later. Also CAPABILITY_UNSUPPORTED (the frontend is too old). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

project_list

ChatGPT
List every Laioutr project the signed-in user has access to, across all organizations. Each row carries mcpEnabled — when false, project-scoped tools will reject calls with MCP_NOT_ENABLED. When to use: Use first, to find a projectId for any other tool. Cheap; no pagination. Re-call only if the human mentions a project that is not in the previous response. When NOT to use: Don't use to read a specific project's structure — once you have a projectId, switch to studio_list_pages / studio_get_page_tree. Don't use to enumerate organizations — this tool returns the org context per project already. Example call: {} Response: { projectCount, projects: Array<{ id, name, slug, organizationId, organizationName, organizationSlug, mcpEnabled, locales: Array<{ code, name, fallbacks }> }> } — locales are the project's configured languages (the allowed values for studio_set_static_props.writes[].locales). Usually well under 5 KB.

studio_add_array_item

ChatGPT
Append a new item to an array-typed prop on a section or block, addressed by the same at + keyPath shape as a studio_set_static_props write item (here keyPath points at the ARRAY field). The new item is seeded with the component schema defaults and its generated id is returned — fill the item afterward with studio_set_static_props. When to use: Use to add a slide, card, row, or any repeated entry to an array prop. Discover the entity id with studio_get_page_tree, the array field name with studio_get_component_schemas, and existing item ids via studio_get_section. After adding, set the new item's fields with studio_set_static_props, using a write item's keyPath: [["<arrayField>", "<arrayItemId>"], "<field>"]. When NOT to use: Don't use to set a value on an item that already exists — use studio_set_static_props. Don't use to add a block to a slot — use studio_add_block. Global sections are read-only via this server. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","at":{"sectionId":"b8h2k4m6p0r3t5v7c9d1"},"keyPath":["features"]} Response: { arrayItemId, catalogVersion, warnings } — arrayItemId is the new item's stored key; pass it back as keyPath: [["<arrayField>", arrayItemId], "<field>"] in a studio_set_static_props write item. catalogVersion is the component-catalog fingerprint at write time. INVALID_INPUT means the keyPath did not resolve to an array field. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_add_block

ChatGPT
Add a block to a slot of an existing section (local or global). The slot must exist on the section's component and the block component must be allowed in that slot — verify both with studio_get_component_schemas for the owner section. When to use: Use to fill out a section — drop product cards into a hero, add feature tiles into a grid, append a button into a CTA slot. Discover the owner sectionId (or globalSectionId) and slot names via studio_get_page_tree / studio_get_section. When NOT to use: Don't use to add a whole new section — use studio_add_section. Don't use to change props on a block that already exists — use studio_set_static_props. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","owner":{"sectionId":"b8h2k4m6p0r3t5v7c9d1"},"slot":"items","componentName":"BlockFeatureTile"} Response: { blockId, catalogVersion, warnings } — blockId is what subsequent prop tools target; catalogVersion is the component-catalog fingerprint at write time. Catalog-related errors carry detail.catalogVersion + detail.refresh.tool — when either signal changes, re-list with studio_list_components. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_add_global_section_reference

ChatGPT
Place an EXISTING global section onto a page-variant container (header/body/footer) as a reference — not a copy. Discover available globalSectionId values with studio_list_global_sections. This does NOT create a global section; it only references one that already exists. When to use: Use to reuse a site-wide header, footer, or any shared section on a page variant. Discovery chain: studio_list_global_sections (list) → studio_add_global_section_reference (place) → studio_get_section with the globalSectionId (read its blocks) → studio_add_block / studio_set_static_props (edit them). When NOT to use: Don't use to add a local (page-specific) section — use studio_add_section. Don't use to create or edit the global section container itself (creating, detaching, or setting its own props is not exposed) — ask the human to do that in Studio. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","globalSectionId":"d4f6h8k0m2p4r6t8v0x2","at":{"pageVariantId":"a1b2c3d4e5f6g7h8j9k0","location":"header"}} Response: { sectionReferenceId, catalogVersion, warnings } — sectionReferenceId is the placement node on the variant (distinct from globalSectionId, the global it points at); catalogVersion is the component-catalog fingerprint at write time. CAPABILITY_UNSUPPORTED means the connected frontend-core lacks globalSectionReferences (check studio_get_capabilities). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_add_section

ChatGPT
Add a new section to a page variant container (header/body/footer) at a chosen position. Look up the componentName with studio_list_components and its prop shape with studio_get_component_schemas before passing props. When to use: Use to compose or extend a page — add a hero, add a feature grid, drop a CTA. Pre-configure props when the values are known; otherwise add empty and follow up with studio_set_static_props. When NOT to use: Don't use to add a block inside an existing section — use studio_add_block. Don't use to change props on an existing section — use studio_set_static_props. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","pageVariantId":"a1b2c3d4e5f6g7h8j9k0","location":"body","componentName":"SectionHero"} Response: { sectionId, catalogVersion, warnings } — sectionId is what subsequent block/prop tools target; catalogVersion is the component-catalog fingerprint at write time. Catalog-related errors carry detail.catalogVersion + detail.refresh.tool — when either signal changes, re-list with studio_list_components. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_delete_block

ChatGPT
Permanently remove a block from its section slot. Destructive — confirm with the human before issuing on a non-trivial block. When to use: Use when explicitly asked to remove a block (cleaning up a section, retiring a feature tile). Discover the blockId with studio_get_page_tree. When NOT to use: Don't use to clear props — use studio_set_static_props with a null write value. Don't use to hide a block — use studio_update_block with a visibility decorator. There is no host-side undo; recovery is via manual snapshots taken before significant edits. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","blockId":"c3e5g7j9l1n3p5r7t9v1"} Response: { blockId, catalogVersion, warnings } — catalogVersion is the component-catalog fingerprint at write time. Catalog-related errors carry detail.catalogVersion + detail.refresh.tool; re-list with studio_list_components when either changes. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_delete_section

ChatGPT
Permanently remove a section (and every block inside it) from a page variant. Destructive — confirm with the human before issuing on a non-trivial section. When to use: Use when explicitly asked to remove a section (rebuilding a page, retiring a feature). Discover the sectionId with studio_get_page_tree first. When NOT to use: Don't use to clear props — use studio_set_static_props with a null write value. Don't use to hide a section — use studio_update_section with a visibility decorator. There is no host-side undo; recovery is via manual snapshots taken before significant edits. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","sectionId":"b8h2k4m6p0r3t5v7c9d1"} Response: { sectionId, catalogVersion, warnings } — catalogVersion is the component-catalog fingerprint at write time. Catalog-related errors carry detail.catalogVersion + detail.refresh.tool; re-list with studio_list_components when either changes. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_get_capabilities

ChatGPT
Report whether the project's frontend is reachable, which version-gated frontend-core capabilities it supports, and which media libraries it has. When to use: Read before a version-sensitive edit (e.g. global-section references) and before a media task: mediaLibraries gives each library id and what it can do, for media_list_assets and media_import_from_url. frontendReachable: false is also the pre-flight signal that the component catalog, schemas, style tokens, and all mutations are unavailable right now. When NOT to use: Don't use to discover components or props — use studio_list_components / studio_get_component_schemas. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g"} Response: { projectId, frontendCoreVersion, frontendReachable, capabilities, thresholds, mediaLibraries, note? } — under 1 KB plus about 1.5 KB per library. mediaLibraries is Array<{ id, label, iconSrc?, capabilities }> as the frontend reports it. DEGRADES instead of erroring: when the frontend is down it returns frontendReachable: false with an all-false capability set and mediaLibraries: [] (no FRONTEND_UNREACHABLE). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_get_component_schemas

ChatGPT
Return the full Studio-shaped usage detail for one or more components in a single call — per component: its prop fields (each tagged translatable: boolean), its ai usage guidance (purpose, constraints, hints, relationships, supports) when set, and, for a section, its slots with the block names each slot accepts; for a block, the sections it's designed to live in (belongsIn). When to use: Use to construct valid props for studio_add_section / studio_add_block, pick a keyPath for studio_set_static_props, check which blocks a slot allows, or read a component's usage guidance. Pass every component you are about to work with in one call (e.g. a section and the blocks that go in its slots) rather than one call per name. Discover the componentNames via studio_list_components first. When NOT to use: Don't use to enumerate components — use studio_list_components; pass only the specific names you need, never the whole catalog. The value shapes for complex fields (link/color/media/json) live in the studio_get_data_model tool, not here. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","componentNames":["SectionHero","BlockFeatureTile"]} Response: { projectId, catalogVersion, schemas: Array<{ componentName, kind, studioLabel, ai?, schema, slots?, belongsIn? }>, notFound: string[] } — one schemas entry per resolved component (slots is section-only, belongsIn is block-only); projectId/catalogVersion are hoisted to the root. notFound lists requested names absent from the catalog at catalogVersion — a typo or catalog drift; re-list with studio_list_components and retry them. Duplicate names resolve once. Roughly (name count × 5-25 KB). Requires a reachable frontend; returns FRONTEND_UNREACHABLE when the project frontend is down. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_get_data_model

ChatGPT
Return the Studio data-model primer (markdown): page-types vs pages vs page-variants, sections vs blocks, slots, global sections, static vs translatable props, the complex-prop value shapes (link/color/media/json), content collections, and a worked example. Static and project-independent. Delivered as a tool so it loads reliably on every host, including those that can't read MCP resources autonomously. When to use: Call this FIRST, once per session, before listing or editing anything — it is the domain context every other tool assumes. Re-read its "Complex prop subtypes" section before writing a link / color / media / json prop with studio_set_static_props. When NOT to use: Don't use to discover a project's installed components or their schemas — use studio_list_components / studio_get_component_schemas. This is generic Studio documentation, not project data. Example call: {} Response: { markdown } — the primer as a single markdown string (~24 KB plus a "Collections" section of about 5.0 KB). Static; cache it for the session and do not refetch.

studio_get_page_tree

ChatGPT
Return one page variant's section/block tree — IDs, component names, slot membership. Excludes props by default; pass includeProps: true to inline each LOCAL section's full payload in the same call (see below). When to use: Use to find a sectionId or blockId to mutate. Call after studio_list_pages to look up pageVariantId. To read the props of MANY sections on a page, prefer includeProps: true here over a studio_get_section per section — one call instead of N. Use a bare studio_get_section only for a SINGLE section or a global-section reference. When NOT to use: Don't use to enumerate pages — use studio_list_pages. Don't set includeProps when you only need structure (it can add hundreds of KB). Global-section references are never inlined — read one via studio_get_section with its globalSectionId. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","pageVariantId":"a1b2c3d4e5f6g7h8j9k0","includeProps":true} Response: { pageVariantId, pageId, pageType, path, variantLabel, seo, sections, queryCount }. Structure-only is usually 5-10 KB. seo is the variant's { title, description, robots? } where title/description are the raw { <locale>: value } maps (empty {} when unset) — edit them via studio_update_page_variant. queryCount is the number of queries defined on this page variant (no per-query payload via this server yet). With includeProps: true, every LOCAL sections[<loc>][] entry additionally carries payload — the exact object studio_get_section returns for that id (props + its blocks) — growing the response to roughly (section count × 5-25 KB); global-reference entries are unchanged. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_get_prop

ChatGPT
Read one prop value off a section or block, addressed by the same at + keyPath shape as a studio_set_static_props write item. Returns just the addressed value — the targeted read-before-write counterpart of studio_get_section (which returns the whole 5–25 KB section payload). When to use: Use to read the current value of a prop before overwriting it with studio_set_static_props. Discover the entity id via studio_get_page_tree. For a translatable field value is the { <lang>: value } map — edit the entries you want and write them back through a studio_set_static_props write item's values field (a write item's single value field writes one value, optionally fanned across locales, and does NOT accept the map). For a complex primitive (link/color/media/json) value is the subtype-tagged object, which a studio_set_static_props write item's value accepts directly — see the "Complex prop subtypes" section of the studio_get_data_model tool for each shape. value: null means there is no stored value at keyPath — covering BOTH a never-set prop AND an unknown field/path (this read is storage-direct and schema-unaware, so it cannot tell the two apart; validate field names with studio_get_component_schemas). A field that exists but is empty returns its stored value (e.g. "" for a freshly-created text field), NOT null. And null means "not set in storage", not "renders nothing" — an unset field still renders its field type fallback, so do not infer the rendered value from null. When NOT to use: Don't use to read a section's whole prop set — use studio_get_section. Don't use to enumerate structure — use studio_get_page_tree. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","at":{"blockId":"c3e5g7j9l1n3p5r7t9v1"},"keyPath":["cta","label"]} Response: { value } — the prop value at keyPath (primitive, subtype-tagged complex object, or { <lang>: value } for a translatable field), or null when nothing is stored at keyPath — which covers a never-set prop AND an unknown field/path (this read is schema-unaware); a field that exists but is empty returns its stored value (e.g. ""), not null. Typically well under 1 KB. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_get_section

ChatGPT
Return one section's full payload — component name, studio metadata, visibility, props, slots. Resolves either a local section (on a page variant) or a global section by id. When to use: Use to read the current value of a prop before deciding how to mutate it with studio_set_static_props, or to inspect a complex-primitive prop shape before overwriting it. Discover the sectionId via studio_get_page_tree first. When NOT to use: Don't use to enumerate sections — use studio_get_page_tree. Don't use to fetch a component's schema — use studio_get_component_schemas. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","sectionId":"b8h2k4m6p0r3t5v7c9d1"} Response: { sectionId, componentName, studioLabel?, scope: "local"|"global", payload, …plus pageVariantId+location when scope==="local" } — 5-25 KB depending on props. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_get_style_tokens

ChatGPT
Return the project's color palette (flattened to a single list) and icon catalog — { themeId, colors, icons }. When to use: Use before setting a color prop (use a palette entry's id as token and its value as the hex) or an icon prop (use an icon name). Read the field's type from studio_get_component_schemas to know which applies. When NOT to use: Don't use to discover components — use studio_list_components. For a media prop, use media_list_assets or media_import_from_url. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g"} Response: { themeId, colors: Array<{ id, label?, value, hint?, group? }>, icons: Array<{ name, label? }> } — a few KB. Requires a reachable frontend; returns FRONTEND_UNREACHABLE when the project frontend is down. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_list_components

ChatGPT
List the section and block components installed in this project — a thin { name, kind, label, description?, purpose?, tags? } per entry (purpose is the agent-facing one-liner). Pass kind to list only sections or only blocks. When to use: Use to discover valid componentName values before studio_add_section / studio_add_block. Component names are arbitrary per-project strings (customers install different apps) — never guess them, read them here — then fetch one component's full usage detail (prop fields, slots, ai usage fields, belongsIn) with studio_get_component_schemas. When NOT to use: Don't use to read a component's prop fields, slots, or usage guidance — use studio_get_component_schemas. Don't use to list reusable global sections — use studio_list_global_sections. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g"} Response: { projectId, catalogVersion, components: Array<{ name, kind: "section"|"block", label, description?, purpose?, tags? }> } — a few KB. catalogVersion is the catalog fingerprint (also surfaced in mutation error detail.catalogVersion) — re-list when it changes. Requires a reachable frontend; returns FRONTEND_UNREACHABLE when the project frontend is down. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_list_global_sections

ChatGPT
List the project's reusable global sections — { globalSectionId, componentName, studioLabel?, usageCount } per entry, ids only, no block contents. When to use: Use to discover which global sections exist before placing one with studio_add_global_section_reference, then read a global's blocks via studio_get_section with its globalSectionId. Served straight from Storage — works even when the frontend is unreachable. When NOT to use: Don't use to read a global section's blocks — use studio_get_section. Don't use to list a project's installed component types — use studio_list_components. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g"} Response: { projectId, globalSections: Array<{ globalSectionId, componentName, studioLabel?, usageCount }> } — ~1–2 KB. usageCount is how many page-variant references point at the global. An empty project returns globalSections: [], never an error. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_list_pages

ChatGPT
List every page in the project with id, type, path, and each variant's { id, label } — no section tree, no props. When to use: Use first to inventory pages and grab the pageVariantId you need to pass to studio_get_page_tree and any page-targeted mutation. When NOT to use: Don't use to read a page's structure — use studio_get_page_tree. Don't use to read a single section's props — use studio_get_section. Page and variant creation are not supported via this server — ask the human to create the page in Studio, then add sections/blocks to it with studio_add_section. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g"} Response: { projectId, pageCount, pages: PageSummary[] } where PageSummary = { id, type, path, variantCount, variants: { id, label }[] } — usually under 2 KB. Each PageSummary.type is a stable token defined by the customer's frontend (typical values: home, category, product, static). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_move_block

ChatGPT
Relocate a block to a LOCAL section's slot, or reorder it within its current slot — preserving the block id and all its props (unlike delete + re-add, which loses both). The destination block component must be allowed in the target slot — verify with studio_get_component_schemas for the target section. When to use: Use to reposition an existing block: move a CTA into a different section, or change a block's order within a slot (same to.sectionId + to.slot, different to.atIndex). Discover the blockId and target sectionId/slot with studio_get_page_tree / studio_get_section. When NOT to use: Don't use to add a new block — use studio_add_block. Don't use to move a SECTION — use studio_move_section. Targets are LOCAL sections only: global sections are read-only via this server, so neither the target nor a block currently INSIDE a global section is accepted (moving one out is rejected with INVALID_INPUT). NOTE: a block nested below a global-section reference on a page is detected as global only when it resides in the global's own storage; the source guard is best-effort. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","blockId":"c3e5g7j9l1n3p5r7t9v1","to":{"sectionId":"b8h2k4m6p0r3t5v7c9d1","slot":"items"}} Response: { blockId, catalogVersion, warnings } — blockId is the moved block (id unchanged). catalogVersion is the component-catalog fingerprint at write time. SLOT_NOT_FOUND (carries detail.availableSlots) means the target slot name does not exist on the section component; BLOCK_NOT_ALLOWED_IN_SLOT (carries detail.catalogVersion + detail.refresh.tool) means the slot exists but the block is not permitted in it. QUERY_SCOPE_VIOLATION means the move would orphan or import a query across the global/page boundary. BLOCK_NOT_FOUND / SECTION_NOT_FOUND mean the source block or target section id did not resolve. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_move_section

ChatGPT
Reorder a section within its container, or relocate it between containers (header/body/footer) and between page variants — preserving the section (and, for a global-section reference, its link to the global). Works for a LOCAL section OR a global-section reference placed on a page. When to use: Use to reposition an existing section: reorder it in its container (same variant + location, new to.atIndex), move it from body to header/footer, or move it onto another page variant (to.pageVariantId). Moving a global-section reference around a page is allowed — it edits the PAGE, not the global. Discover the sectionId and target variant/container with studio_get_page_tree / studio_list_pages. When NOT to use: Don't use to add a new section — use studio_add_section. Don't use to move a BLOCK — use studio_move_block. A query-bound (dynamic) LOCAL section cannot be moved to a different page variant (QUERY_SCOPE_VIOLATION): its page-scoped query would be orphaned. Reorders and same-page relocations are always fine; references move freely across pages. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","sectionId":"b8h2k4m6p0r3t5v7c9d1","to":{"location":"header","atIndex":0}} Response: { sectionId, catalogVersion, warnings } — sectionId is the moved section (id unchanged). catalogVersion is the component-catalog fingerprint at write time. QUERY_SCOPE_VIOLATION means a cross-page move would orphan the section's page query. SECTION_NOT_FOUND / PAGE_VARIANT_NOT_FOUND mean the source section or target variant id did not resolve. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_set_static_props

ChatGPT
Write 1–50 static prop values on sections or blocks (local or inside a global section) in ONE atomic mutation. Each item in writes is a self-contained write: at + keyPath address the prop, and exactly one of value (one value, optionally fanned to several locales) or values (a per-locale map writing DIFFERENT text per locale) carries the payload. Mixed targets are fine — different sections/blocks, across page variants, in one call. The global section container itself cannot be targeted — only blocks within it, via their blockId. For complex primitives (link/color/media/json) build the subtype-tagged object documented in the "Complex prop subtypes" section of the studio_get_data_model tool, and read the current shape via studio_get_prop / studio_get_section before overwriting. When to use: Use to fill in copy, images, links, colors — any static values on existing entities. BATCH related edits: conceptually "set the props of this page" is ONE call, not one call per prop. Discover entity ids with studio_get_page_tree, inspect current props via studio_get_section, and read each field's translatable flag with studio_get_component_schemas: when true, pass the SAME value to several locales via value + locales, or DIFFERENT text per locale via the values map (which studio_get_prop returns ready to edit); when false locales/values are optional. values merges (only listed locales change; a null entry clears just that locale). Duplicate targets in one batch apply in order, last one wins. For a media prop, take the value from media_list_assets or media_import_from_url (shape in the data-model primer). When NOT to use: Don't use to write a value bound to a query result — not yet available via this server (ask the human to wire it up in Studio). Don't use to rename or hide an entity — use studio_update_section / studio_update_block. Cap is 50 writes per call; split larger jobs across calls. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","writes":[{"at":{"blockId":"c3e5g7j9l1n3p5r7t9v1"},"keyPath":["cta","label"],"value":"Shop now","locales":["en","de"]},{"at":{"sectionId":"b8h2k4m6p0r3t5v7c9d1"},"keyPath":["heading"],"values":{"en":"Sale","de":"Angebot"}}]} Response: { results, catalogVersion, warnings } — results is index-aligned with writes, each { writtenLocales, warnings }; catalogVersion is the component-catalog fingerprint at write time (once per batch); warnings is snapshot-level. On failure the whole batch is rejected atomically: the message is prefixed writes[<i>]: and detail.itemIndex (0-based) names the bad item. Catalog-drift errors (COMPONENT_NOT_FOUND / BLOCK_NOT_ALLOWED_IN_SLOT) carry detail.catalogVersion + detail.refresh.tool; locale errors (MISSING_LOCALES / INVALID_LOCALES) carry detail.allowed (the project locales). Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_update_block

ChatGPT
Update a block's studio metadata (label), visibility decorator, or rules. Pass only the top-level keys (studio, visibility, rules) you want to touch — omitted keys are preserved. visibility and rules are absolute-state: each provided object replaces the stored one in full. studio is shallow-merged: the studio keys you provide overwrite their stored values, other studio keys are preserved. When to use: Use to rename a block in the layer tree, change its visibility condition, or update its rules. Discover the blockId with studio_get_page_tree. When NOT to use: Don't use to change component props — use studio_set_static_props. Don't use to remove the block — use studio_delete_block. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","blockId":"c3e5g7j9l1n3p5r7t9v1","data":{"studio":{"label":"Primary CTA"}}} Response: { blockId, catalogVersion, warnings } — catalogVersion is the component-catalog fingerprint at write time. Catalog-related errors carry detail.catalogVersion + detail.refresh.tool; re-list with studio_list_components when either changes. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_update_page_variant

ChatGPT
Update a page variant's SEO metadata (title, description) and/or its Studio layer-tree label. SEO fields are localized via the same value / values / locales contract as a studio_set_static_props write item (always translatable), and merge per-locale — writing en never clobbers an existing de. Pass the fields under data; omitted keys are preserved. This edits PAGE-level metadata; it does not touch section/block props. When to use: Use to set or rewrite a page's SEO title/description, or to rename a variant in the layer tree. Read the current values first from studio_get_page_tree (its seo block returns the { <locale>: value } maps ready to edit). SEO is stored PER VARIANT — on a localized site, update each locale's variant (or pass every locale via values). When NOT to use: Don't use to edit a section or block's component props — use studio_set_static_props. Page and variant creation are not supported — ask the human to create them in Studio. Setting robots is not yet exposed. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","pageVariantId":"a1b2c3d4e5f6g7h8j9k0","data":{"seo":{"title":{"value":"Best Running Shoes","locales":["en"]},"description":{"values":{"en":"Shop our range.","de":"Entdecke unser Sortiment."}}}}} Response: { pageVariantId, writtenLocales, catalogVersion, warnings } — writtenLocales is { title?: string[]; description?: string[] }, the locales written per SEO field touched (absent for a label-only change). PAGE_VARIANT_NOT_FOUND means the id did not resolve; INVALID_LOCALES / MISSING_LOCALES carry detail.allowed (the project locales); INVALID_INPUT means data had no actionable key or a field set both value and values. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

studio_update_section

ChatGPT
Update a section's studio metadata (label) or visibility decorator. Pass the fields under data — data.studio (label) and/or data.visibility — that you want to touch; omitted keys are preserved. visibility is absolute-state: the provided object replaces the stored one in full. studio is shallow-merged: the studio keys you provide overwrite their stored values, other studio keys are preserved. When to use: Use to rename a section in the layer tree or change its visibility conditions. Read the current value with studio_get_section first so the overwrite is informed. When NOT to use: Don't use to change the section's component props — use studio_set_static_props. Don't use to remove a section — use studio_delete_section. Example call: {"projectId":"9m4e2mr0ui3e8a215n4g","sectionId":"b8h2k4m6p0r3t5v7c9d1","data":{"studio":{"label":"Above-the-fold hero"}}} Response: { sectionId, catalogVersion, warnings } — catalogVersion is the component-catalog fingerprint at write time. Catalog-related errors carry detail.catalogVersion + detail.refresh.tool; re-list with studio_list_components when either changes. Scoped to projectId. IDs (sectionId, blockId, pageVariantId, …) from one project are not valid in another.

collections_create_entry

Claude

collections_edit_array_items

Claude

collections_get_entry

Claude

collections_get_field

Claude

collections_get_schema

Claude

collections_list_collections

Claude

collections_list_entries

Claude

collections_publish_entries

Claude

collections_remove_array_items

Claude

collections_set_fields

Claude

distributr_create_feed

Claude

distributr_feed_health

Claude

distributr_feed_options

Claude

distributr_feed_readiness

Claude

distributr_get_feed

Claude

distributr_list_feeds

Claude

distributr_list_runs

Claude

distributr_source_fields

Claude

distributr_update_feed

Claude

feedback_file_report

Claude

feedback_get_report

Claude

feedback_list_reports

Claude

media_import_from_url

Claude

media_list_assets

Claude

project_list

Claude

studio_add_array_item

Claude

studio_add_block

Claude

studio_add_global_section_reference

Claude

studio_add_section

Claude

studio_delete_block

Claude

studio_delete_section

Claude

studio_get_capabilities

Claude

studio_get_component_schemas

Claude

studio_get_data_model

Claude

studio_get_page_tree

Claude

studio_get_prop

Claude

studio_get_section

Claude

studio_get_style_tokens

Claude

studio_list_components

Claude

studio_list_global_sections

Claude

studio_list_pages

Claude

studio_move_block

Claude

studio_move_section

Claude

studio_set_static_props

Claude

studio_update_block

Claude

studio_update_page_variant

Claude

studio_update_section

Claude

Capabilities

Writes

App Stats

95

Tools

ChatGPT, Claude

Platforms

Category

Productivity

Works with

ChatGPT
Claude

Data refreshed daily