MCP Emails

Servidor de e-mail hospedado para Gmail, Fastmail, iCloud, Yahoo, Zoho, Yandex e qualquer caixa de correio IMAP/SMTP: leia, pesquise, envie, organize, rascunhe e agende e-mails de qualquer cliente MCP, buscados ao vivo e nunca armazenados. Documentação em https://mcpemails.com/docs

Documentação

MCPEmails

Dê uma caixa de entrada ao seu agente de IA. Um servidor hospedado de Model Context Protocol que permite ao Claude, Cursor ou qualquer cliente compatível com MCP ler, pesquisar, enviar, organizar e agendar e-mails através das suas caixas de entrada existentes — sem nunca armazenar seus e-mails.

Glama quality grade npm version MCP registry License: AGPL-3.0

Conecte uma caixa de entrada uma vez, cole uma URL no seu agente, e ele poderá trabalhar na sua caixa de entrada ao vivo. Os e-mails são buscados sob demanda e nunca retidos; as credenciais são criptografadas em repouso e descriptografadas apenas no momento da chamada, dentro de uma função de borda isolada.

🔗 mcpemails.com · 📚 Documentação · 💳 Preços


Conteúdo


Como funciona

  1. Conecte uma caixa de entrada. Entre em mcpemails.com e conecte Outlook / Microsoft 365 (Entrar com Microsoft, via Microsoft Graph), Gmail (uma senha de aplicativo do Google via IMAP por padrão, ou Entrar com Google), ou qualquer conta IMAP/SMTP (senha de aplicativo). As credenciais são criptografadas com AES‑256‑GCM antes de tocarem o banco de dados.
  2. Obtenha acesso. Clientes compatíveis com OAuth (claude.ai, Claude Desktop, Cursor) conectam-se com um clique via OAuth 2.0 + PKCE. Todo o resto usa uma chave de API com escopo (mcpe_…).
  3. Aponte seu cliente para o servidor. O endpoint MCP é uma única URL:
    https://mcpemails.com/api/mcp
    
  4. Seu agente trabalha na caixa de entrada. Ele chama ferramentas como inbox_list, email_read (action: "search"), email_compose (action: "send") e schedule (action: "create"). Cada requisição busca dados ao vivo do seu provedor — nada é espelhado ou armazenado em cache no servidor.

As permissões são definidas por chave, então você pode dar a um agente apenas read:email, ou conceder envio e gerenciamento de pastas sem nunca expor a exclusão.

Início rápido (conectando um agente)

Claude Desktop / Cursor (OAuth): adicione um servidor MCP remoto apontando para https://mcpemails.com/api/mcp e aprove a tela de consentimento. Escolha os escopos que o agente deve ter.

Chave de API (qualquer cliente MCP): crie uma chave no painel, escolha seus escopos e (opcionalmente) restrinja-a a caixas de entrada específicas, depois envie-a como um token de portador:

// Example MCP client config
{
  "mcpServers": {
    "mcpemails": {
      "url": "https://mcpemails.com/api/mcp",
      "headers": { "Authorization": "Bearer mcpe_your_key_here" }
    }
  }
}

O protocolo é JSON‑RPC 2.0 sobre HTTP (MCP 2025-06-18, transporte Streamable). Inicie cada sessão com inbox_list — ele retorna as caixas de entrada que a chave pode acessar, seus recursos por provedor e um perfil de compatibilidade versionado. O perfil marca operações normalizadas como exact, different ou unavailable, para que os agentes possam preservar diferenças entre provedores em vez de enfraquecer silenciosamente uma requisição.

Guias de configuração

Instruções de copiar e colar por cliente, incluindo onde cada um guarda seu arquivo de configuração: mcpemails.com/docs/clients.

Claude · Claude Code · ChatGPT · Cursor · VS Code · Cline · Windsurf · Gemini CLI · Zed · JetBrains · Raycast · Warp · curl

Recursos

  • Ao vivo, nunca armazenado — os e-mails são lidos diretamente do seu provedor a cada chamada; nenhum corpo de mensagem é persistido.
  • Multi-provedor — Outlook / Microsoft 365 via Microsoft Graph (Entrar com Microsoft), Gmail via senha de aplicativo do Google ou Entrar com Google, além de qualquer caixa de entrada IMAP/SMTP (Fastmail, iCloud, Yahoo, Zoho, Yandex, auto-hospedada…) via senha de aplicativo.
  • Sem relay — e-mails de saída são enviados pelo SMTP/API do seu provedor, do seu endereço real.
  • Escopos granulares — oito escopos de permissão, concedíveis independentemente por chave de API e por caixa de entrada.
  • Lote e busca-e-ação — leia, mova, exclua ou sinalize até centenas de mensagens em uma única chamada, incluindo combinadores de "buscar e mover/excluir".
  • Rascunhos e agendamento — componha rascunhos e enfileire mensagens para envio futuro (despacho no servidor).
  • Busca independente de provedor — sintaxe do Gmail, KQL do Microsoft Graph e IMAP SEARCH são normalizados atrás de uma única interface email_read (action: "search").
  • Pronto para equipes: workspaces, membros, papéis, SSO e um log de auditoria no plano Team.

Ferramentas

17 ferramentas que você chama diretamente. A maioria é orientada a recursos e recebe um argumento action que seleciona a operação específica (e, para ações que precisam de privilégios diferentes, o escopo necessário):

  • inbox_list - Lista as caixas de entrada que a chave pode acessar, com os recursos de cada provedor.
  • email_read - Lista, lê e pesquisa mensagens, em lotes, além de anexos, texto extraído de anexos e o .eml original.
  • email_organize - Move, copia, sinaliza e arquiva mensagens que você identifica por id, individualmente ou em lotes.
  • email_search_and_move - Move todas as mensagens que correspondem a uma busca para uma pasta. É uma ferramenta própria, e a destrutiva, porque um filtro errado realoca uma caixa de entrada inteira.
  • email_delete - Envia para a lixeira ou exclui permanentemente mensagens, individualmente, em lotes ou por busca.
  • email_compose - Envia, responde e encaminha através do seu próprio provedor, do seu endereço real.
  • folder_list - Lista pastas (rótulos no Gmail) com seus IDs nativos do provedor e contagens de mensagens. Somente leitura.
  • folder - Cria, renomeia e exclui pastas (rótulos no Gmail).
  • draft_list - Lista os rascunhos salvos na caixa de entrada, com seus IDs de rascunho. Somente leitura.
  • draft - Cria, atualiza, envia e exclui rascunhos, incluindo respostas nativas do provedor.
  • schedule_list - Lista o que está enfileirado para entrega futura. Somente leitura.
  • schedule - Enfileira uma mensagem para entrega futura e cancela uma que esteja enfileirada.
  • signature_get - Lê a assinatura e o nome do remetente configurados para uma caixa de entrada. Somente leitura.
  • signature_set - Define a assinatura anexada a e-mails de saída e o nome do remetente.
  • automation_read - Lista regras de triagem, lê uma, mostra histórico de execução e faz teste seco de um filtro. Somente leitura.
  • automation - Cria, atualiza, ativa, desativa e exclui regras de triagem automática, sem modelo no loop.
  • contact_search - Consulta contatos escaneando e-mails recentes ao vivo, sem lista de endereços armazenada.
FerramentaAçõesEscopo(s)
inbox_list(ação única)read:email
email_readlist, read, read_batch, search, attachment, extract, originalread:email (search também aceita search:email)
email_organizemove, move_batch, copy, copy_batch, flag, archivemanage:folders
email_search_and_move(ação única)manage:folders
email_deletedelete, delete_batch, search_and_deletedelete:email
email_composesend, reply, forwardsend:email
folder_list(ação única)read:email
foldercreate, rename, deletemanage:folders
draft_list(ação única)manage:drafts
draftcreate, reply, update, send, deletemanage:drafts (criar/responder/atualizar/excluir), read:email (responder também), send:email (enviar)
schedule_list(ação única)schedule:email
schedulecreate, cancelschedule:email
signature_get(ação única)read:email
signature_set(ação única)send:email
automation_readlist, get, runs, previewmanage:automations
automationcreate, update, enable, disable, deletemanage:automations
contact_search(ação única)manage:contacts (também aceita read:email)

Uma chave com escopo total vê 22 ferramentas em tools/list: as 16 acima mais seis ferramentas exclusivas do aplicativo (approval_review, approval_decide, approval_update, approval_schedule, bulk_execute, bulk_cancel). Elas carregam _meta.ui.visibility: ["app"] e conduzem o cartão de revisão que um cliente MCP renderiza para um envio retido ou uma operação em lote pré-visualizada, em vez de serem compostas manualmente.

Observações:

  • As ferramentas aceitam um inbox_id explícito (UUID) ou um endereço de e-mail inbox; chaves de caixa única resolvem o destino automaticamente.
  • Ações em lote têm limite de 50 (email_read's read_batch) a 500 (mover/excluir/sinalizar) mensagens por chamada.
  • Para uma mutação direcionada, primeiro use email_read com action: "search", depois passe o message_id ou message_ids retornado para email_organize ou email_delete. Campos de busca são aceitos apenas por email_search_and_move e pela ação search_and_delete de email_delete.
  • contact_search escaneia e-mails recentes ao vivo, então não há lista de endereços armazenada.
  • A ação original de email_read retorna uma mensagem MIME completa armazenada no provedor como um arquivo .eml portátil (até 25 MB). É somente leitura e nunca marca a mensagem como lida.
  • A ação send de draft exige send:email, não manage:drafts, para que uma chave que só pode gerenciar rascunhos não possa usá-los para contornar o consentimento de envio de e-mail.
  • A ação reply de draft cria uma resposta não enviada, nativa do provedor, na conversa de origem. Ela precisa de manage:drafts e read:email, e por padrão responde apenas ao remetente.
  • As metades somente leitura (folder_list, draft_list, schedule_list, signature_get, automation_read) foram separadas de suas ferramentas de escrita em 2026-09-09, para que uma chave somente leitura nunca veja uma ferramenta de escrita. As formas antigas combinadas (folder action: "list", draft action: "list", schedule action: "list", signature action: "get"/"set", automation action: "list"/"get"/"runs"/"preview") ainda são aceitas na rede para clientes já conectados, mas não são mais anunciadas.
  • automation gerencia regras de triagem agendadas e automáticas: uma busca armazenada mais uma ação fixa, avaliadas em uma cadência sem modelo no loop. Não há ação de excluir e-mail, um forward sempre aguarda aprovação humana, e draft_reply apenas escreve um rascunho. Veja docs/automations-trust-boundary.md.
  • tools/list retorna apenas as ferramentas para as quais sua chave (ou token OAuth) realmente tem escopo.

Escopos OAuth

EscopoConcessões
read:emailListar caixas de entrada e pastas; listar, ler e pesquisar mensagens; ler a assinatura de uma caixa de entrada; consultar contatos
search:emailAlternativa mais restrita que concede apenas a ação search de email_read
send:emailEnviar, responder e encaminhar; definir a assinatura e o nome do remetente; também necessário para enviar um rascunho
manage:foldersCriar/renomear/excluir pastas; mover, copiar, sinalizar e arquivar mensagens
delete:emailMover para a lixeira ou excluir permanentemente mensagens
manage:draftsCriar, editar e excluir rascunhos (enviar um também requer send:email)
manage:contactsConsulta de contatos ao vivo a partir de e-mails recentes
schedule:emailEnfileirar mensagens para entrega futura
manage:automationsCriar e gerenciar regras de triagem agendadas sem supervisão (sem ação de exclusão; encaminhamentos permanecem sujeitos a aprovação)

Provedores suportados

ProvedorConectar viaLer/PesquisarEnviarPastasExclusão permanenteRascunhos
Gmail / Google WorkspaceSenha de aplicativo (IMAP/SMTP) por padrão, ou OAuth 2.0 (Entrar com o Google)✅✅RótulosSomente lixeira✅
FastmailSenha de aplicativo (IMAP/SMTP)✅✅✅✅✅
iCloud, Yahoo, AOL, GMX, Zoho, YandexSenha de aplicativo (IMAP/SMTP)✅✅✅✅✅
IONOS, STRATO, One.com, OVHcloud, Namecheap Private Email, Hostinger, Infomaniak, HetznerSenha da caixa de correio (IMAP/SMTP)✅✅✅✅✅
cPanel, Plesk, SiteGround, Bluehost e outros hosts compartilhadosSenha da caixa de correio (IMAP/SMTP)✅✅✅✅✅
Qualquer outra caixa de correio IMAP/SMTPSenha de aplicativo ou senha da caixa de correio✅✅✅✅✅

E-mails no seu próprio domínio em um host da web conectam-se como qualquer caixa de correio IMAP, e um workspace pode conter várias delas (info@, sales@, support@). Configurações por host e armadilhas conhecidas para 100 provedores estão em mcpemails.com/connect. | Outlook / Microsoft 365 | OAuth 2.0 (Microsoft Graph) | ✅ | ✅ | ✅ (aninhadas) | ✅ | ✅ |

O Outlook usa o Microsoft Graph com "Entrar com a Microsoft", não IMAP. Contas pessoais da Microsoft (outlook.com, hotmail.com, live.com, msn.com) conectam-se diretamente. Em locatários do Microsoft 365 de trabalho ou escola, a política de consentimento padrão da Microsoft impede que os funcionários aprovem permissões de e-mail por conta própria, então um administrador de TI aprova o aplicativo uma vez para a organização; o painel fornece ao usuário um link de aprovação compartilhável para enviar a eles (/auth/outlook/admin-consent), e o administrador não precisa de uma conta MCP Emails. Uma conta da Microsoft sem caixa de correio Exchange Online é recusada, com uma indicação para IMAP. As ferramentas de rótulos são exclusivas do Gmail (o Outlook usa pastas), exceto que a ação de rótulo de uma automação aplica uma categoria do Outlook; e o Graph não pode combinar uma pesquisa de texto com os filtros de não lido, anexo, sinalizado ou data.

Preços

A métrica de valor é caixas de entrada conectadas. O plano Gratuito conecta uma caixa de correio, o Pessoal conecta até três, o Pro conecta todas as caixas de correio que você possui, e o Team adiciona pessoas, funções e um workspace separado por cliente. A cobrança anual economiza cerca de 20%.

GratuitoPessoalProTeam
Preço$0$9/mês · $86,40/ano ($7,20/mês)$15/mês · $144/ano ($12/mês)$79/mês · $756/ano ($63/mês)
Caixas de entrada conectadas13IlimitadasIlimitadas
Ações de e-mail / mês150 (primeiros 7 dias não contados)Sem limite mensal (uso justo)Sem limite mensal (uso justo)Sem limite mensal (uso justo)
Chaves de APIIlimitadasIlimitadasIlimitadasIlimitadas
Membros1 (somente proprietário)1 (somente proprietário)1 (somente proprietário)Ilimitados, com funções
Limite de taxa de uso justo60 req/min120 req/min300 req/min1.000 req/min
Funções e workspaces do TeamNãoNãoNão✅
SSO (SAML/OIDC) + log de auditoriaNãoNãoNão✅
SuporteComunidadeE-mailE-mailPrioritário

Limites por chave de API também se aplicam (100 req/min · 1.000/h · 10.000/dia). Os limites de taxa são repetíveis: eles retornam como erro JSON-RPC -32003 com data.retry_after em segundos.

Workspaces gratuitos recebem 150 ações de e-mail por mês calendário (UTC). Os primeiros 7 dias após o cadastro não são contados, e inbox_list e o painel nunca são contados. Quando a cota é atingida, todas as outras ações de e-mail são recusadas até o dia 1º do próximo mês, automações sem supervisão pausam e retomam automaticamente no dia 1º, e o proprietário recebe um e-mail em 80% e em 100%. Pessoal, Pro e Team não têm limite mensal, sujeito a uso justo (seus tetos são proteções contra abuso, não recursos do plano, e não são exibidos em lugar nenhum). Uma recusa não é repetível e não é um erro JSON-RPC: ela retorna como um resultado de ferramenta normal com isError: true, texto que abre com a contagem e a data de redefinição, e um bloco _meta["com.mcpemails/usage_limit"] que limpa em reset_at.

Os IDs internos de plano são anteriores aos nomes: solo é vendido como Pro e pro é vendido como Team. O ID mais novo personal é o único que corresponde ao seu nome de exibição, Pessoal. Todo usuário que existia antes do reajuste de 2026-08-19 mantém caixas de entrada ilimitadas gratuitamente, permanentemente, e todo workspace criado antes do lançamento da cota de ações em 2026-09-12 é um membro inicial que não é medido contra ela. Veja apps/web/src/lib/stripe/plans.ts.

Arquitetura

flowchart LR
    Agent["MCP client<br/>(Claude, Cursor, …)"] -->|"JSON-RPC / OAuth or API key"| Web

    subgraph Vercel["Vercel — Next.js 16"]
      Web["/api/mcp route<br/>+ marketing site + dashboard"]
    end

    subgraph Supabase
      Edge["mcp-server<br/>edge function (Deno)"]
      DB[("Postgres<br/>RLS + encrypted creds")]
      Cron["token-refresh<br/>edge functions"]
    end

    Web -->|proxies| Edge
    Edge -->|decrypt creds, fetch live| Providers["Email providers<br/>Gmail API · Microsoft Graph · IMAP/SMTP"]
    Edge --> DB
    Cron --> DB
    Web --> Stripe[("Stripe<br/>billing")]
  • /api/mcp é um manipulador de rota fino do Next.js que faz proxy para a função de borda do Supabase mcp-server — a implementação real do MCP, onde as credenciais são descriptografadas e as chamadas ao provedor são feitas.
  • O banco de dados Postgres armazena workspaces, membros, caixas de entrada (tokens/senhas criptografados), chaves de API com hash, clientes OAuth, envios agendados e um log de atividades — tudo protegido por Segurança em Nível de Linha.
  • Funções de borda Cron atualizam tokens OAuth do Gmail/Outlook antes da expiração.

Stack: Next.js 16 (App Router) · React 19 · next‑intl 4 · Supabase (Auth, Postgres, Edge Functions) · Stripe · Resend · TypeScript. Análise/sanitização de e-mail via mailparser, jsdom e isomorphic-dompurify.

Estrutura do repositório

.
├── apps/
│   └── web/                     # Next.js 16 app (marketing, dashboard, /api/mcp proxy)
│       ├── app/                 # App Router routes ([locale], dashboard, api, auth)
│       ├── components/          # marketing/ + dashboard/ React components
│       ├── messages/            # next-intl translations (en, nb, es, fr, zh)
│       ├── src/lib/             # stripe/, supabase/, blog/, crypto helpers
│       └── proxy.ts             # middleware: i18n + Supabase session + CDN cache
├── supabase/
│   ├── functions/
│   │   ├── mcp-server/          # the MCP server (tools, auth, scopes)
│   │   ├── gmail-token-refresh/
│   │   └── outlook-token-refresh/
│   └── migrations/              # SQL migrations (schema + RLS)
└── package.json                 # npm workspaces (apps/*)

Desenvolvimento local

Pré-requisitos: Node.js 20+, npm e a CLI do Supabase (para migrações e funções de borda).

# 1. Install (npm workspaces — run from the repo root)
npm install

# 2. Configure environment
cp .env.example apps/web/.env.local
#   then fill in the values (see below) and generate the two secrets:
openssl rand -hex 32   # ENCRYPTION_KEY
openssl rand -hex 32   # CSRF_SECRET

# 3. Run the web app (http://localhost:3000)
npm run dev

# 4. Production build
npm run build

next.config.js valida as variáveis de ambiente necessárias no build/início e rejeita valores fracos de ENCRYPTION_KEY, então um ambiente mal configurado falha rapidamente em vez de em tempo de execução.

Variáveis de ambiente

Copie .env.example e preencha com valores reais. Necessário em todos os ambientes:

VariávelFinalidade
NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEYCliente Supabase (público)
SUPABASE_SERVICE_ROLE_KEYChave de administração do lado do servidor (ignora RLS) — secreta
NEXT_PUBLIC_APP_URLURL base canônica; orienta URIs de redirecionamento OAuth
GOOGLE_SITE_VERIFICATION (opcional)Token de verificação de tag HTML do Google Search Console; definir apenas em produção
ENCRYPTION_KEYChave AES‑256‑GCM de 64 hex para credenciais em repouso — secreta
CSRF_SECRETChave HMAC de 64 hex para tokens CSRF (distinta da acima) — secreta

Dependente de recurso:

Variável(is)Necessário para
GMAIL_CLIENT_ID / GMAIL_CLIENT_SECRETOAuth do Gmail (gmail.readonly, gmail.send, gmail.modify)
OUTLOOK_CLIENT_ID / OUTLOOK_CLIENT_SECRET / OUTLOOK_TENANT_IDOAuth do Outlook (Mail.ReadWrite, Mail.Send, offline_access, openid, profile, email). OUTLOOK_TENANT_ID é opcional e o padrão é common
NEXT_PUBLIC_OAUTH_VERIFICATION_PENDINGMostra o aviso de aplicativo não verificado até que a verificação do Google seja concluída (o editor da Microsoft já está verificado)
STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRET / NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYCobrança
STRIPE_PRICE_PERSONAL_MONTHLY / _YEARLY, STRIPE_PRICE_SOLO_MONTHLY / _YEARLY, STRIPE_PRICE_PRO_MONTHLY / _YEARLYIDs de preço do plano (personal = Pessoal, solo = Pro, pro = Team)
STRIPE_WEBHOOK_PROXY_KEYOpcional. Restringe /api/stripe/webhook à fila de entrega à sua frente. Não definido = sem restrição. Defina-o apenas DEPOIS que a fila estiver enviando a chave, ou cada entrega falhará com 401 e será enviada para a fila de mensagens mortas.
STRIPE_WEBHOOK_TOLERANCE_SECONDSOpcional. Limite de idade da assinatura do Stripe, padrão de 7 dias. Amplo porque uma reprodução enfileirada carrega sua assinatura original; o padrão de 300s do próprio Stripe rejeitaria todas as tentativas retidas.

Fastmail e outros provedores IMAP conectam-se via senha de aplicativo e não precisam de credenciais OAuth.

Webhooks do Stripe são entregues por meio de uma fila. O Stripe publica no ingress do Queuey, que encaminha para /api/stripe/webhook. Duas configurações nessa fila são essenciais: o payload deve ser passagem bruta (a assinatura é sobre bytes exatos), e um cabeçalho mapeado deve encaminhar header:Stripe-Signature. Sem o cabeçalho mapeado, cada entrega falha com Missing stripe-signature header.. Observe que STRIPE_WEBHOOK_SECRET deve ser o segredo de assinatura do endpoint do Stripe apontado para o ingress, não de qualquer endpoint direto mais antigo.

Banco de dados e migrações

O esquema e as políticas de Segurança em Nível de Linha estão em supabase/migrations/. Tabelas principais: workspaces, workspace_members, inboxes (credenciais criptografadas, com exclusão suave), api_keys (com hash, com escopo, restrito à caixa de entrada), oauth_clients, scheduled_sends, workspace_invites e um activity_log particionado por mês.

# Apply one migration to the linked project, then record it in the history
npx supabase db query --linked -f supabase/migrations/<file>.sql
npx supabase migration repair --status applied <version> --linked

# Regenerate TypeScript types from the live schema
npm run gen:types

A CLI do Supabase é a fonte da verdade para alterações no banco de dados neste projeto.

apps/web/src/types/database.types.ts é GERADO

Ele é escrito integralmente por npm run gen:types (supabase gen types typescript --linked), que lê o projeto vinculado ao vivo, não os arquivos de migração. Não o edite manualmente: uma coluna adicionada manualmente é silenciosamente descartada na próxima regeneração, e uma coluna adicionada manualmente que nunca existiu no banco de dados compila limpa e retorna 500 em produção. Regere-o na mesma alteração que aplica uma migração e confirme o resultado.

Tabelas, visualizações e funções RPC são todas cobertas, e cada cliente Supabase declarado no .ts/.tsx de apps/web (que é todo o programa verificado por tipos) é SupabaseClient<Database>, então .from(), .select(), .insert() e .rpc() são verificados por tipos contra o esquema real. Se uma tabela ou coluna parecer ausente, a correção é npm run gen:types, nunca um as any local no cliente Supabase. As conversões que permanecem são para coisas que o gerador genuinamente não pode expressar: formas de payload jsonb, argumentos de função anuláveis e um auxiliar que despacha muitos RPCs por meio de uma única assinatura. Cada um desses carrega um comentário dizendo isso.

O qualificador .ts/.tsx é essencial. apps/web/tsconfig.json não define checkJs e seu include é **/*.ts e **/*.tsx, então um arquivo .js como app/dashboard/[[...section]]/page.js está fora do programa inteiramente: seus tipos JSDoc @param são documentação e nada os verifica. Eles são escritos como SchemaTypedClient (um @typedef para SupabaseClient<Database>) para que a documentação pelo menos concorde com o que os chamadores passam, mas mantê-lo honesto é um trabalho manual.

Nunca escreva um SupabaseClient puro. Sem um argumento de tipo, ele resolve para SupabaseClient<any, "public", any>, que é um as any que nenhum grep por as any encontrará: uma função declarada db: SupabaseClient não recebe verificação de coluna alguma, e uma coluna inexistente em um .insert() compila limpa. SupabaseClient<any> é o mesmo buraco escrito por extenso, e também SupabaseClient<any | Database> e SupabaseClient<Alias> onde o alias é any. apps/web/eslint.config.mjs portanto não caça por any; ele exige Database, e npm run lint gera erro em qualquer referência de tipo SupabaseClient que não o carregue, além de um createServerClient(...) / createBrowserClient(...) não parametrizado. Esses são seletores sintáticos (o repositório não executa linting com verificação de tipos), então eles correspondem à grafia no local de uso e três coisas poderiam, de outra forma, passar direto por eles: import { SupabaseClient as SB }, import * as Supa e depois Supa.SupabaseClient, e const mk = createServerClient; mk(...). Nenhum seletor consegue enxergar através de qualquer um deles, então a configuração os fecha um nível acima: renomear o import de SupabaseClient e fazer import de namespace de @supabase/ssr ou @supabase/supabase-js são, por si só, erros, e no-restricted-imports mantém createClient / createServerClient / createBrowserClient fora de cada arquivo, exceto os wrappers em src/lib/supabase/, que são o único lugar que constrói um cliente e sempre passa <Database>. Todo o resto importa esses wrappers.

As regras não estão limitadas a **/*.ts(x), então as restrições de import e chamada se aplicam também em .js/.jsx/.mjs. O que elas não conseguem fazer lá é ler um tipo JSDoc: um seletor sintático não vê nenhum nó de AST para ele. Esse é o limite conhecido acima, não uma lacuna que as regras fingem cobrir.

Duas coisas que um tsc verde ainda não te diz:

  • --linked lê produção, não supabase/migrations/. O que o projeto ativo realmente tem é o que chega no arquivo, incluindo divergências, e uma migração que existe localmente mas não foi enviada é invisível para ele. Regenerar exige credenciais do projeto vinculado, então CI não consegue reproduzir este arquivo apenas a partir do repositório. Verifique supabase migration list --linked antes de acreditar que os tipos descrevem o que as migrações dizem. Em 2026-09-16, esse comando relata oito divergências em ambas as direções.
  • Um cast ainda desativa a verificação. (row as any).some_column e client as unknown as SupabaseClient<Database> compilam qualquer coisa que você escrever. As regras de lint acima pegam a declaração do cliente, não um cliente que é convertido para any no local da chamada; @typescript-eslint/no-explicit-any é o que pega esses casos, e um eslint-disable nele é uma escolha deliberada que deveria explicar o porquê.

Implantação

Aplicativo web → Vercel (projeto mcp-emails-web):

vercel --prod --yes

Cabeçalhos de segurança e timeouts de função são definidos em vercel.json. As rotas de marketing são servidas com um Cache-Control armazenável em cache de CDN (definido em proxy.ts) para que rastreadores e visitantes recorrentes atinjam o cache de borda; o dashboard, autenticação e rotas de API permanecem no-store.

Servidor MCP → função de borda Supabase:

npx supabase functions deploy mcp-server --project-ref <your-project-ref> --no-verify-jwt

Migrações primeiro, função depois. PostgREST não retorna undefined para uma coluna que ele não conhece — ele gera erro — e a projeção de caixa de entrada compartilhada do servidor (INBOX_SELECT_COLUMNS) é usada por todas as ferramentas de e-mail, que leem um erro de consulta como "caixa de entrada não encontrada". Implantar a função antes da migração pode, portanto, derrubar toda a superfície de e-mail, não apenas o recurso que queria a nova coluna. Colunas de caixa de entrada recém-migradas são deliberadamente lidas em suas próprias consultas pequenas (readSendReviewMode, readBulkReviewMode, readInboxDraftEditorHidden) para que uma implantação fora de ordem degrade apenas aquele recurso em vez de quebrar tudo — isso é uma rede de segurança, não uma licença para pular a ordem.

Autohospedagem

Não quer confiar seu e-mail ao serviço hospedado? Execute o mesmo servidor MCP na sua própria máquina. self-host/ entrega uma stack conteinerizada (Postgres + PostgREST + o servidor Deno, sem Supabase/Stripe/dashboard), então suas credenciais são criptografadas com uma chave que só você possui e descriptografadas apenas dentro do seu próprio contêiner.

cd self-host
make setup      # generate secrets (.env)
make up         # build + start the stack
export IMAP_PASSWORD='your-app-password'
make provision EMAIL=you@example.com IMAP_HOST=imap.fastmail.com SMTP_HOST=smtp.fastmail.com SERVICE=fastmail
make key NAME="my agent"   # mint an mcpe_ key, then point your client at http://localhost:8787

É IMAP/SMTP-first (Fastmail, iCloud, Yahoo, Zoho, Yandex, genérico) via senha de aplicativo; OAuth Gmail/Outlook e o dashboard web permanecem apenas hospedados (Outlook também exigiria seu próprio registro de aplicativo Microsoft Entra). O contêiner executa supabase/functions/mcp-server/ sem modificações; veja self-host/README.md para o guia completo.

Internacionalização

Construído com next‑intl (localePrefix: 'as-needed', localeDetection: false para URLs canônicas estáveis). Inglês é servido em /; outros idiomas têm um prefixo (/nb, /es, /fr, /zh). As traduções ficam em apps/web/messages/.

Idiomas suportados: Inglês, Norueguês Bokmål, Espanhol, Francês, Chinês (Simplificado).

Modelo de segurança

  • Credenciais criptografadas em repouso com AES‑256‑GCM; descriptografadas apenas dentro da função de borda no momento da chamada.
  • Sem armazenamento de mensagens — corpos de e-mail e anexos são buscados ao vivo e nunca persistidos. A extração de texto de anexos é executada de forma transitória na requisição e não retorna bytes brutos de anexos.
  • Chaves de API são hashadas (apenas um prefixo é armazenado para exibição) e limitadas por permissão e por caixa de entrada, com expiração opcional.
  • OAuth 2.0 + PKCE para autorização de clientes; Registro Dinâmico de Clientes (RFC 7591) para clientes MCP.
  • Segurança em Nível de Linha isola os dados de cada workspace na camada do banco de dados.
  • CSP estrito, HSTS, X-Frame-Options: DENY e cabeçalhos relacionados em cada resposta.

Licença

MCP Emails é open source sob a GNU Affero General Public License v3.0 (AGPL‑3.0). O serviço hospedado em mcpemails.com executa o mesmo servidor que você pode autohospedar, então você pode ler o código, verificá-lo e executá-lo você mesmo. Veja /security para o modelo de confiança.


Envie e receba e-mails de qualquer agente. © MCPEmails, AGPL‑3.0.