Email Agent MCP

Conectividade de e-mail local para agentes de IA — ler, rascunhar, enviar e organizar e-mails do Outlook via MCP. Licenciado sob Apache-2.0.

Documentação

Agent Email

npm version npm downloads License: Apache-2.0 CI codecov GitHub stargazers Tests: Vitest OpenSpec Traceability Socket Badge install size

English | Español | 简体中文 | Português (Brasil) | Deutsch

email-agent-mcp por UseJunior -- conectividade de e-mail local para agentes de IA.

Agent Email é um servidor MCP TypeScript de código aberto que permite ao Claude Code, Cursor, Gemini CLI, OpenClaw e outros runtimes compatíveis com MCP ler e-mails, pesquisar conversas, redigir respostas, rotular mensagens, alterar estado de leitura, mover mensagens e enviar correspondência pela sua própria caixa de entrada. Microsoft 365 / Outlook e Gmail são suportados hoje. Padrões com foco em segurança significam que agentes não podem enviar e-mails até que você configure explicitamente uma lista de permissões.

Início Rápido

npx -y email-agent-mcp

O assistente de configuração interativo guia você pela configuração OAuth e seleção da caixa de entrada.

O Que Funciona Hoje

  • Acesso à caixa de entrada do Microsoft 365 / Outlook via MCP stdio
  • list_emails, read_email, search_emails e get_thread
  • create_draft, update_draft, send_draft, send_email e reply_to_email
  • label_email, mark_read e move_to_folder
  • listas de permissões de envio, exclusão desabilitada por padrão e erros sanitizados

A passagem atual de preparação para lançamento foi validada contra uma caixa de entrada real do Outlook para fluxos de leitura, rascunho, envio, categorização, movimentação e estado de leitura.

Por Que Isso Existe

Agentes de IA precisam ler, responder e agir sobre e-mails, mas as APIs de e-mail são complexas. Fluxos OAuth, consultas delta do Graph, assinaturas push do Gmail, conversão de HTML para markdown, semântica de conversas -- cada provedor tem suas peculiaridades.

Agent Email encapsula essa complexidade em ferramentas MCP determinísticas com proteções de segurança:

  • listas de permissões de envio e recebimento que controlam com quem os agentes podem contatar
  • exclusão desabilitada por padrão (exige aceitação explícita)
  • sanitização de erros que remove chaves de API, caminhos de arquivo e rastreamentos de pilha
  • sandboxing de arquivos de corpo com proteção contra travessia de caminho

Uso com Claude Code

Adicione ao ~/.claude/settings.json ou ao .claude/settings.json do seu projeto:

{
  "mcpServers": {
    "email-agent-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "email-agent-mcp"]
    }
  }
}

Uso com Cursor

// .cursor/mcp.json
{
  "mcpServers": {
    "email-agent-mcp": {
      "command": "npx",
      "args": ["-y", "email-agent-mcp"]
    }
  }
}

Uso com Gemini CLI

gemini extensions install https://github.com/UseJunior/email-agent-mcp

Uso com OpenClaw

Adicione um bloco mcp ao ~/.openclaw/openclaw.json:

{
  // ... existing config ...
  mcp: {
    servers: {
      email: {
        command: "npx",
        args: ["tsx", "/path/to/email-agent-mcp/packages/email-mcp/src/serve-entry.ts"],
        transport: "stdio"
      }
    }
  }
}

Nota de versão: A chave de configuração mcp exige OpenClaw app >= 2026.3.24. Se o CLI for mais antigo que o app, ele pode rejeitar essa chave durante a validação, mesmo que o gateway a aceite. Atualize o CLI com npm install openclaw@latest no seu diretório NemoClaw, ou reinicie o gateway diretamente com launchctl kickstart -k gui/501/ai.openclaw.gateway.

Observador de e-mail

O observador consulta sua caixa de entrada e envia sinais de ativação ao OpenClaw quando novos e-mails chegam:

# Set the hooks token (must match hooks.token in openclaw.json)
export OPENCLAW_HOOKS_TOKEN="your-hooks-token"

# Start the watcher (defaults to http://localhost:18789/hooks/wake)
npm run dev:watch

O observador exige pelo menos uma caixa de entrada configurada. Execute npx email-agent-mcp ou npm run dev:configure primeiro para concluir o fluxo OAuth.

Teste Rápido de Preparação para Lançamento

Antes de gravar uma demonstração, execute o script de teste rápido ao vivo contra uma caixa de entrada real e uma lista de permissões de envio segura. O script exercita:

  • get_mailbox_status
  • list_emails + read_email
  • mark_read não lido -> lido -> não lido
  • label_email em um candidato seguro da caixa de entrada
  • create_draft
  • reply_to_email apenas rascunho
  • send_email opcional

Exemplo:

EMAIL_AGENT_MCP_HOME=/tmp/email-agent-mcp-live \
AGENT_EMAIL_SEND_ALLOWLIST=/tmp/email-agent-mcp-live/send-allowlist.json \
npm run launch:prep:smoke -- --live-write --send-to beta@usejunior.com

A seleção padrão de candidato seguro procura por notifications@github.com na caixa de entrada para que você possa ensaiar o fluxo de gravação em uma mensagem pública segura em vez de correspondência de clientes. Se o nome do status da sua caixa de entrada não for um endereço de e-mail, passe --reply-sender <email> ou defina EMAIL_AGENT_MCP_REPLY_SENDER para que o script possa encontrar uma mensagem enviada por você mesmo para a verificação de resposta a rascunho.

Referência de Ferramentas

Perfis de escopo

Defina EMAIL_AGENT_MCP_SCOPE_PROFILE antes de configurar e iniciar o servidor para escolher as permissões expostas a um agente. O padrão é full para compatibilidade retroativa.

PerfilEscopos delegados da MicrosoftFerramentas expostas
observeMail.Read, User.Read, offline_accessFerramentas de e-mail somente leitura, menos list_inbox_rules (veja abaixo)
full (padrão)Mail.Read, Mail.ReadWrite, Mail.Send, MailboxSettings.ReadWrite, User.Read, offline_accessTodas as ferramentas

Para uma implantação somente observação, defina o perfil tanto na configuração quanto no runtime para que o consentimento OAuth e a lista de ferramentas MCP concordem:

export EMAIL_AGENT_MCP_SCOPE_PROFILE=observe
npx email-agent-mcp configure
npx email-agent-mcp serve

Os escopos de observe são um subconjunto estrito deliberado dos de full. É isso que torna o perfil adotável: um locatário que já consentiu com o conjunto completo concede observe silenciosamente, então alternar full → observe não exige novo consentimento. Alternar observe → full exige um novo consentimento interativo, porque solicita escopos que nunca foram concedidos.

Pela mesma razão, observe não expõe list_inbox_rules. O Graph bloqueia /mailFolders/inbox/messageRules atrás de MailboxSettings, e o Entra trata MailboxSettings.Read como um escopo distinto do full's MailboxSettings.ReadWrite em vez de implicado por ele. Solicitá-lo quebraria a propriedade de subconjunto e forçaria um novo consentimento em cada implantação observe — uma solicitação de aprovação de administrador em locatários que restringem o consentimento do usuário. Use full se você precisar de visibilidade das regras da caixa de entrada.

Um valor de perfil inválido interrompe a inicialização em vez de conceder silenciosamente acesso mais amplo. Se as credenciais em cache não cobrirem os escopos do perfil, o servidor falha rapidamente com um erro acionável em vez de bloquear em um login interativo.

O que observe garante e não garante

observe sempre remove as ferramentas de escrita da superfície de ferramentas MCP, então um agente não pode invocá-las. Essa parte vale em todos os lugares.

Ele apenas restringe o token OAuth em uma caixa de entrada que ainda não consentiu com os escopos de escrita. O Entra emite um token de acesso que carrega todos os escopos que o usuário ou locatário já consentiu para esse aplicativo — não apenas o subconjunto solicitado no momento da aquisição do token. Então, se você apontar observe para uma caixa de entrada anteriormente configurada como full, o token subjacente ainda carrega Mail.ReadWrite e Mail.Send; apenas a superfície de ferramentas é reduzida.

Para um token genuíno de privilégio mínimo, consinta com observe a partir de uma caixa de entrada que nunca recebeu os escopos de escrita — um configure novo contra um registro de aplicativo cujas permissões delegadas param em Mail.Read/User.Read. Trate a redução da superfície de ferramentas como defesa em profundidade, não como uma fronteira OAuth, a menos que você controle a concessão.

Ferramentas

O perfil full expõe 26 ferramentas MCP; observe omite toda ferramenta cuja ação seja marcada como mutação de caixa de entrada:

FerramentaDescriçãoTipo
list_emailsLista e-mails recentes com filtragemleitura
read_emailLê o conteúdo completo do e-mail como markdown, ou HTML bruto com format: "html"leitura
search_emailsPesquisa de texto completo nas caixas de entradaleitura
list_mailboxesEnumera caixas de entrada configuradas, seu status e a padrãoleitura
get_mailbox_statusStatus da conexão e avisosleitura
get_threadContexto completo da conversaleitura
list_attachmentsLista metadados de anexos de um e-mailleitura
download_attachmentBaixa um anexo de arquivo como base64leitura
send_emailEnvia novo e-mail (controlado por lista de permissões)escrita
reply_to_emailResponde dentro da conversa (controlado por lista de permissões no envio)escrita
create_draftCria rascunho de e-mailescrita
update_draftAtualiza o conteúdo do rascunhoescrita
send_draftEnvia um rascunho salvoescrita
list_scheduled_sendsLista envios agendados pendentes mantidos pelo provedor (Microsoft 365)leitura
cancel_scheduled_sendCancela um envio agendado pendente (Microsoft 365)destrutiva
label_emailAplica rótulos/categoriasescrita
flag_emailMarca/desmarca e-mails com sinalizadorescrita
mark_readMarca como lido/não lidoescrita
move_to_folderMove entre pastasescrita
delete_emailExclui (exige env do operador + sinalizador do chamador)destrutiva
list_foldersLista recursivamente pastas e caminhos calculados (Microsoft 365)leitura
create_folderCria uma subpasta personalizada (Microsoft 365)escrita
delete_folderExclui uma pasta personalizada (exige env do operador + sinalizador do chamador); pastas do sistema são protegidas (Microsoft 365)destrutiva
list_inbox_rulesLista regras de caixa de entrada do servidor (Microsoft 365)leitura
create_inbox_ruleCria uma regra de caixa de entrada segura persistente; encaminhamento, redirecionamento, exclusão e descarte para Itens Excluídos são bloqueados (Microsoft 365)escrita
delete_inbox_ruleExclui uma regra de caixa de entrada do servidor (exige env do operador + sinalizador do chamador) (Microsoft 365)destrutiva

Esta é uma superfície de ferramentas compartilhada entre provedores. Embora label_email, flag_email, mark_read, move_to_folder e delete_email sejam anunciadas, o adaptador Gmail intencionalmente não implementa essas capacidades de mutação. Elas falham fechadas antes de qualquer solicitação de mutação Gmail: ações não suportadas retornam NOT_SUPPORTED, enquanto a exclusão pode parar primeiro no portão padrão do operador DELETE_DISABLED. O gmail.readonly padrão mais a concessão gmail.compose não autorizariam essas mutações também; não adicione gmail.modify para tentar tornar as ferramentas disponíveis. Elas permanecem disponíveis apenas para provedores cujos adaptadores e concessões as suportam.

Cada linha retornada por list_emails, search_emails e get_thread, e a resposta read_email, carrega um booleano isDraft sempre presente. isDraft: true significa que a mensagem é um rascunho não enviado: ela não foi enviada, e seu receivedAt é metadado fornecido pelo provedor em vez de evidência de entrega. O campo nunca é omitido, então um agente consumidor pode distinguir "não é um rascunho" de "status de rascunho não informado" — mas observe que false afirma apenas que o provedor não marcou a mensagem como um rascunho não enviado, não que o proprietário da caixa de entrada a enviou (correspondência recebida também é false). Rascunhos aparecem de outra forma em listagens e resultados de pesquisa como antes.

O gerenciamento de pastas e regras de caixa de entrada exige consentimento do Microsoft Graph MailboxSettings.ReadWrite. Conexões existentes de caixa de entrada da Microsoft devem reconsentir após a atualização. O Gmail usa rótulos em vez de pastas hierárquicas/regras Exchange do servidor, então essas seis ferramentas retornam NOT_SUPPORTED para caixas de entrada do Gmail.

Formatos de corpo

Corpos atravessam o fio como markdown por padrão em ambas as direções. Esse padrão é deliberado — markdown é eficiente em tokens, e uma leitura rotineira deve permanecer barata. Ambas as direções podem optar por sair dele.

Escrita — send_email, reply_to_email, create_draft e update_draft aceitam um format opcional:

formatComportamento
markdown (padrão)Renderizado para HTML via marked (GFM, breaks: true). HTML bruto embutido no markdown é preservado.
htmlPassagem direta — seu HTML é enviado como está.
textSem renderização; enviado como texto simples.

html é passagem direta não sanitizada: sem sanitizador, sem lista de permissões, sem reescrita do seu markup. CSS inline e tags arbitrárias sobrevivem até o fio — é isso que torna possível e-mail estilizado, e significa que você é responsável pelo que enviar. A única modificação padrão é o wrapper preto forçado abaixo; com force_black: false o corpo passa byte por byte.

Para markdown e html o HTML renderizado é envolvido em um <div style="color: #000000;"> para que o modo escuro do Outlook não transforme o texto em branco sobre branco. Arquivos de corpo — send_email, create_draft e update_draft também aceitam body_file: um caminho para um arquivo .md, .html ou .txt (lido em relação a EMAIL_MCP_SAFE_DIR, por padrão o diretório de trabalho do processo, além de quaisquer raízes de AGENT_EMAIL_ALLOWED_DIRS) usado como corpo em vez de body. Um arquivo de corpo .md pode abrir com um bloco de frontmatter YAML:

Para update_draft, body e body_file são permitidos apenas em um rascunho que não seja de resposta e exigem replace_body: true; o corpo armazenado é então substituído por completo. Corpos de rascunhos de resposta não podem ser editados com segurança porque incluem histórico citado montado pelo provedor, então crie um novo rascunho. Assunto, destinatário e anexos permanecem disponíveis em rascunhos de resposta.

---
to: alex@example.com
subject: Quarterly summary
format: html
force_black: false
---
<p>The body starts after the closing delimiter.</p>

As chaves reconhecidas são to, cc, subject, reply_to, draft, format e force_black (draft: true transforma uma chamada send_email em um salvamento de rascunho). Um valor de frontmatter substitui o parâmetro de ferramenta de mesmo nome. O frontmatter é analisado apenas de arquivos .md, e a extensão do arquivo nunca seleciona o formato — sem um parâmetro de ferramenta format explícito, até mesmo um arquivo de corpo .html recebe a renderização markdown padrão; passe format: "html" para passagem direta.

Leitura — read_email aceita um format opcional de markdown (padrão) ou html:

{ "id": "AAMkAD...", "format": "html" }

format: "html" retorna o HTML bruto do corpo da mensagem verbatim. Use-o quando precisar de estilos que o markdown não pode carregar — color, background-color, text-decoration, <u> — por exemplo, para alterar uma frase de um corpo formatado e deixar o resto intacto. Pelo caminho markdown, esse estilo é silenciosamente destruído na saída.

Dois campos retornam com ele:

  • bodyFormat — sempre presente: markdown, html ou text. Você recebe text quando solicitou html mas a mensagem não tem parte HTML, caso em que o corpo em texto simples é retornado. Verifique isso antes de escrever um corpo de volta.
  • bodyTruncated — presente e true somente se o corpo excedeu o orçamento de resposta de 256 KB para format: "html" (o caminho markdown é ilimitado, como antes). Não escreva um corpo truncado de volta em um rascunho.

HTML bruto custa muito mais tokens do que sua redução em markdown, então deixe o padrão intacto a menos que precise do estilo. strip_quoted_history e strip_signatures são transformações de texto em formato markdown e não são aplicadas quando format é html — o HTML bruto é retornado intocado.

Escrevendo de volta. Passe format: "html" e force_black: false:

{ "draft_id": "AAMkAD...", "body": "<edited html>", "format": "html", "force_black": false }

force_black assume como padrão true, que envolve qualquer HTML que você enviar em um <div style="color: #000000;">. Isso é correto para HTML que você mesmo criou, mas em um corpo que você acabou de ler, ele aninha mais um wrapper a cada ciclo — após quinze revisões, você tem quinze divs aninhados. Com force_black: false, os bytes sobrevivem à ida e volta intactos.

Envio agendado

send_email e send_draft aceitam scheduled_send_at, um timestamp ISO 8601 futuro com fuso horário explícito. O Microsoft 365 mantém a mensagem no lado do servidor, então a entrega sobrevive à saída deste processo. Use o messageId retornado com cancel_scheduled_send enquanto estiver pendente, ou inspecione itens pendentes com list_scheduled_sends. Essa listagem cobre mensagens que você agendou do próprio Outlook, não apenas as agendadas por este servidor — o Outlook estaciona a mensagem retida onde quiser (frequentemente em Itens Excluídos), então a descoberta varre a caixa de correio em vez de uma pasta, e relata apenas envios cujo horário ainda está por vir.

O Microsoft Graph altera o ID da mensagem quando o rascunho retido vai para Itens Enviados, então o ID retornado é um identificador de gerenciamento pré-entrega, não um ID permanente de mensagem enviada. A API pública do Gmail não expõe envio agendado; todas as superfícies de envio agendado retornam NOT_SUPPORTED para Gmail, enquanto envios imediatos permanecem inalterados.

Anexos de saída

send_email, reply_to_email, create_draft e update_draft aceitam um array opcional de attachments. Cada entrada aceita um arquivo path em sandbox (lido em relação a EMAIL_MCP_SAFE_DIR, por padrão o diretório de trabalho do processo, além de quaisquer raízes de AGENT_EMAIL_ALLOWED_DIRS — veja abaixo) ou base64 inline, além de substituições opcionais de filename / mimeType:

{
  "to": "alice@example.com",
  "subject": "Signed agreement",
  "body": "Attached as requested.",
  "attachments": [
    { "path": "./out/agreement.pdf" },
    { "base64": "iVBORw0KGgo...", "filename": "screenshot.png" }
  ]
}

Arquivos são limitados a 25MB cada; o Microsoft Graph adicionalmente limita envios inline a ~3MB no total (arquivos maiores precisam de uma sessão de upload — ainda não suportada). Para update_draft, omitir attachments preserva os arquivos existentes do rascunho; passar um array (mesmo vazio) os substitui.

Anexando arquivos de fora do diretório de trabalho — defina AGENT_EMAIL_ALLOWED_DIRS como uma lista separada por delimitadores de diretórios absolutos (: no macOS/Linux, ; no Windows; um ~ inicial é expandido) que attachments[].path e body_file também podem ler:

{
  "mcpServers": {
    "email-agent-mcp": {
      "command": "npx",
      "args": ["-y", "@usejunior/email-agent-mcp"],
      "env": { "AGENT_EMAIL_ALLOWED_DIRS": "~/Downloads:/Volumes/Shared/Contracts" }
    }
  }
}

Como o caminho de um chamador é resolvido — as duas regras abaixo aparecem como FILE_NOT_FOUND, que é fácil de interpretar erroneamente como um arquivo ausente:

Caminho que você passaResolve contraEncontra um arquivo em uma raiz permitida?
contract.pdfEMAIL_MCP_SAFE_DIR (padrão: cwd)❌ caminhos relativos nunca buscam nas raízes extras
~/Downloads/contract.pdfEMAIL_MCP_SAFE_DIR — o ~ não é expandido❌
/Users/you/Downloads/contract.pdfcada raiz por vez✅

A abreviação ~ é expandida em AGENT_EMAIL_ALLOWED_DIRS (a configuração do operador), mas não em attachments[].path ou body_file (o argumento do chamador) — passe-os como caminhos absolutos. E um caminho relativo é deliberadamente confinado ao diretório seguro: buscar em cada raiz permitida por um contract.pdf simples anexaria silenciosamente qualquer cópia que existisse primeiro.

Cada raiz é canonicalizada com realpath antes da verificação de contenção: uma raiz na lista de permissões que é em si um symlink resolve para sua localização real, uma raiz que não pode ser canonicalizada não autoriza nada, e um symlink que escapa de toda raiz ainda é rejeitado. Não definido (o padrão) mantém o diretório de trabalho como a única raiz — é por isso que um agente que não consegue acessar um arquivo deve pedir que você coloque seu diretório na lista de permissões em vez de copiar documentos confidenciais para uma árvore de trabalho git.

Colocar um diretório na lista de permissões confia em todos que podem escrever nele. Validação e abertura são operações separadas em um caminho, então um principal que pode substituir um diretório dentro de uma raiz permitida entre as duas ainda pode redirecionar a leitura; apenas coloque na lista de permissões raízes cujos ancestrais não sejam graváveis por usuários não confiáveis. O arquivo final é aberto com O_NOFOLLOW, então o arquivo em si não pode ser trocado por um symlink após a validação.

Suporte do Provedor

ProvedorStatusPacote
Microsoft 365 (Graph API)Totalmente suportado@usejunior/provider-microsoft
GmailSuportado via OAuth interativo por CLI (cliente padrão ou seu próprio) ou configuração manual de refresh-token@usejunior/provider-gmail

Use email-agent-mcp configure --provider gmail para executar o fluxo OAuth no navegador local, ou adicione um arquivo de token de caixa de correio manual em ~/.email-agent-mcp/tokens/. Veja Configuração do Gmail abaixo e packages/provider-gmail/README.md.

Configuração do Gmail

O Gmail tem dois caminhos OAuth suportados. Ambos terminam com o mesmo resultado: um refresh token na sua máquina, e chamadas à API do Gmail indo diretamente da sua máquina para o Google.

CaminhoComandoProjeto Google Cloud necessário?
Cliente OAuth padrãoemail-agent-mcp configure --provider gmailNão
Traga sua própria chave (BYOK)mesmo comando mais --client-id / --client-secretSim, seu

Recomendado por enquanto: BYOK. Nosso cliente OAuth padrão ainda está no status de publicação "Teste" do Google enquanto a verificação está em andamento, o que o limita a 100 usuários de teste registrados e mostra o aviso "O Google não verificou este aplicativo" durante o consentimento. A verificação para o escopo restrito do Gmail exige uma avaliação de segurança CASA e leva várias semanas; o progresso é acompanhado em issue #112. O BYOK contorna o limite compartilhado de 100 usuários e coloca o status de publicação do aplicativo sob seu controle; seu próprio aplicativo ainda tem as restrições de Teste do Google até que você o publique.

Outras razões para escolher BYOK: cota de API dedicada, sua própria política de privacidade e status de verificação, e nenhuma dependência do broker hospedado em https://oauth.usejunior.com.

Escopos solicitados

O Email Agent MCP solicita exatamente estes dois escopos do Gmail por padrão:

https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/gmail.compose

gmail.readonly é necessário para ler mensagens e threads; gmail.compose gerencia rascunhos e envio, mas não autoriza users.threads.get ou users.messages.get. A concessão padrão não inclui gmail.modify. Separadamente, o adaptador do Gmail intencionalmente deixa alterações de rótulos, alterações de estado de leitura, movimentações, lixeira e operações de exclusão sem suporte, então essas ferramentas falham fechadas com NOT_SUPPORTED. Adicione ambos os escopos à sua tela de consentimento OAuth.

Implantações que definem explicitamente GMAIL_OAUTH_SCOPES devem atualizá-lo para os dois escopos separados por espaço acima. Novas autorizações e autorizações repetidas devem re-consentir com o novo par de escopos. Arquivos de caixa de correio existentes e seus metadados de refresh-token armazenados permanecem inalterados.

BYOK: crie seu próprio cliente OAuth do Google

  1. Crie um projeto no Console do Google Cloud, ou selecione um existente.
  2. Ative a API do Gmail em APIs & Serviços → Biblioteca → Gmail API → Ativar.
  3. Configure a tela de consentimento OAuth em APIs & Serviços → Tela de consentimento OAuth:
    • Tipo de usuário Externo para uma conta pessoal @gmail.com, ou Interno se você estiver no Google Workspace e apenas sua própria organização precisar de acesso.
    • Adicione ambos https://www.googleapis.com/auth/gmail.readonly e https://www.googleapis.com/auth/gmail.compose.
    • Enquanto o aplicativo estiver em Teste, adicione seu próprio endereço de Gmail em Usuários de teste, ou o consentimento será recusado.
  4. Crie o cliente OAuth em APIs & Serviços → Credenciais → Criar credenciais → ID do cliente OAuth. Escolha o tipo de aplicativo Aplicativo de desktop. Desktop é obrigatório: configure inicia um listener descartável em uma porta loopback efêmera (http://127.0.0.1:<port>/oauth2callback), e apenas clientes Desktop permitem que o Google aceite uma porta loopback arbitrária sem pré-registrar o URI de redirecionamento exato. Um cliente de aplicativo Web falhará com redirect_uri_mismatch.
  5. Copie o ID do cliente e o segredo do cliente.

BYOK: entregue as credenciais ao email-agent-mcp

Passe ambas as partes como flags:

npx email-agent-mcp configure \
  --provider gmail \
  --mailbox personal \
  --client-id YOUR_GOOGLE_CLIENT_ID \
  --client-secret YOUR_GOOGLE_CLIENT_SECRET

Ou defina as duas variáveis de ambiente com namespace e omita as flags:

export AGENT_EMAIL_GMAIL_CLIENT_ID=YOUR_GOOGLE_CLIENT_ID
export AGENT_EMAIL_GMAIL_CLIENT_SECRET=YOUR_GOOGLE_CLIENT_SECRET

npx email-agent-mcp configure --provider gmail --mailbox personal

Ambas as partes são obrigatórias. Fornecer apenas uma sai com erro em vez de silenciosamente cair para o cliente padrão. Fornecer nenhuma seleciona o cliente OAuth padrão.

Seu navegador abre a tela de consentimento do Google, a CLI captura o callback na loopback, troca o código com PKCE e escreve a caixa de correio em ~/.email-agent-mcp/tokens/<safe-key>.json com "source": "byok" ao lado do seu clientId, clientSecret e o refreshToken resultante. Atualizações de token então vão direto para o endpoint de token do Google; nenhum broker está envolvido.

Re-executar configure para uma caixa de correio já salva reutiliza as credenciais salvas, então você só passa as flags uma vez. Passar --client-id e --client-secret para uma caixa de correio previamente configurada contra o cliente padrão a migra para BYOK.

BYOK: evite que a concessão expire após 7 dias

O Google expira refresh tokens após 7 dias enquanto seu app OAuth estiver no status Testing (Teste) de publicação, o que aparece como um prompt de reautenticação cerca de uma vez por semana. email-agent-mcp status avisa quando uma caixa de entrada está se aproximando dessa janela. Publicar seu app (OAuth consent screen → Publish app) remove a expiração de 7 dias. Como você é o dono do app e seu único usuário, o limite de 100 usuários de teste não se aplica a você de qualquer forma.

Desconectar o Gmail e revogar o acesso

Desconectar tem duas partes independentes:

  1. Pare qualquer processo email-agent-mcp em execução. No Finder, abra ~/.email-agent-mcp/tokens/, identifique o único arquivo JSON da caixa de entrada que você pretende desconectar e mova exatamente esse arquivo para a Lixeira. Não abra, cole ou compartilhe seu conteúdo, e não exclua o diretório inteiro ~/.email-agent-mcp se outras caixas de entrada estiverem configuradas. Se você definiu EMAIL_AGENT_MCP_HOME, use a pasta tokens/ desse diretório.
  2. Abra Conexões de terceiros da Conta Google, selecione Email Agent MCP (ou o nome do seu aplicativo BYOK) e remova seu acesso.

Excluir o arquivo local impede que esta instalação use a credencial salva. Remover a conexão da Conta Google revoga a concessão no Google. Execute email-agent-mcp status depois para confirmar que a caixa de entrada não está mais configurada.

Padrões de Segurança

O Agent Email vem com padrões restritivos que você afrouxa conforme necessário:

  • Lista de permissão de envio: vazia por padrão — os agentes não podem enviar e-mails até você adicionar destinatários
  • Lista de permissão de recebimento: aceita tudo por padrão — controla quais remetentes acionam o watcher
  • Exclusão desabilitada: os agentes não podem excluir e-mails por padrão. Duas condições devem ser satisfeitas:
    1. o operador define AGENT_EMAIL_DELETE_ENABLED=true no ambiente do processo email-agent-mcp (e AGENT_EMAIL_HARD_DELETE_ENABLED=true para exclusão permanente). Reinicialização necessária após a alteração.
    2. o chamador passa user_explicitly_requested_deletion: true na chamada da ferramenta.
  • Sanitização de erros: chaves de API, caminhos de arquivo e stack traces são removidos das respostas de erro
  • Sandbox de arquivos do corpo: sem travessia de ../, sem symlinks, detecção de binários
  • Proteção contra entrega duplicada: ativada por padrão — um envio, resposta ou envio de rascunho idêntico repetido em até 15 minutos é recusado em vez de ser entregue duas vezes

Proteção contra entrega duplicada

Os endpoints de envio dos provedores (Graph POST /sendMail, Gmail users.messages.send) não aceitam chave de idempotência, então o Agent Email despacha cada entrega exatamente uma vez e nunca tenta novamente automaticamente. Isso impede que a biblioteca duplique uma mensagem. Não impede o chamador: um agente cujo resultado da ferramenta foi perdido — um contexto compactado, um transporte interrompido, um supervisor reiniciando a rodada, uma pessoa tentando novamente algo que parecia travado — reproduz a mesma instrução aprovada, e a segunda chamada parece exatamente igual à primeira.

send_email, reply_to_email e send_draft registram, portanto, cada despacho em um registro em processo, com chave baseada em um resumo das entradas efetivas da ação — caixa de entrada, destinatários, assunto, corpo renderizado, conteúdo dos anexos e o pai da resposta ou o ID do rascunho. (Entradas efetivas, não bytes finais do fio: um provedor pode transformar uma mensagem no caminho de saída, e o Graph, por exemplo, trunca um assunto em 255 caracteres, então duas entradas diferentes podem sair como e-mails idênticos. A proteção detecta uma chamada de ferramenta reproduzida, que é o que realmente acontece.) Uma repetição dentro da janela é recusada antes de o despacho ser enviado:

CódigoSignificadoO que fazer
DUPLICATE_SEND_IN_FLIGHTUma entrega idêntica ainda não retornouAguarde a primeira chamada
DUPLICATE_SEND_BLOCKEDUma entrega idêntica já foi bem-sucedidaPare — a resposta carrega o messageId original
DUPLICATE_SEND_UNRESOLVEDUma entrega idêntica terminou de forma ambíguaVerifique os Itens Enviados antes de reenviar

Uma falha que prova que nada foi entregue — qualquer código derivado de 4xx, um 429 ou uma falha de conexão — libera o registro imediatamente, então reenviar após uma rejeição nunca é bloqueado. Qualquer outra coisa, incluindo um código de um provedor que não vimos, é mantida como não resolvida: uma mensagem retida indevidamente custa um reenvio bloqueado; uma liberada indevidamente custa uma duplicata na caixa de entrada de alguém.

Para enviar a mesma mensagem novamente de propósito, passe allow_duplicate: true. É um desvio incondicional por solicitação — uma reprodução que também carrega a flag despacha novamente, porque a flag afirma que uma pessoa decidiu sobre esse envio. A tentativa forçada é registrada junto com a anterior, em vez de substituí-la, então se a substituição for rejeitada, a entrega original ainda recusa uma reprodução comum.

Os registros são limitados a uma caixa de entrada: mailbox quando o chamador fornece uma, caso contrário, a instância do provedor. Os operadores podem alterar a janela com AGENT_EMAIL_DUPLICATE_SEND_WINDOW_MS (padrão 900000); 0 desativa a proteção inteiramente.

O registro vive no processo do servidor e na memória. Ele fecha a janela de reprodução que realmente acontece — uma nova tentativa dentro de um servidor em execução — e não sobrevive ao reinício desse servidor.

Pacotes

PacoteDescrição
@usejunior/email-coreAções principais de e-mail, mecanismo de conteúdo, segurança e interfaces de provedor
@usejunior/email-mcpAdaptador de servidor MCP, CLI e watcher
@usejunior/provider-microsoftProvedor de e-mail da API Microsoft Graph
@usejunior/provider-gmailProvedor de e-mail da API Gmail
email-agent-mcpWrapper de distribuição (npx email-agent-mcp)
@usejunior/email-agent-mcpWrapper de compatibilidade, publicado em conjunto; use email-agent-mcp para novas instalações

Sinais de Qualidade e Confiança

  • CI é executado em cada pull request e push para main (lint, typecheck, testes no Node 20 + 22)
  • Varredura de segurança CodeQL e Semgrep
  • Cobertura publicada no Codecov
  • Aplicação de rastreabilidade OpenSpec via npm run check:spec-coverage
  • Mais de 300 testes no conjunto
  • Mantenedor: Steven Obiajulu

Arquitetura

email-agent-mcp/
├── packages/
│   ├── email-core          Core actions, content engine, security
│   ├── email-mcp           MCP server adapter, CLI, watcher
│   ├── provider-microsoft  Microsoft Graph provider
│   ├── provider-gmail      Gmail API provider
│   └── email-agent-mcp         Distribution wrapper (npx entry point)
├── openspec/               Spec-driven development
└── scripts/                CI and validation scripts

Lançamentos

Lançamento orientado por tags via GitHub Actions com publicação confiável npm OIDC. Todos os 6 pacotes são publicados em ordem de dependência com --provenance, depois server.json é publicado no Registro MCP oficial com mcp-publisher.

FAQ

Isso funciona com o Claude Code?

Sim. Execute npx email-agent-mcp para iniciar o servidor MCP e configure-o nas configurações do seu Claude Code.

Os agentes podem enviar e-mails sem minha permissão?

Não. A lista de permissão de envio está vazia por padrão. Os agentes não podem enviar nenhum e-mail até você configurar explicitamente os destinatários permitidos.

Isso armazena minhas credenciais de e-mail?

Os tokens OAuth são gerenciados pelo MSAL (Microsoft) e armazenados no chaveiro do seu sistema operacional ou em arquivos de configuração locais em ~/.email-agent-mcp/. O Agent Email nunca armazena senhas em texto puro.

Posso conectar várias caixas de entrada?

Sim. Você pode configurar Microsoft 365 e Gmail simultaneamente. As ações de leitura usam sua caixa de entrada principal por padrão; as ações de escrita exigem especificar uma caixa de entrada quando várias estão configuradas.

O CLI do OpenClaw rejeita minha configuração com "Unrecognized key: mcp"

O CLI do OpenClaw e o app macOS podem ser versões diferentes. O app (que executa o gateway) pode suportar chaves de configuração que o CLI ainda não reconhece. Atualize o CLI: cd ~/Projects/NemoClaw && npm install openclaw@latest. Alternativamente, reinicie o gateway diretamente: launchctl kickstart -k gui/501/ai.openclaw.gateway.

O watcher inicia, mas encontra zero caixas de entrada

As credenciais das caixas de entrada são armazenadas em ~/.email-agent-mcp/tokens/. Se este diretório estiver vazio, execute npx email-agent-mcp ou npm run dev:configure para autenticar via OAuth. O watcher sairá sem caixas de entrada para consultar até que pelo menos uma seja configurada.

O OpenClaw diz "Demo mode -- run email-agent-mcp configure to connect"

O servidor MCP está em execução, mas não tem credenciais reais de caixa de entrada. Execute npx email-agent-mcp para concluir a configuração interativa de OAuth e reinicie o gateway do OpenClaw para que o servidor MCP se reconecte com tokens válidos.

Token expirou após uma semana mesmo eu tendo acabado de autenticar

Os refresh tokens da Microsoft normalmente duram 90 dias, mas seu locatário do Azure AD pode impor durações mais curtas. O código usa MSAL com persistência no chaveiro do sistema operacional (@azure/identity-cache-persistence), que lida com a renovação silenciosa de tokens automaticamente. Se o MSAL relatar interaction_required ou invalid_grant, execute novamente npx email-agent-mcp para reautenticar. Causas comuns: políticas de acesso condicional, requisitos de reverificação de MFA ou políticas de duração de token configuradas pelo administrador.

O bot do Telegram do OpenClaw recebe mensagens, mas não responde

Verifique se o canal do Telegram está saudável com openclaw status. Se o canal mostrar OK, mas nenhuma resposta voltar, verifique se: (1) seu ID de usuário do Telegram está em channels.telegram.allowFrom em openclaw.json, (2) existe uma vinculação correspondente a channel: "telegram" e (3) o gateway foi reiniciado após alterações de configuração. Para bots de um único dono, use dmPolicy: "allowlist" com IDs allowFrom explícitos em vez de depender de aprovações de pareamento.

Desenvolvimento

npm ci
npm run build
npm run lint --workspaces --if-present
npm run test:run
npm run check:spec-coverage

Veja Também

  • Safe DOCX Suite — edição cirúrgica de documentos do Word com agentes de codificação
  • Open Agreements — preencha modelos jurídicos padrão com agentes de codificação

Privacidade

O Agent Email é executado inteiramente na sua máquina local. As credenciais de e-mail são armazenadas no chaveiro do seu sistema operacional (MSAL) e em arquivos de configuração locais. Nenhum conteúdo de e-mail é enviado a servidores externos pelo próprio Agent Email.

Governança