formbasedocs
Aller à l'applicationAppli

Développeurs

Serveur MCP

Le serveur Model Context Protocol (MCP) permet aux agents IA de lire et de modifier vos formulaires formbase grâce à des outils riches et pilotés par schéma.


Qu’est-ce que c’est

MCP est un standard ouvert permettant aux outils IA de se connecter à des services externes. formbase expose un point de terminaison MCP hébergé auquel tout client compatible MCP peut se connecter, notamment Claude Code, Claude desktop et Cursor.

Connexion

text
URL:  https://api.formbase.so/api/mcp   (POST, streamable HTTP)
Auth: Bearer <token>

Deux types de token porteur (bearer) fonctionnent :

  • Token API (fb_…) — créé depuis les tokens API. Idéal pour un usage personnel et une configuration rapide.

  • Token d’accès OAuth (fbo_…) — émis par le flux OAuth. Idéal pour les applications tierces qui se connectent au nom d’un utilisateur.

Les deux sont liés à exactement un espace de travail et atteignent les mêmes outils. Un appel d’outil qui nomme un autre espace de travail, ou un formulaire qui s’y trouve, échoue avec FORBIDDEN. Les tokens OAuth portent aussi des portées mcp:read, mcp:write et offline_access, mais aucun outil n’est aujourd’hui conditionné par elles — traitez tout token comme un accès complet à l’intérieur de son espace de travail.

Les appels d’outils sont limités à 120 par minute et par token, en commun avec l’API : seul tools/call consomme ce budget, tandis que initialize, tools/list, prompts/ et resources/ sont gratuits. Au-delà du budget, l’appel renvoie tout de même HTTP 200 avec un résultat d’outil en échec portant RATE_LIMITED et un retryAfterMs — sondez sur une minuterie, jamais en boucle.

Où obtenir un token

Ouvrez OAuth et clés API dans la barre latérale de votre espace de travail pour créer des tokens API et consulter les applications OAuth connectées. Consultez les tokens API pour un guide pas à pas.

Outils principaux

Chaque outil est annoncé sur tools/list lorsqu’un client se connecte. Les clients qui chargent les schémas à la demande, comme Claude Code, récupèrent le schéma complet d’un outil quand une tâche en a besoin. Le tableau ci-dessous couvre les outils principaux par lesquels la plupart des tâches commencent ; load_tools (catalogues) et load_skill (guides métier) documentent le reste.

OutilCe qu’il fait
form_listLister les formulaires dans un espace de travail. Prend en charge le filtre par dossier, la recherche floue par nom et la pagination par curseur.
form_getObtenir les détails complets d’un formulaire : questions, couverture, logo et une URL d’aperçu en direct.
form_createCréer un nouveau formulaire vide dans un espace de travail. Retourne une URL d’aperçu pour l’édition en direct.
form_updateMettre à jour les métadonnées d’un formulaire : nom, dossier, emoji, couverture ou logo.
form_deleteSuppression douce d’un formulaire (déplace vers la corbeille, révoque les liens de partage).
form_publishPublier un formulaire pour qu’il puisse accepter des réponses. Idempotent.
workspace_listLister tous les espaces de travail accessibles par votre token.
workspaceFolder_listLister les dossiers dans un espace de travail.
formSubmission_listLister les soumissions d’un formulaire avec pagination. Inclut les brouillons sur Pro et Business ; Free ne liste que les réponses complètes.
fields_listListe les clés de champ qu’une demande peut adresser sur un formulaire publié, chacune avec son type de valeur, les clés d’options, et une ligne d’utilisation. À appeler avant request_create.
request_createAssigne un formulaire publié à un destinataire nommé : préremplissage, champs verrouillés, contexte, livraison, expiration, et un callback optionnel.
request_getLit une demande : statut, chronologie, et — une fois terminée — les réponses indexées par clé de champ, plus display.
request_listListe les demandes d’un formulaire ou de tout un espace de travail, filtrées par statut, résultat, ou votre propre id externe.
editor_getDocumentObtenir la structure complète du document d’un formulaire : tous les éléments, leurs types et propriétés.
editor_updateElementModifier un élément de formulaire existant : remplacer son texte, changer ses propriétés (titre, obligatoire, etc.) ou le repositionner.
editor_deleteElementSupprimer un élément du formulaire.
editor_insertTextQuestionInsérer une question de texte court ou long. Chaque type de question possède son propre outil d’insertion avec un schéma précis.
editor_insertContactQuestionInsérer une question d’email, de numéro de téléphone ou d’URL de site web.
editor_insertNumberQuestion · editor_insertDateQuestionInsérer une question de nombre ou de date.
editor_insertRadioQuestion · editor_insertCheckboxQuestion · editor_insertSelectQuestionInsérer des questions à choix unique (radio), à choix multiple (case à cocher) ou à liste déroulante.
editor_insertDecisionQuestionInsérer la question de décision : le choix approuver / refuser / demander des modifications dont la réponse devient le résultat d’une demande. Un bouton radio construit à la main n’en produit jamais un.
editor_insertRatingQuestion · editor_insertLinearScaleQuestionInsérer une question d’évaluation par étoiles ou d’échelle linéaire.
editor_insertHeader · editor_insertParagraph · editor_insertImage · editor_insertPageDividerInsérer du contenu non-question : titres, paragraphes, images et sauts de page.
load_toolsCharger la documentation d’un catalogue d’outils. Retourne les schémas et les patterns d’utilisation pour les outils groupés.
load_skillCharger un guide de connaissances métier (thèmes, types de questions, règles de logique, etc.).

D’autres variantes d’insertion — heure, téléchargement de fichier, signature, paiement, matrice/grille, classement, choix d’image, bouton bascule, tableau, liste, ligne, champ calculé, champ masqué, variable en ligne, contenu intégré (editor_insertEmbedded pour YouTube, Google Maps ou des intégrations iframe) et un bloc de logique conditionnelle (editor_insertLogic) — sont aussi sur tools/list. Chargez load_skill(“question-types”) pour l’ensemble complet, avec le nom de l’outil et les champs de chacun. La logique conditionnelle s’écrit avec editor_setLogic dans le catalogue editor-actions.

Catalogues d’outils

Ces outils sont aussi sur tools/list. Exécutez load_tools avec un nom de catalogue pour obtenir une documentation enrichie (introduction, schémas complets, patterns d’utilisation, cas limites) pour les outils groupés, puis appelez-les directement.

CatalogueOutils inclus
form-dataformAnalytics_get — métriques agrégées (vues, soumissions, taux de complétion, répartitions par appareil, pays, navigateur, source). Nécessite le plan Pro ou Business ; sans lui, l’appel échoue avec un message qui nomme le plan.
form-appearanceformTheme_get, formTheme_set, form_update — thèmes par mode (clair et sombre), plus la couverture et le logo sur form_update.
form-behaviorformSettings_get, formSettings_update — notifications par email, redirection après complétion, mot de passe, rétention, langue, paiement.
form-sharingformShareLink_list, formShareLink_create, formShareLink_update — CRUD des liens de partage avec prise en charge des domaines personnalisés.
form-translationstranslationLanguage_list, translationDraft_get, translationDraft_update, translationDraft_publish, translationLanguage_delete — flux de travail multilingue brouillon puis publication. Publier un brouillon vide est le seul moyen de dépublier une langue.
form-lifecycleform_unpublish, form_restore — opérations de cycle de vie au-delà de la publication et suppression principales.
workspace-managementworkspaceFolder_create, workspaceFolder_update, workspaceFolder_delete — CRUD des dossiers au-delà des verbes de liste principaux.
editor-actionseditor_formatText, editor_setLogic, editor_testLogic — mise en forme du texte, création de logique conditionnelle et simulation de logique.
request-lifecyclefields_list, request_create, request_get, request_list, request_cancel, request_remind, request_replayCallback, document_create — toute la surface des demandes : retirer une demande en attente, relancer le destinataire, rejouer un callback qui n’est jamais arrivé, réserver un téléversement de document par demande.
editor-insertsLa longue traîne des outils editor_insert* : heure, interrupteur, fichier, signature, bloc Documents, matrice, classement, paiement, rendez-vous, choix d’image, contenu intégré, tableau, liste, ligne, champ calculé, champ masqué, groupe répétable, logique et variable.

Le catalogue request-lifecycle liste les huit outils de demandes car le chat intégré annonce un ensemble principal plus restreint. Sur ce point de terminaison, les huit sont déjà sur tools/list, donc ce que le catalogue ajoute, c’est la documentation.

Compétences (connaissances métier)

Les compétences sont des guides intégrés que l’agent peut charger via load_skill. Elles fournissent des connaissances métier qui aident l’agent à prendre de meilleures décisions — pas des schémas d’outils, mais des conseils de conception et la sémantique des champs.

CompétenceCe qu’elle couvre
question-typesChaque type de question, ses champs et quand utiliser chacun.
logic-rulesLogique conditionnelle : opérateurs, actions, combinateurs et cas limites.
editing-flowsSchémas pour construire des formulaires : ordre, sauts de page, piping.
form-best-practicesRecommandations UX pour une conception de formulaire efficace.
form-themesStructure des thèmes, référence des tokens et directives de style.
form-settingsRéférence des paramètres : notifications, modèles d’email, variables.
analyticsDéfinitions des métriques et comment interpréter les analytiques des formulaires.
toon-formatFormat de sortie compact pour l’affichage de données structurées.
requestsLes demandes de bout en bout : clés de champ, formes de valeur de préremplissage, livraison, documents par demande, callbacks, sondage, et récupération d’erreurs.

Demandes

Une demande assigne un formulaire publié à un destinataire nommé, avec son propre lien, ses propres réponses préremplies, et son propre résultat. C’est ainsi qu’un agent demande quelque chose à une personne réelle et découvre ce qu’elle a répondu.

Créer une demande

Commencez toujours par fields_list(formId). Cela renvoie les clés adressables de la version actuellement publiée du formulaire, chacune avec une ligne usage indiquant dans quel argument la clé doit aller — les questions visibles vont dans prefill, les champs cachés dans context. Ne dérivez jamais une clé à partir du titre d’une question, et relisez après form_publish.

request_create
json
{
  "formId": "j57...",
  "recipient": { "email": "ada@acme.com", "name": "Ada" },
  "prefill": { "company_name": "Acme", "plan": "pro" },
  "readonly": ["company_name"],
  "context": { "crm_id": "A-42" },
  "metadata": { "run_id": "exec_918" },
  "delivery": "email",
  "expiresAt": 1780000000000,
  "callbackUrl": "https://hooks.acme.com/formbase",
  "idempotencyKey": "po-42"
}

Le résultat contient le lien et l’horloge :

result
json
{
  "id": "kd7...",
  "status": "pending",
  "url": "https://form.formbase.so/r/rq_...",
  "deliveryStatus": "queued",
  "expiresAt": 1780000000000,
  "createdAt": 1747000000000,
  "deduplicated": false,
  "next": "..."
}

delivery vaut “none” par défaut, ce qui vous donne url à livrer vous-même ; “email” envoie l’invitation et nécessite recipient.email sur un plan Pro ou Business, ou sur l’une des 10 invitations gratuites d’un compte Free. readonly verrouille des champs que le destinataire ne peut pas modifier, et toute clé verrouillée doit aussi être préremplie. context n’accepte que des clés de champs cachés, tandis que metadata est un suivi opaque renvoyé dans request_get et dans le callback. expiresAt est en millisecondes epoch, par défaut 30 jours et plafonné à 365 jours. idempotencyKey est valable à l’échelle de l’espace de travail pendant 30 jours : la même clé avec le même corps renvoie la demande d’origine avec deduplicated: true, et un corps différent est un conflit. Chaque réponse porte aussi une ligne next qui indique à l’agent quoi faire ensuite.

deliveryStatus vaut not_requested jusqu’à ce qu’une invitation soit mise en file, puis queued → sent ou failed, et bounced une fois que le fournisseur d’e-mail signale un rejet définitif ou une plainte. Créer une demande dépense une unité de l’allocation mensuelle de l’espace de travail, que le destinataire réponde ou non ; une fois épuisée, request_create échoue avec MONTHLY_ALLOWANCE_REACHED.

Callbacks ou sondage

Avec une callbackUrl, formbase envoie un POST une fois par événement terminal — complétion, expiration, annulation — signé avec le secret de signature des demandes de l’espace de travail. Voir Callbacks et signature pour le payload et la recette de vérification.

Les agents autonomes devraient sonder

Le secret de signature des demandes n’apparaît que sur la page Identifiants de votre espace de travail — il n’est jamais renvoyé via MCP ou l’API. Un agent qui s’exécute seul, sans humain pour mettre en place et configurer un récepteur, ne peut donc pas vérifier un callback. Omettez callbackUrl et sondez plutôt request_get(requestId), à l’échelle de quelques minutes plutôt que de quelques secondes, jusqu’à ce que status quitte “pending”. expiresAt borne combien de temps cela vaut la peine.

Mode test

Passez test: true pour répéter tout le circuit avant une exécution réelle. Le lien s’ouvre toujours et peut être complété, et le callback se déclenche avec “test”: true — mais rien n’est envoyé par e-mail quoi que dise delivery, la demande reste masquée de la page Demandes et de l’entonnoir analytique, et sa soumission ne compte nulle part : pas de quota, pas d’exports, pas d’intégrations. Les demandes de test n’apparaissent dans request_list que si vous passez includeTest: true. Le lien se ferme dans les 24 heures, et sur Free un workspace peut créer 10 demandes de test par jour.

Documents par demande

Pour remettre un fichier à un destinataire — un projet de contrat, son propre devis — le formulaire a besoin d’un bloc Documents, qu’un auteur ou un agent insère avec editor_insertDocumentsBlock. fields_list le signale comme type: “documents”. Les octets ne transitent jamais par un outil :

  1. Appelez document_create avec formId, name, contentType, et le size exact en octets. Vous récupérez { id, name, contentType, size, uploadUrl, expiresAt }. PDF et images uniquement (pas de documents Office), 25 Mo par fichier, et 100 Mo de documents par demande.

  2. Faites un PUT des octets bruts vers uploadUrl dans l’heure, avec Content-Type réglé sur le type déclaré.

  3. Référencez-le depuis request_create : documents: [{ documentId, field?, name? }]. field est la clé de champ du bloc Documents, optionnelle seulement quand le formulaire a exactement un bloc de ce type. name remplace le nom d’affichage pour cette demande.

Les documents de l’auteur du bloc restent en place et les vôtres apparaissent en dessous, pour ce seul destinataire. request_create vérifie le téléversement avant que la demande n’existe, donc DOCUMENT_NOT_UPLOADED signifie que l’étape 2 a été sautée. Un téléversement peut être référencé par un nombre quelconque de demandes, et ses octets comptent dans le stockage de votre espace de travail.

Domaines personnalisés

Passez domainId à request_create pour créer le lien sur l’un des domaines personnalisés de l’espace de travail. Les ids viennent de formShareLink_list, qui les renvoie sous availableCustomDomains. Si vous l’omettez, le lien prend le domaine sur lequel le formulaire est déjà publié.

Lire les résultats

request_get renvoie la demande entière. Une fois terminée, answers contient les valeurs du destinataire indexées par clé de champ, display les mêmes clés en texte lisible, et outcome — approbation, refus ou modifications — est son verdict quand le formulaire a une question de décision. Un horodatage callbackFailedAt signifie que la livraison a épuisé ses tentatives et que rien n’a atteint votre endpoint ; réparez le récepteur, puis appelez request_replayCallback, qui renvoie l’id de l’événement d’origine pour que votre récepteur déduplique au lieu de relancer. Une fois que la politique de rétention du formulaire a supprimé une demande, dataPurgedAt est défini et les réponses sont perdues pour de bon.

request_list balaie plusieurs demandes à la fois, filtrées par status, outcome, externalId, et includeTest. Paginez avec nextCursor : une page peut rarement revenir avec des items vides et hasMore: true, ce qui ne marque pas la fin de la liste — renvoyez le curseur et continuez.

Ressources et prompts

Chaque compétence et catalogue d’outils est aussi une ressource MCP à skill://<nom> — skill://requests, skill://editor-inserts. Un client qui prend en charge resources/list peut les parcourir et les lire sans appeler load_skill ou load_tools. Le serveur sert aussi quatre prompts sur prompts/list : identity, capabilities, data_tools, et editor_tools.

Les outils qui demandent d’abord confirmation

Chaque outil porte les indices MCP readOnlyHint et destructiveHint, dérivés de son verbe. Ces outils sont marqués comme destructifs, car les annuler nécessite un autre appel ou n’est pas possible : form_delete, form_unpublish, workspaceFolder_delete, editor_deleteElement, translationLanguage_delete, et request_cancel. La plupart des clients demandent une confirmation à l’utilisateur avant de les exécuter, mais l’invite reste la décision du client — vérifiez ses paramètres d’approbation si vous avez besoin d’un blocage strict.

Limites

  • Aucun téléversement binaire via un appel d’outil. Les images sont définies par URL : couvertures, logos et blocs image acceptent des URI http(s):// ou data:image. Un document par demande fait exception : document_create renvoie une URL de téléversement qu’un client avec accès HTTP peut cibler avec PUT (voir Documents par demande). Pour transformer un PDF ou une capture d’écran en formulaire, utilisez le chat IA intégré.

  • Aucune compétence IA d’espace de travail. Les compétences écrites dans formbase ne sont disponibles que dans le chat IA intégré. Les compétences propres au serveur (load_skill) sont disponibles via MCP.

Se connecter avec un token API

La plupart des clients se connectent avec OAuth : ajoutez l’URL sans en-tête et suivez Connecter un agent IA. Un client qui ne peut pas ouvrir de navigateur, comme un script, un job CI ou un agent headless, envoie plutôt un token API en en-tête.

Claude Code, en ligne de commande :

bash
claude mcp add --transport http formbase https://api.formbase.so/api/mcp \
  --header "Authorization: Bearer fb_YOUR_TOKEN"

Ou dans le .mcp.json d’un projet :

.mcp.json
json
{
  "mcpServers": {
    "formbase": {
      "type": "http",
      "url": "https://api.formbase.so/api/mcp",
      "headers": {
        "Authorization": "Bearer fb_YOUR_TOKEN"
      }
    }
  }
}

Cursor, dans .cursor/mcp.json ou ~/.cursor/mcp.json :

mcp.json
json
{
  "mcpServers": {
    "formbase": {
      "url": "https://api.formbase.so/api/mcp",
      "headers": {
        "Authorization": "Bearer fb_YOUR_TOKEN"
      }
    }
  }
}

Pour vous connecter avec OAuth plutôt qu’avec un token, utilisez

Ajouter à Cursor

. Cela ajoute l’URL du serveur sans en-tête, et Cursor vous demande de vous connecter à formbase.

Les autres clients prennent la même URL et le même en-tête ; consultez leur documentation pour savoir où les placer.

Utiliser OAuth plutôt que des tokens API

Une application tierce qui se connecte au nom d’un utilisateur devrait utiliser OAuth plutôt que de demander un token collé à la main. formbase est un serveur d’autorisation OAuth 2.1 avec PKCE obligatoire (S256) et des tokens opaques — pas de JWT, pas de grant implicite. Claude desktop, Claude Code et le connecteur web Claude.ai découvrent tout cela depuis le point de terminaison MCP, donc coller l’URL sans en-tête suffit : le 401 pointe vers /.well-known/oauth-protected-resource, et le client prend le relais à partir de là.

Le flux, pour un client que vous écrivez vous-même :

  1. GET /.well-known/oauth-protected-resource, puis GET /.well-known/oauth-authorization-server pour les URLs des points de terminaison, les portées et les méthodes d’authentification prises en charge.

  2. POST /oauth/register avec vos redirect_uris (enregistrement de client dynamique, aucun identifiant requis). Vous obtenez un client_id, plus un client_secret si vous avez demandé autre chose que token_endpoint_auth_method: “none”. Les URIs de redirection doivent être en HTTPS, ou en HTTP sur localhost. L’enregistrement est plafonné à 20 par heure et par IP.

  3. Envoyez l’utilisateur vers /oauth/authorize avec response_type=code, votre client_id, le redirect_uri enregistré, scope=mcp:read mcp:write offline_access, state, et un code_challenge avec code_challenge_method=S256. Il se connecte, choisit un espace de travail, et autorise.

  4. Échangez le code sur POST /oauth/token avec grant_type=authorization_code et votre code_verifier, dans les 60 secondes. Les codes sont à usage unique.

  5. Appelez le point de terminaison MCP avec Authorization: Bearer fbo_…. Les tokens d’accès durent 1 heure ; les tokens de rafraîchissement durent 30 jours et tournent à chaque utilisation. Réutiliser un token de rafraîchissement déjà consommé brûle toute la chaîne, donc conservez le plus récent.

POST /oauth/revoke (RFC 7009) révoque un token d’accès ou de rafraîchissement. Un utilisateur peut aussi déconnecter toute l’application depuis Applications connectées sur la page OAuth et clés API, ce qui tue tous les tokens qu’elle détient pour cet espace de travail.

Si vous avez déjà un token en main, il va au même endroit qu’une clé API :

MCP config with OAuth token
json
{
  "mcpServers": {
    "formbase": {
      "type": "http",
      "url": "https://api.formbase.so/api/mcp",
      "headers": {
        "Authorization": "Bearer fbo_USER_OAUTH_TOKEN"
      }
    }
  }
}

Applications connectées

Chaque connexion OAuth est listée sous Applications connectées sur la page OAuth et clés API, avec la date de connexion et de dernière utilisation. Les connexions sont personnelles : seul l’utilisateur qui a autorisé une connexion peut la voir, et les administrateurs de l’espace de travail ne peuvent ni la consulter ni la révoquer pour un autre membre. La déconnexion prend effet immédiatement. Un utilisateur qui quitte l’espace de travail ou en est retiré perd toutes ses connexions à celui-ci.

Prochaines étapes