mail-shadow-mcp
Servidor MCP para acesso estruturado e somente leitura a e-mails. Expõe uma superfície de API mínima e auditável — agentes de IA podem pesquisar e ler e-mails, mas não podem enviar, excluir ou modificar sua caixa de entrada.
Documentação
A caixa de entrada privada, segura e inteligente do seu agente de IA
Pare de dar ao seu agente de IA acesso direto ao seu e-mail. Dê a ele uma cópia "sombra" segura, ultrarrápida e cheia de recursos.
O que você pode fazer com o mail-shadow-mcp?
Imagine ter um assistente pessoal que leu todos os seus e-mails, sabe exatamente o que é importante e pode responder suas perguntas em segundos — sem nunca arriscar sua caixa de entrada real por causa de uma IA com mau comportamento ou alucinando.
Com o mail-shadow-mcp, você pode pedir à sua IA (como OpenClaw, Hermes Agent, Claude, Cursor ou qualquer outro agente personalizado):
- "Recebi alguma fatura da Amazon nos últimos 3 dias?"
- "Resuma o último tópico de e-mail do meu chefe sobre o status do projeto."
- "Resuma todos os e-mails não lidos na minha pasta 'Projeto'."
- "Verifique se há e-mails de confirmação de voo na minha caixa de entrada para a próxima semana."
- "Encontre todos os e-mails de 'newsletter@example.com' que tenham anexos."
- "Há algo na minha caixa de entrada que pareça spam ou lixo?"
Por que isso existe?
A maioria dos agentes de IA exige acesso direto ao seu e-mail (IMAP) para "ver" suas mensagens. Isso é arriscado — porque, uma vez que um agente tenha credenciais IMAP ativas, ele tem as mesmas permissões que você: pode ler, mover, excluir ou até enviar e-mails. Uma única alucinação, uma instrução mal interpretada ou um bug pode levar uma IA a excluir acidentalmente toda a sua caixa de entrada, enviar uma resposta que você nunca pretendia ou expor suas credenciais a terceiros.
O mail-shadow-mcp resolve isso criando uma "Zona Segura":
- A Cópia Sombra: Em vez de se conectar ao seu servidor de e-mail real, criamos um banco de dados "sombra" local e de alta velocidade (SQLite) dos seus e-mails. Isso também desbloqueia recursos que o IMAP puro não pode oferecer: pesquisa instantânea de texto completo em todas as pastas e contas ao mesmo tempo, filtragem complexa por status de lido/respondido, anexos, intervalos de datas e remetente — tudo sem idas e voltas ao seu servidor de e-mail. E funciona igualmente bem com várias caixas de correio simultaneamente — basta adicionar mais contas à configuração.
- Privacidade Total: Seu agente de IA apenas fala com esse banco de dados local. Suas credenciais IMAP são usadas exclusivamente pelo mecanismo de sincronização — elas nunca são expostas por nenhuma chamada de ferramenta MCP nem retornadas ao agente em qualquer resposta.
- A "Rede de Segurança" (Exclusão Suave): Mesmo se você pedir à IA para "excluir" um e-mail, ela não o exclui de verdade. Ela simplesmente o move para uma pasta "Lixeira" que você designou. Se algo der errado, você sempre pode revisar a pasta, restaurar e-mails individuais ou excluí-los permanentemente você mesmo — você permanece no controle total.
[Remote IMAP Server] ──IMAP──▶ [Sync Engine] ──▶ [SQLite FTS5] ◀──▶ [MCP Server] ◀──▶ [AI Agent]
Começando
A maneira recomendada de executar o mail-shadow-mcp é via Docker. Executá-lo em um contêiner mantém o mecanismo de sincronização, as credenciais e o banco de dados totalmente isolados do seu agente de IA, que se conecta via HTTP. O agente nunca tem acesso ao sistema de arquivos do host ou à sua senha IMAP — apenas à API MCP.
Se preferir executá-lo localmente sem Docker, você pode baixar um binário pré-compilado da página de Releases e usar o transporte stdio em vez disso. No entanto, isso significa que o processo do agente e o mail-shadow-mcp compartilham o mesmo contexto de usuário, o que reduz os benefícios de isolamento descritos acima.
Etapa 1 — Inicie o contêiner para gerar a configuração de exemplo
Crie diretórios locais para configuração e dados e, em seguida, faça uma primeira execução para gerar a configuração de exemplo:
mkdir -p ./config ./data
docker run --rm \
-v ./config:/config \
-v ./data:/data \
ghcr.io/dryas/mail-shadow-mcp:latest
O contêiner detectará que não existe config.yaml, copiará uma configuração de exemplo anotada para ./config/, imprimirá uma mensagem e sairá.
Etapa 2 — Edite o arquivo de configuração
Abra ./config/config.yaml (ou onde quer que seu volume /config esteja montado) e preencha seus detalhes IMAP:
sync_interval_min: 15
database:
path: "/data/mail.db"
attachment_dir: "/data/attachments"
transport: http
http_addr: ":8080"
http_bearer_token: "your-secret-token" # generate one: openssl rand -hex 32
accounts:
- id: "work@example.com"
host: "imap.example.com"
port: 993
username: "work@example.com"
password: "$WORK_IMAP_PASS" # resolved from environment variable at startup
tls_mode: tls # tls (default) | starttls | none
tls_skip_verify: false # set true for self-signed certificates
folders: ["INBOX", "Archive"] # omit to sync all folders
idle_folders: ["INBOX"] # optional: instant new-mail push via IMAP IDLE
trash_folder: "llm_delete" # target folder for soft-deletes via delete_mail
Senhas como variáveis de ambiente: Em vez de escrever sua senha IMAP diretamente no arquivo de configuração, use um espaço reservado $VARIABLE_NAME — o mail-shadow-mcp o resolverá a partir do ambiente do contêiner na inicialização. No exemplo acima, password: "$WORK_IMAP_PASS" significa que o contêiner lê o valor da variável de ambiente WORK_IMAP_PASS, que você passa via -e WORK_IMAP_PASS=your_password_here ao iniciá-lo (veja a Etapa 1 ou 3). Dessa forma, nenhuma senha em texto simples acaba no arquivo de configuração.
folders: A lista de pastas IMAP a serem sincronizadas. Se omitida, todas as pastas são sincronizadas. Restringir às pastas que você realmente se importa (por exemplo, ["INBOX", "Archive"]) mantém o banco de dados menor e a sincronização inicial mais rápida.
idle_folders: Lista opcional de pastas para as quais o mail-shadow-mcp abre uma conexão IMAP IDLE persistente. Quando o servidor de e-mail envia uma notificação "EXISTS", uma sincronização é acionada imediatamente, em vez de esperar pelo próximo intervalo de polling, para que você seja informado sobre novos e-mails em segundos. Mantenha esta lista curta — cada entrada mantém uma conexão IMAP aberta durante toda a vida do contêiner. A melhor prática é adicionar apenas "INBOX" aqui, ou deixá-la de fora completamente e confiar no polling regular.
trash_folder: A pasta IMAP para a qual o mail-shadow-mcp move e-mails quando o agente de IA chama a ferramenta delete_mail. A pasta já deve existir no seu servidor de e-mail. Se não estiver definida, delete_mail retornará um erro e não fará nada — um padrão seguro. E-mails na pasta de lixeira são automaticamente excluídos de todos os resultados de consulta MCP (pesquisa, atividade recente, tópicos), então o agente nunca poderá vê-los novamente — independentemente de a pasta estar incluída na configuração de sincronização. Nota: se você mudar trash_folder para um nome de pasta diferente, a pasta de lixeira antiga não será mais excluída e seu conteúdo se tornará visível para o agente novamente na próxima sincronização. Certifique-se de esvaziar manualmente a pasta antiga antes de mudar.
http_bearer_token: Um token secreto que protege o endpoint HTTP do MCP. Cada solicitação do agente de IA deve incluí-lo como Authorization: Bearer <token>. Sem isso, qualquer pessoa que possa alcançar a porta pode falar com seu servidor MCP — então sempre defina isso ao executar com o transporte http. Gere um token aleatório seguro com:
# Linux / macOS / WSL
openssl rand -hex 32
# Windows PowerShell
[System.Convert]::ToBase64String((1..32 | ForEach-Object { [byte](Get-Random -Max 256) }))
Copie a saída para a configuração e passe o mesmo valor para seu agente de IA (veja a Etapa 4).
Etapa 3 — Inicie o contêiner
docker run -d \
--name mail-shadow-mcp \
--restart unless-stopped \
-v ./config:/config:ro \
-v ./data:/data \
-e WORK_IMAP_PASS=your_password_here \
-p 8080:8080 \
ghcr.io/dryas/mail-shadow-mcp:latest
O servidor MCP agora está acessível em http://localhost:8080/mcp.
Imagens multi-arquitetura pré-construídas (linux/amd64, linux/arm64) são publicadas no GitHub Container Registry a cada lançamento:
docker pull ghcr.io/dryas/mail-shadow-mcp:latest
Etapa 4 — Conecte seu agente de IA
Como estamos executando com Docker, o servidor MCP é acessível via HTTP — e isso funciona também com o Claude Desktop, não apenas com agentes remotos. Adicione o seguinte à configuração do seu agente:
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"mail_shadow": {
"url": "http://localhost:8080/mcp",
"headers": {
"Authorization": "Bearer your-secret-token"
}
}
}
}
Substitua localhost pelo IP ou hostname do seu servidor se o mail-shadow-mcp estiver em uma máquina diferente.
Hermes Agent (config.yaml):
mail-shadow:
url: http://localhost:8080/mcp
headers:
Authorization: Bearer your-secret-token
OpenClaw (~/.openclaw/openclaw.json):
{
"mcp": {
"servers": {
"mail_shadow": {
"url": "http://localhost:8080/mcp",
"transport": "streamable-http",
"headers": {
"Authorization": "Bearer your-secret-token"
}
}
}
}
}
Alternativa: stdio local (binário pré-compilado, sem Docker)
Se você escolheu executar o binário diretamente em vez de Docker, use o formato command:
{
"mcpServers": {
"mail_shadow": {
"command": "/path/to/mail-shadow-mcp",
"args": ["serve", "--config", "/path/to/config.yaml"]
}
}
}
É isso — sua IA agora pode pesquisar e ler seus e-mails com segurança.
Segurança: Nada é Realmente Excluído
O mail-shadow-mcp dá aos agentes de IA uma ferramenta delete_mail, mas essa ferramenta nunca emite um comando IMAP destrutivo. Aqui está exatamente o que acontece quando um agente a chama:
- O servidor MCP procura o e-mail no banco de dados local.
- Ele abre uma conexão IMAP de curta duração e executa IMAP MOVE — movendo a mensagem para a
trash_folderque você especifica emconfig.yaml(por exemplo,"llm_delete"). - A entrada do banco de dados local é removida, e a pasta de lixeira é permanentemente excluída de todos os resultados de consulta MCP — o agente nunca poderá ver o e-mail movido novamente, independentemente de a pasta estar sincronizada.
- O e-mail permanece intacto no servidor IMAP, guardado com segurança na pasta de lixeira. Você pode inspecionar, restaurar ou excluí-lo permanentemente a qualquer momento.
O agente de IA não tem acesso IMAP direto. Ele não pode expurgar mensagens, esvaziar pastas ou emitir qualquer comando de escrita além desse movimento controlado. Se trash_folder não estiver configurado para uma conta, delete_mail retorna um erro e não faz nada.
Mergulho Técnico
Ferramentas MCP
| Ferramenta | Descrição |
|---|---|
list_accounts_and_folders | Lista todas as contas sincronizadas e suas pastas |
get_recent_activity | N e-mails mais recentes com filtros opcionais (is_read, has_attachments, paginação) |
get_email_content | Texto completo do corpo, status de lido/respondido e lista de anexos para um único e-mail |
search_emails | Pesquisa de texto completo FTS5 com filtros de assunto/remetente/data/pasta/is_read/sent_by |
get_thread | Todos os e-mails no mesmo tópico de um e-mail específico, ordenados por data crescente |
download_attachments | Busca arquivos de anexo do IMAP e os salva em disco |
get_download_link | Gera uma URL de download HTTP temporária para anexos (fallback opcional) |
delete_mail | Exclusão suave de um e-mail movendo-o para uma pasta de lixeira configurada (IMAP MOVE, sem exclusão permanente) |
Visão Geral dos Recursos
- Banco de dados sombra local — e-mails são sincronizados em um banco de dados SQLite local; o agente de IA nunca se conecta diretamente ao seu servidor IMAP
- Sincronização somente leitura — o mecanismo de sincronização emite apenas comandos de leitura (
SELECT,UID FETCH); nenhumSTORE,APPENDouEXPUNGEé enviado ao seu servidor de e-mail - Sincronização incremental — busca apenas mensagens mais recentes que o último UID conhecido
- Pesquisa de texto completo — índice SQLite FTS5 para consultas rápidas de texto do corpo
- Multi-contas — sincronize qualquer número de contas IMAP simultaneamente
- IMAP IDLE — notificações push opcionais em tempo real; novos e-mails detectados em segundos em vez de esperar pelo próximo intervalo de polling
- Status de lido/respondido — flags
is_readeis_repliedsincronizadas do IMAP e expostas como filtros - Visualização de tópicos —
get_threadpercorre conversas de e-mail completas via cabeçalhosMessage-ID/In-Reply-To - Resultados paginados — todas as ferramentas de lista retornam
total_countpara que os agentes possam percorrer grandes conjuntos de resultados - Anexos sob demanda — arquivos de anexo são buscados do IMAP apenas quando explicitamente solicitados
- Transporte flexível —
stdiopara ferramentas locais (Claude Desktop),http(StreamableHTTP) oussepara implantações remotas e Docker - Pronto para Docker — imagem multi-arquitetura oficial (
linux/amd64,linux/arm64) publicada emghcr.ioa cada lançamento
Referência Completa de Configuração
sync_interval_min: 15
database:
path: "data/mail.db" # path to the local SQLite shadow database
attachment_dir: "data/attachments" # base directory for downloaded attachments
# Optional: log file and level. Omit log_file to write to stderr (default).
# log_file: "logs/mail-shadow-mcp.log" # append mode; directory is created automatically
# log_level: info # debug | info (default) | warn | error
# log_format: text # text (default) | json
# MCP transport mode.
# stdio (default) — stdin/stdout, used by Claude Desktop and most local tools.
# http — StreamableHTTP, recommended for Docker and remote deployments.
# sse — legacy SSE transport (prefer http unless your client requires SSE).
# transport: stdio
# http_addr: ":8080" # bind address for http/sse (default: :8080)
# http_base_url: "http://localhost:8080" # sse only: externally reachable base URL
# http_bearer_token: "" # recommended: set a secret token to protect the HTTP endpoint
# generate one with: openssl rand -hex 32
# Optional: lightweight HTTP server for temporary attachment download links.
# fileserver_port: 8787 # TCP port to listen on (disabled if omitted)
# fileserver_ttl_min: 15 # minutes before a link expires (default: 15)
# fileserver_host: "localhost" # hostname/IP shown in generated URLs
accounts:
- id: "work@example.com"
host: "imap.example.com"
port: 993
username: "work@example.com"
password: "$WORK_IMAP_PASS" # or plain text; prefix with $ to read from env var
tls_mode: tls # tls (default, implicit TLS, port 993)
# starttls (STARTTLS upgrade, port 143)
# none (no encryption — localhost/testing only)
tls_skip_verify: false # set true for self-signed certificates
folders: ["INBOX", "Archive"] # optional: omit to sync all folders
# idle_folders: ["INBOX"] # optional: folders watched via IMAP IDLE for instant new-mail notification
# trash_folder: "llm_delete" # optional: target folder for delete_mail (soft-delete via IMAP MOVE)
Docker Compose
services:
mail-shadow-mcp:
image: ghcr.io/dryas/mail-shadow-mcp:latest
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./config/config.yaml:/config/config.yaml:ro # your config — mount read-only
- ./data:/data # persistent DB + attachments
environment:
- WORK_IMAP_PASS=your_password_here # referenced as $WORK_IMAP_PASS in config
Senhas como variáveis de ambiente: Em
config.yamlvocê pode referenciar senhas como$ENV_VAR— o servidor as resolve na inicialização. Passe-as viaenvironment:no docker-compose ou via-ecomdocker run. Dessa forma, nenhuma senha em texto simples acaba no arquivo de configuração.
Modos TLS
tls_mode | Porta | Descrição |
|---|---|---|
tls | 993 | TLS implícito (padrão) |
starttls | 143 | Atualização STARTTLS |
none | 143 | Sem criptografia — apenas localhost/testes |
Defina tls_skip_verify: true para aceitar certificados autoassinados.
Autenticação (Token Bearer)
Ao usar o transporte http ou sse, sempre defina http_bearer_token — caso contrário, o endpoint MCP fica acessível a qualquer pessoa que possa acessar a porta.
Gere um token criptograficamente seguro:
# Linux / macOS / WSL
openssl rand -hex 32
# PowerShell
[System.Convert]::ToBase64String((1..32 | ForEach-Object { [byte](Get-Random -Max 256) }))
IMAP IDLE (Push em Tempo Real)
Por padrão, o mail-shadow-mcp verifica novas mensagens a cada sync_interval_min minutos. Para pastas onde você deseja notificações quase instantâneas, habilite o IMAP IDLE:
accounts:
- id: "work@example.com"
# ...
idle_folders: ["INBOX"] # IDLE runs on top of regular polling
- Uma conexão IMAP dedicada é aberta por entrada em
idle_folders - Quando o servidor envia uma notificação
EXISTS, uma sincronização é acionada imediatamente - A verificação periódica continua inalterada para todas as outras pastas
- Recorre automaticamente à verificação periódica se o servidor não suportar IDLE
- Backoff exponencial (30 s → 5 min) em erros persistentes de conexão
Servidor de Download de Anexos
O servidor HTTP integrado opcional permite que o agente de IA gere links de download temporários e de uso único para arquivos de anexo — útil como alternativa quando o agente não consegue transferir arquivos pelos canais normais.
Ative-o em config.yaml:
fileserver_port: 8787 # TCP port to listen on
fileserver_ttl_min: 15 # minutes before a link expires (default: 15)
fileserver_host: "localhost" # hostname/IP shown in generated URLs
Compilação a partir do Código-Fonte
make build # current platform
make release # cross-compile for all platforms into dist/
Requer Go 1.25+.
Comandos CLI
Além de funcionar como um servidor MCP, o mail-shadow-mcp expõe alguns comandos CLI úteis para operações manuais, scripts ou depuração — sem precisar de um agente de IA.
Disparar uma sincronização única (busca novos e-mails no banco de dados local e sai):
./mail-shadow-mcp sync
Consultar o banco de dados local (a saída é JSON delimitado por novas linhas, adequado para pipelines jq):
# Search by subject and body keyword
./mail-shadow-mcp query --subject "invoice" --body "Q1"
# Full-text search with attachment filter
./mail-shadow-mcp query -q "budget" --attachments only
# Most recent emails, paginated
./mail-shadow-mcp query --recent --limit 10 --offset 10
Baixar anexos de um e-mail específico pelo seu ID (formato account:folder:uid):
./mail-shadow-mcp attachments --id "work@example.com:INBOX:42"
Licença
Apache 2.0 — consulte LICENSE para obter detalhes.
Copyright (c) 2026 Benjamin Kaiser.