formbasedocs
Ir a la appApp

Desarrolladores

Servidor MCP

El servidor del Model Context Protocol (MCP) permite a los agentes de IA leer y editar tus formularios de formbase con herramientas enriquecidas basadas en esquemas.


Qué es

MCP es un estándar abierto para que las herramientas de IA se conecten a servicios externos. formbase expone un endpoint MCP alojado al que cualquier cliente compatible con MCP puede conectarse, incluyendo Claude Code, Claude desktop y Cursor.

Conexión

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

Funcionan dos tipos de token Bearer:

  • Token de API (fb_…) — se crea desde tokens de API. Ideal para uso personal y configuración rápida.

  • Token de acceso OAuth (fbo_…) — emitido por el flujo OAuth. Ideal para aplicaciones de terceros que se conectan en nombre de un usuario.

Ambos quedan vinculados a exactamente un espacio de trabajo y llegan a las mismas herramientas. Una llamada a una herramienta que nombre otro espacio de trabajo, o un formulario de otro, falla con FORBIDDEN. Los tokens OAuth también llevan ámbitos mcp:read, mcp:write y offline_access, pero hoy ninguna herramienta está restringida por ellos — trata cualquier token como acceso completo dentro de su espacio de trabajo.

Las llamadas a herramientas están limitadas a 120 por minuto por token, compartidas con la API: solo tools/call gasta el presupuesto, mientras que initialize, tools/list, prompts/ y resources/ son gratis. Al superar el límite, la llamada igualmente devuelve HTTP 200 con un resultado de herramienta fallido que lleva RATE_LIMITED y un retryAfterMs — sondea con un temporizador, nunca en un bucle.

Dónde obtener un token

Abre OAuth y claves de API en la barra lateral de tu espacio de trabajo para crear tokens de API y ver las apps OAuth conectadas. Consulta tokens de API para una guía paso a paso.

Herramientas principales

Todas las herramientas se anuncian en tools/list cuando un cliente se conecta. Los clientes que cargan esquemas bajo demanda, como Claude Code, obtienen el esquema completo de una herramienta cuando una tarea lo necesita. La tabla a continuación cubre las herramientas principales con las que empiezan la mayoría de las tareas; load_tools (catálogos) y load_skill (guías de dominio) documentan el resto.

HerramientaQué hace
form_listLista los formularios de un espacio de trabajo. Admite filtro por carpeta, búsqueda aproximada por nombre y paginación con cursor.
form_getObtiene todos los detalles de un formulario: preguntas, portada, logotipo y una URL de vista previa en vivo.
form_createCrea un nuevo formulario vacío en un espacio de trabajo. Devuelve una URL de vista previa para edición en vivo.
form_updateActualiza los metadatos del formulario: nombre, carpeta, emoji, portada o logotipo.
form_deleteElimina un formulario de forma suave (lo mueve a la papelera y revoca los enlaces de compartición).
form_publishPublica un formulario para que pueda recibir respuestas. Idempotente.
workspace_listLista todos los espacios de trabajo accesibles con tu token.
workspaceFolder_listLista las carpetas de un espacio de trabajo.
formSubmission_listLista los envíos de un formulario con paginación. Incluye borradores en Pro y Business; Free lista solo las respuestas completadas.
fields_listLista las claves de campo que una solicitud puede dirigir en un formulario publicado, cada una con su tipo de valor, las claves de las opciones y una línea de uso. Llámalo antes de request_create.
request_createAsigna un formulario publicado a un destinatario con nombre: precompletado, campos bloqueados, contexto, entrega, caducidad y un callback opcional.
request_getLee una solicitud: estado, cronología y — una vez completada — las respuestas indexadas por clave de campo, más display.
request_listLista solicitudes de un formulario o de todo un espacio de trabajo, filtradas por estado, resultado o tu propio id externo.
editor_getDocumentObtiene la estructura completa del documento de un formulario: todos los elementos, sus tipos y propiedades.
editor_updateElementEdita un elemento existente del formulario: reemplaza su texto, cambia propiedades (título, obligatorio, etc.) o lo reposiciona.
editor_deleteElementElimina un elemento del formulario.
editor_insertTextQuestionInserta una pregunta de texto corto o largo. Cada tipo de pregunta tiene su propia herramienta de inserción con un esquema preciso.
editor_insertContactQuestionInserta una pregunta de correo electrónico, número de teléfono o URL de sitio web.
editor_insertNumberQuestion · editor_insertDateQuestionInserta una pregunta de número o fecha.
editor_insertRadioQuestion · editor_insertCheckboxQuestion · editor_insertSelectQuestionInserta preguntas de opción única (radio), opción múltiple (casillas de verificación) o lista desplegable.
editor_insertDecisionQuestionInserta la pregunta de decisión: la opción aprobar / rechazar / cambios cuya respuesta se convierte en el resultado de una solicitud. Un radio creado a mano nunca produce uno.
editor_insertRatingQuestion · editor_insertLinearScaleQuestionInserta una pregunta de valoración por estrellas o escala lineal.
editor_insertHeader · editor_insertParagraph · editor_insertImage · editor_insertPageDividerInserta contenido que no es pregunta: encabezados, párrafos, imágenes y saltos de página.
load_toolsCarga la documentación de un catálogo de herramientas. Devuelve esquemas y patrones de uso para herramientas agrupadas.
load_skillCarga una guía de conocimiento de dominio (temas, tipos de pregunta, reglas de lógica, etc.).

Más variantes de inserción — hora, carga de archivos, firma, pago, matriz/cuadrícula, clasificación, selección de imagen, interruptor, tabla, lista, fila, campo calculado, campo oculto, variable inline, contenido incrustado (editor_insertEmbedded para YouTube, Google Maps o iframes) y un bloque de lógica condicional (editor_insertLogic) — también están en tools/list. Carga load_skill(“question-types”) para el conjunto completo, cada uno con su nombre de herramienta y campos. La lógica condicional se crea con editor_setLogic en el catálogo editor-actions.

Catálogos de herramientas

Estas herramientas también están en tools/list. Ejecuta load_tools con un nombre de catálogo para obtener documentación enriquecida (introducción, esquemas completos, patrones de uso, casos límite) para las herramientas agrupadas, y luego llámalas directamente.

CatálogoHerramientas incluidas
form-dataformAnalytics_get — métricas agregadas (vistas, envíos, tasa de completación, desglose por dispositivo, país, navegador y fuente). Requiere el plan Pro o Business; sin él, la llamada falla con un mensaje que indica el plan.
form-appearanceformTheme_get, formTheme_set, form_update — temas por modo (claro y oscuro), además de la portada y el logotipo en form_update.
form-behaviorformSettings_get, formSettings_update — notificaciones por correo, redirección al completar, contraseña, retención, idioma, pago.
form-sharingformShareLink_list, formShareLink_create, formShareLink_update — CRUD de enlaces de compartición con soporte de dominio personalizado.
form-translationstranslationLanguage_list, translationDraft_get, translationDraft_update, translationDraft_publish, translationLanguage_delete — flujo de trabajo multilingüe de borrador y publicación. Publicar un borrador vacío es la única forma de despublicar un idioma.
form-lifecycleform_unpublish, form_restore — operaciones de ciclo de vida más allá de publicar y eliminar.
workspace-managementworkspaceFolder_create, workspaceFolder_update, workspaceFolder_delete — CRUD de carpetas más allá de los verbos de lista principales.
editor-actionseditor_formatText, editor_setLogic, editor_testLogic — formato de texto, creación de lógica condicional y simulación de lógica.
request-lifecyclefields_list, request_create, request_get, request_list, request_cancel, request_remind, request_replayCallback, document_create — toda la superficie de solicitudes: retira una solicitud pendiente, envía un recordatorio al destinatario, repite un callback que nunca llegó, reserva la subida de un documento para una solicitud.
editor-insertsLa larga cola de herramientas editor_insert*: hora, interruptor, archivo, firma, bloque de documentos, matriz, clasificación, pago, cita, selección de imagen, contenido incrustado, tabla, lista, fila, campo calculado, campo oculto, grupo repetible, lógica y variable.

El catálogo request-lifecycle lista las ocho herramientas de solicitudes porque el chat integrado anuncia un conjunto principal más reducido. En este endpoint las ocho ya están en tools/list, así que lo que el catálogo añade es documentación.

Skills (conocimiento de dominio)

Los skills son guías integradas que el agente puede cargar mediante load_skill. Ofrecen conocimiento de dominio que ayuda al agente a tomar mejores decisiones — no son esquemas de herramientas, sino consejos de diseño y semántica de campos.

SkillQué cubre
question-typesCada tipo de pregunta, sus campos y cuándo usar cada uno.
logic-rulesLógica condicional: operadores, acciones, combinadores y casos límite.
editing-flowsPatrones para construir formularios: orden, saltos de página, piping.
form-best-practicesDirectrices de UX para un diseño de formularios efectivo.
form-themesEstructura de temas, referencia de tokens y directrices de estilo.
form-settingsReferencia de ajustes: notificaciones, plantillas de correo electrónico, variables.
analyticsDefiniciones de métricas y cómo interpretar los análisis de formularios.
toon-formatFormato de salida compacto para la visualización de datos estructurados.
requestsSolicitudes de principio a fin: claves de campo, formas de valor de precompletado, entrega, documentos por solicitud, callbacks, sondeo y recuperación de errores.

Solicitudes

Una solicitud asigna un formulario publicado a una persona con nombre, con su propio enlace, sus propias respuestas precompletadas y su propio resultado. Así es como un agente pide algo a una persona real y descubre qué ha respondido.

Crear una solicitud

Empieza siempre con fields_list(formId). Devuelve las claves direccionables de la versión publicada actual del formulario, cada una con una línea usage que indica en qué argumento va la clave — las preguntas visibles van en prefill, los campos ocultos en context. Nunca derives una clave a partir del título de una pregunta, y vuelve a leer después de 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"
}

El resultado incluye el enlace y el reloj:

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

delivery vale “none” por defecto, lo que te da url para que la entregues tú mismo; “email” envía la invitación y necesita recipient.email en un plan Pro o Business, o con una de las 10 invitaciones gratis de una cuenta Free. readonly bloquea campos que el destinatario no puede editar, y toda clave bloqueada también debe estar precompletada. context solo acepta claves de campos ocultos, mientras que metadata es contabilidad opaca que se refleja en request_get y en el callback. expiresAt son milisegundos epoch, con 30 días por defecto y un máximo de 365 días. idempotencyKey tiene alcance de espacio de trabajo durante 30 días: la misma clave con el mismo cuerpo devuelve la solicitud original con deduplicated: true, y un cuerpo distinto es un conflicto. Cada respuesta también incluye una línea next que le dice al agente qué hacer a continuación.

deliveryStatus es not_requested hasta que se pone en cola una invitación, luego queued → sent o failed, y bounced en cuanto el proveedor de correo reporta un rebote definitivo o una queja. Crear una solicitud gasta una unidad de la asignación mensual del espacio de trabajo, responda o no el destinatario; una vez agotada, request_create falla con MONTHLY_ALLOWANCE_REACHED.

Callbacks o sondeo

Con una callbackUrl, formbase envía un POST una vez por cada evento terminal — finalización, expiración, cancelación — firmado con el secreto de firma de solicitudes del espacio de trabajo. Consulta Callbacks y firma para conocer el payload y la receta de verificación.

Los agentes autónomos deberían sondear

El secreto de firma de solicitudes solo aparece en la página de Credenciales de tu espacio de trabajo — nunca se devuelve por MCP ni por la API. Un agente que se ejecuta por su cuenta, sin ninguna persona que levante y configure un receptor, no puede por tanto verificar un callback. Omite callbackUrl y en su lugar consulta request_get(requestId) periódicamente, del orden de minutos y no de segundos, hasta que status deje de ser “pending”. expiresAt acota cuánto tiempo merece la pena hacerlo.

Modo de prueba

Pasa test: true para ensayar todo el circuito antes de una ejecución real. El enlace se sigue abriendo y se puede completar, y el callback se dispara con “test”: true — pero no se envía nada por correo sea lo que sea lo que diga delivery y la solicitud queda oculta de la página de Solicitudes y del embudo de analíticas, y su envío no cuenta en ningún sitio: ni cuota, ni exportaciones, ni integraciones. Las solicitudes de prueba solo aparecen en request_list cuando pasas includeTest: true. El enlace se cierra en un plazo de 24 horas, y en Free un workspace puede crear 10 solicitudes de prueba al día.

Documentos por solicitud

Para entregarle a un destinatario un archivo — un borrador de contrato, su propio presupuesto — el formulario necesita un bloque de Documentos, que un autor o un agente inserta con editor_insertDocumentsBlock. fields_list lo reporta como type: “documents”. Los bytes nunca pasan por una herramienta:

  1. Llama a document_create con formId, name, contentType y el size exacto en bytes. Recibes { id, name, contentType, size, uploadUrl, expiresAt }. Solo PDF e imágenes (sin documentos de Office), 25 MB por archivo, y 100 MB de documentos por solicitud.

  2. Haz un PUT de los bytes en bruto a uploadUrl antes de que pase una hora, con Content-Type ajustado al tipo que declaraste.

  3. Referéncialo desde request_create: documents: [{ documentId, field?, name? }]. field es la clave de campo del bloque de Documentos, opcional solo cuando el formulario tiene exactamente un bloque de ese tipo. name sobrescribe el nombre visible para esta solicitud.

Los documentos de autor del bloque permanecen intactos y los tuyos aparecen debajo, solo para este destinatario. request_create verifica la subida antes de que la solicitud exista, así que DOCUMENT_NOT_UPLOADED significa que el paso 2 se saltó. Una subida puede ser referenciada por cualquier número de solicitudes, y sus bytes cuentan contra el almacenamiento de tu espacio de trabajo.

Dominios personalizados

Pasa domainId a request_create para generar el enlace en uno de los dominios personalizados del espacio de trabajo. Los ids vienen de formShareLink_list, que los devuelve como availableCustomDomains. Si lo omites, el enlace usa el dominio en el que el formulario ya está publicado.

Leer los resultados

request_get devuelve la solicitud completa. Una vez completada, answers contiene los valores del destinatario indexados por clave de campo, display las mismas claves como texto legible, y outcome — aprobación, rechazo o cambios — es su veredicto cuando el formulario tiene una pregunta de decisión. Una marca de tiempo callbackFailedAt significa que la entrega se quedó sin reintentos y nada llegó a tu endpoint; arregla el receptor y luego llama a request_replayCallback, que reenvía el id del evento original para que tu receptor deduplique en lugar de volver a ejecutarse. Tras que la política de retención del formulario elimine una solicitud, se establece dataPurgedAt y las respuestas se pierden para siempre.

request_list recorre muchas a la vez, filtradas por status, outcome, externalId e includeTest. Pagina con nextCursor: una página puede, en raras ocasiones, volver con items vacío y hasMore: true, lo cual no es el final de la lista — pasa el cursor de vuelta y sigue.

Recursos y prompts

Cada skill y catálogo de herramientas es también un recurso MCP en skill://<name> — skill://requests, skill://editor-inserts. Un cliente que admite resources/list puede explorarlos y leerlos sin necesidad de llamar a load_skill o load_tools. El servidor también sirve cuatro prompts en prompts/list: identity, capabilities, data_tools y editor_tools.

Herramientas que piden confirmación

Cada herramienta lleva las pistas MCP readOnlyHint y destructiveHint, derivadas de su verbo. Estas herramientas están marcadas como destructivas, porque deshacerlas exige otra llamada o no es posible: form_delete, form_unpublish, workspaceFolder_delete, editor_deleteElement, translationLanguage_delete y request_cancel. La mayoría de los clientes piden confirmación al usuario antes de ejecutarlas, pero ese aviso es decisión del cliente, así que revisa sus ajustes de aprobación si necesitas un bloqueo estricto.

Limitaciones

  • Sin subidas binarias mediante una llamada a herramienta. Las imágenes se establecen por URL: portadas, logotipos y bloques de imagen aceptan URIs http(s):// o data:image. Un documento por solicitud es la excepción: document_create devuelve una URL de subida que un cliente con acceso HTTP puede subir con PUT (consulta Documentos por solicitud). Para convertir un PDF o una captura de pantalla en un formulario, usa el chat de IA integrado.

  • Sin AI Skills del espacio de trabajo. Las habilidades escritas en formbase solo están disponibles en el chat de IA integrado. Las skills propias del servidor (load_skill) sí están disponibles por MCP.

Conectar con un token de API

La mayoría de los clientes inician sesión con OAuth: pega la URL sin ninguna cabecera y sigue Conecta un agente de IA. Un cliente que no puede abrir un navegador, como un script, un job de CI o un agente sin interfaz, envía en su lugar un token de API como cabecera.

Claude Code, desde la línea de comandos:

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

O en el .mcp.json de un proyecto:

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

Cursor, en .cursor/mcp.json o ~/.cursor/mcp.json:

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

Para iniciar sesión con OAuth en lugar de un token, usa Añadir a Cursor . Añade la URL del servidor sin cabecera, y Cursor te pide que inicies sesión en formbase.

Otros clientes usan la misma URL y cabecera; consulta su documentación para saber dónde.

Usar OAuth en lugar de tokens de API

Una aplicación de terceros que se conecta en nombre de un usuario debería usar OAuth en lugar de pedir un token pegado. formbase es un servidor de autorización OAuth 2.1 con PKCE obligatorio (S256) y tokens opacos — sin JWT, sin implicit grant. Claude desktop, Claude Code y el conector web de Claude.ai descubren todo esto desde el endpoint MCP, así que pegar la URL sin ninguna cabecera es suficiente: el 401 apunta a /.well-known/oauth-protected-resource, y el cliente se encarga del resto.

El flujo, para un cliente que escribas tú mismo:

  1. GET /.well-known/oauth-protected-resource, luego GET /.well-known/oauth-authorization-server para las URLs de los endpoints, los ámbitos y los métodos de autenticación admitidos.

  2. POST /oauth/register con tus redirect_uris (registro dinámico de cliente, sin necesidad de credenciales). Recibes un client_id, más un client_secret si pediste algo distinto de token_endpoint_auth_method: “none”. Las redirect URIs deben ser HTTPS, o HTTP en localhost. El registro está limitado a 20 por hora por IP.

  3. Envía al usuario a /oauth/authorize con response_type=code, tu client_id, el redirect_uri registrado, scope=mcp:read mcp:write offline_access, state, y un code_challenge con code_challenge_method=S256. Inicia sesión, elige un espacio de trabajo y autoriza.

  4. Intercambia el código en POST /oauth/token con grant_type=authorization_code y tu code_verifier, en un plazo de 60 segundos. Los códigos son de un solo uso.

  5. Llama al endpoint MCP con Authorization: Bearer fbo_…. Los tokens de acceso duran 1 hora; los tokens de actualización duran 30 días y rotan en cada uso. Reutilizar un token de actualización ya gastado quema toda la cadena, así que guarda el más reciente.

POST /oauth/revoke (RFC 7009) revoca un token de acceso o de actualización. Un usuario también puede desconectar toda la aplicación desde Aplicaciones conectadas en la página OAuth y claves de API, lo que elimina todos los tokens que tiene para ese espacio de trabajo.

Si ya tienes un token en la mano, va en el mismo lugar que una clave de 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"
      }
    }
  }
}

Aplicaciones conectadas

Cada conexión OAuth aparece listada en Aplicaciones conectadas, en la página OAuth y claves de API, con la fecha en que se conectó y su último uso. Las conexiones son personales: solo el usuario que la autorizó puede verla, y los administradores del espacio de trabajo no pueden ver ni revocar la de otro miembro. Desconectar surte efecto de inmediato. Un usuario que abandona el espacio de trabajo, o es eliminado de él, pierde todas sus conexiones a ese espacio.

Próximos pasos