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

mail-shadow-mcp logo

Build Latest Release Go Version Go Report Card License

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":

  1. 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.
  2. 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.
  3. 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:

  1. O servidor MCP procura o e-mail no banco de dados local.
  2. Ele abre uma conexão IMAP de curta duração e executa IMAP MOVE — movendo a mensagem para a trash_folder que você especifica em config.yaml (por exemplo, "llm_delete").
  3. 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.
  4. 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

FerramentaDescrição
list_accounts_and_foldersLista todas as contas sincronizadas e suas pastas
get_recent_activityN e-mails mais recentes com filtros opcionais (is_read, has_attachments, paginação)
get_email_contentTexto completo do corpo, status de lido/respondido e lista de anexos para um único e-mail
search_emailsPesquisa de texto completo FTS5 com filtros de assunto/remetente/data/pasta/is_read/sent_by
get_threadTodos os e-mails no mesmo tópico de um e-mail específico, ordenados por data crescente
download_attachmentsBusca arquivos de anexo do IMAP e os salva em disco
get_download_linkGera uma URL de download HTTP temporária para anexos (fallback opcional)
delete_mailExclusã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); nenhum STORE, APPEND ou EXPUNGE é 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_read e is_replied sincronizadas do IMAP e expostas como filtros
  • Visualização de tópicos — get_thread percorre conversas de e-mail completas via cabeçalhos Message-ID / In-Reply-To
  • Resultados paginados — todas as ferramentas de lista retornam total_count para 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 — stdio para ferramentas locais (Claude Desktop), http (StreamableHTTP) ou sse para implantações remotas e Docker
  • Pronto para Docker — imagem multi-arquitetura oficial (linux/amd64, linux/arm64) publicada em ghcr.io a 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.yaml você pode referenciar senhas como $ENV_VAR — o servidor as resolve na inicialização. Passe-as via environment: no docker-compose ou via -e com docker run. Dessa forma, nenhuma senha em texto simples acaba no arquivo de configuração.

Modos TLS

tls_modePortaDescrição
tls993TLS implícito (padrão)
starttls143Atualização STARTTLS
none143Sem 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.