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

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érico | BriefGate |
|---|---|
| Un humano crea el formulario | El agente declara lo que necesita |
| Un humano lee los resultados | El agente consume resultados tipados |
| Respuestas genéricas | Elementos tipados |
| Seguimiento manual | Persecución automática |
| Mentalidad de hoja de cálculo | Flujo de trabajo API / MCP |
| Las credenciales son incómodas | Elemento secreto + revelación controlada |
| Flujo de trabajo humano | Flujo 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:
- 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.
- Llama a
loginde 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
| Variable | Obligatoria | Predeterminada | Descripción |
|---|---|---|---|
BRIEFGATE_API_KEY | No | — | Clave 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_URL | No | https://api.briefgate.dev | Anulación para pruebas o desarrollo local. |
BRIEFGATE_CREDENTIALS_FILE | No | ~/.briefgate/credentials.json | Dónde login/logout guardan la clave. Principalmente para pruebas y configuraciones inusuales. |
BRIEFGATE_NO_BROWSER | No | sin definir | Configúrala en 1 para evitar que login abra un navegador (servidores sin interfaz, CI); la URL se imprime de todos modos. |
BRIEFGATE_MCP_HTTP | No | — | Configúrala en 1 para iniciar Streamable HTTP en lugar de stdio. |
BRIEFGATE_MCP_PORT | No | 3000 | Puerto para el modo HTTP. |
BRIEFGATE_MCP_PUBLIC_HOST | No | — | Publica el servidor como un endpoint OAuth compartido de múltiples clientes. Consulta Endpoint alojado + OAuth. |
BRIEFGATE_MCP_AUTH_SERVER | No | BRIEFGATE_BASE_URL | El 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.0y 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_KEYy la credencial local deloginestá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áquinaloginalmacenó 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 — verBRIEFGATE_MCP_AUTH_SERVERarriba; - cada solicitud MCP ahora necesita un token Bearer — incluyendo
initializeytools/list, que antes funcionaban sin uno para que un registro pudiera inspeccionar la lista de herramientas. Una sin token recibe HTTP401y un encabezadoWWW-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 HTTP401real con el mismo encabezado máserror="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ó.
- sirve
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_webhooky actúa sobreintake.completed. - Eres un agente en una terminal → configura una verificación recurrente que llame a
get_intake_statuscadaevery_hourshoras hastauntil. 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
| Evento | Cuándo | Campos clave |
|---|---|---|
item.submitted | El cliente envía un elemento | item_key, item_status |
intake.completed | Todos los elementos requeridos aprobados | — |
client.viewed | El cliente abre el portal | client_email |
chase.bounced | Un recordatorio rebotó | channel, reason, recipient, still_chasing |
intake.stalled | 3 recordatorios enviados, sin respuesta | attempts |
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).
| Gratis | Solo — $29/mes | Agency — $79/mes | |
|---|---|---|---|
| Admisiones activas | 1 | 15 | 60 |
| Elementos por admisión | 10 | ilimitado | ilimitado |
| Almacenamiento | 1 GB | 25 GB | 100 GB |
| Marca | "powered by" | logotipo + colores personalizados | + dominio de envío personalizado |
| Seguimiento | correo electrónico, predeterminado | correo electrónico, todos los horarios | correo electrónico, todos los horarios |
| Bóveda de secretos | — | sí | sí |
| Webhooks + REST + MCP | sí | sí | sí |
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í:
- Política de privacidad — https://briefgate.dev/docs/privacy
- Seguridad — https://briefgate.dev/docs/security
- Acuerdo de procesamiento de datos — https://briefgate.dev/docs/dpa
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.