Servidor MCP

Conectar agentes de IA à Asender pelo Model Context Protocol: endereço, autenticação e ferramentas.

Servidor MCP

A Asender tem um servidor MCP (Model Context Protocol) remoto. Com ele, um agente de IA (Claude, ChatGPT, Cursor, VS Code e outros clientes MCP) consulta os dados da sua conta: leads, formulários, campanhas, relatórios, conversas e mais. Com chave de API e o escopo certo, o agente também escreve: envia um e-mail e cria ou atualiza leads (veja Ferramentas de escrita). Token OAuth continua somente leitura.

Status

Forma de conectarSituação
Chave de API sk_* no header Authorization: BearerFunciona em qualquer cliente que permita configurar headers (Claude Code, Cursor, VS Code, MCP Inspector). É a alternativa quando o cliente não faz OAuth.
OAuth com registro automático do cliente (CIMD / DCR)Clientes MCP com OAuth (Claude, ChatGPT, Cursor, VS Code, MCP Inspector) se registram sozinhos no servidor de autorização, e o usuário autoriza na tela de consentimento. O cliente aparece com o selo Não verificado até a equipe Asender verificá-lo, e só recebe escopos de leitura. Disponível após a implantação em cada ambiente.
OAuth com app cadastrado (client_id informado manualmente)Para clientes que aceitam client_id (e client_secret, se o app for confidencial) digitados à mão, como as configurações avançadas do conector personalizado do Claude. Veja Aplicativos.

O registro automático está descrito em Aplicativos. O que ainda não existe está em Limites e o que vem a seguir.

Conectar um cliente

A configuração exata muda de cliente para cliente e de versão para versão. Em todos os casos você informa a URL https://api.asender.net/mcp. Clientes com OAuth se registram sozinhos e abrem a tela de consentimento da Asender; nos demais, informe o header Authorization: Bearer sk_live_.... Crie a chave em Chaves de API com só os escopos de leitura de que o agente precisa.

Claude Code

claude mcp add --transport http asender https://api.asender.net/mcp \
  --header "Authorization: Bearer sk_live_..."

Claude (claude.ai e Claude Desktop)

Em Configurações > Conectores, adicione um conector personalizado (Custom connectors) e informe a URL https://api.asender.net/mcp. O cliente se registra sozinho e você autoriza na tela de consentimento da Asender (selo Não verificado até a equipe verificar o cliente). Se preferir, abra as configurações avançadas do conector e informe o client_id de um app cadastrado (e o segredo, se for um app confidencial). Esse caminho não oferece um campo para o header com a chave sk_*; para usar a chave, conecte pelo Claude Code.

ChatGPT

Ative o modo desenvolvedor e adicione um conector (app) MCP remoto com a URL https://api.asender.net/mcp. A autenticação é por OAuth: o ChatGPT se registra sozinho (CIMD ou DCR) e você autoriza na tela de consentimento da Asender; se a sua versão permitir, também dá para informar o client_id de um app cadastrado.

Cursor

No mcp.json do Cursor, declare um servidor com url e headers:

{
  "mcpServers": {
    "asender": {
      "url": "https://api.asender.net/mcp",
      "headers": { "Authorization": "Bearer ${env:ASENDER_API_KEY}" }
    }
  }
}

VS Code

No mcp.json do VS Code, declare um servidor do tipo http:

{
  "servers": {
    "asender": {
      "type": "http",
      "url": "https://api.asender.net/mcp",
      "headers": { "Authorization": "Bearer ${input:asender-key}" }
    }
  },
  "inputs": [
    { "type": "promptString", "id": "asender-key", "description": "Chave de API da Asender", "password": true }
  ]
}

MCP Inspector

npx @modelcontextprotocol/inspector

Escolha o transporte Streamable HTTP, informe a URL https://api.asender.net/mcp e adicione o header Authorization: Bearer sk_live_... (ou use o fluxo OAuth do Inspector, que se registra sozinho). O Inspector, que roda em http://localhost:6274, passa pela verificação de Origin.

Qualquer outro cliente

Adicione um servidor MCP remoto HTTP (Streamable HTTP) com a URL https://api.asender.net/mcp e o header Authorization: Bearer <chave sk_*>. O servidor não usa SSE: um cliente que só fale SSE não conecta.

Autenticação

O servidor é um resource server OAuth 2.1 e também aceita chave de API.

Chave de API

Envie Authorization: Bearer sk_live_.... Valem os escopos da chave: a ferramenta só aparece e só roda se a chave tem o escopo dela. Uma chave sem escopo de leitura enxerga no máximo asender_account_get.

OAuth (app)

  1. Descoberta. Uma chamada sem credencial recebe 401 com WWW-Authenticate: Bearer resource_metadata="https://api.asender.net/.well-known/oauth-protected-resource/mcp".
  2. O cliente lê esse documento (RFC 9728), que lista em authorization_servers o servidor de autorização https://auth.asender.net, os scopes_supported e o link desta documentação.
  3. Em https://auth.asender.net/.well-known/oauth-authorization-server (RFC 8414) estão os endpoints de autorização, de token e de revogação, além do registration_endpoint (https://auth.asender.net/register, DCR) e de client_id_metadata_document_supported: true (CIMD).
  4. Registro. O cliente que ainda não tem client_id se registra: publica um documento de metadados e usa a URL dele como client_id (CIMD) ou faz POST /register (DCR, RFC 7591). O cliente nasce público (PKCE, sem segredo), Não verificado e só com escopos de leitura. Os formatos estão em Aplicativos.
  5. O cliente abre /authorize com PKCE S256 (obrigatório) e o parâmetro resource=https://api.asender.net/mcp (RFC 8707). O resource faz o token nascer com aud do MCP. Um resource fora da lista permitida é recusado com invalid_target.
  6. O usuário entra, escolhe a conta e aprova os escopos na tela de consentimento, que mostra o selo Não verificado e o domínio do cliente até a equipe Asender verificá-lo. Um token vale para um usuário e uma conta. Para trocar de conta, autorize de novo.
  7. O cliente troca o code em /token e chama /mcp com o token. O token de acesso dura 15 minutos e é renovado com refresh token.

Clientes públicos (sem segredo, como apps de desktop) usam PKCE sem client_secret e podem usar redirect de loopback (http://127.0.0.1 ou http://[::1], com porta qualquer), conforme a RFC 8252.

Escopos

O token OAuth só exerce leitura; as ferramentas de escrita (email:send, leads:write) nunca aparecem para ele, mesmo que o token traga o escopo. Escopos disponíveis: account:read, leads:read, conversions:read, forms:read, analytics:read, campaigns:read, email:read, messaging:read, conversations:read, journeys:read, logs:read e openid (identidade do usuário que autorizou). Escopo de envio nunca vale para token OAuth. Para chave, valem os escopos da própria chave, descritos em Chaves de API.

Token do MCP e a API REST

Um token com aud só https://api.asender.net/mcp não vale na API REST (/v1): recebe 401. O inverso funciona: um token emitido sem resource, com aud https://api.asender.net, também é aceito no /mcp.

Catálogo de ferramentas

As de leitura anunciam readOnlyHint: true; as 3 de escrita estão em Ferramentas de escrita (readOnlyHint: false). Ferramenta cujo escopo a credencial não tem não aparece em tools/list, e chamá-la diretamente devolve erro. Além do escopo, a conta precisa ter o produto correspondente: sem ele a chamada falha como a REST falharia.

FerramentaO que fazEscopoProduto exigidoArgumentos principais
asender_account_getConta a que a credencial pertenceaccount:read (OAuth); qualquer chave válidanenhumnenhum
asender_me_getQuem autorizou o app, a conta e os escopos concedidosopenid (só token OAuth)nenhumnenhum
asender_leads_listLista leads do CRM (mais antigo atualizado primeiro)leads:readCRMlimit, cursor, updated_after, created_after
asender_leads_getUm lead pelo idleads:readCRMlead_id (obrigatório)
asender_forms_listLista formulários de capturaforms:readPageslimit, cursor, updated_after, created_after
asender_forms_submissions_listEnvios recebidos por um formulárioforms:readPagesform_id (obrigatório), limit, cursor, updated_after, created_after
asender_conversions_listConversões enviadas às plataformas de anúncioconversions:readCRMlimit, cursor, updated_after, created_after
asender_campaigns_listCampanhas de e-mail marketingcampaigns:readE-mail marketinglimit, cursor, updated_after
asender_campaigns_getUma campanhacampaigns:readE-mail marketingcampaign_id (obrigatório)
asender_campaigns_reportTotais de entrega e engajamento de uma campanhacampaigns:readE-mail marketingcampaign_id (obrigatório)
asender_email_reports_overviewPanorama de e-mail da conta nos últimos N diascampaigns:readE-mail marketingdays (1 a 365)
asender_email_reports_timeseriesEnvios, aberturas e cliques ao longo do tempocampaigns:readE-mail marketingfrom, to, period, granularity (hour, day, week)
asender_email_reports_top_emailsMelhores e piores e-mails da janelacampaigns:readE-mail marketingfrom, to, period, order (volume, open_rate, click_rate), limit, min_delivered
asender_email_reports_domainsResultados por provedor de caixa postalcampaigns:readE-mail marketingfrom, to, period
asender_emails_listE-mails transacionais enviados pela APIemail:readE-mail marketingstatus, q, cursor, limit, created_after
asender_emails_getUm e-mail enviado e seu status de entregaemail:readE-mail marketingemail_id (obrigatório)
asender_messaging_messages_listMensagens de SMS, WhatsApp ou pushmessaging:readSMS, WhatsApp (Zapify) ou Push, conforme o canalchannel (obrigatório: sms, whatsapp, push), limit, cursor, created_after
asender_messaging_overviewPanorama de entrega de um canalmessaging:readSMS, WhatsApp (Zapify) ou Push, conforme o canalchannel (obrigatório), days
asender_analytics_overviewTotais de analytics de site e páginas (padrão: últimos 30 dias)analytics:readPagesfrom, to, page_id, form_id, source, medium, campaign, country, device
asender_analytics_timeseriesSérie diária de analyticsanalytics:readPagesos mesmos filtros de asender_analytics_overview
asender_analytics_breakdownAnalytics agrupado por dimensãoanalytics:readPagesfiltros acima, dimension (page, source, medium, campaign, country, device, form), limit
asender_analytics_formsFunil de formulários (visualizações, inícios, envios)analytics:readPagesfrom, to, form_id (omitido = resumo de todos), limit
asender_conversations_listConversas de atendimentoconversations:readAtendimentolimit, cursor, updated_after
asender_conversations_messages_listLinha do tempo de uma conversaconversations:readAtendimentoconversation_id (obrigatório), limit, cursor, created_after
asender_journeys_listJornadas de automaçãojourneys:readCRMlimit, cursor, updated_after, created_after
asender_journeys_getUma jornadajourneys:readCRMjourney_id (obrigatório)
asender_logs_listLog de requisições da API pública da contalogs:readnenhumlimit, after, before, status_class, status, method, path, api_key_id, error_code, idempotency_key, message_id, mode, since, until
asender_dns_zones_listZonas de DNS da conta (só chave)dns:readnenhumnenhum
asender_dns_records_listRegistros de DNS de uma zona (só chave)dns:readnenhumzone_id (obrigatório), type, name, page, per_page
asender_emails_sendEnvia um e-mail transacional (só chave; escrita)email:sendE-mail marketingfrom, to (obrigatórios), subject, text/html, cc, bcc, reply_to, tags, idempotency_key
asender_leads_createCria um lead (só chave; escrita)leads:writeCRMemail e/ou phone, first_name, last_name, job_title, stage, tags, custom_fields, idempotency_key…
asender_leads_updateAtualiza um lead (só chave; escrita)leads:writeCRMlead_id (obrigatório), os campos de asender_leads_create, idempotency_key

Datas aceitam instante RFC 3339 (por exemplo 2026-10-01T00:00:00Z); nos relatórios e no analytics também YYYY-MM-DD. limit vai de 1 a 200 (padrão 50). A conta é sempre a da credencial: não há argumento de conta.

Ferramentas de escrita

São três e só aparecem em tools/list para uma chave sk_* que tenha o escopo (email:send para o e-mail, leads:write para os leads). Chamá-las sem o escopo, ou com token OAuth, devolve isError. Cada uma roda o mesmo handler da API REST (POST /v1/emails/send, POST /v1/leads, PATCH /v1/leads/{id}): mesmas validações, mesmo corpo fechado (argumento desconhecido é recusado), a conta é sempre a da chave.

FerramentadestructiveHintidempotentHintopenWorldHintObservação
asender_emails_sendfalsetruetrueO e-mail vai para pessoas reais e não volta. O remetente (from) precisa ser de um domínio verificado da conta; senão 422 RemetenteNaoVerificado. Fora de produção nada é entregue de verdade.
asender_leads_createfalsetruefalsePrecisa de email ou phone; outro lead da conta com o mesmo e-mail ou telefone dá 409.
asender_leads_updatetruetruefalseSó os campos enviados mudam; tags substitui a lista e "" limpa os textos opcionais, por isso é anunciada como destrutiva.

Todas têm readOnlyHint: false. As anotações são dicas ao cliente (por exemplo, para pedir confirmação ao usuário), não uma garantia de segurança: quem protege é o escopo da chave.

Idempotência. Toda escrita leva um Idempotency-Key:

Exemplo (enviar um e-mail):

curl -s https://api.asender.net/mcp \
  -H "Authorization: Bearer $ASENDER_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"asender_emails_send","arguments":{"from":"contato@exemplo.com","to":["cliente@exemplo.org"],"subject":"Seu pedido","text":"Obrigado pela compra.","idempotency_key":"pedido-1042-aviso"}}}'

Formato da resposta

Uma chamada com sucesso devolve o mesmo JSON da API REST em duas formas: em content (um bloco text com o JSON) e em structuredContent (o objeto). Uma resposta acima de 1 MiB é recusada com a orientação de reduzir limit, usar cursor ou estreitar a janela de tempo.

Erros

Paginação

As listas devolvem next_cursor quando há mais itens. Para a próxima página, repita a chamada passando esse valor em cursor (valor opaco: não o monte nem o interprete). asender_logs_list pagina por after/before, com ids de log.

Exemplos com curl

Defina a chave em uma variável de ambiente:

export ASENDER_API_KEY='sk_live_...'

initialize

curl -s https://api.asender.net/mcp \
  -H "Authorization: Bearer $ASENDER_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

A resposta traz protocolVersion, capabilities (tools), serverInfo e as instructions do servidor. Depois do initialize, um cliente completo envia a notificação notifications/initialized (resposta 202 sem corpo); com curl isso é opcional, porque o servidor não guarda sessão.

tools/list

curl -s https://api.asender.net/mcp \
  -H "Authorization: Bearer $ASENDER_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

Só aparecem as ferramentas que a chave pode usar.

tools/call

curl -s https://api.asender.net/mcp \
  -H "Authorization: Bearer $ASENDER_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"asender_leads_list","arguments":{"limit":10}}}'

Para a página seguinte, repita com "arguments":{"limit":10,"cursor":"<next_cursor>"}.

Segurança

Limites e o que vem a seguir