BriefGate

Recepción de clientes para agentes de IA: solicita archivos, copias e inicios de sesión de un cliente a través de un portal sin cuenta con recordatorios automáticos, y luego lee los resultados escritos de vuelta.

Servidor MCP alojado

npx add-mcp 'https://mcp.briefgate.dev/mcp'

Se instala en Claude Code, Codex, Cursor y más

Documentación

BriefGate

Captación de clientes para agentes de IA que programan.

Tu agente puede construir el sitio web. BriefGate obtiene del cliente lo que falta.

Claude Code / Cursor / Codex → BriefGate → Client portal
  → Files · copy · credentials · structured data → Agent continues building

BriefGate demo: an intake being defined, the client filling the portal, results coming back

Ver como MP4 (25 s) · Recorrido completo de 47 s

Sitio web · Referencia MCP · llms.txt · Guías y listas de verificación

¿No trabajas con un agente? Las mismas captaciones se pueden crear desde el panel del navegador: consulta el inicio rápido del panel.

El problema

Los agentes son rápidos. El cuello de botella es la persona al otro lado del proyecto.

En algún punto de la construcción, el agente necesita algo que solo el cliente tiene: un logotipo, el texto de la página de inicio, los colores de la marca, el horario de apertura, las credenciales de alojamiento, una clave de API, un dato estructurado como una lista de precios. Nada de eso existe en el chat y nada de eso se puede adivinar.

Lo habitual es detenerse y pedirle al desarrollador que persiga al cliente por correo. En su lugar, el agente crea una captación de BriefGate. BriefGate envía un correo al cliente, recopila lo que llega, persigue automáticamente cuando no llega y devuelve resultados tipados que el agente puede usar directamente. Mientras tanto, el agente sigue construyendo.

Inicio rápido

Claude Code — alojado, sin clave que gestionar:

claude mcp add --transport http briefgate https://mcp.briefgate.dev/mcp

Luego ejecuta /mcp en Claude Code, elige briefgate y selecciona Autenticar.

Claude Code — paquete local:

claude mcp add briefgate -- npx -y @briefgate/mcp
npx -y @briefgate/mcp login

¿Prefieres omitir el inicio de sesión por completo? Obtén una clave en briefgate.dev (plan gratuito, sin tarjeta) y pásala como BRIEFGATE_API_KEY.

Cursor — agrégalo a .cursor/mcp.json:

{
  "mcpServers": {
    "briefgate": {
      "command": "npx",
      "args": ["-y", "@briefgate/mcp"]
    }
  }
}

Luego ejecuta npx -y @briefgate/mcp login, o pídele al agente que llame a la herramienta login.

Codex:

codex mcp add briefgate --env BRIEFGATE_API_KEY=bg_live_xxxxx -- npx -y @briefgate/mcp

Gemini CLI — se instala como extensión desde el gemini-extension.json de este repositorio, apuntando al endpoint alojado:

gemini extensions install https://github.com/sekera-radim/briefgate-mcp

Se autentica igual que los demás clientes alojados anteriores: mediante OAuth, en el primer uso. La extensión también incluye GEMINI.md, un archivo de contexto que le explica al modelo qué es BriefGate y cuándo recurrir a él.

De forma predeterminada, gemini extensions install obtiene la última versión de GitHub Release del repositorio en lugar de la rama main; si esa versión es anterior a la gemini-extension.json actual y el comando informa de un archivo de configuración faltante, instala desde main directamente en su lugar: gemini extensions install --ref main https://github.com/sekera-radim/briefgate-mcp.

Claude Desktop — instalación con un clic como Extensión de escritorio (.mcpb), que ejecuta el paquete local @briefgate/mcp en lugar del endpoint alojado. Detalles de compilación: consulta paquete MCPB más abajo.

Cursor — como plugin desde el .cursor-plugin/plugin.json de este repositorio, que agrupa la misma configuración de MCP junto con la habilidad collect-from-client que se indica más abajo.

Cualquier herramienta compatible con Agent Skills (OpenAI Codex, GitHub Copilot / VS Code, Cursor, Gemini CLI y otros clientes con ese estándar) — instala la habilidad collect-from-client con la CLI de skills:

npx skills add https://github.com/sekera-radim/briefgate-mcp/tree/main/skills/collect-from-client

La abreviatura simple owner/repo que muestran los propios documentos de la CLI no funciona con esta estructura a partir de skills@1.5.26: o devuelve 404 contra su registro o, con la URL simple del repositorio, clona todo el repositorio e informa "No SKILL.md found" porque el nuestro vive un directorio más profundo que la raíz. La URL completa de /tree/main/skills/<name> de arriba es la que realmente lo instala; verificado ejecutándola en un directorio de prueba vacío antes de documentarlo. Esto copia SKILL.md al directorio local de habilidades de esa herramienta; la habilidad sigue asumiendo que el servidor MCP briefgate (consulta las instrucciones específicas del cliente arriba) está configurado por separado.

Detalles completos de configuración, configuración manual y precedencia de claves de API: consulta Referencia más abajo.

Para agentes que leen instrucciones de proyecto (AGENTS.md, reglas de Copilot, Cursor)

Si tu agente lee un archivo de instrucciones de proyecto en lugar de (o además de) las descripciones de herramientas MCP o Agent Skills, agrega este bloque a tu AGENTS.md, .github/copilot-instructions.md o .cursor/rules:

## BriefGate

BriefGate (MCP server `briefgate`, or `npx @briefgate/mcp`) collects files,
text, choices, or credentials from a human who is not in this conversation
(a client, colleague, or customer) — it emails them a no-account portal link
and chases them automatically until everything is submitted.

Use it when a task is blocked on input only that outside person can supply,
especially if they may take days and need reminders. Do not use it when the
information is already available, or when the person who should answer is
the user you're talking to.

Flow: `define_intake` (with items) -> tell the user it was sent ->
`get_intake_status` later ("not ready" is normal, not an error) ->
`get_intake_results` once completed. `request_revision` for a bad item.
Secret items are revealed in plaintext exactly once.

Ejemplo: construir el sitio web de un cliente

Un agente está construyendo el sitio web de un restaurante. Tiene el diseño y el flujo de reservas, pero aún necesita el logotipo, una foto principal, el horario de apertura, una descripción breve del restaurante, los enlaces a redes sociales y acceso de administrador a la instalación de WordPress del cliente. Llama a define_intake:

{
  "project_name": "Website for Trattoria Bella",
  "client": { "email": "owner@trattoriabella.example", "name": "Marco", "language": "en" },
  "items": [
    { "key": "logo", "type": "image", "label": "Restaurant logo",
      "constraints": { "formats": ["svg", "png"], "min_width": 512 } },
    { "key": "hero_image", "type": "image", "label": "Hero photo for the homepage" },
    { "key": "opening_hours", "type": "structured", "label": "Opening hours",
      "schema": { "type": "object", "properties": { "mon_fri": { "type": "string" }, "sat": { "type": "string" }, "sun": { "type": "string" } } } },
    { "key": "about_copy", "type": "longtext", "label": "Short description of the restaurant" },
    { "key": "social_links", "type": "structured", "label": "Social media links" },
    { "key": "wp_admin", "type": "secret", "label": "WordPress admin credentials" }
  ]
}

A partir de ahí, BriefGate (1) crea un portal con la marca, (2) envía un correo al cliente, (3) valida cada recurso a medida que llega, (4) persigue al cliente automáticamente hasta que todo esté enviado y (5) notifica al agente cuando termina.

El agente sigue construyendo el diseño, el flujo de reservas y todo lo demás que no dependa de esto; luego llama a get_intake_results(intake_id) y recibe datos tipados y URL firmadas para los archivos, además de una revelación única de las credenciales de WordPress. Guarda el secreto y continúa.

¿Por qué no un formulario?

Formulario genéricoBriefGate
Un humano crea el formularioEl agente declara lo que necesita
Un humano lee los resultadosEl agente consume resultados tipados
Respuestas genéricasElementos tipados
Seguimiento manualPersecución automática
Mentalidad de hoja de cálculoFlujo de trabajo API / MCP
Las credenciales son incómodasElemento secreto + revelación controlada
Flujo de trabajo humanoFlujo de trabajo de agente

BriefGate no intenta reemplazar a todos los creadores de formularios. Está diseñado para el punto en que un agente de IA necesita información de un humano.

Plan gratuito, sin tarjeta. BriefGate es un servicio alojado: este repositorio es el cliente MCP de código abierto, con licencia MIT. Regístrate en briefgate.dev.

Referencia

Todo lo que sigue es detalle técnico sin cambios: configuración manual, variables de entorno, modo HTTP/OAuth, la referencia completa de herramientas, webhooks, precios y aspectos legales.

Claude Code: configuración manual y claves de API

Pega una clave de API (para CI, scripts o si prefieres gestionar la clave tú mismo). Obtén una en briefgate.dev (plan gratuito disponible, sin tarjeta):

claude mcp add briefgate \
  -e BRIEFGATE_API_KEY=bg_live_... \
  -- npx -y @briefgate/mcp

O agrega manualmente a ~/.claude/settings.json:

{
  "mcpServers": {
    "briefgate": {
      "command": "npx",
      "args": ["-y", "@briefgate/mcp"],
      "env": {
        "BRIEFGATE_API_KEY": "bg_live_..."
      }
    }
  }
}

BRIEFGATE_API_KEY (o --api-key en la línea de comandos), si está configurada, siempre tiene prioridad sobre una clave login almacenada localmente: ejecutar login mientras una está configurada solo lo indica en lugar de hacer nada.

Verifica que se cargó — ejecuta /mcp en Claude Code y busca briefgate con 15 herramientas.

La misma configuración de paquete local y clave de API funciona para cualquier cliente MCP que ejecute el paquete localmente (Cursor, Codex, otros): regístralo sin clave y ejecuta login, o pega BRIEFGATE_API_KEY en la configuración MCP de ese cliente de la misma manera.

Iniciar sesión sin clave de API

Dos formas de obtener una clave en esta máquina sin pegar una: ambas ejecutan el mismo flujo de autorización de dispositivo (RFC 8628) contra el mismo archivo de credenciales, así que elige la que se adapte a cómo usas el paquete.

Desde una terminal — los subcomandos login / logout:

npx -y @briefgate/mcp login     # prints a code + URL, waits for approval, saves the key
npx -y @briefgate/mcp logout    # removes the local key, best-effort revokes it remotely

login se bloquea hasta que lo apruebes (o se agote a los 10 minutos), luego imprime Signed in as <account_name> y sale con 0 — o imprime por qué no funcionó (denegado, expirado, un error) y sale con 1. logout siempre elimina la copia local; también envía DELETE /v1/keys/current usando esa misma clave para revocarla en el servidor, y si esa llamada falla (sin red, API inaccesible) lo indica y apunta al panel de BriefGate en lugar de dejarte sin saber si la clave sigue activa.

Desde un agente — las herramientas login / logout (consulta Herramientas):

Mismo flujo, para un cliente que no puede bloquear una terminal mientras haces clic. login es de dos fases porque una llamada de herramienta no puede permanecer abierta durante minutos:

  1. La primera llamada inicia el flujo y regresa de inmediato con el código y la URL. Se abre un navegador automáticamente cuando es posible.
  2. Llama a login de nuevo — en cualquier momento, o una vez que lo hayas aprobado — para verificar el progreso. Mientras aún espera, lo indica; una vez aprobado, esa misma llamada informa éxito y la clave se guarda. No se necesita reinicio: la siguiente llamada de herramienta ya está autenticada.

logout como herramienta hace exactamente lo que hace el subcomando, incluida la revocación remota de mejor esfuerzo.

En cualquier caso, la clave se guarda en ~/.briefgate/credentials.json (modo directorio 0700, modo archivo 0600; anula la ruta con BRIEFGATE_CREDENTIALS_FILE), identificada por el servidor BriefGate al que corresponde, para que un BRIEFGATE_BASE_URL de prueba y la producción nunca colisionen. Una clave explícita siempre gana sobre una almacenada — --api-key, luego BRIEFGATE_API_KEY, luego lo que login haya guardado por última vez — y login lo indica en lugar de ejecutar el flujo cuando una de esas ya está configurada. Ni los subcomandos ni las herramientas se aplican al endpoint alojado compartido (mcp.briefgate.dev) — consulta Endpoint alojado + OAuth, donde conectar un cliente activa OAuth real en su lugar.

Variables de entorno

VariableObligatoriaPredeterminadaDescripción
BRIEFGATE_API_KEYNoClave de API (bg_live_... o bg_test_...). Tiene prioridad sobre una credencial almacenada por login. Si no hay nada configurado, las llamadas a herramientas fallan con un mensaje que apunta a login.
BRIEFGATE_BASE_URLNohttps://api.briefgate.devAnulación para pruebas o desarrollo local.
BRIEFGATE_CREDENTIALS_FILENo~/.briefgate/credentials.jsonDónde login/logout guardan la clave. Principalmente para pruebas y configuraciones inusuales.
BRIEFGATE_NO_BROWSERNosin definirConfigúrala en 1 para evitar que login abra un navegador (servidores sin interfaz, CI); la URL se imprime de todos modos.
BRIEFGATE_MCP_HTTPNoConfigúrala en 1 para iniciar Streamable HTTP en lugar de stdio.
BRIEFGATE_MCP_PORTNo3000Puerto para el modo HTTP.
BRIEFGATE_MCP_PUBLIC_HOSTNoPublica el servidor como un endpoint OAuth compartido de múltiples clientes. Consulta Endpoint alojado + OAuth.
BRIEFGATE_MCP_AUTH_SERVERNoBRIEFGATE_BASE_URLEl servidor de autorización OAuth anunciado a los clientes en modo publicado. El valor predeterminado es BRIEFGATE_BASE_URL para desarrollo local, donde suelen ser la misma dirección; un despliegue real detrás de una red de contenedores lo configura explícitamente (consulta más abajo).

--api-key bg_live_... también se acepta en la línea de comandos, por delante de BRIEFGATE_API_KEY en prioridad. login y logout también se aceptan como primer argumento de línea de comandos (npx @briefgate/mcp login), en lugar de --http/sin indicador.

Modo HTTP (Streamable HTTP)

Para despliegues remotos o de múltiples sesiones, inicia el servidor en modo HTTP:

BRIEFGATE_API_KEY=bg_live_... npx @briefgate/mcp --http --port 3000

El servidor se vincula solo a 127.0.0.1 e incluye protección contra el reenlace de DNS. Detrás de un proxy inverso, termina TLS allí y reenvía al puerto local: no expongas el puerto directamente.

Endpoint alojado + OAuth

Configura BRIEFGATE_MCP_PUBLIC_HOST con el nombre de host bajo el que se publica el servidor y se convierte en un endpoint compartido de múltiples clientes: cada llamador envía su propia clave como Authorization: Bearer bg_live_... (un token de acceso OAuth, para esta API, es esa misma clave — consulta más abajo), y el servidor habla con la API de BriefGate como ese llamador. La instancia pública es https://mcp.briefgate.dev/mcp.

BRIEFGATE_MCP_PUBLIC_HOST=mcp.example.com npx @briefgate/mcp --http --port 3000

Varias cosas cambian, a propósito:

  • el listener se enlaza a 0.0.0.0 y el guard de Host acepta ese nombre, porque un servidor detrás de un proxy inverso se alcanza por su nombre público;
  • el fallback de BRIEFGATE_API_KEY y la credencial local de login están ambos desactivados. Dejar cualquiera activo permitiría que un llamador anónimo gaste la clave del operador, o lea lo que la propia máquina login almacenó por última vez;
  • login/logout, tanto herramientas como subcomandos, no están disponibles — conectar un cliente dispara OAuth real en su lugar, descrito abajo;
  • el servidor se convierte en un servidor de recursos OAuth 2.1, según la especificación de autorización de MCP, por lo que un cliente compatible con OAuth puede añadirlo con solo la URL. Este paquete nunca ejecuta el flujo de autorización en sí — solo anuncia dónde encontrarlo y exige que una solicitud lleve un token:
    • sirve GET /.well-known/oauth-protected-resource (RFC 9728), y el mismo contenido de nuevo bajo /.well-known/oauth-protected-resource/mcp (la ruta con ámbito de recurso que la especificación MCP también hace que los clientes intenten), ambas con CORS abierto y nombrando la API de BriefGate como servidor de autorización — ver BRIEFGATE_MCP_AUTH_SERVER arriba;
    • cada solicitud MCP ahora necesita un token Bearer — incluyendo initialize y tools/list, que antes funcionaban sin uno para que un registro pudiera inspeccionar la lista de herramientas. Una sin token recibe HTTP 401 y un encabezado WWW-Authenticate: Bearer resource_metadata="https://<host>/.well-known/oauth-protected-resource", que es la señal que un cliente OAuth usa para comenzar a iniciar sesión;
    • si la clave de una llamada a herramienta resulta expirada o revocada (la API responde 401), la respuesta se reescribe en un HTTP 401 real con el mismo encabezado más error="invalid_token", en lugar de un error de herramienta ordinario — para que el cliente sepa refrescar en lugar de solo reportar que la llamada falló.

Lo que un cliente que se conecta realmente hace, contra el servidor de autorización nombrado en esos metadatos: descubrimiento estándar de OAuth 2.1 (GET /.well-known/oauth-authorization-server), registro dinámico de clientes (POST /v1/oauth/register), luego un intercambio de código de autorización con PKCE (S256) en POST /v1/oauth/token — sin secreto de cliente, ya que los clientes MCP son clientes públicos — y POST /v1/oauth/revoke para terminar una sesión. Nada de eso es preocupación de este paquete; solo tiene que ser un servidor de recursos correcto apuntando a ello. El token de acceso que sale al otro extremo es una clave bg_live_... como cualquier otra, con una expiración de una hora que la API aplica.

Nada de esto aplica sin BRIEFGATE_MCP_PUBLIC_HOST: una ejecución local de --http sigue comportándose exactamente como antes, incluyendo una clave ausente que llega a initialize/tools/list y un encabezado Authorization: Bearer ... simple funcionando sin OAuth involucrado.

Herramientas

define_intake

Crear una nueva admisión de cliente — un portal con marca donde el cliente envía los activos que necesitas. BriefGate envía el correo de invitación y persigue al cliente automáticamente hasta que todo esté recopilado.

project_name: "Website for John Finance"
client: { email: "john@example.com", name: "John", language: "cs" }
// also_notify: [{ email: "jane@example.com", name: "Jane" }]
//   Others at the client who get the same link and the same reminders — either of
//   them can supply the material. Each gets their own email; nobody sees the rest.
due_date: "2026-08-15"
branding: { accent_color: "#1B2A4A", sender_name: "Radim" }
chase_schedule: "default"   // default | gentle | aggressive | custom | off
// chase_interval: 5, chase_interval_unit: "minutes"   // only with "custom"; omit for every 3 days
// respect_quiet_hours: false, max_reminders: 12       // for a deliberately rapid cadence
items:
  - { key: "logo",       type: "image",    label: "Company logo",
      constraints: { formats: ["svg","png"], min_width: 512 } }
  - { key: "hero_copy",  type: "longtext", label: "Homepage headline",
      constraints: { max_chars: 400 } }
  - { key: "brand_colors", type: "color_list", label: "Brand colors", required: false }
  - { key: "ga4_id",    type: "text",     label: "Google Analytics ID",
      pattern: "^G-[A-Z0-9]+$", required: false }
  - { key: "wp_admin",  type: "secret",   label: "WordPress admin credentials" }
  - { key: "photos",    type: "file_list", label: "Photos (5–10 images)",
      constraints: { formats: ["jpg","png","heic"], min_count: 5, max_count: 15 } }
  - { key: "opening_hours", type: "structured", label: "Opening hours",
      schema: { type: "object", properties: { mon_fri: { type: "string" }, sat: { type: "string" } } } }
  - { key: "has_existing_site", type: "boolean", label: "Does the client have an existing website?" }
  - { key: "website_url", type: "url", label: "Current website URL", required: false }
  - { key: "service_tier", type: "select", label: "Service package",
      options: [{ value: "basic", label: "Basic" }, { value: "pro", label: "Pro" }] }
// folder_id: "fld_1"
//   Put the intake straight into an existing folder from list_folders instead
//   of leaving it unfiled.
// client_brief: "Here's the offer we agreed on, plus a few notes on scope..."
//   Free text shown to the client above the requested items — information from
//   you to them, not another thing you're asking them for. Up to 5000 characters.
//   Documents go through POST /v1/intakes/:id/brief/files (dashboard or REST,
//   not through MCP).

Reglas de clave de elemento: debe ser snake_case (p. ej. logo, hero_copy, ga4_id). Las claves se convierten en nombres de propiedad en get_intake_results — sin mayúsculas, sin espacios, sin guiones.

Devuelve { intake_id, portal_url, status }. Guarda intake_id para todas las llamadas de seguimiento.

get_intake_status

Comprobar qué elementos están enviados, pendientes o necesitan revisión. Incluye el historial de correos de seguimiento automáticos y cuándo el cliente abrió el portal por última vez.

intake_id: "in_8f3k"

Devuelve estado por elemento y un historial completo de seguimiento.

get_intake_results

Recuperar valores enviados con tipo. Los archivos son URLs firmadas (válidas 24 horas). Los secretos son de un solo uso — descifrados y devueltos solo en la primera llamada; guárdalos antes de continuar.

intake_id: "in_8f3k"
only_new: true          // only items new since last call
include_pending: false  // omit unsubmitted items

Devuelve { results: { logo: "https://signed...", hero_copy: "text...", wp_admin: "s3cr3t" }, meta: { ... } }.

request_revision

Pedir al cliente que reenvíe un elemento con una nota explicando qué está mal.

intake_id: "in_8f3k"
item_key: "logo"
note: "Logo is blurry — we need at least 512 px wide in SVG or PNG with a transparent background"

Devuelve { status: "revision_requested", item_key }.

send_chase

Enviar un recordatorio manual fuera del horario automático. Úsalo cuando se acerca una fecha límite o los intentos de correo han fallado.

intake_id: "in_8f3k"

Devuelve { sent: true }.

list_intakes

Listar todas las admisiones entre proyectos, opcionalmente filtradas por estado, correo del cliente, carpeta o una búsqueda de texto.

status: "in_progress"   // draft | sent | in_progress | completed | archived
client_email: "john@example.com"
folder_id: "fld_1"      // or "none" for intakes not in any folder
q: "Finance"             // substring match on project name, client name, or client email
limit: 20
offset: 0

Devuelve { intakes: [...], total }.

add_items

Añadir nuevos elementos a una admisión ya enviada — por ejemplo un favicon que olvidaste, o credenciales adicionales necesarias a mitad de proyecto.

intake_id: "in_8f3k"
items:
  - { key: "favicon", type: "image", label: "Favicon (32×32 PNG or ICO)" }

Devuelve la admisión actualizada.

update_item

Cambiar la definición de un elemento después de que la admisión fue enviada — el tipo, la etiqueta, el texto de ayuda o las restricciones. Úsalo cuando pediste lo incorrecto, p. ej. solicitaste una imagen pero el cliente tiene un PDF.

intake_id: "in_8f3k"
item_key: "logo"
type: "file"                        // was "image"
constraints: { formats: ["pdf","ai","svg"] }
discard_submitted_value: false      // true is required if the change invalidates what the client already sent

Devuelve el elemento actualizado. Si el cliente ya envió un valor que la nueva definición rechazaría, la llamada falla con item_answer_would_be_discarded hasta que pases discard_submitted_value: true.

update_intake

Cambiar configuraciones en una admisión ya enviada — nombre del proyecto, fecha límite, cadencia de recordatorios, horas de silencio, el resumen del cliente, o el nombre, teléfono, idioma y zona horaria del cliente. Úsalo en lugar de eliminar y recrear la admisión, lo que reenviaría la invitación.

intake_id: "in_8f3k"
due_date: "2026-12-01"
chase_schedule: "gentle"            // was "default"
max_reminders: "unlimited"          // reactivates a stalled intake if it had hit its cap
// folder_id: "fld_1"                // move it into a folder; null removes it from any folder
// client_brief: "Updated offer..."  // replaces the brief shown above the items; null clears it

Si cualquier campo relacionado con seguimiento cambia (chase_schedule, chase_interval, chase_interval_unit, chase_at_time, max_reminders, respect_quiet_hours, due_date, client.timezone) en una admisión enviada, cada recordatorio pendiente se cancela y se replanifica desde ahora — los recordatorios ya enviados aún cuentan hacia max_reminders. folder_id nunca toca el horario de seguimiento.

La dirección de correo del cliente no se puede cambiar aquí — el enlace del portal y el inicio de sesión están vinculados a ella. Usa manage_recipients para eso. Falla si la admisión está archivada. Devuelve el objeto de admisión completo y actualizado.

manage_recipients

Añadir, eliminar o restablecer a una persona que recibe la invitación y los recordatorios de una admisión, junto con o en lugar del cliente principal.

intake_id: "in_8f3k"
action: "reinstate"                 // add | remove | reinstate
email: "extra@example.com"
name: "Petr"                        // only used with action="add"

action="add" invita a otra dirección de la misma manera que also_notify lo hace en el momento de define_intake. action="remove" detiene futuros recordatorios a esa dirección. action="reinstate" es para un rebote que fue incorrecto — la persona sí recibió el correo — limpia la marca de rebote para que los recordatorios se reanuden, y replanifica el horario de seguimiento desde ahora si esa dirección era la única que aún se estaba persiguiendo.

manage_webhook

Registrar, listar o eliminar un endpoint de webhook para que los eventos se envíen a tu servicio en lugar de que tú hagas polling.

action: "create"                    // create | list | delete
url: "https://your.service/hooks/briefgate"
events: ["intake.completed", "intake.overdue"]
format: "raw"                       // raw | slack | discord

action: "create" devuelve un secret una vez — guárdalo, verifica cada firma de entrega y no se puede recuperar de nuevo. Elimina con action: "delete" y webhook_id.

Debido a que un agente recibe el secreto en un resultado de herramienta, puede terminar donde sea que esa conversación se almacene. No hay endpoint de rotación: si una transcripción se filtra, elimina el endpoint y crea uno nuevo para obtener un secreto fresco.

Solo registra un endpoint que realmente puedas recibir. Un agente que se ejecuta en una terminal no tiene dirección HTTPS pública; para ese caso no registres nada y verifica en un horario en su lugar (ver abajo).

list_folders

Listar las carpetas en tu cuenta, usadas para agrupar admisiones por cliente o proyecto. No toma argumentos.

Llama a esto antes de create_folder o antes de establecer folder_id en define_intake, update_intake, o list_intakes — reutiliza una carpeta existente para un cliente recurrente en lugar de crear un duplicado.

Devuelve { folders: [{ id, name, sort_order, intake_count, created_at }] }.

create_folder

Crear una nueva carpeta para agrupar admisiones, p. ej. una por cliente.

name: "Acme Inc"

Llama a list_folders primero y reutiliza una carpeta que coincida — solo crea una cuando ninguna de las carpetas existentes encaje. Falla con folder_exists si una carpeta con este nombre ya existe. Devuelve la carpeta creada.

login

Iniciar sesión sin una clave API — ver Iniciar sesión sin una clave API. No toma argumentos.

Llámalo cuando otra herramienta reporte "No has iniciado sesión" o que la clave almacenada fue revocada o expirada. La primera llamada inicia un flujo de autorización de dispositivo y devuelve una URL y un código corto inmediatamente; llámalo de nuevo (en cualquier momento) para comprobar si ya ha sido aprobado. No tiene efecto — lo dice en su lugar — si --api-key o BRIEFGATE_API_KEY ya proporciona una clave. No disponible en el endpoint alojado. Mismo flujo que ejecutar npx @briefgate/mcp login desde una terminal (que bloquea hasta que se aprueba en lugar de necesitar una segunda llamada) — ver Iniciar sesión sin una clave API.

logout

Elimina la clave API login almacenada localmente para este servidor BriefGate, y de mejor esfuerzo la revoca también en el servidor. No toma argumentos.

Si la llamada de revocación falla — sin red, API inalcanzable — la copia local aún se elimina; la respuesta lo dice y apunta al panel de BriefGate para revocarla allí en su lugar. No disponible en el endpoint alojado. Mismo efecto que ejecutar npx @briefgate/mcp logout desde una terminal — ver Iniciar sesión sin una clave API.

Decisiones — preguntas para el desarrollador

Un agente que construye algo se encuentra con cosas que solo el titular de la cuenta puede resolver: ¿el plan con descuento cuesta $19 o $29? Detenerse a esperar desperdicia la ejecución; elegir silenciosamente entierra la suposición. Una decisión es la tercera opción — plantea la pregunta, registra la respuesta con la que procedes, sigue construyendo.

{ "key": "discount_price", "type": "select", "assignee": "owner",
  "label": "What does the discounted subscription cost?",
  "options": [ { "value": "19", "label": "$19/month" },
               { "value": "29", "label": "$29/month" } ],
  "proposed": { "value": "19", "rationale": "matches the competitor we benchmarked" } }

type: "multiselect" toma varias respuestas, limitadas por constraints.min_count / max_count.

La propuesta se almacena aparte de la respuesta real, para que nunca pueda confundirse con una que el desarrollador dio — y sobrevive a ser anulada, que es el punto: en tres meses aún puedes ver que $19 fue asumido, no acordado. Léelo de vuelta desde get_intake_results:

"results": { "discount_price": "19" },
"meta": { "discount_price": { "decided_by": "agent_proposal", "proposed_value": "19" } }

decided_by es "owner" una vez que una persona lo ha resuelto y "agent_proposal" mientras sigue siendo tu propia elección. Una decisión propuesta regresa incluso sin include_pending — necesitas la suposición sobre la que estás construyendo. No incrementa revision, por lo que una lectura de only_new muestra exactamente las decisiones que alguien ha respondido desde entonces.

No puedes responder tu propia pregunta. El endpoint de respuesta toma una sesión de panel, no una clave API: si el agente pudiera confirmar su propia propuesta y que se registrara como la del desarrollador, la distinción no valdría nada. Las decisiones se responden en el panel de BriefGate.

Los elementos del propietario nunca llegan al portal del cliente, nunca aparecen en un recordatorio y nunca retrasan la finalización — la admisión está terminada cuando el cliente está terminado.

Saber cuándo el cliente ha terminado

Nada empuja a un cliente MCP por sí solo — MCP es solicitud/respuesta, por lo que el servidor no puede despertar a tu agente cuando el cliente termina. define_intake por lo tanto devuelve un bloque follow_up nombrando el mecanismo que se ajusta a tu configuración:

"follow_up": {
  "recommended": "schedule",        // or "webhook" when an endpoint already exists
  "webhook": { "active_endpoints": 0, "events": ["intake.completed", "item.submitted"],
               "register_with": "manage_webhook" },
  "schedule": { "check_with": "get_intake_status", "every_hours": 24,
                "until": "2026-10-01T08:00:00.000Z" }
}
  • Ejecutas un servicio → registra un webhook con manage_webhook y actúa sobre intake.completed.
  • Eres un agente en una terminal → configura una verificación recurrente que llame a get_intake_status cada every_hours horas hasta until. Una entrada de cron, un temporizador de systemd, o el propio programador de tu host de agente funcionan todos.

Eventos que valen la pena actuar: intake.completed (todo está dentro) y intake.overdue (la fecha límite pasó con elementos requeridos faltantes — el proyecto está bloqueado y el cliente necesita un humano, no otro recordatorio).

La cadencia se ajusta cerca de la fecha límite (24h normalmente, 12h dentro de una semana, 6h dentro de dos días) y no está vinculada al horario de recordatorios: un cliente puede enviar todo a las 2am sin haber abierto nunca un recordatorio.

Ejemplo de extremo a extremo

# System prompt excerpt
You are a web development agent. When you need client assets:

1. Call define_intake with all assets needed for this project.
   Use type=secret for passwords/credentials.
   The chase engine runs automatically — do not poll more often than once per day.

2. Read follow_up in the response and set up how you will hear back:
   register a webhook with manage_webhook if you have an HTTPS endpoint,
   otherwise schedule a get_intake_status check at follow_up.schedule.every_hours.

3. When intake.completed arrives (or the scheduled check reports "completed"),
   call get_intake_results. Download file URLs within 24 hours.
   Secrets are shown only on the first retrieval.

4. If a submitted asset does not meet requirements (blurry logo, broken URL),
   call request_revision with a clear note for the client.
   If the client has the asset in another form, call update_item to change the type.

5. If the client is still unresponsive after 9 days, call send_chase for an
   extra nudge outside the automatic schedule, or tell the developer the intake
   is stuck and let them pick up the phone.

Verificación de webhooks

BriefGate firma cada webhook con HMAC-SHA256 para prevenir falsificación y ataques de repetición. El paquete @briefgate/mcp exporta un helper listo para usar:

import { verifyWebhookSignature, parseWebhookEvent } from "@briefgate/mcp/webhook";

La firma vive en el encabezado X-BriefGate-Signature como t=<unix>,v1=<hex>:

Fastify (recomendado)

import Fastify from "fastify";
import { verifyWebhookSignature, parseWebhookEvent } from "@briefgate/mcp/webhook";

const app = Fastify();

// Parse body as raw string — JSON-parsing before verification breaks the HMAC.
app.addContentTypeParser("application/json", { parseAs: "string" }, (req, body, done) => {
  done(null, body);
});

app.post("/briefgate/webhook", (request, reply) => {
  const rawBody = request.body as string;

  const ok = verifyWebhookSignature(
    process.env.BRIEFGATE_WEBHOOK_SECRET!,
    request.headers["x-briefgate-signature"] as string,
    rawBody,
    // { toleranceSec: 300 }  ← default; increase for slow networks
  );

  if (!ok) {
    return reply.status(401).send({ error: "Invalid signature" });
  }

  const event = parseWebhookEvent(rawBody);
  console.log("BriefGate event:", event.event, event.intake_id);
  reply.send({ ok: true });
});

Express

import express from "express";
import { verifyWebhookSignature, parseWebhookEvent } from "@briefgate/mcp/webhook";

const app = express();

// raw body parser — must come before express.json()
app.post(
  "/briefgate/webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const rawBody = Buffer.isBuffer(req.body)
      ? req.body.toString("utf8")
      : String(req.body);

    const ok = verifyWebhookSignature(
      process.env.BRIEFGATE_WEBHOOK_SECRET!,
      req.headers["x-briefgate-signature"] as string,
      rawBody,
    );

    if (!ok) return res.status(401).json({ error: "Invalid signature" });

    const event = parseWebhookEvent(rawBody);
    console.log("BriefGate event:", event.event, event.intake_id);
    res.sendStatus(200);
  },
);

Eventos de webhook

EventoCuándoCampos clave
item.submittedEl cliente envía un elementoitem_key, item_status
intake.completedTodos los elementos requeridos aprobados
client.viewedEl cliente abre el portalclient_email
chase.bouncedUn recordatorio rebotóchannel, reason, recipient, still_chasing
intake.stalled3 recordatorios enviados, sin respuestaattempts

Precios

Oferta de lanzamiento: el código LAUNCH20 ofrece un 20% de descuento en Solo y Agency durante toda la vida de la suscripción, válido hasta el 4 de octubre de 2026 (solo para nuevos clientes, planes únicamente).

GratisSolo — $29/mesAgency — $79/mes
Admisiones activas11560
Elementos por admisión10ilimitadoilimitado
Almacenamiento1 GB25 GB100 GB
Marca"powered by"logotipo + colores personalizados+ dominio de envío personalizado
Seguimientocorreo electrónico, predeterminadocorreo electrónico, todos los horarioscorreo electrónico, todos los horarios
Bóveda de secretos
Webhooks + REST + MCP

Precios completos en GET https://api.briefgate.dev/pricing.json (no se requiere autenticación — los agentes pueden leerlo directamente).

Residencia de datos

BriefGate está alojado en la UE: servidores de aplicaciones en netcup GmbH en Núremberg, Alemania; archivos en Cloudflare R2 bajo jurisdicción de la UE. Consulta las notas de GDPR y el DPA.

Política de privacidad

Este paquete es un cliente ligero: no almacena datos propios y no envía nada a ningún lugar excepto a la API de BriefGate en api.briefgate.dev, usando la clave de API que configures. No escribe telemetría ni analíticas.

Lo que BriefGate en sí recopila, cuánto tiempo lo conserva, con quién se comparte y cómo solicitar su eliminación se cubre en detalle aquí:

Contacto para solicitudes de privacidad: privacy@briefgate.dev

Paquete MCPB (Extensión de Claude Desktop)

manifest.json en la raíz del repositorio empaqueta el paquete local @briefgate/mcp como una instalación de Claude Desktop con un clic (especificación MCPB). Ejecuta dist/index.js localmente y solicita una clave de API opcional en el momento de la instalación — la misma configuración de login/BRIEFGATE_API_KEY documentada arriba, no el flujo OAuth del endpoint alojado.

Compila el paquete (solo dependencias de producción, empaquetadas en un directorio de preparación desechable para que nunca toque el node_modules propio de este repositorio):

npm run package:mcpb

Esto produce briefgate.mcpb en la raíz del repositorio (ignorado por git — instálalo localmente para probar, no lo confirmes). Aún no enviado a ningún lugar; consulta scripts/build-mcpb.mjs para ver qué hace el comando.

Contribuciones

Este repositorio es solo el cliente MCP de BriefGate — un envoltorio ligero sobre la API REST pública de BriefGate. El servicio BriefGate en sí es de código cerrado.

npm install
npm run typecheck   # TypeScript check
npm run lint        # ESLint
npm run test        # Vitest
npm run check       # all three
npm run build       # compile to dist/

Licencia

MIT — úsalo libremente en proyectos comerciales.


Hecho por Radim Sekera. Proyecto relacionado: impri.dev — bandeja de entrada de aprobación con intervención humana para agentes de IA.