BriefGate
Coleta de informações de clientes para agentes de IA: solicite arquivos, cópias e logins de um cliente por meio de um portal sem conta, com lembretes automáticos, e leia os resultados digitados de volta.
Servidor MCP hospedado
npx add-mcp 'https://mcp.briefgate.dev/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
BriefGate
Captação de clientes para agentes de IA que codificam.
Seu agente pode construir o site. O BriefGate obtém do cliente o que está faltando.
Claude Code / Cursor / Codex → BriefGate → Client portal
→ Files · copy · credentials · structured data → Agent continues building

Assista como MP4 (25 s) · Passo a passo completo de 47 s
Site · Referência MCP · llms.txt · Guias e listas de verificação
Não está trabalhando com um agente? As mesmas captações podem ser criadas pelo painel do navegador — veja o início rápido do painel.
O problema
Agentes são rápidos. O gargalo é o humano do outro lado do projeto.
Em algum ponto da construção, o agente precisa de algo que só o cliente tem: um logotipo, textos para a página inicial, cores da marca, horário de funcionamento, credenciais de hospedagem, uma chave de API, um dado estruturado como uma lista de preços. Nada disso existe no chat, e nada disso pode ser adivinhado.
A jogada usual é parar e pedir ao desenvolvedor que vá atrás do cliente por e-mail. Em vez disso, o agente cria uma captação no BriefGate. O BriefGate envia e-mail ao cliente, coleta o que volta, cobra automaticamente quando não volta e retorna resultados tipados que o agente pode usar diretamente. O agente continua construindo enquanto isso.
Início rápido
Claude Code — hospedado, sem chave para gerenciar:
claude mcp add --transport http briefgate https://mcp.briefgate.dev/mcp
Depois execute /mcp no Claude Code, escolha briefgate e selecione Autenticar.
Claude Code — pacote local:
claude mcp add briefgate -- npx -y @briefgate/mcp
npx -y @briefgate/mcp login
Prefere pular o login totalmente? Obtenha uma chave em briefgate.dev (plano gratuito, sem cartão) e passe-a como BRIEFGATE_API_KEY.
Cursor — adicione a .cursor/mcp.json:
{
"mcpServers": {
"briefgate": {
"command": "npx",
"args": ["-y", "@briefgate/mcp"]
}
}
}
Depois execute npx -y @briefgate/mcp login, ou peça ao agente para chamar a ferramenta login.
Codex:
codex mcp add briefgate --env BRIEFGATE_API_KEY=bg_live_xxxxx -- npx -y @briefgate/mcp
Gemini CLI — instala como uma extensão deste repositório gemini-extension.json, apontando para o endpoint hospedado:
gemini extensions install https://github.com/sekera-radim/briefgate-mcp
Ele autentica da mesma forma que os outros clientes hospedados acima — via OAuth, no primeiro uso. A extensão também inclui GEMINI.md, um arquivo de contexto que informa ao modelo o que é o BriefGate e quando usá-lo.
Por padrão, gemini extensions install busca o Release mais recente do GitHub do repositório em vez do branch main; se esse release for anterior ao gemini-extension.json atual e o comando relatar um arquivo de configuração ausente, instale a partir de main diretamente: gemini extensions install --ref main https://github.com/sekera-radim/briefgate-mcp.
Claude Desktop — instalação com um clique como Extensão de Desktop (.mcpb), executando o pacote local @briefgate/mcp em vez do endpoint hospedado. Detalhes de build: veja pacote MCPB abaixo.
Cursor — como um plugin deste repositório .cursor-plugin/plugin.json, que agrupa a mesma configuração MCP junto com a habilidade collect-from-client abaixo.
Qualquer ferramenta compatível com Agent Skills (OpenAI Codex, GitHub Copilot / VS Code, Cursor, Gemini CLI e outros clientes nesse padrão) — instale a habilidade collect-from-client com a CLI skills:
npx skills add https://github.com/sekera-radim/briefgate-mcp/tree/main/skills/collect-from-client
A forma abreviada owner/repo que a documentação da própria CLI mostra não funciona com esta estrutura a partir de skills@1.5.26 — ela retorna 404 no registro ou, dado o URL simples do repositório, clona o repositório inteiro e relata "No SKILL.md found" porque o nosso vive um diretório mais fundo que a raiz. O URL completo /tree/main/skills/<name> acima é o que realmente instala; verificado executando-o em um diretório de teste vazio antes de documentar. Isso copia SKILL.md para o diretório local de habilidades da ferramenta; a habilidade ainda pressupõe que o servidor MCP briefgate (veja as instruções específicas do cliente acima) esteja configurado separadamente.
Detalhes completos de configuração, configuração manual e precedência de chaves de API: veja Referência abaixo.
Para agentes que leem instruções de projeto (AGENTS.md, regras do Copilot, regras do Cursor)
Se o seu agente lê um arquivo de instruções do projeto em vez de (ou além de) descrições de ferramentas MCP ou Agent Skills, adicione este bloco ao seu AGENTS.md, .github/copilot-instructions.md ou .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.
Exemplo: construindo o site de um cliente
Um agente está construindo um site para um restaurante. Ele tem o layout e o fluxo de reservas, mas ainda precisa do logotipo, de uma foto de destaque, do horário de funcionamento, de uma descrição curta do restaurante, dos links de redes sociais e do acesso de administrador à instalação WordPress do cliente. Ele chama 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 daí, o BriefGate (1) cria um portal com a marca, (2) envia e-mail ao cliente, (3) valida cada recurso conforme chega, (4) cobra o cliente automaticamente até que tudo seja enviado e (5) notifica o agente quando terminar.
O agente continua construindo o layout, o fluxo de reservas e tudo o mais que não depende disso — depois chama get_intake_results(intake_id) e recebe dados tipados e URLs assinadas para os arquivos, além de uma revelação única das credenciais do WordPress. Ele armazena o segredo e continua.
Por que não um formulário?
| Formulário genérico | BriefGate |
|---|---|
| Um humano cria o formulário | O agente declara o que precisa |
| Um humano lê os resultados | O agente consome resultados tipados |
| Respostas genéricas | Itens tipados |
| Acompanhamento manual | Cobrança automática |
| Mentalidade de planilha | Fluxo de trabalho API / MCP |
| Credenciais são complicadas | Item secreto + revelação controlada |
| Fluxo de trabalho humano | Fluxo de trabalho do agente |
O BriefGate não tenta substituir todos os criadores de formulários. Ele é projetado para o ponto em que um agente de IA precisa de informações de um humano.
Plano gratuito, sem cartão. O BriefGate é um serviço hospedado — este repositório é o cliente MCP de código aberto, licenciado sob MIT. Cadastre-se em briefgate.dev.
Referência
Tudo abaixo é detalhe técnico inalterado: configuração manual, variáveis de ambiente, modo HTTP/OAuth, a referência completa de ferramentas, webhooks, preços e aspectos legais.
Claude Code: configuração manual e chaves de API
Cole uma chave de API (para CI, scripts ou se preferir gerenciar a chave você mesmo). Obtenha uma em briefgate.dev (plano gratuito disponível, sem cartão):
claude mcp add briefgate \
-e BRIEFGATE_API_KEY=bg_live_... \
-- npx -y @briefgate/mcp
Ou adicione manualmente a ~/.claude/settings.json:
{
"mcpServers": {
"briefgate": {
"command": "npx",
"args": ["-y", "@briefgate/mcp"],
"env": {
"BRIEFGATE_API_KEY": "bg_live_..."
}
}
}
}
BRIEFGATE_API_KEY (ou --api-key na linha de comando), se definido, sempre tem precedência sobre uma chave login armazenada localmente — executar login enquanto uma está configurada apenas informa isso em vez de fazer qualquer coisa.
Verifique se carregou — execute /mcp no Claude Code e procure por briefgate com 15 ferramentas.
A mesma configuração de pacote local e chave de API funciona para qualquer cliente MCP que execute o pacote localmente (Cursor, Codex, outros) — registre-o sem chave alguma e execute login, ou cole BRIEFGATE_API_KEY na própria configuração MCP desse cliente da mesma forma.
Entrar sem chave de API
Duas maneiras de obter uma chave nesta máquina sem colar uma — ambas executam o mesmo fluxo de autorização de dispositivo (RFC 8628) contra o mesmo arquivo de credenciais, então escolha a que melhor se adequa ao seu uso do pacote.
De um terminal — os 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 bloqueia até você aprovar (ou expirar em 10 minutos), depois imprime Signed in as <account_name> e sai com 0 — ou imprime por que não funcionou (negado, expirado, um erro) e sai com 1. logout sempre remove a cópia local; também envia DELETE /v1/keys/current usando essa mesma chave para revogá-la no servidor, e se essa chamada falhar (sem rede, API inacessível) ele informa e aponta para o painel do BriefGate em vez de deixá-lo em dúvida se a chave ainda está ativa.
De um agente — as ferramentas login / logout (veja Ferramentas):
Mesmo fluxo, para um cliente que não pode bloquear um terminal esperando seu clique. login é em duas fases porque uma chamada de ferramenta não pode ficar aberta por minutos:
- A primeira chamada inicia o fluxo e retorna imediatamente com o código e o URL. Um navegador é aberto automaticamente quando possível.
- Chame
loginnovamente — a qualquer momento, ou depois de aprovar — para verificar o progresso. Enquanto ainda está aguardando, ele informa isso; uma vez aprovado, essa mesma chamada relata sucesso e a chave é salva. Sem necessidade de reiniciar: a próxima chamada de ferramenta já estará autenticada.
logout como ferramenta faz exatamente o que o subcomando faz, incluindo a revogação remota de melhor esforço.
De qualquer forma, a chave vai para ~/.briefgate/credentials.json (modo diretório 0700, modo arquivo 0600; substitua o caminho com BRIEFGATE_CREDENTIALS_FILE), identificada por qual servidor BriefGate é para ela, para que um BRIEFGATE_BASE_URL de staging e a produção nunca colidam. Uma chave explícita sempre vence uma armazenada — --api-key, depois BRIEFGATE_API_KEY, depois o que login salvou por último — e login informa isso em vez de executar o fluxo quando uma delas já está definida. Nem os subcomandos nem as ferramentas se aplicam ao endpoint hospedado compartilhado (mcp.briefgate.dev) — veja Endpoint hospedado + OAuth, onde conectar um cliente aciona OAuth real.
Variáveis de ambiente
| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
BRIEFGATE_API_KEY | Não | — | Chave de API (bg_live_... ou bg_test_...). Tem precedência sobre uma credencial armazenada por login. Se nada estiver configurado, as chamadas de ferramenta falham com uma mensagem apontando para login. |
BRIEFGATE_BASE_URL | Não | https://api.briefgate.dev | Substituição para staging ou desenvolvimento local. |
BRIEFGATE_CREDENTIALS_FILE | Não | ~/.briefgate/credentials.json | Onde login/logout armazenam a chave. Principalmente para testes e configurações incomuns. |
BRIEFGATE_NO_BROWSER | Não | não definido | Defina como 1 para impedir que login abra um navegador (servidores headless, CI); o URL é impresso de qualquer forma. |
BRIEFGATE_MCP_HTTP | Não | — | Defina como 1 para iniciar Streamable HTTP em vez de stdio. |
BRIEFGATE_MCP_PORT | Não | 3000 | Porta para o modo HTTP. |
BRIEFGATE_MCP_PUBLIC_HOST | Não | — | Publica o servidor como um endpoint OAuth compartilhado e multicliente. Veja Endpoint hospedado + OAuth. |
BRIEFGATE_MCP_AUTH_SERVER | Não | BRIEFGATE_BASE_URL | O servidor de autorização OAuth anunciado aos clientes no modo publicado. Padrão BRIEFGATE_BASE_URL para desenvolvimento local, onde geralmente são o mesmo endereço; uma implantação real atrás de uma rede de contêineres define isso explicitamente (veja abaixo). |
--api-key bg_live_... também é aceito na linha de comando, à frente de BRIEFGATE_API_KEY em prioridade. login e logout também são aceitos como o primeiro argumento de linha de comando (npx @briefgate/mcp login), em vez de --http/sem sinalizador.
Modo HTTP (Streamable HTTP)
Para implantações remotas ou de múltiplas sessões, inicie o servidor no modo HTTP:
BRIEFGATE_API_KEY=bg_live_... npx @briefgate/mcp --http --port 3000
O servidor vincula-se apenas a 127.0.0.1 e inclui proteção contra rebinding de DNS. Atrás de um proxy reverso, encerre o TLS lá e encaminhe para a porta local — não exponha a porta diretamente.
Endpoint hospedado + OAuth
Defina BRIEFGATE_MCP_PUBLIC_HOST para o nome do host sob o qual o servidor é publicado e
ele se torna um endpoint compartilhado e multicliente: cada chamador envia sua própria chave como
Authorization: Bearer bg_live_... (um token de acesso OAuth, para esta API, é
essa mesma chave — veja abaixo), e o servidor fala com a API do BriefGate como esse
chamador. A instância pública é https://mcp.briefgate.dev/mcp.
BRIEFGATE_MCP_PUBLIC_HOST=mcp.example.com npx @briefgate/mcp --http --port 3000
Várias coisas mudam, de propósito:
- o listener vincula
0.0.0.0e o guard de Host aceita esse nome, porque um servidor atrás de um proxy reverso é acessado pelo seu nome público; - o fallback
BRIEFGATE_API_KEYe a credencial localloginestão ambos desativados. Deixar qualquer um ligado permitiria que um chamador anônimo gastasse a chave do operador, ou lesse o que a própria máquinaloginarmazenou por último; login/logout, ferramentas e subcomandos igualmente, ficam indisponíveis — conectar um cliente dispara OAuth real em vez disso, descrito abaixo;- o servidor se torna um resource server OAuth 2.1, conforme a especificação de
autorização do MCP, então um cliente com suporte a OAuth pode adicioná-lo apenas com a URL. Este
pacote nunca executa o fluxo de autorização em si — ele apenas anuncia onde
encontrá-lo e exige que uma requisição carregue um token:
- ele serve
GET /.well-known/oauth-protected-resource(RFC 9728), e o mesmo conteúdo novamente em/.well-known/oauth-protected-resource/mcp(o caminho com escopo de recurso que a especificação MCP também faz os clientes tentarem), ambos com CORS aberto e nomeando a API do BriefGate como servidor de autorização — vejaBRIEFGATE_MCP_AUTH_SERVERacima; - toda requisição MCP agora exige um token Bearer — incluindo
initializeetools/list, que antes funcionavam sem um para que um registry pudesse inspecionar a lista de ferramentas. Uma requisição sem token recebe HTTP401e um cabeçalhoWWW-Authenticate: Bearer resource_metadata="https://<host>/.well-known/oauth-protected-resource", que é o sinal que um cliente OAuth usa para iniciar o login; - se a chave de uma chamada de ferramenta estiver expirada ou revogada (a API responde
401), a resposta é reescrita em um HTTP401real com o mesmo cabeçalho maiserror="invalid_token", em vez de um erro comum de ferramenta — para que o cliente saiba que deve renovar em vez de apenas reportar que a chamada falhou.
- ele serve
O que um cliente conectado realmente faz, contra o servidor de autorização nomeado
nesse metadata: descoberta OAuth 2.1 padrão
(GET /.well-known/oauth-authorization-server), registro dinâmico de cliente
(POST /v1/oauth/register), e então uma troca de código de autorização com PKCE
(S256) em POST /v1/oauth/token — sem client secret, já que clientes MCP são
clientes públicos — e POST /v1/oauth/revoke para encerrar uma sessão. Nada disso é
preocupação deste pacote; ele só precisa ser um resource server correto apontando
para isso. O access token que sai do outro lado é uma chave bg_live_...
como qualquer outra, com expiração de uma hora que a API impõe.
Nada disso se aplica sem BRIEFGATE_MCP_PUBLIC_HOST: uma execução local --http
continua se comportando exatamente como antes, incluindo uma chave ausente alcançando
initialize/tools/list e um cabeçalho Authorization: Bearer ... simples
funcionando sem envolvimento de OAuth.
Ferramentas
define_intake
Crie um novo intake de cliente — um portal com marca onde o cliente envia os ativos que você precisa. O BriefGate envia o e-mail de convite e cobra o cliente automaticamente até que tudo seja coletado.
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).
Regras de chave do item: deve ser snake_case (ex.: logo, hero_copy, ga4_id). Chaves viram nomes de propriedades em get_intake_results — sem maiúsculas, sem espaços, sem hífens.
Retorna { intake_id, portal_url, status }. Salve intake_id para todas as chamadas de acompanhamento.
get_intake_status
Verifique quais itens estão enviados, pendentes ou precisam de revisão. Inclui o histórico de e-mails de cobrança automáticos e quando o cliente abriu o portal pela última vez.
intake_id: "in_8f3k"
Retorna o status por item e um histórico completo de cobranças.
get_intake_results
Recupere valores enviados e tipados. Arquivos são URLs assinadas (válidas por 24 horas). Segredos são de uso único — descriptografados e retornados apenas na primeira chamada; armazene-os antes de prosseguir.
intake_id: "in_8f3k"
only_new: true // only items new since last call
include_pending: false // omit unsubmitted items
Retorna { results: { logo: "https://signed...", hero_copy: "text...", wp_admin: "s3cr3t" }, meta: { ... } }.
request_revision
Peça ao cliente para reenviar um item com uma nota explicando o que está errado.
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"
Retorna { status: "revision_requested", item_key }.
send_chase
Envie um lembrete manual fora do agendamento automático. Use quando um prazo estiver se aproximando ou tentativas de e-mail falharam.
intake_id: "in_8f3k"
Retorna { sent: true }.
list_intakes
Liste todos os intakes entre projetos, opcionalmente filtrados por status, e-mail do cliente, pasta ou uma busca por 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
Retorna { intakes: [...], total }.
add_items
Adicione novos itens a um intake já enviado — por exemplo, um favicon que você esqueceu, ou credenciais adicionais necessárias no meio do projeto.
intake_id: "in_8f3k"
items:
- { key: "favicon", type: "image", label: "Favicon (32×32 PNG or ICO)" }
Retorna o intake atualizado.
update_item
Altere a definição de um item depois que o intake foi enviado — o tipo, o rótulo, o texto de ajuda ou as restrições. Use quando você pediu a coisa errada, ex.: você solicitou uma imagem mas o cliente tem um 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
Retorna o item atualizado. Se o cliente já enviou um valor que a nova definição rejeitaria, a chamada falha com item_answer_would_be_discarded até você passar discard_submitted_value: true.
update_intake
Altere configurações de um intake já enviado — nome do projeto, data de vencimento, cadência de lembretes, horários de silêncio, o briefing do cliente, ou o nome, telefone, idioma e fuso horário do cliente. Use isso em vez de excluir e recriar o intake, o que reenviaria o convite.
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
Se qualquer campo relacionado a cobrança mudar (chase_schedule, chase_interval, chase_interval_unit, chase_at_time, max_reminders, respect_quiet_hours, due_date, client.timezone) em um intake enviado, todo lembrete pendente é cancelado e replanejado a partir de agora — lembretes já enviados ainda contam para max_reminders. folder_id nunca toca no agendamento de cobranças.
O endereço de e-mail do cliente não pode ser alterado aqui — o link do portal e o login estão vinculados a ele. Use manage_recipients para isso. Falha se o intake estiver arquivado. Retorna o objeto completo do intake atualizado.
manage_recipients
Adicione, remova ou restaure uma pessoa que recebe o convite e os lembretes de um intake, junto com ou em vez do cliente principal.
intake_id: "in_8f3k"
action: "reinstate" // add | remove | reinstate
email: "extra@example.com"
name: "Petr" // only used with action="add"
action="add" convida outro endereço da mesma forma que also_notify faz no momento de define_intake. action="remove" interrompe futuros lembretes para aquele endereço. action="reinstate" é para um bounce que estava errado — a pessoa realmente recebeu o e-mail — ele limpa a flag de bounce para que os lembretes sejam retomados, e replaneja o agendamento de cobranças a partir de agora se aquele endereço era o único ainda sendo cobrado.
manage_webhook
Registre, liste ou remova um endpoint de webhook para que eventos sejam enviados ao seu serviço em vez de você fazer polling.
action: "create" // create | list | delete
url: "https://your.service/hooks/briefgate"
events: ["intake.completed", "intake.overdue"]
format: "raw" // raw | slack | discord
action: "create" retorna um secret uma única vez — armazene-o, ele verifica a assinatura de cada entrega e não pode ser recuperado novamente. Remova com action: "delete" e webhook_id.
Como um agente recebe o segredo em um resultado de ferramenta, ele pode acabar armazenado onde quer que essa conversa seja salva. Não há endpoint de rotação: se uma transcrição vazar, exclua o endpoint e crie um novo para obter um segredo novo.
Registre apenas um endpoint no qual você realmente consegue receber. Um agente rodando em um terminal não tem endereço HTTPS público; nesse caso, não registre nada e verifique em um agendamento (veja abaixo).
list_folders
Liste as pastas da sua conta, usadas para agrupar intakes por cliente ou projeto. Não recebe argumentos.
Chame isso antes de create_folder ou antes de definir folder_id em define_intake, update_intake, ou list_intakes — reutilize uma pasta existente para um cliente recorrente em vez de criar uma duplicada.
Retorna { folders: [{ id, name, sort_order, intake_count, created_at }] }.
create_folder
Crie uma nova pasta para agrupar intakes, ex.: uma por cliente.
name: "Acme Inc"
Chame list_folders primeiro e reutilize uma pasta correspondente — só crie uma quando nenhuma das pastas existentes servir. Falha com folder_exists se uma pasta com esse nome já existir. Retorna a pasta criada.
login
Entre sem uma chave de API — veja Entrar sem uma chave de API. Não recebe argumentos.
Chame sempre que outra ferramenta reportar "Não conectado" ou que a chave armazenada foi revogada ou expirada. A primeira chamada inicia um fluxo de autorização de dispositivo e retorna uma URL e um código curto imediatamente; chame novamente (a qualquer momento) para verificar se já foi aprovado. Não tem efeito — e diz isso — se --api-key ou BRIEFGATE_API_KEY já fornecer uma chave. Não disponível no endpoint hospedado. Mesmo fluxo de rodar npx @briefgate/mcp login a partir de um terminal (que bloqueia até a aprovação em vez de precisar de uma segunda chamada) — veja Entrar sem uma chave de API.
logout
Remove a chave de API login armazenada localmente para este servidor BriefGate, e faz o melhor esforço para revogá-la também no servidor. Não recebe argumentos.
Se a chamada de revogação falhar — sem rede, API inacessível — a cópia local ainda é removida; a resposta diz isso e aponta para o dashboard do BriefGate para revogá-la lá. Não disponível no endpoint hospedado. Mesmo efeito de rodar npx @briefgate/mcp logout a partir de um terminal — veja Entrar sem uma chave de API.
Decisões — perguntas para o desenvolvedor
Um agente construindo algo encontra coisas que só o titular da conta pode resolver: o plano com desconto custa $19 ou $29? Parar para esperar desperdiça a execução; escolher silenciosamente enterra a suposição. Uma decisão é a terceira opção — faça a pergunta, registre a resposta com a qual você está prosseguindo, continue construindo.
{ "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" aceita várias respostas, limitadas por constraints.min_count / max_count.
A proposta é armazenada separada da resposta real, para que nunca possa ser confundida com uma dada pelo desenvolvedor — e ela sobrevive a ser anulada, que é o ponto: em três meses você ainda pode ver que $19 foi assumido, não acordado. Leia de volta em get_intake_results:
"results": { "discount_price": "19" },
"meta": { "discount_price": { "decided_by": "agent_proposal", "proposed_value": "19" } }
decided_by é "owner" uma vez que uma pessoa resolveu e "agent_proposal" enquanto ainda é sua própria escolha. Uma decisão proposta volta mesmo sem include_pending — você precisa da suposição sobre a qual está construindo. Ela não altera revision, então uma leitura only_new retorna exatamente as decisões que alguém respondeu desde então.
Você não pode responder sua própria pergunta. O endpoint de resposta aceita uma sessão de dashboard, não uma chave de API: se o agente pudesse confirmar sua própria proposta e tê-la registrada como do desenvolvedor, a distinção não valeria nada. Decisões são respondidas no dashboard do BriefGate.
Itens do proprietário nunca chegam ao portal do cliente, nunca aparecem em um lembrete, e nunca seguram a conclusão — o intake está finalizado quando o cliente está finalizado.
Sabendo quando o cliente terminou
Nada envia push para um cliente MCP por conta própria — MCP é request/response, então o servidor não pode acordar seu agente quando o cliente termina. define_intake portanto retorna um bloco follow_up nomeando o mecanismo que se encaixa na sua configuração:
"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" }
}
- Você roda um serviço → registre um webhook com
manage_webhooke aja emintake.completed. - Você é um agente em um terminal → configure uma verificação recorrente que chama
get_intake_statusa cadaevery_hourshoras atéuntil. Uma entrada de cron, um timer do systemd, ou o próprio agendador do seu host de agente funcionam.
Eventos que valem ação: intake.completed (tudo está dentro) e intake.overdue (o prazo passou com itens obrigatórios faltando — o projeto está bloqueado e o cliente precisa de um humano, não de outro lembrete).
A cadência se intensifica perto do prazo (24h normalmente, 12h dentro de uma semana, 6h dentro de dois dias) e não está vinculada ao agendamento de lembretes: um cliente pode enviar tudo às 2h da manhã sem nunca ter aberto um lembrete.
Exemplo de ponta a ponta
# 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.
Verificando webhooks
O BriefGate assina cada webhook com HMAC-SHA256 para prevenir falsificação e ataques de replay. O pacote @briefgate/mcp exporta um helper pronto:
import { verifyWebhookSignature, parseWebhookEvent } from "@briefgate/mcp/webhook";
A assinatura vive no cabeçalho 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 | Quando | Campos-chave |
|---|---|---|
item.submitted | Cliente envia um item | item_key, item_status |
intake.completed | Todos os itens obrigatórios aprovados | — |
client.viewed | Cliente abre o portal | client_email |
chase.bounced | Um lembrete falhou no envio | channel, reason, recipient, still_chasing |
intake.stalled | 3 lembretes enviados, sem resposta | attempts |
Preços
Oferta de lançamento: o código LAUNCH20 dá 20% de desconto nos planos Solo e Agency pela duração da assinatura, válido até 4 de outubro de 2026 (apenas para novos clientes, planos).
| Free | Solo — US$ 29/mês | Agency — US$ 79/mês | |
|---|---|---|---|
| Intakes ativos | 1 | 15 | 60 |
| Itens por intake | 10 | ilimitado | ilimitado |
| Armazenamento | 1 GB | 25 GB | 100 GB |
| Marca | "powered by" | logo + cores personalizados | + domínio de envio personalizado |
| Cobrança | e-mail, padrão | e-mail, todos os agendamentos | e-mail, todos os agendamentos |
| Cofre de segredos | — | sim | sim |
| Webhooks + REST + MCP | sim | sim | sim |
Preços completos em GET https://api.briefgate.dev/pricing.json (sem necessidade de autenticação — agentes podem ler diretamente).
Residência de dados
O BriefGate é hospedado na UE: servidores de aplicação na netcup GmbH em Nuremberg, Alemanha; arquivos no Cloudflare R2 sob jurisdição da UE. Consulte as notas de GDPR e o DPA.
Política de Privacidade
Este pacote é um cliente leve: ele não armazena dados próprios e não envia nada
para nenhum lugar, exceto para a API do BriefGate em api.briefgate.dev, usando a chave de API
que você configura. Ele não grava telemetria nem analytics.
O que o próprio BriefGate coleta, por quanto tempo retém, com quem compartilha e como solicitar a exclusão está totalmente coberto aqui:
- Política de Privacidade — https://briefgate.dev/docs/privacy
- Segurança — https://briefgate.dev/docs/security
- Contrato de Processamento de Dados — https://briefgate.dev/docs/dpa
Contato para solicitações de privacidade: privacy@briefgate.dev
Pacote MCPB (Extensão Claude Desktop)
manifest.json na raiz do repositório empacota o pacote
local @briefgate/mcp como uma instalação de um clique para Claude Desktop
(especificação MCPB). Ele executa dist/index.js
localmente e solicita uma chave de API opcional na instalação — a mesma
configuração login/BRIEFGATE_API_KEY documentada acima, não o fluxo
OAuth do endpoint hospedado.
Crie o pacote (apenas dependências de produção, empacotadas em um diretório de
staging descartável para que nunca toque no node_modules deste repositório):
npm run package:mcpb
Isso gera briefgate.mcpb na raiz do repositório (ignorado pelo git — instale
localmente para testar, não o envie). Ainda não foi enviado a lugar nenhum; veja
scripts/build-mcpb.mjs para saber o que o comando faz.
Contribuindo
Este repositório é apenas o cliente MCP do BriefGate — um wrapper fino sobre a API REST pública do BriefGate. O serviço BriefGate em si é de código fechado.
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/
Licença
MIT — use livremente em projetos comerciais.
Feito por Radim Sekera. Projeto relacionado: impri.dev — caixa de entrada de aprovação com supervisão humana para agentes de IA.