voog-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| voog_list_sitesA | List all sites configured in the global voog.json. Returns [{name, host}, ...]. Call this first to see what sites are available before invoking any other voog_* tool. |
| articles_listA | List blog articles on the Voog site (simplified: id, title, path, public_url, published, published_at, updated_at, created_at, language_code, page_id). All filters optional. Read-only. |
| article_getA | Get full article details by id (title, path, body, autosaved_*, published_at, language, page, data, image, tags). Read-only. |
| article_createA | Create a new blog article. Required: page_id (the parent blog page), title. Optional: body (HTML), excerpt, description (meta), path (auto from title if omitted), image_id, tag_names (array), data (custom dict), publish (default false). Title and body go to autosaved_* fields per Voog convention; if publish=true, publishing:true is set so values copy to published fields atomically. NOT idempotent — repeat calls create multiple articles. |
| article_updateA | Update an existing article. Title/body/excerpt go to autosaved_* per Voog convention (the public fields are read-only — call article_publish to push autosaved → published). description/path/image_id/tag_names/data are non-autosaved fields and update directly. At least one field must be supplied.
|
| article_publishA | Publish an article. Voog only copies autosaved_* → published fields when publishing:true is sent in the SAME PUT as the autosaved values — that's why this needs a separate tool rather than a Two modes:
Mixed (some autosaved_* provided, some not) is rejected — the caller must be explicit. |
| article_deleteA | Delete an article. IRREVERSIBLE — Voog does not retain deleted articles. Requires force=true. |
| article_set_dataA | Set a single article.data. value (PUT /articles/{id}/data/{key}). To delete a key use article_delete_data. Keys starting with 'internal_' are server-protected and rejected client-side. |
| article_delete_dataA | Delete a single article.data. (DELETE /articles/{id}/data/{key}). IRREVERSIBLE — the key is removed permanently. Requires force=true; without it the call is rejected. Keys starting with 'internal_' are server-protected and rejected client-side. |
| cart_rules_listB | List all cart rules (GET /admin/api/ecommerce/v1/cart_rules). Read-only. |
| cart_rule_getB | Get a single cart rule by id (GET /admin/api/ecommerce/v1/cart_rules/{id}). Read-only. |
| cart_rule_createA | Create a cart rule (POST /admin/api/ecommerce/v1/cart_rules). Envelope {cart_rule: {...}}. Required: kind, target_kind, target_id, conditions[], result{}. Inner conditions[] entries are {value, comparator, field, value_type}. result is {value, field, value_type}. Inner key validation is left to Voog — invalid combos return a 422 with the offending field. |
| cart_rule_updateB | Update a cart rule (PUT /admin/api/ecommerce/v1/cart_rules/{id}). Envelope {cart_rule: {...}}. Partial — at least one field must be supplied. Common partial updates: enabled, position. |
| cart_rule_deleteA | Delete a cart rule (DELETE /admin/api/ecommerce/v1/cart_rules/{id}). Requires force=true. Past orders that already had the rule applied are not affected. |
| categories_listA | List all ecommerce product categories (GET /admin/api/ecommerce/v1/categories). Read-only. Each entry has id, name, slug, parent_id, depth, created_at, updated_at. Use category.id from the results as the products_list(category_id=...) filter. |
| category_getA | Get a single category by id (GET /admin/api/ecommerce/v1/categories/{id}). Read-only. |
| category_createB | Create a category (POST /admin/api/ecommerce/v1/categories). Envelope: {category: {...}}. Required: name. Optional: slug (auto-generated if omitted), parent_id (for sub-categories). NOTE: Voog does not support description / image_id on categories despite some doc pages suggesting otherwise — verified empirically 2026-05-27. |
| category_updateA | Update a category (PUT /admin/api/ecommerce/v1/categories/{id}). Envelope: {category: {...}}. Partial — at least one of name / slug / parent_id must be supplied. |
| category_deleteA | Delete a category (DELETE /admin/api/ecommerce/v1/categories/{id}). Requires force=true. Products in the category are NOT deleted; they're orphaned from the category. Voog may reject if the category has child categories. |
| comments_listA | List comments on an article ( |
| comment_deleteA | Remove a comment ( |
| comment_toggle_spamA | Flip a comment's spam flag ( |
| content_partial_updateA | Update a content partial (PUT /content_partials/{id}). Content partials are reusable template fragments embedded in pages and layouts. PUT body is flat (no envelope). At least one of |
| discounts_listB | List all ecommerce discounts (GET /admin/api/ecommerce/v1/discounts). Read-only. |
| discount_getB | Get a single discount by id (GET /admin/api/ecommerce/v1/discounts/{id}). Read-only. |
| discount_createB | Create a discount (POST /admin/api/ecommerce/v1/discounts). Envelope {discount: {...}}. Required: code. Empirically-verified enum values (rejected client-side with a clear error before round-tripping to Voog): status ∈ {open, closed} amount_mode ∈ {net, gross} discount_type ∈ {fixed, percentage} applies_to ∈ {cart, cart_and_shipping, categories, products, shipping} Optional: name, description, amount, valid_from (ISO8601), valid_to, redemption_limit, stackable, currency. |
| discount_updateA | Update a discount (PUT /admin/api/ecommerce/v1/discounts/{id}). Envelope {discount: {...}}. Partial — at least one discount field must be supplied. Enum-restricted fields (client-validated): status ∈ {open, closed}; amount_mode ∈ {net, gross}; discount_type ∈ {fixed, percentage}; applies_to ∈ {cart, cart_and_shipping, categories, products, shipping}. |
| discount_deleteA | Delete a discount (DELETE /admin/api/ecommerce/v1/discounts/{id}). Requires force=true. Already-used discount records remain on past orders; deletion only prevents future use. |
| ecommerce_settings_getA | Get ecommerce store settings (currency, tax_rate, value_date_days, default_language, decimal_places, company_name, bank_details, terms, privacy_policy, products_url_slug, etc.). Includes per-language translations. Read-only. |
| ecommerce_settings_updateA | Update ecommerce settings. attributes: flat root-level fields (currency, tax_rate, notification_email, ...). translations: nested {field: {lang: value}} for translatable settings (products_url_slug, terms_url, company_name, bank_details). Wraps payload in {settings: {...}} envelope. |
| elements_listA | List elements (id, title, path, page_id, element_definition_id, position). Optional filters: page_id, language_id, language_code, element_definition_id, element_definition_title, page_path, page_path_prefix. Pass include_values=true to include the values hash in the projection (off by default — values clutter list views; use element_get for full shape). Read-only. |
| element_getA | Get a single element by id, with full values hash. Use elements_list to find ids. |
| element_definitions_listA | List element definitions (id, title, property_keys — the field keys each definition expects). Use the returned id for element_create.element_definition_id. Read-only. Mutating definitions (POST/PUT/DELETE) is deferred — handle via voog_admin_api_call when needed. |
| element_createA | Create an element (POST /elements). Body is FLAT. Required: element_definition_id OR element_definition_title (id takes precedence per Voog docs); page_id; title. Optional: path (auto-generated from title if omitted), values (custom-properties hash matching the element_definition's schema). |
| element_updateA | Update an element (PUT /elements/{id}). Partial — supply ONLY the fields to change. Body is FLAT. Updatable: title, path, values. At least one besides element_id is required. |
| element_deleteA | Delete an element (DELETE /elements/{id}). Voog returns 204. Requires force=true; without it the call is rejected. Run elements_list first to confirm the id. |
| element_moveA | Re-order or re-parent an element instance ( |
| layout_renameA | Rename a layout (PUT /layouts/{id} {title}). Reversible — rename back to the original title to undo. The new title must not contain '/' or '\' or start with '.'. |
| layout_createA | Create a new layout or component (POST /layouts). kind='layout' for full templates (defaults content_type='page'; use 'blog_article' for blog post templates); kind='component' for shared partials (content_type ignored). Returns the new id. NOT idempotent — calling twice creates two separate layouts. |
| asset_replaceA | Rename a layout_asset by creating a new one with the desired filename (DELETE+POST workaround — Voog API rejects PUT with filename changes). Returns both old and new ids. The OLD asset is intentionally left in place; after updating templates that reference the old filename, delete the old asset manually with DELETE /layout_assets/{old_id}. |
| layout_updateA | Update a layout — body (Liquid template source), title, or both. At least one must be supplied. Reversible by calling again with the previous values; idempotent. |
| layout_deleteA | Delete a layout. IRREVERSIBLE — Voog does not retain deleted layouts. Refuses without force=true. Voog blocks deletion of layouts that still have pages assigned — the API returns an error, the layout is NOT deleted. Reassign those pages first via page_set_layout, then retry. Back up with site_snapshot before this operation. |
| layout_asset_createA | Create a layout_asset (CSS/JS/image). filename + asset_type + data required. asset_type ∈ {stylesheet, javascript, image, plain_text, video, pdf, ...}. For image uploads, use POST /assets + 3-step protocol via product_set_images instead — this tool is for text assets (CSS/JS/HTML fragments). |
| layout_asset_updateA | Update a layout_asset's content (PUT /layout_assets/{id} {data}). filename is read-only — Voog returns 500 if filename is sent on PUT. Use asset_replace to rename. |
| layout_asset_deleteA | Delete a layout_asset. IRREVERSIBLE. Refuses without force=true. Templates referencing the deleted file will render with empty content. |
| layouts_pullA | Fetch every layout + component from /layouts and write per-layout .tpl files to target_dir/layouts/ and target_dir/components/. Builds manifest.json mapping each local path to {id, type, updated_at}. REFUSES to overwrite an existing tree that already contains .tpl files — pick a fresh location or clear it first. Empty/non-tpl content in target_dir is fine (e.g. README.md, .gitignore are preserved). |
| layouts_pushA | Read manifest.json + .tpl files from target_dir and PUT each to /layouts/{id}. Optional files=["layouts/x.tpl", ...] filter pushes only the named relative paths. files=null (or omitted) pushes every type=layout entry in the manifest (non-layout entries — e.g. type=layout_asset from voog.py-pulled trees — are captured as per-file failures rather than mis-PUT to /layouts/{id}). Returns per-file success/failure breakdown; missing files and PUT errors are captured per-entry and do not abort the remaining pushes. Recommended pre-flight: site_snapshot for full backup before a mass push. |
| voog_list_my_sitesA | Probe |
| language_createA | Add a new language to the Voog site (POST /languages). Required: code (ISO 639-1 two-letter), title. Optional: region (ISO 3166-1 alpha-2), site_title, site_header, default_language, published, content_origin_id (duplicate content from another language). Body is FLAT — no envelope wrapper. |
| language_deleteA | Remove a language from the site (DELETE /languages/{id}). IRREVERSIBLE — Voog deletes the language and unbinds associated content. Requires force=true; without it the call is rejected. Run site_snapshot first if uncertain. |
| languages_listA | List all languages on the Voog site (id, code, title, default_language, published, position). Use the returned ids for page_create.language_id / article fields. Read-only. |
| nodes_listA | List all page nodes (id, title, parent_id, position). Each node represents a language-agnostic page identity; its parallel translations are pages sharing the same node.id. Read-only. |
| node_getA | Get a single node by id, with its full pages array — one entry per language. Use this when preparing a parallel translation: read the node id from one page, then pass node_id to page_create with the second-language details. |
| node_updateA | Update a node's title (PUT /nodes/{id}). Per Voog docs, only |
| node_moveA | Move/reorder a node within the page tree (PUT /nodes/{id}/move). Inputs travel as query-string params per Voog docs. Required: parent_id (current or new parent — pass current to just reorder). Optional: position (1-indexed, Voog default 1). |
| node_relocateA | Relocate a node to a precise position relative to a sibling, or to the first slot under a new parent (PUT /nodes/{id}/relocate). Body is FLAT. Supply EXACTLY ONE of: before (place this node before the given sibling id), after (place after sibling id), or parent_node_id (move to first position under new parent). Mutually exclusive — handler rejects multiple. |
| orders_listA | List ecommerce orders (GET /admin/api/ecommerce/v1/orders). Read-only. Optional filters: status (e.g. 'created', 'cancelled'), payment_status (e.g. 'paid', 'unpaid'), created_after (ISO8601), created_before (ISO8601). include_pii=false (default) strips customer email / name / address / phone / IP via whitelist; set include_pii=true for operator workflows that need the full payload. |
| order_getA | Get a single order by id (GET /admin/api/ecommerce/v1/orders/{id}). Read-only. include_pii=false (default) strips PII via whitelist. |
| pages_listA | List pages on the Voog site (id, path, title, hidden, layout name). All filters are optional; with no filters this returns every page. Read-only. |
| page_getA | Get full details of a single page by id (title, path, hidden, layout, language, parent, timestamps, public_url). |
| page_set_hiddenA | Bulk toggle the |
| page_set_layoutA | Reassign a page's layout. Reversible — call again with the original layout_id to revert. |
| page_deleteA | Delete a page. IRREVERSIBLE — Voog does not retain deleted pages. Requires force=true; without it the call is rejected to prevent accidental deletion. Run |
| page_createB | Create a new page. Required: title, slug, language_id. Optional: parent_id (page id, NOT node_id) for subpages, node_id for parallel-translation pages of an existing page in another language, layout_id, content_type ('page'|'link'|'blog'|'product'|...), hidden, image_id, description, keywords, data (custom dict). Multilingual: pass node_id of the first-language page instead of parent_id when creating its translation in another language. Voog binds them as parallels (admin Translate UI works correctly). parent_id and node_id are mutually exclusive. |
| page_updateA | Update arbitrary fields on a page. At least one of title, slug, layout_id, image_id, content_type, parent_id, description, keywords, data must be supplied. For just hidden / layout id, prefer the dedicated page_set_hidden / page_set_layout — they're more explicit in tool listings.
|
| page_set_dataA | Set a single page.data. value (PUT /pages/{id}/data/{key}). To delete a key use page_delete_data. Keys starting with 'internal_' are server-protected and rejected client-side. |
| page_delete_dataA | Delete a single page.data. (DELETE /pages/{id}/data/{key}). IRREVERSIBLE — the key is removed permanently. Requires force=true; without it the call is rejected. Keys starting with 'internal_' are server-protected and rejected client-side. |
| page_duplicateA | POST /pages/{id}/duplicate — create a copy of the page (including its content). The new page is hidden by default per Voog convention. |
| products_listA | List all ecommerce products on the Voog site (simplified: id, name, slug, sku, status, in_stock, on_sale, price, effective_price, stock, reserved_quantity, uses_variants, variants_count, translations, created_at, updated_at). Read-only. Same shape as the voog://products resource — consistent across the tools and resources surfaces. For per-variant stock on a variant-bearing product, follow up with product_get. Pass |
| product_getA | Get full product details by id, including the per-variant |
| product_updateA | Update a product. Three argument shapes (combinable):
|
| product_createA | Create a new product (POST /products on ecommerce v1). Required: name, slug, price (Voog rejects POST without these). Three argument shapes (combinable):
|
| product_deleteA | Delete a product (DELETE /admin/api/ecommerce/v1/products/{id}). IRREVERSIBLE — Voog does not retain deleted products. Requires force=true; without it the call is rejected to prevent accidental deletion. Run products_list or product_get first to confirm the id, and site_snapshot if the product might be needed later. |
| product_duplicateA | Duplicate a product (POST /admin/api/ecommerce/v1/products/{id}/duplicate). The new product inherits status='draft' per Voog default — call product_update(status='live') after editing if the duplicate should be public. Returns the new product's full payload; summary surfaces new_id and new title for easy chaining into product_update. |
| products_bulk_actionA | Apply the same actions to many products in one request (PUT /admin/api/ecommerce/v1/products). This is NOT per-row arbitrary updates — every product in target_ids receives every action in actions. For one-off varied edits use product_update. Request shape:
Response: {counters: {processed, failed}, processed_ids, failed_ids}. Duplicate ids in target_ids are collapsed server-side. No empirical batch-size cap observed up to 1001 ids (Stella, 2026-05-27); send what you need. |
| product_set_imagesA | Replace a product's images. |
| voog_admin_api_readA | Read-only Admin API passthrough. Forward a GET request to https:///admin/api. Use this when no typed read tool covers the endpoint (forms, tickets, tags, media_sets, etc.). Read-only — MCP hosts may skip the destructive-action confirmation prompt. |
| voog_ecommerce_api_readA | Read-only Ecommerce v1 API passthrough. Forward a GET request to https:///admin/api/ecommerce/v1. Supports ?include=... and ?language_code=.... Read-only — MCP hosts may skip the destructive-action confirmation prompt. |
| voog_admin_api_callA | Generic Admin API passthrough. Forward an HTTP request to https:///admin/api using the configured site's API token. method ∈ {GET, POST, PUT, PATCH, DELETE}; body is JSON-serialised on POST/PUT/PATCH. Use this when no typed tool covers the endpoint (orders, forms, tickets, elements, tags, media_sets, webhooks, etc.). Conservative annotations (destructiveHint=true) — Claude will confirm before calling. method='GET' is DEPRECATED in v1.4 — use voog_admin_api_read instead; GET support is removed in v1.5. |
| voog_ecommerce_api_callA | Generic Ecommerce v1 API passthrough. Forward an HTTP request to https:///admin/api/ecommerce/v1. Same shape as voog_admin_api_call, different base URL. Supports ?include=... and ?language_code=... per Voog ecommerce conventions. Use for orders, carts, discounts, shipping_methods, gateways, cart_fields, cart_rules, delivery_provider_configs, templates, bulk product actions, products imports, etc. method='GET' is DEPRECATED in v1.4 — use voog_ecommerce_api_read instead; GET support is removed in v1.5. |
| redirects_listA | List all redirect rules on the Voog site (id, source, destination, redirect_type, active). Read-only. |
| redirect_addA | Add a redirect rule. source/destination are paths (e.g. /old → /new). redirect_type defaults to 301; allowed: 301, 302, 307, 410. Set regexp=true to treat source as a regex pattern. Set active=false to create the rule disabled. For 410 (Gone), destination is semantically meaningless — Voog still stores it but never redirects there; pass any value (e.g. source path). |
| redirect_updateA | Update an existing redirect rule. At least one of source, destination, redirect_type, active, regexp must be supplied. redirect_type ∈ {301, 302, 307, 410}. Reversible by calling again with previous values. Voog's PUT /redirect_rules/{id} is full-replace — missing fields are coerced to defaults (e.g. active flips to True). The tool GETs the current rule, merges your updates, then PUTs the full envelope, so unspecified fields are preserved. |
| redirect_deleteA | Delete a redirect rule. Refuses without force=true. Reversible only by re-creating the rule via redirect_add. |
| voog_searchA | Full-text search across the site's published content ( |
| shipping_methods_listA | List all shipping methods (GET /admin/api/ecommerce/v1/shipping_methods). Read-only. Response includes the full options[] nested list for parcel-machine carriers (Omniva, SmartPost, …) — expect multi-KB payloads per method. |
| gateways_listB | List all payment gateways (GET /admin/api/ecommerce/v1/gateways). Read-only. Each entry has code, name, enabled, enabled_methods[], all_payment_methods[], url, created_at, updated_at. |
| site_getA | Get the site singleton (title, code, data, languages, ...). Read-only. |
| site_updateA | Update site singleton. attributes: flat root-level fields. site.code is immutable once set — passing it raises an error. For per-key data, use site_set_data. |
| site_set_dataA | Set site.data. to a value (PUT /site/data/{key}). To delete a key use site_delete_data. 'internal_*' keys are server-protected and refused client-side. |
| site_delete_dataA | Delete site.data. (DELETE /site/data/{key}). IRREVERSIBLE — the key is removed from site.data permanently. Requires force=true; without it the call is rejected. 'internal_*' keys are server-protected and refused client-side. |
| pages_snapshotA | Backup all pages + per-page contents to JSON files in output_dir. Creates the directory (and parents) if needed; overwrites existing pages.json. Lighter than site_snapshot — use this when you only need page structure and contents. |
| site_snapshotA | Comprehensive read-only backup of every mutable Voog resource: pages, articles, elements, layouts, layout_assets, languages, redirect_rules, nodes, texts, content_partials, tags, forms, media_sets, assets, webhooks, site, me, products (with translations + variant_types), per-page contents, per-article details, per-product details, and rendered HTML samples for VoogStyle capture. By default REFUSES to overwrite an existing directory — pick a fresh location. Pass overwrite=true to write into an existing directory (automation/cron use case); files from a prior snapshot may persist alongside new files if the underlying Voog state has shrunk. REQUIRED pre-flight before any risky operation: layout rename, mass push, layout swap, VoogStyle template push, page_delete. |
| tags_listA | List all tags on the site ( |
| tag_getA | Get a single tag by id ( |
| tag_deleteA | Remove a tag ( |
| text_getA | Get a text resource by id (GET /texts/{id}). Texts hold the body of |
| text_updateA | Update a text body (PUT /texts/{id} {body}). body is the raw HTML rendered into the page where the matching |
| page_add_contentA | Create a content area + linked text on a page (POST /pages/{id}/contents). Use this on freshly-created pages where /contents returns [] until the admin UI's edit-mode opens the page. name must match the layout's {% content %} tag — default 'body' for unnamed, 'gallery_1' for named. content_type defaults to 'text'; valid values: text, gallery, form, content_partial, buy_button, code. By default, the tool first GETs /pages/{id}/contents and refuses if a content area with the same name already exists — calling twice with the same name was silently creating duplicates. To edit the existing area, use text_update on its text.id. Pass force=true to skip the pre-check (legitimate use: page templates with multiple areas sharing the same name). |
| webhooks_listA | List all webhooks on the site (id, enabled, target, event, url, target_id, description). Use the returned id for webhook_update / webhook_delete. Read-only. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| Articles | All blog articles on the Voog site (simplified: id, title, path, public_url, published, published_at, updated_at, created_at, language_code, page_id — without bodies). Single article body (rendered HTML) at voog://{site}/articles/{id} as text/html. |
| Layouts | All layouts on the Voog site (simplified: id, title, component, content_type, updated_at — without bodies). Single layout body (raw .tpl source) at voog://{site}/layouts/{id} as text/plain. |
| Pages | All pages on the Voog site (simplified: id, path, title, hidden, layout, content_type, language, public_url). Per-page details available at voog://{site}/pages/{id}, page contents at voog://{site}/pages/{id}/contents. |
| Products | All ecommerce products on the Voog site (simplified: id, name, slug, sku, status, in_stock, on_sale, price, effective_price, stock, reserved_quantity, uses_variants, variants_count, translations, created_at, updated_at). Full product details with per-variant stock at voog://{site}/products/{id}. |
| Redirect rules | All redirect rules on the Voog site (id, source, destination, redirect_type, active). |
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/runnel/voog-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server