MCP Koongo
Koongo is an e-commerce solution that helps online merchants sell everywhere - connecting their product catalogue to 500+ sales channels through product feed…
Что умеет
- List Projects: List your projects. Each item is {projectId, code, name, apiStatus, dataStatus, language, customerId, customerEmail}. Call this FIRST when you don't know which project to act on, or whe
- List Feeds: List the customer's CREATED feeds (the feeds that already exist, not the catalog of types — use list_feed_templates for that). Each item is {feedId, projectId, feedCode, name, feedType, fi
- List Feed Templates: List the PUBLIC Koongo feed TEMPLATES available for a project — the catalog of feed TYPES you can create from (the feedCode source for create_feed). These are NOT the customer's e
Какие данные видит
Нужен ли аккаунт
Не нужен: сервер работает без входа
Koongo is an e-commerce solution that helps online merchants sell everywhere - connecting their product catalogue to 500+ sales channels through product feed management and marketplace integration, all from one place. This connector lets you run your Koongo account by chatting with Claude instead of clicking through the app: describe what you want, and Claude does it for you, showing each step before it commits.
With Koongo MCP you can: • Browse and inspect your projects, feeds, marketplaces and ads • Create and configure integrations for a wide range of sales and advertising channels - Google Shopping, Amazon, eBay, Kaufland, Bol, Zalando, Cdiscount and many more - through their step-by-step wizards • Map channel (output) attributes to your store fields, fixed values or rules • Map your store categories to each channel's category tree • Enrich products with new attributes (for example an AI-derived colour, material or size) and reuse them across feeds • Build, filter, verify and export product feeds • Track and manage marketplace orders and order connections
Built-in safety: anything that would publish products to a live channel is protected by a confirmation step, and you can ask Claude to set MANUAL mode and publish a single product as a dry run before releasing the rest.
Who it's for: online merchants and agencies who manage product feeds and marketplace listings with Koongo and want to get things done in plain language - no technical skills required.
You sign in securely with your own Koongo account via OAuth (or a personal token). Claude only ever acts on the projects your account can access.
Список инструментов сервера (60)
Технические названия из tools/list. Нужны только разработчикам.
| list_projects | List your projects. Each item is {projectId, code, name, apiStatus, dataStatus, language, customerId, customerEmail}. Call this FIRST when you don't know which project to act on, or when another tool returns project_id_required. Let the user pick, then pass the chosen projectId to the other tools. When you own a single project you usually don't need this — the other tools infer it. Pass `query` to search projects by name, code, or owner email. IMPORTANT: if the call returns an EMPTY list, do not assume there are no projects — some accounts only return projects that MATCH a search term, so ask the user what to look for (a project name/code or the owner's email) and retry with a `query`. A broad search may be capped, so keep the query specific. apiStatus GRANTED = active; REVOKED/OVERLIMIT projects are listed too so the user sees them. After the user picks, the usual next step is get_import_status for that projectId. |
| list_feeds | List the customer's CREATED feeds (the feeds that already exist, not the catalog of types — use list_feed_templates for that). Each item is {feedId, projectId, feedCode, name, feedType, fileFormat, channelCode, status, feedUrl, lastRunAt}. project_id is OPTIONAL: with it you get that project's feeds; WITHOUT it you get your feeds across ALL your projects (each item carries its projectId). If a call returns project_id_required, pick a project (see list_projects) and pass its project_id. feedId is the per-project id you pass as feed_id to get_feed / verify_feed_attributes. Integration-managed feeds are excluded; only standalone feeds are returned. Returns all matching feeds in one call; not paginated. |
| list_feed_templates | List the PUBLIC Koongo feed TEMPLATES available for a project — the catalog of feed TYPES you can create from (the feedCode source for create_feed). These are NOT the customer's existing feeds (use list_feeds for those). Each item is {feedCode, name, type, fileType, channelCode, country}. project_id is OPTIONAL: omit it when the customer has a single project (it is inferred); if they have several you get project_id_required — call list_projects and pass one. Pass `query` as a BROAD coarse filter — ideally just the channel/marketplace name (e.g. 'google'); do NOT put country/format/language words in it, because feed codes are cryptic and a literal match will miss. Instead match the user's request (country e.g. CZ/Czech/Česko, format e.g. xml, type e.g. product vs promotions) against the STRUCTURED fields of the returned items yourself — word order and synonyms don't matter. Show the best matches, let the user confirm which feedCode, then call create_feed. Returns all matching templates in one call; not paginated. |
| create_feed | Create a Koongo product feed for a project. feed_code MUST be one returned by list_feed_templates. Returns {feedId, feedCode, status, customerId, editUrl, categoryMappingNeeded}. project_id is OPTIONAL: omit it when the customer has a single project (it is inferred); if they have several you get project_id_required — call list_projects and pass one. If categoryMappingNeeded is true, map its categories with list_unmapped_categories + search_target_categories + set_category_mapping (pass the returned feedId as feed_id). The core next step is to MAP output attributes: call get_feed + list_source_attributes, then map_feed_attribute per attribute (category mapping only covers categories, not attributes). Requires the project's data imported (dataStatus='ok', see get_import_status). If the plan's channels limit is reached, the call is refused with error 'quota_reached' (HTTP 403) + addonCode + upsellUrl — show the upsellUrl and do not retry (see PLANS, ADDONS & UPGRADES). |
| get_feed | Get the full detail of one feed: identity + state + the attribute mapping (how each output column is sourced). Returns {feedId, projectId, feedCode, name, feedType, fileFormat, channelCode, status, enabled, taxonomyCode, taxonomyLocale, feedUrl, exportOutOfStock, attributeCount, requiredUnmappedCount, attributes:[{code, label, platformCode, constant, composedValue, required, hidden, valueSource, defaultPlatformCode, defaultConstant, allowedValues, formatType, ruleId, ruleName, ruleEnabled, priceAttribute, currency, currencyConversionEnabled}]}. hidden=true means the attribute is internal and must NEVER be mapped or surfaced in output; valueSource is rule|composed|attribute|constant|unmapped; allowedValues is the closed value set (empty = open). ruleId/ruleName/ruleEnabled describe an attached Attribute Rule (null when none); valueSource is 'rule' only when the rule is ENABLED — an attribute with ruleId set but ruleEnabled=false has a rule attached-but-disabled that does NOT drive its value (it reads as its other source, or 'unmapped'), so surface it and offer to enable it. priceAttribute=true marks a money attribute (formatType price / price_with_delete); currency is its target currency and currencyConversionEnabled whether Koongo converts the value into it (null = not a price attribute) — only relevant when the price is in a DIFFERENT currency than the store; if the attribute's name already names a currency (label/code contains "EUR") the value is ALREADY in it, so set currencyConversionEnabled=false to avoid double conversion. requiredUnmappedCount is how many REQUIRED attributes still have no working source (valueSource='unmapped'); 0 means the attribute form is solved and the feed can export. Map source attributes with map_feed_attribute (see list_source_attributes). The response also includes settings (the feed's channel output settings): currency/number-format (read-only here) plus stock {stockInValue, stockOutValue, stockAvailabilityAttribute} and shipping {shippingDependentAttribute, shippingMethodName, shippingIntervals:[{from,to,cost}]} — the stock and shipping settings are EDITABLE via set_feed_settings. feed_id is the id from list_feeds / create_feed. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). A soft-deleted feed returns error 'feed_deleted' (not 'not_found') — the id is still valid and the feed can be brought back with restore_feed; it just won't appear in list_feeds while deleted. Use get_feed for configuration/mapping and get_feed_status for run progress. Requires the project's data imported (dataStatus='ok', see get_import_status). |
| get_feed_status | Get the runtime status of one feed: generation state, progress, last run/submit and any error. Returns {feedId, projectId, feedCode, status, enabled, progressPercent, productsCount, lastRunAt, submitStatus, lastSubmitAt, fileExists, errorMessage}. status is one of new|pending|processing|generated|submited|error|overlimit. Next action per status: generated → verify_feed_attributes then submit_feed; processing/pending → keep polling; error → read errorMessage, fix, export_feed; overlimit → feed exceeds the plan limit. Use get_feed for configuration/mapping and this tool for run progress. feed_id is the id from list_feeds / create_feed. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| get_feed_output | Read the CURRENT output of a feed's already-generated file WITHOUT regenerating it — so it works on a read-only connection (unlike export_feed, which regenerates the file and is a write action). Use this to see what a feed currently contains: its live download URL, product count and a sample of the actual rows, instead of downloading the file and counting it yourself. Inputs: feed_id (the feed's id from list_feeds / create_feed), project_id (OPTIONAL — inferred for a single-project customer; project_id_required if they have several, then call list_projects), sample_size (default 20, max 20), offset (default 0 — skip this many rows to read a deeper page; page by increasing offset in steps of sample_size). Returns {feedId, projectId, feedCode, fileFormat, feedUrl, fileExists, fileSize, productsCount, lastGeneratedAt, sampleRowCount, sample:[{field: value}, ...]}. feedUrl is the public download URL of the current file; productsCount is exactly the number of rows in that file; lastGeneratedAt is when it was last generated. fileExists:false means the feed has not been generated yet — call export_feed, then poll get_feed_status until it is generated. The sample rows are real feed data returned only after you set acknowledge_sensitive:true. The first call (flag absent/false) returns {sensitiveGate:{confirmationRequired:true, itemCount, fields, kind}} with `sample` EMPTY (all the metadata is still returned) — present that gate to the USER, get approval, then re-call with acknowledge_sensitive:true to receive the rows. |
| export_feed | Trigger a (re)generation of the feed file. Returns {feedId, action:'export', status, feedStatus}. status is 'queued' (async via the export queue — normal) or 'done'. After this, poll get_feed_status until status becomes 'generated'. feed_id from list_feeds / create_feed; project_id OPTIONAL. |
| pause_feed | Pause (disable) a feed — it stops being exported/submitted on schedule. Returns {feedId, action:'pause', status:'disabled', feedStatus, enabled:false}. feed_id from list_feeds / create_feed; project_id OPTIONAL. |
| resume_feed | Resume (re-enable) a paused feed. Returns {feedId, action:'resume', status:'enabled', feedStatus, enabled:true}. feed_id from list_feeds / create_feed; project_id OPTIONAL. |
| delete_feed | Delete a feed (soft delete — the generated file and config are removed but it can be restored with restore_feed). DESTRUCTIVE: confirm with the user first, then call with confirm:true. Without confirm:true the call returns error 'confirm_required' (HTTP 400) and nothing is deleted. Returns {feedId, action:'delete', status:'deleted'}. feed_id from list_feeds; project_id OPTIONAL. |
| restore_feed | Restore a soft-deleted feed and re-export it. Use this when a feed was deleted (delete_feed) — get_feed (and other feed actions) report a deleted feed as error 'feed_deleted', which is recoverable; list_feeds simply omits it while deleted — or when the user asks to bring a feed back. The feed id stays valid after deletion; this reverses it. Returns {feedId, action:'restore', status:'restored'}. feed_id from the feed_deleted error or an earlier list_feeds; project_id OPTIONAL. |
| submit_feed | Submit a generated feed to its sales channel (only meaningful for API channels with a connection; file feeds that the channel pulls are not submitted). The feed must be generated first (status='generated' from get_feed_status) — otherwise returns error 'feed_not_generated'. Returns {feedId, action:'submit', status, feedStatus, message}. status is 'submitted' (ok), 'not_submittable' (channel doesn't accept submissions), or 'failed' (with message). feed_id from list_feeds / create_feed; project_id OPTIONAL. Recommended: run verify_feed_attributes before submitting. |
| update_feed | Edit a feed's basic settings: rename (name) and/or enable/disable (enabled). Provide at least one. Returns {feedId, status, changed:[...], name, enabled, revisionBefore, revisionAfter}. status is 'updated' or 'no_changes'. feed_id from list_feeds / create_feed; project_id OPTIONAL. NOTE: attribute mapping and product-filter editing are NOT supported here yet — only name/enabled. For enable/disable only, pause_feed/resume_feed are equivalent; use update_feed when also renaming. |
| verify_feed_attributes | File-level check of a feed's attribute mapping (reads the generated feed file). Inputs: feed_id (the feed's id from list_feeds / create_feed), project_id (OPTIONAL — inferred for a single-project customer; project_id_required if they have several, then call list_projects), sample_size (default 20, max 20), offset (default 0 — skip this many items to verify a deeper page of the feed; page by increasing offset in steps of sample_size). Returns deterministic findings against the generated feed file: missingSource (required attributes with no source in the config), emptyInOutput (required attributes empty in the sampled items), specViolations (values outside the channel's allowed set), plus the feed `spec` (required + allowedValues per attribute) and a `sample` of items {field: value}. After reading the deterministic findings, YOU do the semantic pass: over `sample` vs `spec`, judge whether open-ended values (titles, descriptions, urls, prices, categories) look correct/plausible for the channel, then summarise the problems and suggest concrete config fixes in the feed. status is ok | issues_found | file_missing (file_missing = the feed hasn't been generated yet). The sampled feed rows and violation values are real data returned only after you set acknowledge_sensitive:true. The first call (flag absent/false) returns {sensitiveGate:{confirmationRequired:true, itemCount, fields, kind}} with the sample rows / violation values EMPTY — present that gate to the USER, get their approval, then re-call with acknowledge_sensitive:true to receive the actual values. To fix findings: map_feed_attribute for each, then export_feed, then re-run this tool. |
| list_source_attributes | List the source attributes the store provides that a feed column can be mapped from (the valid platform_code values for map_feed_attribute) — e.g. brand, ean, price, color, category_name. Returns {attributes:[{code, label, dataType}], returned, total}. Pass feed_id for full parity with the feed editor (adds the feed's taxonomy_* attributes); project_id alone omits taxonomy. Call this BEFORE map_feed_attribute to choose a valid platform_code. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). Requires the project's data imported (dataStatus='ok', see get_import_status). Returns all attributes in one call (returned === total); not paginated. |
| map_feed_attribute | Set where one feed attribute's value comes from. Target the output attribute by `code` (from get_feed). Set `platform_code` to a source attribute (from list_source_attributes) to map it, and/or `constant` for a fixed value; `default_platform_code` / `default_constant` are the fallback used when the primary source is empty. `rule_id` attaches a product rule (Attribute Rule, from list_rules / create_rule) — the attribute's value is then computed by that rule; send rule_id:"" to detach it (revert to platform_code/constant), and rule_enabled:false to attach it disabled. To re-enable an attached-but-disabled rule, send its rule_id (from get_feed) together with rule_enabled:true — rule_enabled cannot travel alone. Provide at least one field (send an empty string to clear a text field). rule_id together with platform_code/constant in the same call is contradictory and is rejected. Setting a source (platform_code/constant) on an attribute that currently has a rule DETACHES that rule (source and rule are mutually exclusive; changed then includes rule_id). SAVE-ONLY: persists the mapping and bumps the revision but does NOT regenerate the feed — call export_feed afterwards for the change to reach the output. Map only attributes returned by get_feed. Returns {feedId, code, status, changed:[...], reason, revisionBefore, revisionAfter}; status is 'updated' | 'no_changes' | 'rejected' (reason: unknown_attribute | unknown_source_attribute | value_not_allowed | unknown_rule). (rule_id together with platform_code/constant is a request-level invalid_request/400, not a 'rejected' reason.) project_id is OPTIONAL (inferred for a single-project customer). Attributes flagged hidden in get_feed are internal plumbing and cannot be mapped by regular users; skip them. PRECEDENCE: a feed value is resolved rule → composed → platform_code → constant (valueSource 'rule' is a Rule). If an attribute's valueSource (from get_feed) is 'composed', its value comes from a composed rule, so a platform_code/constant you set here is silently overridden — change composed values in the Koongo UI (the feed's editUrl). A 'rule' value source (a Rule), however, is settable here via rule_id. |
| get_import_status | Check whether a project's store data is connected, imported and fresh before advising on feeds/mapping. Returns {projectId, code, apiStatus, dataStatus, lastImportAt, progressPercent, productsCount, categoriesCount, lastRun:{...}, recentRuns:[{status, type, startedAt, endedAt, productTotal, productsAvailable, errorMessage, importTimeSeconds, running}]}. apiStatus is GRANTED|REVOKED|OVERLIMIT; dataStatus is not_imported|pending|processing|ok|error|suspend|stopped (the project-wide state — map only when 'ok'). recentRuns lists the latest runs newest-first, each tagged by type (normal|partial|api_source|additional_source|upgrade) and running (true while pending/processing); lastRun is the newest of them. Use recentRuns to verify a specific enrichment import: after set_api_source/set_ai_source with apply:true (or run_import), poll here until the newest run of that type (api_source for set_api_source, additional_source for set_ai_source) has running:false and status 'ok' — THEN the new attribute is available in list_source_attributes / list_api_sources and you can map it or continue the integration. A run with status 'error' → read its errorMessage and run_import to retry. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). When dataStatus='ok', proceed to preview_products then list_feed_templates. |
| get_project_profile | Get a project's catalog product profile so you can recommend suitable sales channels for it. Returns {projectId, marketCategories:[{name, score, source}], stats:{productsCount, productsTotal, categoriesCount, avgPrice, medianPrice, currency, eanFillRate, eanBucket, metricsSyncedAt}}. marketCategories is the AI-detected catalog VERTICAL, ordered by score DESC — the first is the dominant vertical (e.g. 'Fashion & Accessories', 'Home & Decoration'); score is 0–1 confidence, source is ai|manual; the list is empty when the catalog has not been categorised yet. stats are catalog aggregates: avgPrice/medianPrice are in `currency`; eanFillRate is the 0–1 EAN/GTIN coverage and eanBucket its coarse form none|low|medium|high; a null means not-yet-computed (metricsSyncedAt shows how fresh the price/EAN figures are). Use the dominant vertical + price band + EAN coverage to suggest fitting marketplaces/ads: cross-reference list_marketplace_channels / list_ad_channels and propose ONLY channels whose `available` is true, then walk the create/configure wizard. Never invent channels that aren't in the catalog. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| preview_products | Get a page of the project's imported products with their real source-attribute values, so you can inspect the data and advise on feed mapping (e.g. see that `brand` holds "Nike" or `color` holds hex codes). Returns {products:[{id, type, attributes:{<sourceCode>:<value>}}], returned, requested, total, offset, hasMore, nextOffset}. attributes keys are source attribute codes (as in list_source_attributes); only catalogued, non-sensitive attributes are included — cost/margin and internal fields are never returned, and empty values are omitted. sample_size is the page window (default 5, max 100); page through the whole catalog with offset — when hasMore is true, re-call with offset=nextOffset until hasMore is false. project_id is OPTIONAL (inferred for a single-project customer). Data must be imported first (see get_import_status). This tool returns real product data values only after you set acknowledge_sensitive:true. The first call (flag absent/false) returns {sensitiveGate:{confirmationRequired:true, itemCount, fields, kind}} with an EMPTY products array — present that gate to the USER, get their approval, then re-call with acknowledge_sensitive:true to receive the actual values. To review the full generated feed output for every product (not just source attributes), use export_feed instead of paging this preview — that is the intended bulk path. Next: pick a template (list_feed_templates) and map attributes (map_feed_attribute). |
| set_feed_filter | Set a feed's product filter — which products reach the output. Common flags: export_out_of_stock (include items with zero stock), export_variants_as_single (export child variants instead of the parent), export_removed_products (no = only active | yes = all incl. removed | only = removed only). Category filter: category_ids (store category ids from list_store_categories) with category_operator include|exclude (default include); category_ids:[] clears the category filter (export all categories). Provide at least one field; a field you omit is left unchanged. SAVE-ONLY: persists and bumps the revision but does NOT regenerate the feed — call export_feed afterwards. Returns {feedId, status, changed:[...], reason, revisionBefore, revisionAfter}; status is 'updated' | 'no_changes' | 'rejected' (reason: invalid_value | unknown_store_category). project_id is OPTIONAL (inferred for a single-project customer). |
| set_feed_attribute_filter | Set (or clear) a feed's ATTRIBUTE filter: conditions on source attributes that decide which products export, joined by combination 'and' | 'or' (default 'and'). Each condition is {attribute, operator, value}: attribute is a source attribute code (from list_source_attributes); operator is one of equals, not_equals, contains, not_contains, starts, not_starts, ends, not_ends, empty, not_empty, greater, greater_or_equal, less, less_or_equal, regex, not_regex, is_true, is_false; value is the comparison string (omit for empty / not_empty). Pass conditions:[] to CLEAR the attribute filter. This is separate from the category filter (set_feed_filter). To include or exclude out-of-stock products use export_out_of_stock on set_feed_filter — NEVER build a qty/stock condition here. SAVE-ONLY: persists and bumps the revision but does NOT regenerate — call export_feed afterwards. Returns {feedId, status, changed, reason, revisionBefore, revisionAfter}; status is 'updated' | 'no_changes' | 'rejected' (reason: invalid_value | unknown_source_attribute | invalid_condition). project_id is OPTIONAL (inferred for a single-project customer). |
| set_feed_settings | Set a feed's general output settings: SHIPPING cost and STOCK. Send `shipping` and/or `stock`; within each object only the keys you include change (omitted keys are left as-is). shipping: {dependent_attribute (a source attribute code from list_source_attributes the cost depends on, e.g. weight/price — '' clears it), method_name (free text), intervals (the cost table — REPLACES the whole set; each row {from, to, cost} numeric with 0 <= from <= to <= 1000000 and cost >= 0; intervals:[] clears all rows)}. stock: {in_value (the value exported when a product is In stock), out_value (the value when Out of stock), availability_attribute (a source attribute code exported as availability when out of stock — '' clears it)}. Provide at least one of shipping / stock. To rename the feed use update_feed (the feed name is not set here). SAVE-ONLY: persists and bumps the revision but does NOT regenerate the feed — call export_feed afterwards. Read the current values from get_feed (settings). Returns {feedId, status, changed:[...], reason, revisionBefore, revisionAfter}; status is 'updated' | 'no_changes' | 'rejected' (reason: invalid_value | unknown_source_attribute | invalid_interval). project_id is OPTIONAL (inferred for a single-project customer). |
| list_store_categories | List the project's store categories (the source side of category mapping and of a feed's category filter). Returns {categories:[{id, name, path}], returned, total, hasMore, nextOffset}; `path` is the full breadcrumb (e.g. "Electronics > Computers > Laptops"). Use the ids with set_category_mapping (map store categories to a marketplace category) or set_feed_filter (category_ids). project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). Paginated: default limit 200, max 1000. When hasMore is true, call again with offset = nextOffset and keep paging until hasMore is false to see every category. |
| get_category_mapping | Get the current category-mapping rules for a taxonomy (store categories → marketplace/taxonomy categories). The rule set is SHARED per project + taxonomy_code + locale (every feed on that taxonomy sees it). Address the taxonomy either by feed_id (its taxonomy is used) OR explicitly by taxonomy_code (+ optional taxonomy_locale). Returns {taxonomyCode, taxonomyLocale, rules:[{type, operator, storeCategoryIds, storeCategoryPaths, attribute, value, targetHash, targetPath}], total}. Use list_unmapped_categories to find gaps, search_target_categories to find a target, and set_category_mapping to fill them. project_id is OPTIONAL (inferred for a single-project customer). |
| list_unmapped_categories | List the project's store categories that have NO mapping rule yet for a taxonomy — the gaps to map. Address the taxonomy by feed_id (its taxonomy is used) OR explicitly by taxonomy_code (+ optional taxonomy_locale). Returns {categories:[{id, name, path}], returned, total, taxonomyCode, taxonomyLocale, hasMore, nextOffset}. For each gap, find a target with search_target_categories and map it with set_category_mapping. project_id is OPTIONAL (inferred for a single-project customer). Paginated: default limit 200, max 1000. When hasMore is true, call again with offset = nextOffset and keep paging until hasMore is false to see every gap. |
| search_target_categories | Search a feed's target taxonomy tree (marketplace categories) by a substring of the category path. Address the taxonomy by feed_id (its taxonomy is used) OR explicitly by taxonomy_code (+ optional taxonomy_locale). Returns {categories:[{hash, name, path}], returned, total, taxonomyCode, taxonomyLocale}; pass a returned `hash` as target_hash to set_category_mapping. `query` matches the full path (e.g. 'laptop', 'shoes'); `limit` bounds the results (default 50). project_id is OPTIONAL (inferred for a single-project customer). |
| set_category_mapping | Map store categories to marketplace/taxonomy categories. Address the taxonomy by feed_id OR explicitly by taxonomy_code (+ optional taxonomy_locale). `rules` is a list of {store_category_ids:[...], target_hash} — each maps those store categories (ids from list_store_categories / list_unmapped_categories) to one target (hash from search_target_categories); a store category already mapped is re-pointed to the new target. The rule set is SHARED per project+taxonomy+locale, so if OTHER feeds use this taxonomy the call returns status=mapping_exists_requires_confirm (HTTP 409) with affectedFeedIds — re-call with confirm:true to apply. SAVE-ONLY: persists but does NOT regenerate — call export_feed afterwards. Returns {taxonomyCode, taxonomyLocale, status, rulesWritten, reason, affectedFeedIds}; status is 'updated' | 'no_changes' | 'mapping_exists_requires_confirm' | 'rejected' (reason: no_taxonomy | unknown_target | unknown_store_category | empty_rules). project_id is OPTIONAL (inferred for a single-project customer). |
| discover_rule_operations | Discover the vocabulary for building a product rule (an attribute-value transformation — the feature Koongo's UI and help call "Attribute Rules" / "Rules"). GUARDRAIL: a Rule must never be keyword-matching — if a value would need MORE THAN 3 text-`contains` conditions to derive (color, material, gender… from free text), STOP and enrich per-product with set_api_source/set_ai_source instead of building the Rule. A Rule patches FEED OUTPUT only and writes NOTHING onto the products; if the user asked to enrich the products, use set_api_source/set_ai_source (or ask first) — never substitute a Rule. Call this FIRST, before you write a rule, so you use only supported operations, conditions and arguments. Returns {operations:[{name, label, group, returnType, valueType, math, attributeVariant, arguments:[{name, label, type, required, options, placeholder, optionsSource}]}], conditions:[{operator, label, group, disabledFor, arguments}], ruleSchema, examples:[{title, description, rule, sampleProduct, expectedValue}]}. A rule document has the shape {name, description, category, icon, rules:[...]}. Each rule is {sortId (int, precedence — the server reassigns it 1,2,3… by position on save), enabled (bool), type, conditions (a condition tree, optional), operationGroups:[{mode, parentMode, attributes:[...], operations:[{name, arguments:{key:value}}]}]}. A rule's `conditions` (when present) is a combine node {type:"combine", operator:"and"|"or", conditions:[ {type:"expression", attribute, operator, value} | nested combine]} — a single condition is a combine wrapping one expression, and the comparison value always goes in the expression's `value` (an operator's arguments only describe that value's input). AUTHOR the unconditional "Default Rule" FIRST, then the "Conditional Rule" exceptions — the server normalizes to that shape and reassigns sortId 1,2,3…; among conditionals a lower sortId is evaluated first and the Default Rule (at most one) is the fallback. Match a condition value's type to its attribute: a numeric attribute (dataType integer/double from list_source_attributes) needs a NUMBER not a quoted string (the server casts on save), and a text operator (disabledFor includes "number": contains/starts_with/ length_exceeds/*_any/…) on a numeric attribute is REJECTED — use greater/less/equals instead. Operations in a group run left-to-right and chain by type: an op's valueType is its INPUT and returnType its OUTPUT, so each op's returnType must match the next op's valueType. The Rules help's text "Functions" (trim, upper/lower case, strip HTML, base64…) are the single textoperations operation via its function argument; collection "Functions" (sort, unique, join, first non-empty…) are the Collections-group operations. An operation's `arguments` object keys come from that operation's argument spec here; enum arguments accept only the listed options ids. Filter to one operation group with `group`; set detail 'full' for the complete argument specs and 'compact' (default) for a lighter list. include_conditions adds the condition operators; include_examples adds curated end-to-end worked examples. VALUE / OPTIONS MAPPING (the map_attribute_value operation) remaps a source attribute's store values onto a target/channel attribute's allowed set (the CP "store value → channel value" table). Its search and replace arguments are ARRAYS OF OBJECTS {value:'<string>'} paired by index (search[i] → replace[i], SAME length) — NOT plain-string arrays. Plain strings save without error but map nothing (empty rows in the UI, passthrough at runtime) — the #1 gotcha. replace is OPTIONAL (the CP "AI Mapping (unmapped)" autofills the rest) but provide it for deterministic output. A source value NOT listed in search passes through UNCHANGED (no implicit default), so for a CLOSED target allowed-value set either map EVERY value or add a Default Rule (set_value) fallback, otherwise unmapped values violate the channel spec. Place it in an operationGroup with mode:'single', attributes:['<source code>']. SET OPTION (the setoption operation) assigns an attribute a fixed value from its CLOSED option list: put it in an operationGroup mode:'set_option', attributes:[], operations:[{name:'setoption', arguments:{value: '<option value>'}}] — value is the option VALUE, not its label. More generally, an argument whose spec has optionsSource (e.g. 'feedAttribute') means its value must be one of the target attribute's options — read them with get_attribute_options. ALWAYS validate_rule a rule before create_rule / update_rule. |
| validate_rule | Validate a product rule (Attribute Rule) WITHOUT saving it. ALWAYS call this before create_rule / update_rule and fix every error first. Pass the full rule document as `rule` — {name, description, category, icon, rules:[{sortId, enabled, type, conditions, operationGroups:[{mode, parentMode, attributes, operations: [{name, arguments:{key:value}}]}]}]} (see discover_rule_operations for the operation/condition/argument vocabulary). Returns {valid, errors:[{path, code, message}], warnings:[{path, code, message}], dryRun}. Errors are blocking — the rule will be rejected on save; warnings are advisory. If you also pass a sample_product (a flat {attributeCode:value} record, e.g. from preview_products) and the rule is structurally valid, the server dry-runs it and returns dryRun:{matchedRuleSortId, computedValue, usedAttributes} so you can confirm the output before saving. This tool NEVER writes. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). When you do NOT pass sample_product, the server auto-samples a real product to compute dryRun, so the computedValue is real data returned only after you set acknowledge_sensitive:true: the first such call (flag absent/false) returns {sensitiveGate:{confirmationRequired:true, itemCount, fields, kind}} with the computedValue EMPTY — present that gate to the USER, get their approval, then re-call with acknowledge_sensitive:true. (If you passed your own sample_product you already hold that data, so no gate applies and the computedValue is returned directly.) DRY-RUN LIMITATION: AI-group operations — notably map_attribute_value (value/options mapping) — are NOT executed by the dry-run. It returns valid:true with computedValue = the input UNCHANGED (passthrough) even when the mapping is correct; this is expected, not a bug, so do NOT treat the unchanged value as a failure. Verify a value/options mapping only AFTER a real build/export: feed → export_feed then verify_feed_attributes; marketplace/ad → repair_marketplace / run_marketplace_operation (or the ad equivalents) then get_*_report. |
| list_rules | List the product rules (Attribute Rules) available to a project. Returns {rules:[{ruleId, name, description, category, scope, usageCount}], returned, total}. usageCount is how many feed attributes currently use the rule. `scope` selects which library to list: 'project' (default) = the project's own rules; 'shared_template' = the reusable shared template library; 'all' = both. Optionally pass `query`: a case-insensitive SUBSTRING match on the rule NAME only (a coarse pre-filter — rule names are not unique, so confirm the match yourself and disambiguate when more than one matches). Use get_rule to fetch a rule's full rules[]. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). Returns all rules in one call (returned === total); not paginated. |
| get_rule | Get the full definition of one product rule (Attribute Rule), including its verbatim rules[] (round-trippable — you can edit it and pass it back to update_rule). Returns {ruleId, name, description, category, scope, rules, createdAt, updatedAt}. rules[] is {sortId, enabled, type, conditions, operationGroups:[{mode, parentMode, attributes, operations:[{name, arguments}]}]} (see discover_rule_operations). `scope` selects the library: 'project' (default) or 'shared_template'. An unknown rule_id returns error 'not_found'. rule_id is from list_rules. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| create_rule | Create a NEW product rule (an Attribute Rule). GUARDRAIL: a Rule is NEVER a substitute for per-product enrichment — if you would need MORE THAN 3 text-`contains` conditions (contains/contains_any/starts_with on a description/title) to derive a value (color, material, gender…), do NOT create a Rule; enrich instead with set_api_source/set_ai_source and map that source attribute (see the server ENRICH guidance). A Rule patches FEED OUTPUT only and writes NOTHING onto the products; if the user asked to enrich the products / add attribute X to the products, use set_api_source/set_ai_source (or ask first) — never substitute a Rule. ALWAYS validate_rule it first and fix every error. Pass the full rule document as `rule` — {name, description, category, icon, rules:[{sortId, enabled, type, conditions, operationGroups:[{mode, parentMode, attributes, operations:[{name, arguments:{key:value}}]}]}]} (see discover_rule_operations for the vocabulary). Any _id/id you include is IGNORED — the server always mints a new one (this tool never overwrites an existing rule; use update_rule for edits). `scope` selects where it is created: 'project' (default) = the project's own library; 'shared_template' = the reusable shared template library (a template_read_only error means your access cannot write there). Returns {ruleId, scope, status, changed, reason, validation}; status 'created' on success, or 'rejected' with the validation errors when the rule is invalid (HTTP 200, nothing written). SAVE-ONLY: a new rule has NO effect on any feed until you attach it to a feed attribute with map_feed_attribute (rule_id) and then export_feed; a shared_template rule affects no feed at all until it is used by a project. VALUE/OPTIONS MAPPING: for a map_attribute_value operation, search and replace are arrays of {value:'<string>'} objects paired by index (NOT plain strings — plain strings save but map nothing, showing empty rows); replace optional. That op is not executed by validate_rule's dry-run (passthrough computedValue) — verify only after a real export/build. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| update_rule | Update an EXISTING product rule (Attribute Rule). ALWAYS validate_rule the new document first and fix every error. Identify the rule by rule_id (from list_rules / get_rule) and pass the full rule document as `rule` — {name, description, category, icon, rules:[{sortId, enabled, type, conditions, operationGroups: [{mode, parentMode, attributes, operations:[{name, arguments:{key:value}}]}]}]}. The safe pattern is: get_rule, edit the returned document, validate_rule, then update_rule with it. Only name, description, category, icon and rules are editable; usage/bookkeeping fields are preserved server-side. A get_rule document already carries map_attribute_value search/replace in the correct {value:'<string>'}-objects form (paired by index) — edit those entries verbatim, never flatten them to plain strings (plain strings save but map nothing). update_rule keeps ruleId + every attachment, so the edit updates all attributes using this rule; the value/options mapping is not run by validate_rule's dry-run — verify after a real export/build. `scope` selects the library: 'project' (default) or 'shared_template' (a template_read_only error means your access cannot write there). Returns {ruleId, scope, status, changed, reason, validation}; status 'updated' / 'no_changes' on success, or 'rejected' with the validation errors when invalid (HTTP 200, nothing written). SAVE-ONLY: the edit reaches a feed's output only after export_feed on the feeds that use this rule. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| delete_rule | Delete a product rule (Attribute Rule) and unlink it from every feed attribute that uses it. DESTRUCTIVE: a rule may shape a live feed — check its usageCount with list_rules / get_rule first, warn the user, then call with confirm:true. Without confirm:true the call returns error 'confirm_required' and nothing is deleted. Identify the rule by rule_id (from list_rules). `scope` selects the library: 'project' (default) or 'shared_template' (a template_read_only error means your access cannot write there). Returns {ruleId, scope, status:'deleted', changed, reason, validation}. Any feed that used this rule reverts to its other value source; run export_feed on those feeds to refresh their output. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| get_value_mapping_inputs | Get the inputs needed to build a value-mapping rule (Attribute Rule) that remaps a source attribute's values onto a target attribute's allowed set (e.g. store colours → the channel's accepted colour list). Works for BOTH a feed and a marketplace/ad. This is for value→value MAPPING (the map_attribute_value operation); to just assign ONE fixed value from an attribute's option list (a "Set option") use get_attribute_options instead. Returns {sourceValues:[{value, label}], targetAllowedValues:[{value, label}], alreadyMapped:[{search, replace}], hasMore, nextOffset}. sourceValues are the distinct values of source_attribute_code in the store; targetAllowedValues are the values target_attribute_code accepts on the target; alreadyMapped are the pairs already configured. YOU propose the search→replace pairs from these two lists — this tool runs no AI and never writes. Apply the pairs by adding a map_attribute_value operation (arguments search/replace) to the rule via create_rule / update_rule, then attach the rule (map_feed_attribute / map_marketplace_attribute / map_ad_attribute with rule_id); values you leave unmapped pass through unchanged for the user to finish manually. search/replace on the map_attribute_value op you build from these are arrays of {value:'<string>'} objects paired by index (NOT plain strings). Pass only_unmapped:true to get only source values that still need a pair; page with offset (from nextOffset) while hasMore is true. TARGET: pass EXACTLY ONE of feed_id (a feed, from list_feeds) or integration_id (a marketplace/ad — the marketplace_id/ad_id from list_marketplaces / list_ads); integration_id resolves the integration's attributes. The attribute codes come from get_feed / get_marketplace_attributes / get_ad_attributes / list_source_attributes. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). This tool returns real store data values only after you set acknowledge_sensitive:true. The first call (flag absent/false) returns {sensitiveGate:{confirmationRequired:true, itemCount, fields, kind}} with the sourceValues / alreadyMapped arrays EMPTY — present that gate to the USER, get their approval, then re-call with acknowledge_sensitive:true to receive the actual values. |
| get_attribute_options | Get the allowed OPTION choices (value + label) of a target feed/channel attribute, so you can pick a VALID value for a "Set option" — an attribute that takes a fixed value from its predefined list (select/dropdown attributes like Fastener Type, Availability, Condition…). Returns {options:[{value, label}], hasMore, nextOffset}. The stored/exported value is the option's `value` (NOT its label); label is the human-readable text (often equal to value). Two ways to apply a Set option once you pick a value: WITHOUT conditions set the attribute's constant to that value via map_feed_attribute / map_marketplace_attribute / map_ad_attribute (cheapest — no rule needed); CONDITIONALLY build a rule with a setoption operation (operationGroups mode 'set_option', operations [{name:'setoption', arguments:{value:'<option value>'}}]) — see discover_rule_operations. Empty options = the attribute is not a closed-option attribute (free text — use set_value instead). Page with offset (from nextOffset) while hasMore is true. TARGET: pass EXACTLY ONE of feed_id (a feed, from list_feeds) or integration_id (a marketplace/ad — the marketplace_id/ad_id from list_marketplaces / list_ads). attribute_code comes from get_feed / get_marketplace_attributes / get_ad_attributes. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| set_ai_source | Store per-product values that YOU (the client's own model) extracted, as a new 'AI source' attribute — so a feed rule can read the attribute directly instead of matching free text with `contains`/conditions. Typical flow: call preview_products to read products, derive ONE value per product with your own reasoning (e.g. the color, gender, or material from the title/description), then call this with `values` as a JSON OBJECT (not an array) mapping each product's `id` (the `id` field from preview_products) to the extracted value. `code` is the new attribute name (e.g. "ai_color"); once applied it becomes the source attribute custom_<code> (visible in list_source_attributes). Send large catalogs in BATCHES: first batch mode:"replace", following batches mode:"append"; set apply:true on the LAST batch only, to materialize (this re-imports the additional sources so the values land on products — an ASYNCHRONOUS import). VERIFY before using it: poll get_import_status until the newest additional_source run in recentRuns has running:false and status 'ok', and the code appears in list_source_attributes; only THEN attach the attribute to a feed with map_feed_attribute. If that run errors, run_import retries without re-sending the values. `handle` overrides the product key to join on (default header.id, which matches the preview_products `id`). project_id is OPTIONAL (inferred for a single-project customer). Requires the additional-sources addon: without it the call is refused with error 'addon_required' (HTTP 403) + addonCode + upsellUrl — show the user the upsellUrl so they can unlock it, and do not retry. Returns {status:'written'|'applied', code, url, valueCount, applied}. |
| list_ai_sources | List the AI sources currently registered on a project (attributes populated via set_ai_source). Returns {items:[{code, url, handle}]} — `code` is the attribute name (available as custom_<code> once applied), `handle` the product key it joins on. project_id is OPTIONAL (inferred for a single-project customer). |
| delete_ai_source | Remove an AI source (its CSV + registration) by `code` so it is no longer applied on future imports. Set apply:true to re-import now. NOTE: the custom_<code> values already written onto products are NOT immediately erased — they clear on the next full product import. project_id is OPTIONAL (inferred for a single-project customer). Requires the additional-sources addon: without it the call is refused with error 'addon_required' (HTTP 403) + addonCode + upsellUrl — show the upsellUrl and do not retry. Returns {status:'deleted'|'not_found', code, applied}. |
| set_api_source | Store per-product values that YOU (the client's own model) computed, as a new 'API source' attribute — written straight into the project's data store (no CSV, no join handle) — so a feed rule can read the attribute directly instead of matching free text with `contains`/conditions. PREFER this whenever a rule would otherwise need a long or complex condition tree. Typical flow: call preview_products to read products, derive ONE value per product with your own reasoning (e.g. the color, gender, or material from the title/description), then call this with `values` as a JSON OBJECT (not an array) mapping each product's `id` (the `id` field from preview_products) to the computed value. Values keep their JSON type — send a NUMBER for a numeric attribute (so numeric rule operators work), a boolean, or a string; a null clears that product. `code` is the new attribute name (e.g. "ai_color"); once applied it becomes the source attribute api_source.<code> (visible in list_source_attributes). Send large catalogs in BATCHES: first batch mode:"replace", following batches mode:"append"; set apply:true on the LAST batch only, to materialize (this re-imports so the values land on products — an ASYNCHRONOUS import). VERIFY before using it: poll get_import_status until the newest api_source run in recentRuns has running:false and status 'ok', and the code appears in list_source_attributes; only THEN attach the attribute to a feed with map_feed_attribute or reference api_source.<code> in a rule (create_rule / update_rule). If that run errors, run_import retries without re-sending the values. `code` must not collide with an existing source attribute of another class. project_id is OPTIONAL (inferred for a single-project customer). Requires the additional-sources addon: without it the call is refused with error 'addon_required' (HTTP 403) + addonCode + upsellUrl — show the user the upsellUrl so they can unlock it, and do not retry. Returns {status:'written'|'applied', code, valueCount, applied}. |
| list_api_sources | List the API source attribute codes registered on a project (populated via set_api_source; usable in rules as api_source.<code>). Returns {codes:[...]}. project_id is OPTIONAL (inferred for a single-project customer). |
| delete_api_source | Remove an API source attribute by `code` from every product so it is no longer applied. Set apply:true to re-import now (otherwise it clears on the next import). project_id is OPTIONAL (inferred for a single-project customer). Requires the additional-sources addon: without it the call is refused with error 'addon_required' (HTTP 403) + addonCode + upsellUrl — show the upsellUrl and do not retry. Returns {status:'deleted', code, applied}. |
| run_import | (Re)run an ENRICHMENT import to materialize previously-written source values onto products, WITHOUT re-sending them. Use it to retry after an import failed or is stuck, or to apply values you wrote with apply:false (set_api_source / set_ai_source). `source` picks which import: "api_source" (the set_api_source values, land as api_source.<code>) or "additional_source" (the set_ai_source CSV values, land as custom_<code>). This does NOT change the stored values — it only dispatches the same import the apply:true flag fires. Returns {status:'dispatched'|'skipped', type}; 'skipped' means the project's store data is not connected (apiStatus not GRANTED) so nothing ran. The import is asynchronous — after dispatch, poll get_import_status until the newest run of this type in recentRuns has running:false and status 'ok', then the attribute is available in list_source_attributes. project_id is OPTIONAL (inferred for a single-project customer). Requires the additional-sources addon: without it the call is refused with error 'addon_required' (HTTP 403) + addonCode + upsellUrl — show the user the upsellUrl so they can unlock it, and do not retry. |
| koongo_knowledge | Fetch Koongo help/reference knowledge ON DEMAND — glossaries and deep-detail topics kept out of the always-loaded instructions to save context. Call with NO args for the topic index (slug + title + summary); with `slug` for one topic's full body (plus a canonical help url when available); with `query` to keyword-search the corpus. Reach for it when you need to interpret a marketplace/ad listing status or item status (from list_*_items / get_*_item_report / *_status / *_report), or need the reference for the product filter, value/options mapping, currency conversion, or safe activation. Topics: listing-and-item-status, product-filter, value-and-options-mapping, currency-conversion, safe-activation. Read-only. |
| list_marketplaces | List the CREATED marketplace integrations of a project — the marketplace integrations that already exist, not the catalog of channels you can add (use list_marketplace_channels for that). Each item is {integrationId, projectId, name, channelCode, kind, definitionCode, status, ready, lastStep, isReady, isConnected, isOverlimit, productMode, orderMode, orderSync}. The response wrapper is {integrations, returned, total}. project_id is OPTIONAL: with it you get that project's marketplaces; WITHOUT it you get marketplaces across ALL your projects (each item carries its projectId). If a call returns project_id_required, pick a project (see list_projects) and pass its project_id. integrationId is what you pass as marketplace_id to get_marketplace / marketplace_status and the other marketplace tools. |
| list_marketplace_channels | Search the CATALOG of marketplace channels you can ADD — every sales channel (Amazon, eBay, Kaufland, Bol, Zalando, comparison sites, …) you can create a marketplace integration for (to list the marketplaces that ALREADY exist, use list_marketplaces). The catalog is large (many country variants), so it is SEARCHABLE + PAGED: pass query to match a channelCode/label (e.g. "amazon"), and page with limit/offset (the response carries hasMore + nextOffset). Response = {channels, returned, total, kind, hasMore, nextOffset}; each channel = {channelCode, label, kind, available, availabilityReason, authType, orderSyncSupported, multichannel, multichannelCode, primaryChannelCode, devOnly, upgradeUrl, appstoreUrl, feedManagerUrl}. available=false means you cannot add it now and availabilityReason says why: 'plan_limit' (upgradeUrl to upgrade the plan), 'appstore' (appstoreUrl — available in the Koongo App), or 'fallback' (feedManagerUrl — connect it via Feed Manager). authType is oauth|credentials|null. Use channelCode with get_marketplace_channel (to see the definition types + capabilities) and then create_marketplace. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| get_marketplace_channel | Get, for ONE marketplace channel, the integration TYPES it supports and each type's capabilities. Returns {channelCode, label, kind, devOnly, multichannel, multichannelCode, definitions:[{definitionCode, type, typeLabel, label, versionType, primary, capabilities:{orderSync, categoryMapping, productFilter, attributeMapping}}]}. kind is always 'marketplace' here. versionType is 'primary' or 'secondary' and primary marks the default definition. capabilities tell you what a given definition supports (order sync, category mapping, product filtering, attribute mapping). Call this before create_marketplace to choose the right definition for the channel. channel_code is the channelCode from list_marketplace_channels. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects and pass its project_id). |
| create_marketplace | Create a new marketplace integration for a project from one of the channels in list_marketplace_channels. channel_code is the channelCode from list_marketplace_channels. Returns {integrationId, action:'create', status, kind:'marketplace', editUrl, nextStepType, message}. status is 'created' (the marketplace exists; continue with configure_marketplace_step starting at nextStepType) or 'prerequisite_not_met' (HTTP 409 — message explains what must be done first, e.g. an offer/primary feed must exist first, a plan limit is reached (the message carries the upgrade link — see PLANS, ADDONS & UPGRADES), or the primary channel must be created first — see nextStepType). primary_sync marks this as the primary product source; order_sync enables order synchronization if the channel supports it; multichannel_code links a multichannel definition when the channel offers one (see get_marketplace_channel). definition_code picks a SPECIFIC definition of the channel when it has more than one (e.g. Amazon/Kaufland expose 'Offers' AND 'New Products') — take it from get_marketplace_channel definitions[].definitionCode; OMIT it to create the channel's default/primary definition. (versionType primary/secondary in get_marketplace_channel tells the definitions apart; it is NOT the same as primary_sync, which just marks this integration as the primary product source.) name is an OPTIONAL human-readable label so you can later find this marketplace by name (names are not unique — set_marketplace_name can change it later). project_id is OPTIONAL (inferred for a single-project customer; if project_id_required is returned, call list_projects). |
| get_marketplace | Get the full detail of one marketplace: identity + state + the configuration wizard steps. CRITICAL — read activationBehavior in the RESULT: 'summary_step_activates_and_submits_all' means completing the wizard's SUMMARY step ACTIVATES the marketplace and publishes EVERY matching product to the LIVE channel (spends budget), so to test safely set MANUAL mode FIRST (set_marketplace_product_mode) — it then reads 'summary_step_activates_no_auto_submit' and activation auto-submits nothing; 'already_active' = already live. Returns {integrationId, projectId, name, channelCode, kind, definitionCode, status, ready, lastStep, isReady, isConnected, isOverlimit, primarySync, orderSync, canEnableOrderSync, productMode, orderMode, taxonomyCode, categoryMappingRequired, connectionStatus, connectionMessage, connectionExpiresAt, steps:[{type, label, sort, index, ready, current, fields:[{code, label, type, required, options, optionsSource, htmlAttributes, value, help, showIf, hiddenIf}]}], editUrl, activationBehavior}. kind is 'marketplace'. steps describe the setup wizard: 'current' is the next step to configure (via configure_marketplace_step, targeting it by its index — two steps can share a type) and 'ready' marks completed steps. fields is the step's input schema: for a form/order-settings step, build configure_marketplace_step payload {items:{code:value}} from it — required marks mandatory fields, options is the allowed value set (value→label), htmlAttributes carry constraints, value is the current value. Steps with an empty fields list take a structured payload instead (category mapping / product filter / attribute table). The connection/auth step (OAuth or credentials) is NOT configurable via MCP: the user completes it in the browser / Koongo UI, and configure_marketplace_step returns oauth_required / credentials_in_ui for it — terminal, never retry it with a payload. Each marketplace owns exactly ONE connection (never shared): connectionStatus is its health (NEW / OK / WARNING / ERROR / EXPIRED), connectionMessage/connectionExpiresAt add detail, and test_marketplace_connection re-checks it live. taxonomyCode is set AUTOMATICALLY from the channel and is READ-ONLY — it cannot be changed via MCP; category mapping (a wizard step) maps your store categories TO this fixed taxonomy, and categoryMappingRequired says whether that step applies. Secrets are never returned. ORDER SYNC: orderSync is whether this marketplace pulls orders (adds an 'order-settings' step); orderMode is the active on/off state (enabled/disabled/null). canEnableOrderSync:true means order sync is not on yet but the channel allows it — you may offer enable_marketplace_order_sync to add it (then configure the order-settings step and set_marketplace_order_mode enabled:true to start). marketplace_id is the id from list_marketplaces / create_marketplace. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). Use get_marketplace for configuration and marketplace_status for run progress. |
| marketplace_status | Get the live run status of one marketplace: readiness, connection, and product/order counts. Returns {integrationId, status, ready, lastStep, isReady, isConnected, isOverlimit, productsRefreshing, productsSubmitting, productStats:{listed, processing, errors, inactive, total}, orderStats:{total, synced, error, pending}, upgradeUrl}. productStats counts the listing on the channel; orderStats is present only when order sync is enabled. isOverlimit=true means the plan product limit is exceeded — upgradeUrl then points to the plan upgrade. productsRefreshing=true means an export / feed generation is running (the integration is 'updating'); productsSubmitting=true means items are being pushed to the channel. While EITHER is true the data is still changing — this is the signal to WAIT: after any export (finishing the wizard summary, repair_marketplace, a step transition that re-exports, or a submit) poll marketplace_status until BOTH productsRefreshing AND productsSubmitting are false, THEN read the results. The KOONGO DATA CHECK (get_marketplace_report's dataCheckErrors) and the productStats counts are only current once the refresh has finished — reading mid-refresh gives stale/empty data. marketplace_id is the id from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). Use marketplace_status for run progress and get_marketplace for configuration/mapping. For the detailed error breakdown use get_marketplace_report. |
| configure_marketplace_step | Configure ONE step of a marketplace's setup wizard. CRITICAL: configuring the SUMMARY step FINISHES + ACTIVATES the marketplace — in AUTO product mode that publishes EVERY matching product to the LIVE channel (spends budget), so to test safely set MANUAL mode FIRST (set_marketplace_product_mode) and submit one item with run_marketplace_item_action; check activationBehavior in get_marketplace before finishing. Marketplaces are set up step by step IN ORDER: call this repeatedly, targeting each step the previous result reported as nextStepType, until nextStepType is null (setup complete). Identify the step by step_index (from get_marketplace steps[].index) — REQUIRED to disambiguate when two steps share a step_type (e.g. two 'form' steps: Identifiers and Offer Features); step_type alone targets the FIRST step of that type. Configuring out of order or before prerequisites are met returns 'prerequisite_not_met' / 'step_not_available' (e.g. category mapping precedes the attribute step). PAYLOAD: for a form / order-settings step, payload = {items: {fieldCode: value, ...}} built from that step's fields (get_marketplace steps[].fields — each field is {code, label, type, required, options, optionsSource, htmlAttributes, value, help}); send ONLY the fields you want to change — the others keep their current value and nothing is deleted. For a dropdown/options field the value is the field's NUMERIC option id (from that field's options / optionsSource), NOT the attribute code — e.g. set external_product_id to the option id that maps your GTIN/barcode/SKU source attribute, never the string "barcode"/"ean"/"sku"; read steps[].fields[].options first. Structured steps use their own payload: the product-filter step accepts attribute_filter (the condition tree as a JSON string, or "" to clear it), category_filter (a JSON string {categories_operator, categories:[...]}), and the flag export_out_of_stock ("0"|"1"); send ONLY what changes — it merges over the current filter, so the untouched flags/filters are kept. To include or exclude out-of-stock products use the export_out_of_stock flag — NEVER put a qty/stock condition in attribute_filter (it is an invalid state and is rejected). (export_children_as_parent and export_removed_products are managed in the Koongo UI and CANNOT be set here — sending either is rejected.) category-mapping and mapping-table likewise take their own payload. Returns {integrationId, stepType, status, ready, lastStep, nextStepType, oauthUrl, transitions[], message}. When transitions[] reports a product export/generation (e.g. moving into the summary/preview), that runs ASYNC — poll marketplace_status until productsRefreshing AND productsSubmitting are false before reading get_marketplace_report (its dataCheckErrors = the KOONGO DATA CHECK) or trusting counts. status: 'saved' (applied; transitions[] lists automation that ran), 'oauth_required' or 'credentials_in_ui' (a CONNECTION step — see below; TERMINAL, do not retry), 'prerequisite_not_met' / 'step_not_available', or 'validation_failed' (the message lists the field problems — unknown field, value outside its options, non-numeric value, or missing required field — fix them using the step's fields). CONNECTION IS NOT CONFIGURABLE HERE: the connection/auth step (credentials, API keys, OAuth, auth settings) can NEVER be set through MCP — this is intentional and permanent for security, not a limitation to work around. When a step returns 'oauth_required' or 'credentials_in_ui', that status is FINAL for that step: do NOT resend it, do NOT guess field codes or a payload, do NOT keep retrying — the result will not change (it is not transient and not a validation error you can fix). Hand the returned oauthUrl (OAuth) or editUrl (credentials, entered in the Koongo UI) to the USER, then STOP and wait; once they finish, re-check marketplace_status (isConnected) and continue with the NEXT step. marketplace_id is from list_marketplaces / create_marketplace. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| get_marketplace_report | Get the validation report for one marketplace: the aggregated errors and warnings that block or degrade its listing, with fix suggestions. The errors are SPLIT into two groups (as in the CP's two separate views). Returns {integrationId, errorCount, warningCount, statusCounts:[{status, count}], listingStatusCounts:[{status, count}], dataCheckErrors:[...], channelErrors:[...]}, where each error is {source, field, message, code, level, count, fixSuggestions:[{type, stepType, label}]}. dataCheckErrors = the pre-submission KOONGO DATA CHECK (feed-generation validation, source='export' — the same the wizard summary/preview shows, produced when the feed is generated BEFORE anything reaches the channel). channelErrors = the marketplace's OWN responses AFTER submission (source='adapter'/'api_error' — the integration detail). errorCount/warningCount are the COMBINED totals across both groups. Data-check errors exist only after a generation has run — finish the wizard, or repair_marketplace to (re)generate; export is async, so poll marketplace_status until productsRefreshing AND productsSubmitting are false, then read the report. statusCounts is how many items sit in each koongo processing status (e.g. completed / error / pending); listingStatusCounts the same by channel listing status (e.g. active / rejected / error). level is error|danger(=warning)|info; count is how many products hit that error. fixSuggestions.type is add_category_mapping|fix_settings|rewrite_attribute| exclude_product, and stepType (when set) names the wizard step to open with configure_marketplace_step. This is the marketplace-wide breakdown; for a single product's report use get_marketplace_item_report. marketplace_id is the id from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| list_marketplace_items | List the individual listing items of one marketplace — the per-product rows of what is (or should be) listed on the channel. Applies to marketplace integrations. Returns {integrationId, total, returned, items:[{itemId, koongoProductId, parentId, productType, status, channelStatus, listingId, listingUrl, hasErrors, errorCount}]}. status is the Koongo-side listing state; channelStatus is the channel's own state; listingId / listingUrl are the item's identity on the channel. Rows carry only identifiers and statuses — never a raw product attribute VALUE — so no confirmation is needed here; to see an item's actual attribute value plus its full error report, use get_marketplace_item_report (which gates the value behind a user confirmation). Filter with koongo_status (e.g. the failed items), channel_status, listing_id or product_id to drive a fix; page with limit / offset. itemId is what you pass as item_id to get_marketplace_item_report. marketplace_id is the id from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| get_marketplace_item_report | Get the detailed report for ONE listing item of a marketplace: why this product fails or warns on the channel. Returns {itemId, koongoProductId, status, statusDescription, channelStatus, channelStatusLabel, channelStatusDescription, reportMessage, reportCode, errors:[{source, field, fieldLabel, message, code, level, additionalInfo, currentValue}], sensitiveGate}. statusDescription/channelStatusLabel/ channelStatusDescription and each error's fieldLabel are the human wording the Koongo UI shows (status + attribute name); status/channelStatus/field are the raw codes. source is export|adapter|api_error; level is error|danger(=warning)|info. currentValue is the offending value that was sent to the channel. SENSITIVE-GATE: currentValue exposes real product data, so the first call (acknowledge_sensitive absent/false) returns the report with currentValue withheld and a {sensitiveGate:{confirmationRequired:true, itemCount, fields, kind}} — present that gate to the USER, get their approval, then re-call with acknowledge_sensitive:true to receive the actual values. item_id is the id from list_marketplace_items; marketplace_id is the id from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). For the marketplace-wide breakdown use get_marketplace_report. |
| get_marketplace_item_history | Get ONE listing item's action-log timeline — the sequence of events that acted on the product and its Koongo/channel state at each point, so you can explain WHY an item ended in its current state (e.g. it was created, changed, validated, pre-paired, submitted, rescheduled, removed, locked). Returns {itemId, returned, entries:[{createdAt, event, eventLabel, message, messageLabel, operation, operationLabel, koongoStatus, channelStatus}]} newest first. eventLabel/messageLabel/operationLabel are the human-readable rendering the Koongo UI shows (event name, plain-language explanation, operation title); event/message/ operation are the raw codes. Entries are process metadata only (no raw product values). item_id is the itemId from list_marketplace_items (the same id get_marketplace_item_report uses). Pair this with get_marketplace_item_report (current errors) to diagnose a failing product. marketplace_id is the integrationId from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| run_marketplace_item_action | Run a listing action on one, several, or all items of a marketplace. DESTRUCTIVE: these actions PUSH TO THE LIVE MARKETPLACE — they submit, relist, remove or otherwise change what buyers see on the channel. Confirm with the user first, then call with confirm:true. Without confirm:true the call returns error 'confirm_required' (HTTP 400) and nothing runs. action is one of: 'submit' (send items to the channel — works even in MANUAL product mode: it forces the targeted item(s) through, so submitting a single item_id is the safe way to test-publish one item and watch the result before doing the rest), 'clean_resubmit' (clear the channel listing and submit again), 'clean' (clear the channel listing), 'remove' (remove/end the listing on the channel), 'force_insert' (force a fresh insert), 'lock' / 'unlock' (lock/unlock items from automatic changes), 'pause' (pause the items), 'repricer_enable' (enable the repricer for the items). Target items with item_ids (an array of itemId from list_marketplace_items) OR all_items:true for every item; provide exactly one. Returns {integrationId, action, status, itemCount, async, message}. status is 'queued' (async — running in the background), 'done' (applied synchronously) or 'not_allowed' (the action is not available for this marketplace; message explains). marketplace_id is from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| run_marketplace_operation | Run a WHOLE-INTEGRATION control-panel operation on a marketplace (acts on every item, not a chosen subset — for specific items use run_marketplace_item_action). operation is one of: 'submit_all' (submit every item to the channel — ONLY works in manual product mode; in Auto-Pilot mode submission is automatic and this returns status:'not_allowed'), 'clean_resubmit_all' (clear every item record from the Koongo wizard and re-submit — allowed once every ~5 minutes; refused if the connection is down), 'pre_pair' (attempt to pre-pair existing channel items with your Koongo items — non-destructive, no removal or full resync), 'remove_all' (remove every item from the channel and lock them — PERMANENT). DESTRUCTIVE + pushes to the LIVE marketplace: submit_all / clean_resubmit_all / remove_all require confirm:true after you confirm with the user (pre_pair does not). Returns {integrationId, action, status ('queued'|'done'|'not_allowed'), itemCount, async, message}. marketplace_id is the integrationId from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| set_marketplace_product_mode | Set how a marketplace synchronizes products to its channel. mode is 'auto' (products are synced automatically — publishes every matching product), 'manual' (NOTHING is auto-published; products go to the channel only when you trigger them, so this is the safe way to activate for a test) or 'pause' (product sync is paused). In MANUAL mode you push items yourself: run_marketplace_item_action (submit) forces a single item through, and run_marketplace_operation (submit_all / clean_resubmit_all) forces the whole set — even though auto-publish is off. Returns {integrationId, action:'set_product_mode', status, kind, editUrl, message} — status is 'updated' for auto/manual and 'paused' for pause; read marketplace_status or get_marketplace afterwards to confirm the applied mode. marketplace_id is from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |
| set_marketplace_order_mode | Start or stop ACTIVE order synchronization for a marketplace that ALREADY has order sync. enabled:true starts syncing, enabled:false stops it. This is the on/off switch, NOT the capability: if the marketplace does not have order sync yet (get_marketplace orderSync:false / canEnableOrderSync:true), this returns status 'prerequisite_not_met' (HTTP 409) — call enable_marketplace_order_sync first (and configure its order-settings step), then come back here to start it. Returns {integrationId, action:'set_order_mode', status, kind, editUrl, message}: status is 'updated' on success, 'prerequisite_not_met' when order sync is not enabled yet, or 'rejected' (HTTP 409) when the plan does not allow it (message explains — e.g. an upgrade is needed). marketplace_id is from list_marketplaces. project_id is OPTIONAL (inferred for a single-project customer; project_id_required otherwise — then call list_projects). |