目录 / duckhub-mcp
MCP
需 API Key
未评级
已上架
duckhub-mcp
Hosted Model Context Protocol (MCP) server for Duckhub — connect Claude, Cursor, ChatGPT and other AI agents to build, translate and publish restaurant menus. 39 tools over a secure API. Docs: docs.duck-hub.com/mcp
该来源不提供完整文件导出(国内平台多为平台内托管),仅存元数据与原链
模型生成摘要(rules/v1 · 2026-09-27 16:28):Hosted Model Context Protocol (MCP) server for Duckhub — connect Claude, Cursor, ChatGPT and other AI agents to build, t…
这是模型对公开材料的总结,不是官方声明,请以原链内容为准。
这是模型对公开材料的总结,不是官方声明,请以原链内容为准。
接入信息
- 传输形态
- http
- 鉴权方式
- 需 API Key(需要配置:apiKey)
- 端点
https://duckhub-mcp--tykhokhod-d.run.tools
该服务需要凭证,请按官方文档申请后替换占位符
{
"mcpServers": {
"duckhub-mcp": {
"headers": {
"Authorization": "Bearer \u003cYOUR_KEY\u003e"
},
"url": "https://duckhub-mcp--tykhokhod-d.run.tools"
}
}
}
能力清单
| 工具 | 说明 |
|---|---|
| get_reference | Call this FIRST. Returns everything needed to use the other tools correctly: allowed enum values (units, badge colors, modifier types, card styles, currencies, usable languages), THIS venue’s plan limits and current usage, rate-limit budgets, order-status transitions, request caps, and the index of all API resources. Also documents conventions: all money amounts are integers in minor currency units. |
| get_menu | Read the venue’s current (draft) menu. view:"structure" (default) returns a tiny name↔ref map of categories/products — the cheapest overview; use it to learn existing refs before mutating. view:"full" returns every product with all fields (heavy — only when field-level detail is needed). Pass locale to resolve all translatable fields into that language. Rows are keyed by `ref` (externalId if set, else id). |
| build_menu | THE bulk tool: create or update the whole menu in one call — categories, ingredients and products (with composition, modifier groups and inline translations), all keyed by YOUR externalId and idempotent (safe to retry; re-running updates in place). For large or first-time payloads call with dryRun:true first — full validation and plan-limit checking with a create/update/skip preview and ZERO writes. CAUTION (replace semantics): when a product includes ingredientExternalIds, modifierGroups or modifierGroupExternalId, that array is treated as the FULL set and REPLACES what exists — anything unlisted is detached. For single-field edits of one product prefer the set_product tool (which never touches those arrays). Changes affect the DRAFT menu only — nothing is guest-visible until publish. Money is in minor units (12.50 → 1250). |
| list_products | Filtered, paginated product list. Default view:"summary" returns sparse rows (ref, name, price, flags — token-cheap); view:"full" returns complete product objects. Filters: category (ref), search (name), withoutDescription:true (only products missing a description — useful for content gap-filling). Pagination: page (1-based) + limit (max 50, default 15); the response envelope carries total/totalPages. Rows are keyed by `ref` (externalId if set, else id) — use refs with get_product/set_product/delete_product. |
| get_product | Full single-product read by ref (externalId or id). The result includes an `etag` field — pass it as ifMatch to set_product so a concurrent change is detected (412) instead of silently overwritten. Pass locale to resolve translated fields. |
| list_categories | Lightweight category index with live product counts, keyed by ref. Pass locale to resolve translated names. |
| set_product | Partial update of ONE product by ref — the safe alternative to build_menu for single-field edits. TRI-STATE semantics on every field: a field you OMIT keeps its current value; explicit null CLEARS it (nullable fields only); a value SETS it. Never resend fields you do not want to change. Composition and modifier groups are deliberately NOT editable here (their full-set replace semantics belong to build_menu). categoryRef: null detaches the product from its category; an unknown categoryRef is a hard 404. Concurrency: pass ifMatch with the etag from get_product — on 412 STALE_RESOURCE re-read and retry with the fresh etag. The result includes the NEW etag for chained edits. Money in minor units (12.50 → 1250). |
| delete_product | Soft-deletes ONE product by ref. Unlike cleanup_menu (which only HIDES products from the menu), this frees plan-limit capacity — deleted products no longer count toward maxProducts. Cannot be undone via the API. |
| list_publications | Publication history (rollback buffer, newest first, ~5 retained snapshots) with ids and timestamps. Use before rollback_publish to pick a snapshot. |
| publish_menu | Publishes the current DRAFT menu to the public guest-facing menu — takes effect immediately. All build_menu/set_product changes stay invisible to guests until this is called. Each publish keeps a snapshot in the rollback history (rollback_publish undoes a bad publish). |
| rollback_publish | Restores a retained snapshot as the LIVE public menu (undo for a bad publish) — replaces what guests currently see, immediately. Omit publicationId to roll back to the previous snapshot; otherwise pick an id from list_publications. |
| cleanup_menu | ⚠️ DANGEROUS BULK OPERATION with KEEP-LIST semantics: each array lists the externalIds to KEEP — everything else of that type is affected (products get HIDDEN from the menu [menuVisible:false, plan capacity NOT freed — use delete_product for that], categories and ingredients get DELETED). An omitted array leaves that type untouched; an EMPTY array wipes ALL items of that type and requires force:true. ALWAYS call with dryRun:true first — it returns counts plus a preview of exactly what WOULD be hidden/deleted, with zero writes. Typical use: after a full build_menu, remove leftovers not present in your source data. |
| get_settings | The complete curated settings view: venue info, working hours, SEO + social links, design, languages, ordering/delivery config, notification wiring — plus read-only context (publicMenuUrl = the live guest menu URL, lastPublishedAt). The result includes an `etag` field; the update_* settings tools handle concurrency automatically, so you normally never need it. |
| update_venue_info | Core venue identity: name, address, phone, Google-Maps link, Wi-Fi password, extra info text, country (ISO alpha-2, uppercase), cuisine type, IANA timezone, default currency. Valid currency codes are in get_reference → currencies. NOTE: renaming (name) changes the DISPLAYED venue name only — the public menu URL slug (yourvenue.duck-hub.com) is fixed at venue creation and never changes (protects printed QR codes and links). Omit = keep current value, null = clear, value = set. — null works only on country and cuisineType; leave other fields out to keep them. Returns a COMPACT delta — only this tool’s own fields plus the new etag — not the full settings object; read complete state via get_settings. |
| update_working_hours | schedule = the venue’s opening hours shown on the public menu (full 7-day array replaces the current one). orderSchedule = the separate hours during which ONLINE ORDERS are accepted — it is delivery-plan-gated: on a plan without the delivery feature setting it fails with 403 DELIVERY_NOT_AVAILABLE (plain schedule always works). Returns a COMPACT delta — only this tool’s own fields plus the new etag — not the full settings object; read complete state via get_settings. |
| update_menu_design | Public-menu look: theme (LIGHT/DARK), brandColor (#RRGGBB), menuFontFamily (font id — lowercase letters/digits/hyphens; null = default font), menuCardStyle (venue-wide card design — valid values in get_reference → cardStyles; per-category overrides live on categories via build_menu cardStyle). Returns a COMPACT delta — only this tool’s own fields plus the new etag — not the full settings object; read complete state via get_settings. |
| update_languages | defaultLanguage = the canonical content language; enabledLanguages = ALL locales the public menu offers (min 1, replaces the current list — include the default). Valid codes are in get_reference → languages. Enable a locale HERE first, then fill content via build_menu inline translations (a locale that is not enabled fails with LOCALE_NOT_ENABLED). Returns a COMPACT delta — only this tool’s own fields plus the new etag — not the full settings object; read complete state via get_settings. |
| update_seo_and_links | Search/social presence of the public menu page: seoTitle (max 60), seoDescription (max 160), googlePlaceId, and social/review links (Instagram, Telegram, TikTok, Twitter/X, TripAdvisor, Google Reviews). Omit = keep current value, null = clear, value = set. — null works on seoTitle, seoDescription and googlePlaceId. Returns a COMPACT delta — only this tool’s own fields plus the new etag — not the full settings object; read complete state via get_settings. |
| update_ordering_config | Online-ordering configuration — REQUIRES a plan with the delivery feature (get_reference → planLimits.features.hasDelivery); on other plans every field here fails with 403 DELIVERY_NOT_AVAILABLE. Toggles: deliveryEnabled, pickupEnabled, dineInOrderingEnabled. Money fields are integers in MINOR currency units (12.50 → 1250): minimumOrderAmount, deliveryFee, freeDeliveryThreshold. pickupDiscount is a PERCENT (0-100). Times are minutes. deliveryEmail receives order notifications. (Ordering HOURS live in update_working_hours → orderSchedule.) Returns a COMPACT delta — only this tool’s own fields plus the new etag — not the full settings object; read complete state via get_settings. |
| update_notifications | Staff-notification wiring: notify toggles (waiter call, hookah, bill request, booking, order) and the Telegram chat ids that receive them (telegramChatId for service actions, orderTelegramChatId for orders; null disconnects a chat). NOTE: every change here is recorded in the venue audit log — agents must not silently redirect staff notifications. Returns a COMPACT delta — only this tool’s own fields plus the new etag — not the full settings object; read complete state via get_settings. |
| set_image | Attach an image: target "product" or "banner" (ref required) or "logo" (venue logo, no ref). Source: EXACTLY ONE of sourceUrl (public https URL, server fetches it, ~15 MB cap) or base64 (inline bytes). Aspect rules: product and logo images must be SQUARE 1:1 — pass crop:"square" to have the server center-crop automatically; banner images must be 16:9 (no crop option). The server re-encodes/optimizes everything (WebP). preoptimized:true (product/banner only) uses the softer fast-lane rate bucket but REQUIRES the bytes to already be a target-size WebP — otherwise 400 PREOPTIMIZED_INVALID; when unsure, omit it. |
| set_translations | Cross-entity BULK translation upsert — up to 50 items in ONE call (one rate-limit hit) with per-item results (one bad item fails alone). Each item: model + ref (externalId or id) + translations. Translatable fields per model: product = name/description/badgeLabel; category/ingredient/modifierGroup = name; banner = title/description. translations accepts BOTH equivalent forms: the entries ARRAY [{"locale":"uk","name":"Піца"}] (canonical wire form) or the locale-keyed OBJECT {"uk":{"name":"Піца"}} — the SAME form build_menu inline translations use; the object form is normalized before sending. MERGE semantics per field: omitted = keep, empty string "" = delete that translation, non-empty = set. The locale must be enabled for the venue first (update_languages) — otherwise LOCALE_NOT_ENABLED. TIP: when building a menu from scratch, prefer inline `translations` on build_menu items; use this tool for after-the-fact localization passes. |
| get_translations | statsOnly:true → multilingual completeness in one call: per locale × model counts of translated/untranslated rows (no other params needed) — start here to find gaps. Otherwise a batch translation read: locale AND model are REQUIRED; filter narrows to untranslated/translated/stale rows; fields limits which fields return; refs scopes to specific entities. Rows are keyed by ref. Paginated (limit max 50). |
| list_modifier_groups | The venue’s reusable modifier-group library (restaurant-scoped option groups), keyed by ref, including usedOnProducts (which products each group is attached to). Attach groups to products via build_menu modifierGroupExternalId[]. |
| set_modifier_group | Upsert a REUSABLE modifier group (edit once, applies on every product it is attached to). Pass ref to UPDATE an existing group (only the provided fields change; options — when provided — REPLACE the whole option set); omit ref to CREATE (name + type required; set externalId so you can address it later). type: single_choice | add_ingredients | remove_ingredients — legacy multiple_choice is NOT accepted here (build_menu’s INLINE modifierGroups still accept it for backward compatibility and normalize it to add_ingredients; this tool takes canonical types only). Options reference ingredients by ingredientRef (externalId or id); priceAdjustment is in minor units and may be negative. Attach to products via build_menu modifierGroupExternalId[]; translate via set_translations. |
| delete_modifier_group | Deletes a reusable modifier group by ref. If the group is attached to any product the call fails with 409 MODIFIER_GROUP_IN_USE — pass force:true to detach it from every product and delete. |
| list_promotions | All promotions with their items (each item: productId, salePriceMinor, product summary). Paginated (limit max 100). Keyed by ref (externalId if set, else id). |
| set_promotion | Upsert a promotion in ONE call — pass ref to update, omit to create (name required; set externalId for stable addressing). Optional items[] is the FULL desired item set: the server diffs it against the current items and adds/updates/removes accordingly (item identity = the product; salePriceMinor in minor units). Products not listed are REMOVED from the promotion — omit items entirely to leave them untouched. isActive toggles the promotion AND syncs the products’ live sale prices. schedule = optional weekly activity hours (day/isOpen/HH:MM). NOT atomic: the result reports added/updated/removed/unchanged/errors per item — on partial failure the promotion and successful items ARE saved; re-run set_promotion with the same ref/externalId and the full desired items[] to converge (the diff is idempotent). |
| delete_promotion | Deletes a promotion by ref (externalId or id). Its items are removed with it and the affected products’ live sale prices are un-synced back to normal. Cannot be undone. |
| list_banners | Menu banners keyed by ref. Pass locale to localize title/description. Paginated (limit max 100). |
| set_banner | Upsert a menu banner: pass ref to update, omit to create (title required, max 60 chars; description max 2000; set externalId for stable addressing). linkedProductRef links the banner to a product (null clears the link). isActive shows/hides it. Upload the banner image (16:9) separately via set_image target:"banner". Plan-limited (BANNER_LIMIT_REACHED — check get_reference limits). Note on create with isActive: two internal steps (create, then set isActive) — if the second fails the banner EXISTS without it; re-run with ref (or the same externalId → the conflict hint points you at the existing banner). |
| delete_banner | Deletes a menu banner by ref (externalId or id), including its uploaded image. To just hide a banner temporarily, prefer set_banner with isActive:false. Cannot be undone. |
| list_tables | The venue’s tables keyed by ref — each row carries its guest QR-menu URL (qrUrl). Paginated (limit max 100). |
| set_table | Upsert a table: pass ref to update (name, isActive, floor-plan positionX/positionY, capacity), omit to create (name required, max 50; set externalId for stable addressing). The response includes the table’s guest QR-menu URL (qrUrl). Plan-limited (TABLE_LIMIT_REACHED — check get_reference limits). Note on create with extras (isActive/position/capacity): two internal steps (create, then patch extras) — if the second fails the table EXISTS without them; re-run with ref to finish. |
| delete_table | Deletes a table by ref (externalId or id) — its printed QR code stops resolving immediately. To take a table out of service temporarily, prefer set_table with isActive:false. Cannot be undone. |
| list_orders | Guest orders (paid plans only — 403 PAID_PLAN_REQUIRED on the free plan). Filters: status, since/until/updatedSince (ISO 8601). Paginated (limit max 100). Poll updatedSince for changes. |
| get_order | Full single-order read by order id (paid plans only — 403 PAID_PLAN_REQUIRED on the free plan). |
| update_order_status | Advances an order through its lifecycle (paid plans only). Allowed transitions are in get_reference → orderStatusTransitions (e.g. new → confirmed|cancelled); an invalid transition is rejected. Statuses: new, confirmed, preparing, delivering, completed, cancelled. |
| get_audit_log | What this API key changed and when — every v1 write is recorded (action, entity, timestamp). Filter by exact action (e.g. "menu.sync", "settings.update"); paginated (limit max 100, default 20). Useful to review your own session or debug unexpected state. |
纠错与举报(发现条目失效、署名有误或涉及侵权?)
提交举报 / 纠错
侵权举报经核验成立后,我们会即时下线该条目并删除已存的内容副本。