Fulfiller — print catalogue & quotes

Print catalogue and live quotes from Fulfiller, a French online printer shipping across the EU.

Should I use this

Quality & Safety

A
Description quality
97%
Schema completeness
97%
Naming quality
95%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Findings (1)

  • LOWTool 'quote_by_quantity' description lacks action verbin quote_by_quantity

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~4,927Tokens (tool definitions)
~3.2 KBTypical response size
Significant attention impact (3.85% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "agentic-commerce-api": {
      "url": "https://www.fulfiller.com/agenticopenapi/mcp"
    }
  }
}

Remote endpoints

https://www.fulfiller.com/agenticopenapi/mcpstreamable-http

What it can do

Tool inventory

Tools (11)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢search_products(q, limit)

Recherche plein-texte dans le catalogue Fulfiller et renvoie des produits COTABLES (productId, sku, url, et le prix d’appel du site quand il en affiche un). Point d’entrée obligatoire : les autres outils travaillent sur le productId renvoyé ici. `startingPrice` est le prix d’appel AFFICHÉ par le site : indicatif, parfois périmé ou propre à une configuration, ni plancher garanti ni prix ferme — seul quote_product l’est. Sa base (TOTAL, UNIT, PER_SQUARE_METER) change d’un produit à l’autre : ne comparez jamais deux bases différentes. Pour le citer, utilisez `startingPrice.displayLabel`. Un résultat peut lister dans `alsoListedAs` d’autres fiches du site qui vendent le MÊME produit : ne les présentez pas comme des produits distincts.

Input Schema

{
  "type": "object",
  "properties": {
    "q": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "description": "Un ou deux mots produit en français (ex. « carte de visite », « bâche publicitaire »), pas une phrase : le moteur exige TOUS les mots. Une phrase qui ne trouve rien est réessayée une fois sans ses mots de contexte (`relaxedQuery` le signale). Les dimensions (« 300x100 »), les mesures (« 350g », « 1 000 ex ») et une quantité en tête de requête (« 500 cartes ») sont ignorées : elles se précisent à la cotation. Il faut au moins un mot de 3 lettres ou plus : une requête sans mot exploitable (« ab », « 50 ») est refusée."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 24,
      "description": "Nombre de résultats souhaité (1 à 24)."
    }
  },
  "required": [
    "q"
  ]
}
🟢resolve_product(productId, sku, url)

Convertit une identité EXACTE en identité complète (productId, sku, nom, url) : `sku` (lisible dans le JSON-LD d’une page produit), `url` de la page, ou `productId`. À PRÉFÉRER à search_products dès que vous tenez l’un des trois — la recherche est approximative, celle-ci ne l’est pas. Fournissez exactement un argument.

Input Schema

{
  "type": "object",
  "properties": {
    "productId": {
      "type": "integer",
      "minimum": 1,
      "description": "Identifiant rendu par search_products (alias : `zeloomProductId`)."
    },
    "sku": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "SKU exact (ex. « POSTER_PHOTO_SUR_MESURE »)."
    },
    "url": {
      "type": "string",
      "minLength": 1,
      "maxLength": 2048,
      "description": "URL d’une fiche produit de www.fulfiller.com (http, sans www ou relative acceptées). Une page catégorie est refusée : cherchez alors avec search_products."
    }
  },
  "required": []
}
🟢get_product_details(productId, sku, url)

Fiche PIM d’un produit : descriptions, points clés, questions fréquentes, contraintes de fichier (fond perdu, résolution, marges, mode colorimétrique) et ressources (visuels, gabarits, consignes techniques). À utiliser pour DÉCRIRE un produit ou aider à préparer un fichier. Ne renvoie aucun prix — pour coter, passez par quote_product ; un prix écrit dans les textes de la fiche (« Dès 14.5 € ») est souvent périmé, ne l’annoncez pas. Les vidéos sont dans `videos`, pas dans `images`. Fournissez exactement un argument (`productId`, `sku` ou `url`). Les champs absents ne sont pas renseignés au PIM ; la FAQ est rare.

Input Schema

{
  "type": "object",
  "properties": {
    "productId": {
      "type": "integer",
      "minimum": 1,
      "description": "Identifiant rendu par search_products (alias : `zeloomProductId`)."
    },
    "sku": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "SKU exact, tel que rendu par search_products ou resolve_product."
    },
    "url": {
      "type": "string",
      "minLength": 1,
      "maxLength": 2048,
      "description": "URL d’une fiche produit de www.fulfiller.com (http, sans www ou relative acceptées). Une page catégorie est refusée : cherchez alors avec search_products."
    }
  },
  "required": []
}
🟢get_product_configuration(productId)

Renvoie les options configurables d’un produit (quantités, délais, valeurs, tailles) et leurs valeurs disponibles. À appeler AVANT validate_selection ou quote_product : chez Fulfiller, un produit n’est pas un SKU à prix figé mais un espace de configuration. `presets` : configurations prêtes à l’emploi, cotables telles quelles via `selection.preset`. Les dépendances entre options (une finition qui exige le recto verso…) n’y figurent pas : validate_selection les révèle (`enabledOptions`).

Input Schema

{
  "type": "object",
  "properties": {
    "productId": {
      "type": "integer",
      "minimum": 1,
      "description": "Identifiant rendu par search_products."
    }
  },
  "required": [
    "productId"
  ]
}
🟢validate_selection(productId, selection)

Résout une sélection tolérante en codes canoniques et vérifie sa COMMANDABILITÉ, sans renvoyer de prix. Sert à corriger une sélection avant de la coter. `summary` décrit en clair la sélection retenue, et son `status` dit pour chaque option si la valeur est celle demandée, un défaut, ou un changement. `requiresReview` à `true` : la sélection retenue diffère de celle demandée, `alerts` dit pourquoi. `enabledOptions` liste, pour chaque option, les valeurs activables AVEC cette sélection : c’est là que se lisent les dépendances entre options.

Input Schema

{
  "type": "object",
  "properties": {
    "productId": {
      "type": "integer",
      "minimum": 1,
      "description": "Identifiant rendu par search_products."
    },
    "selection": {
      "type": "object",
      "properties": {
        "options": {
          "type": "array",
          "maxItems": 50,
          "items": {
            "type": "object",
            "properties": {
              "option": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "QUANTITY",
                  "DELIVERY_TIME",
                  "LIST_OF_VALUES",
                  "SIZE"
                ]
              },
              "value": {
                "type": "string"
              },
              "quantity": {
                "type": "integer",
                "minimum": 1
              },
              "size": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "width": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "height": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  }
                },
                "required": [
                  "code"
                ]
              }
            },
            "required": [
              "option",
              "type"
            ]
          }
        },
        "preset": {
          "type": "string",
          "maxLength": 128
        }
      },
      "required": [
        "options"
      ],
      "description": "Sélection d’options : même forme et mêmes règles que `selection` de quote_product (codes ou libellés, défauts du produit, `preset`, tailles)."
    }
  },
  "required": [
    "productId",
    "selection"
  ]
}
🟢quote_product(productId, selection)

Devis RÉEL pour une sélection : prix HT calculé par le moteur de tarification (jamais lu dans une table de SKU), devise, délai, promotion. C’est le seul prix ferme. Le prix à annoncer est `devis.finalPriceHt` (promotion déduite) ; `devis.priceHt` est le prix catalogue, BARRÉ quand `devis.promo` est présent. Pour dire à l’utilisateur ce qui est coté, citez `summary` (libellés lisibles). Si `requiresReview` vaut `true`, le prix porte sur la sélection décrite par `summary`, pas sur la demande : les lignes dont le `status` n’est ni AS_REQUESTED ni DEFAULT disent ce qui a changé.

Input Schema

{
  "type": "object",
  "properties": {
    "productId": {
      "type": "integer",
      "minimum": 1,
      "description": "Identifiant rendu par search_products."
    },
    "selection": {
      "type": "object",
      "description": "Sélection d’options. Une option non précisée prend la valeur de la préselection par défaut du produit (`preselections` de get_product_configuration), comme sur le site ; `{\"options\": []}` cote donc la configuration par défaut. La résolution est TOLÉRANTE : code ou libellé, sans souci de casse ni d’accents ; une valeur partielle est retenue si une SEULE valeur la contient (« vinyle » → « Impression sur vinyle adhésif contrecollé », « A5 » → « 14,8 x 21 cm (A5) »), ou par ses mesures (« 148x210 mm ») ; parmi plusieurs, la plus proche est retenue et signalée, ou la SEULE compatible avec le reste de la sélection (« soft touch » sur une carte recto verso). Ce qui n’est pas retenu tel quel est signalé dans `alerts` et dans `summary`.",
      "properties": {
        "options": {
          "type": "array",
          "maxItems": 50,
          "items": {
            "type": "object",
            "properties": {
              "option": {
                "type": "string",
                "description": "Code de l’option, tel que rendu par get_product_configuration. Un libellé (« Délai de livraison ») est rattaché à la seule option qui lui correspond, et c’est signalé."
              },
              "type": {
                "type": "string",
                "enum": [
                  "QUANTITY",
                  "DELIVERY_TIME",
                  "LIST_OF_VALUES",
                  "SIZE"
                ],
                "description": "Seuls ces 4 types sont SÉLECTIONNABLES. Un autre type déclaré par la configuration (LIST_OF_RANGES, QUANTITY_BY_VALUE) est décrit mais non sélectionnable : le défaut du produit s’applique."
              },
              "value": {
                "type": "string",
                "description": "Code ou libellé de la valeur retenue (types LIST_OF_VALUES et DELIVERY_TIME)."
              },
              "quantity": {
                "type": "integer",
                "minimum": 1,
                "description": "Quantité demandée (type QUANTITY). Hors des paliers du produit, l’alerte donne les quantités possibles et la plus proche."
              },
              "size": {
                "type": "object",
                "description": "Gabarit de taille (option de type SIZE). Gabarit FIXE (bornes min = max) : le code suffit, ses dimensions sont complétées, et des dimensions données dans un sens ou dans l’autre (60×80 ou 80×60) désignent le même gabarit. Gabarit à SAISIE LIBRE (`allowsCustomInput`) : width et height sont requises, dans l’unité de l’option (`unit`, souvent cm : une bâche de 3 m × 1 m s’écrit width 300, height 100) et DANS les bornes du gabarit : hors bornes, la cotation est refusée (SIZE_OUT_OF_RANGE, bornes dans le message).",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "Code ou libellé du gabarit, ou ses mesures (« 60x80 », « 148x210 mm ») : elles désignent le gabarit fixe de ces dimensions, sinon le gabarit sur mesure."
                  },
                  "width": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "height": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  }
                },
                "required": [
                  "code"
                ]
              }
            },
            "required": [
              "option",
              "type"
            ]
          }
        },
        "preset": {
          "type": "string",
          "maxLength": 128,
          "description": "Code ou nom d’un preset de get_product_configuration (`presets` : « Le moins cher », « Top vente »…) : ses valeurs servent de base, `options` les précise ou les remplace."
        }
      },
      "required": [
        "options"
      ]
    }
  },
  "required": [
    "productId",
    "selection"
  ]
}
🟢quote_by_quantity(productId, selection, quantities)

Grille de devis pour plusieurs paliers de quantité en UN appel — la bonne façon de répondre à « combien pour 100, 250, 500 ? ». Prix de chaque palier : `devis.finalPriceHt` (promotion déduite). Même règle que quote_product, palier par palier : hors plage → erreur localisée sans invalider les autres ; hors du pas → coté au palier commandable le plus proche, que `quotedQuantity` indique (le prix porte sur cette quantité, pas sur le palier demandé).

Input Schema

{
  "type": "object",
  "properties": {
    "productId": {
      "type": "integer",
      "minimum": 1,
      "description": "Identifiant rendu par search_products."
    },
    "selection": {
      "type": "object",
      "properties": {
        "options": {
          "type": "array",
          "maxItems": 50,
          "items": {
            "type": "object",
            "properties": {
              "option": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "QUANTITY",
                  "DELIVERY_TIME",
                  "LIST_OF_VALUES",
                  "SIZE"
                ]
              },
              "value": {
                "type": "string"
              },
              "quantity": {
                "type": "integer",
                "minimum": 1
              },
              "size": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "width": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "height": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  }
                },
                "required": [
                  "code"
                ]
              }
            },
            "required": [
              "option",
              "type"
            ]
          }
        },
        "preset": {
          "type": "string",
          "maxLength": 128
        }
      },
      "required": [
        "options"
      ],
      "description": "Sélection d’options : même forme et mêmes règles que `selection` de quote_product (codes ou libellés, défauts du produit, `preset`, tailles)."
    },
    "quantities": {
      "type": "array",
      "minItems": 1,
      "maxItems": 20,
      "items": {
        "type": "integer",
        "minimum": 1
      },
      "description": "Paliers de quantité à coter (1 à 20)."
    }
  },
  "required": [
    "productId",
    "selection",
    "quantities"
  ]
}
🟡create_cart(lines, idempotencyKey)

Crée un panier anonyme, éventuellement avec ses premières lignes (cotées à l’ajout, prix FIGÉ). Un panier n’est PAS une commande : rien n’est engagé, et le total est HT — hors TVA et hors port. Chaque ligne désigne le produit par son productId (rendu par search_products) ; le sku est facultatif. `unitPriceHt` et `lineTotalHt` sont promotion déduite. Renvoie le panier complet : n’appelez pas get_cart juste après.

Input Schema

{
  "type": "object",
  "properties": {
    "lines": {
      "type": "array",
      "maxItems": 5,
      "items": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "minimum": 1,
            "description": "Identifiant produit rendu par search_products (alias : `zeloomProductId`)."
          },
          "sku": {
            "type": "string",
            "maxLength": 128,
            "description": "SKU exact rendu par search_products. FACULTATIF : absent, il est déduit du productId (PRODUCT_AMBIGUOUS si plusieurs fiches vendent ce produit : le message cite leurs SKU)."
          },
          "selection": {
            "type": "object",
            "properties": {
              "options": {
                "type": "array",
                "maxItems": 50,
                "items": {
                  "type": "object",
                  "properties": {
                    "option": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "QUANTITY",
                        "DELIVERY_TIME",
                        "LIST_OF_VALUES",
                        "SIZE"
                      ]
                    },
                    "value": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "size": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "width": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        },
                        "height": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        }
                      },
                      "required": [
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "option",
                    "type"
                  ]
                }
              },
              "preset": {
                "type": "string",
                "maxLength": 128
              }
            },
            "required": [
              "options"
            ],
            "description": "Sélection d’options : même forme et mêmes règles que `selection` de quote_product (codes ou libellés, défauts du produit, `preset`, tailles)."
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "description": "Nombre de LOTS identiques au prix unitaire figé — PAS un palier de volume : 2×50 exemplaires n’a pas le même prix qu’1×100. Pour changer de volume, re-cotez avec une autre QUANTITY dans `selection`, puis remplacez la ligne. Défaut 1."
          }
        },
        "required": [
          "productId",
          "selection"
        ]
      },
      "description": "Lignes initiales (0 à 5). Un panier vide est légitime."
    },
    "idempotencyKey": {
      "type": "string",
      "format": "uuid",
      "description": "UUID optionnel. Rejouer le MÊME appel avec la même clé renvoie le panier déjà créé au lieu d’en créer un second : à utiliser si vous devez réessayer après une erreur."
    }
  },
  "required": []
}
🟢get_cart(cartId, display)

Renvoie le panier tel que FIGÉ à l’ajout : aucune re-cotation à la lecture. `pricedAt` par ligne et `expiresAt` donnent l’âge des prix — au-delà, re-cotez avec quote_product. Sert à RELIRE un panier existant (plus tard dans la conversation, ou quand l’utilisateur demande à le revoir) : inutile juste après create_cart ou update_cart, qui renvoient déjà le panier complet.

Input Schema

{
  "type": "object",
  "properties": {
    "cartId": {
      "type": "string",
      "description": "Identifiant du panier (UUID) rendu par create_cart. C’est une CAPACITÉ : qui le détient accède au panier — ne le publiez pas hors de la conversation qui l’a créé."
    },
    "display": {
      "type": "boolean",
      "description": "Afficher la carte du panier à l’utilisateur, dans les clients qui affichent les interfaces MCP Apps. `false` pour un appel intermédiaire qu’il n’a pas besoin de voir (vérifier avant de répondre) ; omis ou `true` dès qu’il doit voir le résultat. Sans effet sur le résultat lui-même."
    }
  },
  "required": [
    "cartId"
  ]
}
🔴update_cart(cartId, remove, update, add)

Applique, DANS CET ORDRE : retraits (`remove`), changements de quantité (`update`, sans re-cotation), puis ajouts (`add`, cotés). Renvoie le panier complet après application : n’appelez pas get_cart juste après.

Input Schema

{
  "type": "object",
  "properties": {
    "cartId": {
      "type": "string",
      "description": "Identifiant du panier (UUID) rendu par create_cart. C’est une CAPACITÉ : qui le détient accède au panier — ne le publiez pas hors de la conversation qui l’a créé."
    },
    "remove": {
      "type": "array",
      "maxItems": 20,
      "items": {
        "type": "string"
      },
      "description": "`lineId` des lignes à retirer."
    },
    "update": {
      "type": "array",
      "maxItems": 20,
      "items": {
        "type": "object",
        "properties": {
          "lineId": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          }
        },
        "required": [
          "lineId",
          "quantity"
        ]
      },
      "description": "Nouveau nombre de LOTS pour des lignes existantes (prix unitaire figé inchangé)."
    },
    "add": {
      "type": "array",
      "maxItems": 5,
      "items": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "integer",
            "minimum": 1,
            "description": "Identifiant produit rendu par search_products (alias : `zeloomProductId`)."
          },
          "sku": {
            "type": "string",
            "maxLength": 128,
            "description": "SKU exact rendu par search_products. FACULTATIF : absent, il est déduit du productId (PRODUCT_AMBIGUOUS si plusieurs fiches vendent ce produit : le message cite leurs SKU)."
          },
          "selection": {
            "type": "object",
            "properties": {
              "options": {
                "type": "array",
                "maxItems": 50,
                "items": {
                  "type": "object",
                  "properties": {
                    "option": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "QUANTITY",
                        "DELIVERY_TIME",
                        "LIST_OF_VALUES",
                        "SIZE"
                      ]
                    },
                    "value": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "size": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "width": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        },
                        "height": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        }
                      },
                      "required": [
                        "code"
                      ]
                    }
                  },
                  "required": [
                    "option",
                    "type"
                  ]
                }
              },
              "preset": {
                "type": "string",
                "maxLength": 128
              }
            },
            "required": [
              "options"
            ],
            "description": "Sélection d’options : même forme et mêmes règles que `selection` de quote_product (codes ou libellés, défauts du produit, `preset`, tailles)."
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "description": "Nombre de LOTS identiques au prix unitaire figé — PAS un palier de volume : 2×50 exemplaires n’a pas le même prix qu’1×100. Pour changer de volume, re-cotez avec une autre QUANTITY dans `selection`, puis remplacez la ligne. Défaut 1."
          }
        },
        "required": [
          "productId",
          "selection"
        ]
      },
      "description": "Nouvelles lignes, cotées à l’ajout."
    }
  },
  "required": [
    "cartId"
  ]
}
🔴delete_cart(cartId)

Supprime DÉFINITIVEMENT un panier et toutes ses lignes. Irréversible. Pour retirer une seule ligne, utilisez update_cart avec `remove`.

Input Schema

{
  "type": "object",
  "properties": {
    "cartId": {
      "type": "string",
      "description": "Identifiant du panier (UUID) rendu par create_cart. C’est une CAPACITÉ : qui le détient accède au panier — ne le publiez pas hors de la conversation qui l’a créé."
    }
  },
  "required": [
    "cartId"
  ]
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded11 tools
verifiedversion not recorded11 tools
verifiedversion not recorded11 tools
verifiedversion not recorded11 tools
verifiedversion not recorded11 tools
verifiedversion not recorded11 tools