Utviklere
MCP-server
Model Context Protocol-serveren (MCP) lar AI-agenter lese og redigere formbase-skjemaene dine med rike, schemadrevne verktøy.
Hva det er
MCP er en åpen standard for AI-verktøy som kobler til eksterne tjenester. formbase tilbyr et hostet MCP-endepunkt som enhver MCP-kompatibel klient kan koble til, inkludert Claude Code, Claude desktop og Cursor.
Tilkobling
URL: https://api.formbase.so/api/mcp (POST, streamable HTTP)
Auth: Bearer <token>To typer bearer-token fungerer:
API-token (
fb_…) — opprettet fra API-tokens. Best egnet for personlig bruk og rask oppsett.OAuth-tilgangstoken (
fbo_…) — utstedt av OAuth-flyten. Best egnet for tredjepartsapper som kobler til på vegne av en bruker.
Begge er bundet til nøyaktig ett arbeidsområde og når de samme verktøyene. Et verktøykall som navngir et annet arbeidsområde, eller et
skjema i ett, feiler med FORBIDDEN. OAuth-tokens har også scopes (mcp:read, mcp:write,
offline_access), men ingen verktøy er i dag låst til dem — behandle ethvert token som full tilgang innenfor sitt
arbeidsområde.
Verktøykall er begrenset til 120 per minutt per token, delt med API-et: bare tools/call
bruker av budsjettet, mens initialize, tools/list, prompts/ og er gratis.
Over budsjettet returnerer kallet fortsatt HTTP 200 med et mislykket verktøyresultat som bærer resources/RATE_LIMITED og en
retryAfterMs — poll på en timer, aldri i en løkke.
Hvor du får et token
Åpne OAuth og API-nøkler i arbeidsområdets sidepanel for å opprette API-tokens og se tilkoblede OAuth-apper. Se API-tokens for en trinn-for-trinn-guide.
Kjerneverktøy
Alle verktøy annonseres på tools/list når en klient kobler til. Klienter som laster skjemaer ved behov, som Claude Code,
henter det fullstendige skjemaet for et verktøy når en oppgave trenger det. Tabellen nedenfor dekker kjerneverktøyene de fleste oppgaver
starter med; load_tools (kataloger) og load_skill (domeneguider) dokumenterer resten.
| Verktøy | Hva det gjør |
|---|---|
| form_list | List skjemaer i et arbeidsområde. Støtter mappefilter, uskarpt navnesøk og markørpaginering. |
| form_get | Hent fullstendige detaljer for et skjema: spørsmål, cover, logo og en forhåndsvisnings-URL. |
| form_create | Opprett et nytt tomt skjema i et arbeidsområde. Returnerer en forhåndsvisnings-URL for live-redigering. |
| form_update | Oppdater skjemametadata: navn, mappe, emoji, cover eller logo. |
| form_delete | Myk-slett et skjema (flyttes til papirkurv, tilbakekaller delingslenker). |
| form_publish | Publiser et skjema slik at det kan motta svar. Idempotent. |
| workspace_list | List alle arbeidsområder tilgjengelige for tokenet ditt. |
| workspaceFolder_list | List mapper i et arbeidsområde. |
| formSubmission_list | List innsendinger for et skjema med paginering. Inkluderer kladder på Pro og Business; Gratis lister bare fullførte svar. |
| fields_list | Lister feltnøklene en forespørsel kan adressere på et publisert skjema, hver med verditype, alternativnøkler og en usage-linje. Kall den før request_create. |
| request_create | Tildel et publisert skjema til én navngitt mottaker: prefill, låste felt, context, levering, utløp, og en valgfri callback. |
| request_get | Les én forespørsel: status, tidslinje, og — når den er fullført — svar nøkkelsatt etter feltnøkkel, pluss display. |
| request_list | List forespørsler for et skjema eller en hel arbeidsområde, filtrert etter status, outcome, eller din egen eksterne ID. |
| editor_getDocument | Hent den fullstendige dokumentstrukturen til et skjema: alle elementer, typer og egenskaper. |
| editor_updateElement | Rediger et eksisterende skjemaelement: erstatt teksten, endre egenskaper (tittel, obligatorisk osv.) eller flytt det. |
| editor_deleteElement | Fjern et element fra skjemaet. |
| editor_insertTextQuestion | Sett inn et kort eller langt tekstspørsmål. Hver spørsmålstype har sitt eget innsettingsverktøy med et presist skjema. |
| editor_insertContactQuestion | Sett inn et e-post-, telefonnummer- eller nettstedURL-spørsmål. |
| editor_insertNumberQuestion · editor_insertDateQuestion | Sett inn et tall- eller datospørsmål. |
| editor_insertRadioQuestion · editor_insertCheckboxQuestion · editor_insertSelectQuestion | Sett inn enkeltvalg (radio), flervalg (avkrysning) eller nedtrekksspørsmål. |
| editor_insertDecisionQuestion | Sett inn beslutningsspørsmålet: valget godkjenn / avslå / endringer der svaret blir et forespørselsutfall. Et radiospørsmål bygget for hånd gir aldri et slikt utfall. |
| editor_insertRatingQuestion · editor_insertLinearScaleQuestion | Sett inn et stjernebedømmings- eller lineærskala-spørsmål. |
| editor_insertHeader · editor_insertParagraph · editor_insertImage · editor_insertPageDivider | Sett inn ikke-spørsmålsinnhold: overskrifter, avsnitt, bilder og sideskift. |
| load_tools | Last dokumentasjon for en verktøykatalog. Returnerer skjemaer og bruksmønstre for grupperte verktøy. |
| load_skill | Last en domenekunnskap-guide (temaer, spørsmålstyper, logikregler osv.). |
Flere innsettingsvarianter — klokkeslett, filopplasting, signatur, betaling, matrise/rutenett, rangering, bildevelger, veksleknapp,
tabell, liste, rad, beregnet felt, skjult felt, innebygd variabel, innebygd innhold (editor_insertEmbedded for YouTube,
Google Maps eller iframe-innbygging) og en betinget logikkblokk (editor_insertLogic) — er også på tools/list.
Last load_skill(“question-types”) for hele settet, med verktøynavn og felt for hver type. Betinget logikk redigeres med
editor_setLogic i editor-actions-katalogen.
Verktøykataloger
Disse verktøyene er også på tools/list. Kjør load_tools med et katalognavn for å få utvidet dokumentasjon
(intro, fullstendige skjemaer, bruksmønstre, kanttilfeller) for de grupperte verktøyene, og kall dem deretter direkte.
| Katalog | Inkluderte verktøy |
|---|---|
| form-data | formAnalytics_get — aggregerte målinger (visninger, innsendinger, fullføringsrate, fordeling etter enhet, land, nettleser, kilde). Krever Pro- eller Business-planen; uten den feiler kallet med en melding som nevner planen. |
| form-appearance | formTheme_get, formTheme_set, form_update — temaer per modus (lys og mørk), pluss cover og logo via form_update. |
| form-behavior | formSettings_get, formSettings_update — varselsmeldinger, fullføringsomdirigering, passord, oppbevaring, språk, betaling. |
| form-sharing | formShareLink_list, formShareLink_create, formShareLink_update — CRUD for delingslenker med støtte for egendefinert domene. |
| form-translations | translationLanguage_list, translationDraft_get, translationDraft_update, translationDraft_publish, translationLanguage_delete — flerspråklig kladd-og-publiser-arbeidsflyt. Å publisere en tom kladd er eneste måte å avpublisere et språk på. |
| form-lifecycle | form_unpublish, form_restore — livssyklusoperasjoner utover kjernens publisering og sletting. |
| workspace-management | workspaceFolder_create, workspaceFolder_update, workspaceFolder_delete — mappe-CRUD utover kjernens liste-verb. |
| editor-actions | editor_formatText, editor_setLogic, editor_testLogic — tekstformatering, redigering av betinget logikk og logikksimulering. |
| request-lifecycle | fields_list, request_create, request_get, request_list, request_cancel, request_remind, request_replayCallback, document_create — hele forespørselsoverflaten: trekk tilbake en ventende forespørsel, purr på mottakeren, spill av på nytt en callback som aldri kom frem, reserver en dokumentopplasting for én forespørsel. |
| editor-inserts | Den lange halen av editor_insert*-verktøy: klokkeslett, veksleknapp, fil, signatur, dokumentblokk, matrise, rangering, betaling, avtale, bildevelger, innebygd innhold, tabell, liste, rad, beregnet felt, skjult felt, gjentakende gruppe, logikk og variabel. |
Katalogen request-lifecycle lister alle de åtte forespørselsverktøyene fordi in-app-chatten annonserer et mindre kjernesett.
Over dette endepunktet er alle åtte allerede på tools/list, så det katalogen legger til er dokumentasjonen.
Ferdigheter (domenekunnskap)
Ferdigheter er innebygde guider agenten kan laste via load_skill. De gir domenekunnskap som hjelper agenten med å ta bedre
beslutninger — ikke verktøyskjemaer, men designråd og feltssemantikk.
| Ferdighet | Hva den dekker |
|---|---|
| question-types | Alle spørsmålstyper, feltene deres og når man bør bruke hver enkelt. |
| logic-rules | Betinget logikk: operatorer, handlinger, kombinatorer og kanttilfeller. |
| editing-flows | Mønstre for å bygge skjemaer: rekkefølge, sideskift, piping. |
| form-best-practices | UX-retningslinjer for effektivt skjemadesign. |
| form-themes | Temastruktur, tokenreferanse og stilretningslinjer. |
| form-settings | Innstillingsreferanse: varsler, e-postmaler, variabler. |
| analytics | Definisjoner av målinger og hvordan man tolker skjemaanalyse. |
| toon-format | Kompakt utdataformat for strukturert datavisning. |
| requests | Forespørsler fra start til slutt: feltnøkler, verdiformer for prefill, levering, per-forespørsel-dokumenter, callbacks, polling og feilgjenoppretting. |
Forespørsler
En forespørsel tildeler ett publisert skjema til én navngitt mottaker, med sin egen lenke, sine egne forhåndsutfylte svar, og sitt eget utfall. Det er slik en agent ber et virkelig menneske om noe og finner ut hva de svarte.
Opprette en forespørsel
Start alltid med fields_list(formId). Den returnerer de adresserbare nøklene til skjemaets nåværende publiserte versjon, hver
med en usage-linje som sier hvilket argument nøkkelen hører til i — synlige spørsmål går i prefill, skjulte felt
i context. Avled aldri en nøkkel fra en spørsmålstittel, og les på nytt etter form_publish.
{
"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"
}Resultatet inneholder lenken og klokken:
{
"id": "kd7...",
"status": "pending",
"url": "https://form.formbase.so/r/rq_...",
"deliveryStatus": "queued",
"expiresAt": 1780000000000,
"createdAt": 1747000000000,
"deduplicated": false,
"next": "..."
}delivery er som standard “none”, som gir deg url til å levere selv; “email” sender
invitasjonen og krever recipient.email på en Pro- eller Business-plan, eller en av de 10 gratis invitasjonene til en
Gratis-konto. readonly låser felt mottakeren ikke kan redigere, og hver låst nøkkel må også være forhåndsutfylt.
context tar bare imot nøkler for skjulte felt, mens metadata er ugjennomsiktig bokføring som ekkoes tilbake på
request_get og i callbacken. expiresAt er epoke-millisekunder, standard er 30 dager og maks er 365.
idempotencyKey er gyldig i 30 dager innenfor arbeidsområden: samme nøkkel med samme body returnerer den opprinnelige
forespørselen med deduplicated: true, og en annen body er en konflikt. Hver respons har også en next-linje som
forteller agenten hva den skal gjøre videre.
deliveryStatus er not_requested til en invitasjon legges i kø, deretter queued → sent
eller failed, og bounced når e-postleverandøren melder om en hard retur eller en klage. Å opprette en
forespørsel bruker én enhet av arbeidsområdets månedlige kvote enten mottakeren svarer eller ikke; når den er brukt opp, feiler
request_create med MONTHLY_ALLOWANCE_REACHED.
Callbacks eller polling
Med en callbackUrl POST-er formbase én gang per avsluttende hendelse — fullføring, utløp, kansellering — signert med
arbeidsområdens signeringshemmelighet for forespørsler. Se Callbacks og signering
for nyttelasten og verifiseringsoppskriften.
Autonome agenter bør polle
Signeringshemmeligheten for forespørsler vises kun på siden for legitimasjon i arbeidsområdet ditt — den returneres aldri over MCP eller
API-et. En agent som kjører på egen hånd, uten et menneske til å sette opp og konfigurere en mottaker, kan derfor ikke verifisere en
callback. La callbackUrl være tom og poll heller request_get(requestId) i størrelsesorden minutter snarere enn
sekunder, helt til status forlater “pending”. expiresAt setter en grense for hvor lenge det er
verdt å gjøre det.
Testmodus
Send test: true for å øve på hele oppsettet før en ekte kjøring. Lenken åpnes fortsatt og kan fullføres, og callbacken fyrer
med “test”: true — men ingenting sendes på e-post uansett hva delivery sier, forespørselen forblir skjult fra
Forespørsler-siden og analysetrakten, og innsendingen teller ingen steder: ingen kvote, ingen eksporter, ingen integrasjoner.
Testforespørsler vises bare i request_list når du sender includeTest: true. Lenken lukkes innen 24 timer, og på
Free kan et workspace opprette 10 testforespørsler per dag.
Dokumenter per forespørsel
For å gi én mottaker en fil — et kontraktsutkast, deres eget tilbud — trenger skjemaet en dokumentblokk, som en forfatter
eller en agent setter inn med editor_insertDocumentsBlock. fields_list rapporterer den som
type: “documents”. Bytene reiser aldri gjennom et verktøy:
Kall
document_createmedformId,name,contentType, og den eksaktesizei bytes. Du får tilbake{ id, name, contentType, size, uploadUrl, expiresAt }. Kun PDF og bilder (ingen Office-dokumenter), 25 MB per fil, og 100 MB dokumenter per forespørsel.PUTde rå bytene tiluploadUrlinnen timen, medContent-Typesatt til typen du oppga.Referer den fra
request_create:documents: [{ documentId, field?, name? }].fielder dokumentblokkens feltnøkkel, valgfri bare når skjemaet har nøyaktig én slik blokk.nameoverstyrer visningsnavnet for denne forespørselen.
Blokkens faste dokumenter blir stående, og dine dukker opp under dem, kun for denne mottakeren. request_create verifiserer
opplastingen før forespørselen finnes, så DOCUMENT_NOT_UPLOADED betyr at steg 2 ble hoppet over. Én opplasting kan refereres
av et hvilket som helst antall forespørsler, og bytene teller mot arbeidsområdens lagring.
Egendefinerte domener
Send domainId til request_create for å utstede lenken på ett av arbeidsområdens
egendefinerte domener. IDene kommer fra formShareLink_list, som returnerer
dem som availableCustomDomains. Utelater du den, bruker lenken det domenet skjemaet allerede er publisert under.
Lese resultater
request_get returnerer hele forespørselen. Når den er fullført, inneholder answers mottakerens verdier,
nøkkelsatt etter feltnøkkel, display de samme nøklene som lesbar tekst, og outcome — godkjent, avvist, eller
endringer — er deres avgjørelse når skjemaet har et beslutningsspørsmål. Et
callbackFailedAt-tidsstempel betyr at leveringen gikk tom for nye forsøk og at ingenting nådde endepunktet ditt; fiks
mottakeren, og kall deretter request_replayCallback, som sender den opprinnelige hendelses-IDen på nytt slik at mottakeren
din dedupliserer i stedet for å kjøre på nytt. Etter at skjemaets oppbevaringspolicy fjerner en forespørsel, settes
dataPurgedAt, og svarene er borte for godt.
request_list feier gjennom mange på én gang, filtrert etter status, outcome,
externalId, og includeTest. Sideinndel med nextCursor: en side kan sjelden komme tilbake med en tom
items og hasMore: true, noe som ikke er slutten på listen — send cursoren tilbake og fortsett.
Ressurser og prompter
Hver ferdighet og verktøykatalog er også en MCP-ressurs på skill://<name> — skill://requests,
skill://editor-inserts. En klient som støtter resources/list kan bla gjennom og lese dem uten å kalle
load_skill eller load_tools. Serveren tilbyr også fire prompter på prompts/list:
identity, capabilities, data_tools, og editor_tools.
Verktøy som spør først
Hvert verktøy bærer MCP-hintene readOnlyHint og destructiveHint, avledet fra verbet sitt. Disse verktøyene er
merket destruktive, fordi det å angre dem krever et nytt kall eller ikke er mulig: form_delete, form_unpublish,
workspaceFolder_delete, editor_deleteElement, translationLanguage_delete, og
request_cancel. De fleste klienter spør brukeren før de kjører dem, men ledeteksten er klientens avgjørelse, så sjekk
godkjenningsinnstillingene dens hvis du trenger en garantert stopp.
Begrensninger
Ingen binæropplastinger via et verktøykall. Bilder settes med URL: covers, logoer og bildeblokker godtar
http(s)://ellerdata:image-URI-er. Et dokument per forespørsel er unntaket:document_createreturnerer en opplastings-URL som en klient med HTTP-tilgang kanPUTe filen til (se Dokumenter per forespørsel). For å gjøre en PDF eller et skjermbilde om til et skjema, bruk den innebygde AI-chatten.Ingen arbeidsområde-AI-ferdigheter. Ferdigheter skrevet i formbase er bare tilgjengelige i den innebygde AI-chatten. Serverens egne ferdigheter (
load_skill) er tilgjengelige over MCP.
Koble til med et API-token
De fleste klienter logger inn med OAuth: lim inn URL-en uten header og følg Koble til en AI-agent. En klient som ikke kan åpne en nettleser, som et skript, en CI-jobb eller en hodeløs agent, sender i stedet et API-token som en header.
Claude Code, fra kommandolinjen:
claude mcp add --transport http formbase https://api.formbase.so/api/mcp \
--header "Authorization: Bearer fb_YOUR_TOKEN"Eller i et prosjekts .mcp.json:
{
"mcpServers": {
"formbase": {
"type": "http",
"url": "https://api.formbase.so/api/mcp",
"headers": {
"Authorization": "Bearer fb_YOUR_TOKEN"
}
}
}
}Cursor, i .cursor/mcp.json eller ~/.cursor/mcp.json:
{
"mcpServers": {
"formbase": {
"url": "https://api.formbase.so/api/mcp",
"headers": {
"Authorization": "Bearer fb_YOUR_TOKEN"
}
}
}
}For å logge inn med OAuth i stedet for et token, bruk
Legg til i Cursor
. Den legger til server-URL-en uten header, og Cursor ber deg logge inn på formbase.
Andre klienter tar samme URL og header; se deres dokumentasjon for hvor.
Bruke OAuth i stedet for API-tokens
En tredjeparts-app som kobler til på vegne av en bruker, bør bruke OAuth i stedet for å be om et innlimt token. formbase er en OAuth
2.1-autorisasjonsserver med obligatorisk PKCE (S256) og opake tokens — ingen JWT-er, ingen implisitt grant. Claude desktop, Claude Code og
Claude.ai-nettkobleren oppdager alt dette fra MCP-endepunktet, så det holder å lime inn URL-en uten header: 401-en peker til
/.well-known/oauth-protected-resource, og klienten tar det derfra.
Flyten, for en klient du skriver selv:
GET /.well-known/oauth-protected-resource, deretterGET /.well-known/oauth-authorization-serverfor endepunkt-URL-ene, scopene og de støttede autentiseringsmetodene.POST /oauth/registermed dineredirect_uris(dynamisk klientregistrering, ingen legitimasjon nødvendig). Du får enclient_id, pluss enclient_secrethvis du ba om noe annet enntoken_endpoint_auth_method: “none”. Redirect-URI-er må være HTTPS, eller HTTP pålocalhost. Registrering er begrenset til 20 per time per IP.Send brukeren til
/oauth/authorizemedresponse_type=code, dinclient_id, den registrerteredirect_uri,scope=mcp:read mcp:write offline_access,state, og encode_challengemedcode_challenge_method=S256. De logger inn, velger ett arbeidsområde, og autoriserer.Bytt inn koden på
POST /oauth/tokenmedgrant_type=authorization_codeog dincode_verifier, innen 60 sekunder. Koder kan bare brukes én gang.Kall MCP-endepunktet med
Authorization: Bearer fbo_…. Tilgangstokens varer i 1 time; refresh-tokens varer i 30 dager og roteres ved hver bruk. Gjenbruk av et brukt refresh-token brenner hele kjeden, så lagre det nyeste.
POST /oauth/revoke (RFC 7009) tilbakekaller et tilgangs- eller refresh-token. En bruker kan også koble fra hele appen fra
Tilkoblede apper på siden OAuth og API-nøkler, som dreper alle tokens den har for det arbeidsområdet.
Har du allerede et token for hånden, går det samme sted som en API-nøkkel:
{
"mcpServers": {
"formbase": {
"type": "http",
"url": "https://api.formbase.so/api/mcp",
"headers": {
"Authorization": "Bearer fbo_USER_OAUTH_TOKEN"
}
}
}
}Tilkoblede apper
Hver OAuth-tilkobling er listet under Tilkoblede apper på siden OAuth og API-nøkler, med når den ble tilkoblet og sist brukt. Tilkoblinger er personlige: bare brukeren som autoriserte den, ser den, og arbeidsområdeadministratorer kan verken se eller tilbakekalle et annet medlems. Å koble fra trer i kraft umiddelbart. En bruker som forlater eller fjernes fra arbeidsområdet, mister alle sine tilkoblinger til det.