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

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

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éricoBriefGate
Um humano cria o formulárioO agente declara o que precisa
Um humano lê os resultadosO agente consome resultados tipados
Respostas genéricasItens tipados
Acompanhamento manualCobrança automática
Mentalidade de planilhaFluxo de trabalho API / MCP
Credenciais são complicadasItem secreto + revelação controlada
Fluxo de trabalho humanoFluxo 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:

  1. A primeira chamada inicia o fluxo e retorna imediatamente com o código e o URL. Um navegador é aberto automaticamente quando possível.
  2. Chame login novamente — 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ávelObrigatóriaPadrãoDescrição
BRIEFGATE_API_KEYNãoChave 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_URLNãohttps://api.briefgate.devSubstituição para staging ou desenvolvimento local.
BRIEFGATE_CREDENTIALS_FILENão~/.briefgate/credentials.jsonOnde login/logout armazenam a chave. Principalmente para testes e configurações incomuns.
BRIEFGATE_NO_BROWSERNãonão definidoDefina como 1 para impedir que login abra um navegador (servidores headless, CI); o URL é impresso de qualquer forma.
BRIEFGATE_MCP_HTTPNãoDefina como 1 para iniciar Streamable HTTP em vez de stdio.
BRIEFGATE_MCP_PORTNão3000Porta para o modo HTTP.
BRIEFGATE_MCP_PUBLIC_HOSTNãoPublica o servidor como um endpoint OAuth compartilhado e multicliente. Veja Endpoint hospedado + OAuth.
BRIEFGATE_MCP_AUTH_SERVERNãoBRIEFGATE_BASE_URLO 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.0 e 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_KEY e a credencial local login estã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áquina login armazenou 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 — veja BRIEFGATE_MCP_AUTH_SERVER acima;
    • toda requisição MCP agora exige um token Bearer — incluindo initialize e tools/list, que antes funcionavam sem um para que um registry pudesse inspecionar a lista de ferramentas. Uma requisição sem token recebe HTTP 401 e um cabeçalho WWW-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 HTTP 401 real com o mesmo cabeçalho mais error="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.

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_webhook e aja em intake.completed.
  • Você é um agente em um terminal → configure uma verificação recorrente que chama get_intake_status a cada every_hours horas 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

EventoQuandoCampos-chave
item.submittedCliente envia um itemitem_key, item_status
intake.completedTodos os itens obrigatórios aprovados
client.viewedCliente abre o portalclient_email
chase.bouncedUm lembrete falhou no enviochannel, reason, recipient, still_chasing
intake.stalled3 lembretes enviados, sem respostaattempts

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).

FreeSolo — US$ 29/mêsAgency — US$ 79/mês
Intakes ativos11560
Itens por intake10ilimitadoilimitado
Armazenamento1 GB25 GB100 GB
Marca"powered by"logo + cores personalizados+ domínio de envio personalizado
Cobrançae-mail, padrãoe-mail, todos os agendamentose-mail, todos os agendamentos
Cofre de segredossimsim
Webhooks + REST + MCPsimsimsim

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:

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.