icloud-mcp
MCP stdio para iCloud Calendar com Contatos e Mail opcionais
Documentação
icloud-mcp
Acesse Calendário, Contatos e E-mail do iCloud através do Model Context Protocol. Um único binário Go serve JSON-RPC via stdio e conecta-se por CalDAV, CardDAV, IMAP e SMTP.
O servidor opera sem interface gráfica, usando senhas específicas de app. Ele utiliza protocolos remotos, sem frameworks macOS, automação de navegador ou APIs privadas da Apple. Os arquivos de lançamento suportam Linux amd64/arm64 e macOS arm64. O CI também compila para Windows amd64.
Qualquer host MCP com stdio pode iniciar o binário com as variáveis de ambiente do processo.
O binário não carrega .env nem arquivos de configuração específicos do host.
| Domínio | Protocolo | Padrão |
|---|---|---|
| Calendário | CalDAV HTTPS | Sempre ativo (leitura + escrita, exceto em modo somente leitura global) |
| Contatos | CardDAV HTTPS | Desativado até ICLOUD_MCP_ENABLE_CONTACTS |
| Leitura de e-mail | IMAP TLS | Desativado até ICLOUD_MCP_ENABLE_MAIL |
| Mutação de e-mail | IMAP | Desativado até E-mail + ICLOUD_MCP_ENABLE_MAIL_WRITE |
| Envio de e-mail | SMTP STARTTLS | Desativado até E-mail + ICLOUD_MCP_ENABLE_MAIL_SEND + política de destinatários |
Lembretes, Notas, Fotos, Drive, Buscar, Chaves, Mensagens e Casa estão fora do escopo suportado. Lembretes modernos não usam o conector CalDAV deste servidor.
Início rápido
Use Go 1.26.0 ou posterior:
go install github.com/ThomasCrouzet/icloud-mcp/cmd/icloud-mcp@latest
- Crie uma senha específica de app. Nunca use a senha principal da Conta Apple.
- Armazene a identidade e a senha em arquivos regulares separados, fora do repositório.
- Dê a cada arquivo modo
0600ou mais restritivo e um tamanho máximo de 4 KiB. - Defina o ambiente para acesso somente leitura ao Calendário:
export ICLOUD_EMAIL='file:///private/path/icloud-email'
export ICLOUD_PASSWORD='file:///private/path/icloud-password'
export ICLOUD_MCP_READ_ONLY=true
export ICLOUD_MCP_DEFAULT_TZ=Europe/Paris # owner IANA zone; default UTC
- Registre o caminho absoluto do binário e o ambiente no seu host MCP.
- Reinicie o processo MCP após alterações de configuração.
Stdio transporta JSON-RPC. Stderr transporta logs e eventos de auditoria de mutação. O servidor lê os arquivos de credenciais apenas na inicialização. A descoberta do Calendário exige acesso à rede antes do início do stdio.
Esta configuração expõe 7 ferramentas: leituras de Calendário, auxiliares locais e
icloud_capabilities. O processo não constrói um cliente de Contatos ou E-mail.
Domínios opcionais (ainda na forma export agnóstica de host):
# Contacts reads (writes also need ICLOUD_MCP_READ_ONLY=false)
export ICLOUD_MCP_ENABLE_CONTACTS=true
# Mail reads: IMAP identity may differ from ICLOUD_EMAIL (e.g. name@icloud.com)
export ICLOUD_MCP_ENABLE_MAIL=true
export ICLOUD_MAIL_ADDRESS='file:///private/path/icloud-mail-address'
# Optional separate password; otherwise Mail uses ICLOUD_PASSWORD.
# export ICLOUD_MAIL_PASSWORD='file:///private/path/icloud-mail-password'
# Mail mutation (flags / move / trash); independent of send
export ICLOUD_MCP_ENABLE_MAIL_WRITE=true
export ICLOUD_MCP_READ_ONLY=false
# Mail send: requires exact recipient allowlist even under global read-only
export ICLOUD_MCP_ENABLE_MAIL_SEND=true
export ICLOUD_MCP_SMTP_ALLOWED_RECIPIENTS='alice@example.com,bob@example.net'
Consulte .env.example para o contrato completo de 12 variáveis.
Ferramentas MCP
O servidor expõe no máximo 23 ferramentas. Ferramentas desativadas estão ausentes de
tools/list. O processo não constrói clientes para domínios desativados.
| Contagem | Quando |
|---|---|
| 10 | Padrão: leitura+escrita de Calendário + icloud_capabilities |
| 7 | Somente leitura global, domínios opcionais desativados (recomendado para a primeira execução) |
| 23 | Contatos + leitura de E-mail + mutação + envio, somente leitura desativado |
ICLOUD_MCP_READ_ONLY=true remove todas as escritas de Calendário/Contatos, toda mutação
de E-mail e o envio de E-mail. Ele não ativa um domínio de leitura desativado.
| Grupo | Ferramentas |
|---|---|
| Global | icloud_capabilities |
| Leitura de Calendário | list_calendars, search_events, get_event, find_free_slots, validate_event, calendar_capabilities |
| Escrita de Calendário | create_event, update_event, delete_event |
| Leitura de Contatos | list_address_books, search_contacts, get_contact |
| Escrita de Contatos | create_contact, update_contact, delete_contact |
| Leitura de E-mail | list_mailboxes, search_messages, get_message |
| Mutação de E-mail | set_message_flags, move_message, trash_message |
| Envio de E-mail | send_message |
As operações de atualização e exclusão de Calendário suportam ocorrências e usam
If-Match forte. Contatos usa IDs de livro opacos e grava vCard 3.0.
E-mail usa identidades (mailbox, UIDVALIDITY, UID), leituras PEEK e uma política de
destinatários exata para SMTP. set_message_flags falha de forma segura com
protocol_error quando CONDSTORE é anunciado. Isso ocorre porque o go-imap
beta.8 não consegue observar MODIFIED marcado. Consulte as notas completas de comportamento:
docs/caldav-compatibility.md,
docs/carddav-compatibility.md,
docs/mail-compatibility.md.
UIDs de criação e idempotência de atualização
create_event e create_contact usam client_uid ou seu alias idempotency_key
como o UID do recurso. Uma criação retorna conflict se esse UID existir.
Ela nunca sobrescreve silenciosamente o objeto.
Apenas update_event e update_contact armazenam resultados em cache via idempotency_key.
O cache local do processo mantém 1.024 entradas, com um máximo de 256 KiB por carga útil.
A mesma chave e parâmetros retornam o resultado salvo. Parâmetros diferentes retornam
conflict. Sucessos e erros definitivos permanecem por 15 minutos. Resultados desconhecidos
permanecem até a saída do processo. Reivindicações pendentes não expiram.
Um cache cheio rejeita novas reivindicações antes de uma escrita. Mantenha a chave e aguarde capacidade.
Após uma resposta ambígua, use get_event ou get_contact antes de uma nova atualização.
Uma nova chave ou reinicialização do processo não prova que a escrita anterior falhou.
Use um novo etag forte para uma atualização nova necessária.
Consulte o contrato de cache e o procedimento de recuperação.
Configuração
Exatamente 12 variáveis de ambiente do produto:
| Variável | Padrão | Contrato |
|---|---|---|
ICLOUD_EMAIL | nenhum | Identidade obrigatória de Calendário/Contatos. file:// suportado (arquivo regular, <=4 KiB, modo 0600+). |
ICLOUD_PASSWORD | nenhum | Senha específica de app obrigatória. O E-mail a usa como fallback. file:// como acima. |
ICLOUD_MCP_READ_ONLY | false | Interruptor global de mutação. |
ICLOUD_MCP_LOG_LEVEL | info | Nível de stderr. Consulte os formatos aceitos abaixo. |
ICLOUD_MCP_DEFAULT_TZ | UTC | Fuso IANA para entradas de Calendário sem offset e fallback de escrita recorrente. |
ICLOUD_MCP_ENABLE_CONTACTS | false | Ferramentas de Contatos. Escritas exigem que o modo somente leitura esteja desativado. |
ICLOUD_MCP_ENABLE_MAIL | false | Leituras de E-mail. Exige um endereço e senha de E-mail. |
ICLOUD_MAIL_ADDRESS | nenhum | Endereço IMAP/SMTP completo quando o E-mail está ativo. file:// como acima. |
ICLOUD_MAIL_PASSWORD | ICLOUD_PASSWORD | Senha de E-mail dedicada opcional. file:// como acima. |
ICLOUD_MCP_ENABLE_MAIL_WRITE | false | Três ferramentas de mutação IMAP. |
ICLOUD_MCP_ENABLE_MAIL_SEND | false | send_message (independente da escrita de E-mail). |
ICLOUD_MCP_SMTP_ALLOWED_RECIPIENTS | nenhum | Obrigatório se o envio estiver ativo. Use endereços exatos ou o literal *. O literal * causa um aviso na inicialização. Use endereços exatos quando possível. |
Booleanos aceitam apenas não definido, 0, false, 1 ou true. Valores inválidos causam
falha na inicialização. O servidor valida a configuração antes do acesso à rede.
Escrita ou envio de E-mail sem E-mail causa um erro de inicialização. E-mail sem endereço ou
senha também causa um erro de inicialização. Envio sem política de destinatários causa um
erro de inicialização, inclusive no modo somente leitura.
O modo somente leitura global pode coexistir com flags de escrita e envio, mas impede o registro delas.
O servidor remove espaços dos níveis de log e ignora maiúsculas/minúsculas. Ele aceita debug ou -4,
info, warn, warning ou 2, e error ou 4. Valores não definidos ou não reconhecidos
usam info.
Use -version para imprimir a versão. A flag opcional
-health 127.0.0.1:port serve /healthz e /status no loopback. Ambos os
endpoints retornam JSON com domínios e limites de taxa. A flag opcional
-audit-format=json|text seleciona o formato de auditoria de mutação no stderr.
O formato padrão é json.
Datas
- Entrada de Calendário
starteendaceitam RFC3339 com offset. Elas também aceitam valores de hora local sem offset emICLOUD_MCP_DEFAULT_TZ. Use valores sem offset para a hora local do usuário. Criações recorrentes e criações com fuso horário explícito gravam TZID e VTIMEZONE. Criações temporizadas não recorrentes usam UTCZpor padrão no fio. Criações de dia inteiro usamVALUE=DATE. - Saída de Calendário usa RFC3339 para eventos temporizados. Ela sempre inclui um
offset numérico explícito em
ICLOUD_MCP_DEFAULT_TZ, nuncaZpuro. Datas de dia inteiro usamYYYY-MM-DD. Consultecalendar_capabilities.outputFormat. - Aniversários de Contatos: grave apenas
YYYY-MM-DD. - Pesquisa de E-mail:
sinceinclusivo,beforeexclusivo (YYYY-MM-DD).
Segurança (resumo)
Texto remoto não confiável pode influenciar um LLM no host. Rótulos não formam uma fronteira de segurança. Um modelo comprometido pode chamar todas as ferramentas registradas. Esse risco se aplica a todos os hosts e fornecedores.
- Egresso fixo: Calendário usa
caldav.icloud.come hostsp[0-9]{1,3}-caldav.icloud.com:443correspondentes. Contatos usa hosts de Contatos correspondentes. IMAP usaimap.mail.me.com:993. SMTP usasmtp.mail.me.com:587com STARTTLS obrigatório. Os destinos não são configuráveis. O servidor ignora variáveis de ambiente de proxy DAV e verifica TLS 1.2 ou posterior. - Isolamento: cada domínio tem credenciais, transportes, dialers, limitadores, semáforos e pilhas de protocolo separados. Nenhum cliente HTTP autenticado se conecta a múltiplos domínios.
- Segredos: o servidor remove segredos, incluindo formas Basic e SASL PLAIN.
Leituras de
file://somente na inicialização exigem modo 0600 ou mais restritivo. O servidor não usaos/execnem telemetria. Ele não grava em disco após a inicialização. - Auditoria: logs de mutação incluem
domain,resourceTypee o HMACresourceTokenlocal do processo. Eles nunca contêm caminhos brutos, UIDs, caixas de correio ou destinatários. - Risco residual: um processo mantém credenciais para todos os domínios ativados. Flags de recurso não removem código compilado. Para isolamento mais forte, use o modo somente leitura e ative menos domínios. Você também pode usar uma senha de E-mail dedicada ou processos separados.
Política completa: SECURITY.md, docs/security.md. Arquitetura: docs/architecture.md.
Limites (resumo)
| Prazo da ferramenta | 25s (DAV HTTP 30s) |
| Resultado Stdio / MCP | Quadro de 1 MiB. Resultado de 256 KiB. Erros de protocolo refletidos têm um limite. |
| Calendário | Intervalo de pesquisa: 366 dias. Resultados: 400 no total, 2.500 por calendário e 10.000 materializados entre calendários. Recorrência: 2.000 expansões, 100k passos por série e 250k passos por pesquisa. Taxa: 60 leituras e 20 escritas por minuto. Concorrência: 4 leituras e 2 escritas. |
| Contatos | 100 livros. 100 resumos. 2.000 cartões verificados. Taxa: 60 leituras e 20 escritas por minuto. Concorrência: 4. |
| Taxa: 60 leituras, 20 mutações e 20 envios por minuto. Semáforos: 2 leituras, 1 mutação e 1 envio. Sem nova tentativa de mutação ou envio. | |
| Escritas | Sem reprodução automática de PUT/DELETE de Calendário, escritas de Contatos, mutações IMAP ou SMTP. Resultados ambíguos usam outcome_unknown. |
O servidor descobre o Calendário na inicialização e os Contatos no primeiro uso. Cada chamada usa uma sessão IMAP ou SMTP nova. Consulte estes documentos para taxas, orçamentos de parser e regras de nova tentativa: docs/testing.md, docs/architecture.md.
Múltiplas contas
Um processo mantém uma identidade iCloud. Inicie um processo separado para cada identidade. Dê a cada processo um ambiente separado e uma porta de saúde opcional. Consulte integração de host.
Dependências
Use Go 1.26.0 ou mais recente. O projeto tem um módulo e exatamente 10 dependências diretas. Se você adicionar uma dependência direta, adicione sua justificativa aqui.
| Dependência | Versão exata | Justificativa |
|---|---|---|
github.com/emersion/go-webdav | v0.7.0 | Primitivas CalDAV. Descoberta e operações condicionais permanecem escritas manualmente. |
github.com/emersion/go-ical | v0.0.0-20250609112844-439c63cef608 | Parse/encode iCalendar |
github.com/mark3labs/mcp-go | v1.2.0 | MCP stdio, schemas, JSON-RPC |
github.com/teambition/rrule-go | v1.8.2 | Recorrência limitada com preservação de fuso horário |
golang.org/x/time | v0.16.0 | Limitadores de taxa por domínio |
github.com/emersion/go-vcard | v0.1.0 | Leitura vCard 3.0/4.0, escrita 3.0 |
github.com/emersion/go-imap/v2 | v2.0.0-beta.8 | IMAP por trás de internal/mail/imapadapter |
github.com/emersion/go-message | v0.18.2 | Limites MIME / texto simples |
github.com/emersion/go-smtp | v0.25.0 | SMTP + STARTTLS |
github.com/emersion/go-sasl | v0.0.0-20241020182733-b788ff22d5a6 | SASL PLAIN após STARTTLS |
Build e teste
make build # local host binary, VERSION defaults to dev
make test # go test ./... -race -cover
make lint # go vet + pinned golangci-lint
make release VERSION=v0.4.0 # packaged linux/arm64, digest-pinned Go 1.26.9 image
make release-all VERSION=v0.4.0 # packaged linux/amd64, linux/arm64, darwin/arm64 (host Go)
make install # host-compatible build to INSTALL_DIR (default ~/.local/bin)
Os alvos de release exigem uma árvore de trabalho limpa e uma versão não dev. Os arquivos contêm
o binário, LICENSE e THIRD_PARTY_NOTICES.md. O diretório dist/ também
contém um arquivo de soma de verificação SHA-256. Releases de tags do GitHub executam make release-all
somente após CI e gitleaks terem sucesso para essa tag. Eles usam Go 1.26.9 com
check-latest desabilitado.
O make release local usa o caminho de contêiner com digest fixado para linux/arm64.
Os blobs de release incluem assinaturas keyless do cosign. -version primeiro usa o
valor de ldflags do release. Se esse valor estiver ausente, ele usa informações de build
do módulo Go. Assim, go install ...@version reporta a versão do módulo.
O CI verifica formatação, testes de corrida, fuzzing, vulnerabilidades, segredos, texto público
e builds multi-arquitetura. Ele impõe pisos de cobertura e um limite de binário de 20 MiB.
Testes ao vivo exigem a tag de build integration e portões explícitos de domínio/escrita.
O CI nunca os executa. Veja Testes.
Para evidência de protocolo somente com fixtures, use um caminho de saída absoluto fora do repositório:
make protocol-evidence EVIDENCE_DIR=/external/path
O runner compila um executável a partir dos testes cmd/icloud-mcp com registro MCP
compartilhado e código de inicialização stdio. Ele também executa cenários de idempotência e
recorrência em processo. Ele salva transcrições, metadados de execução, revisão da fonte,
diff de trabalho, valores SHA-256 dos fixtures e resultados fora do repositório.
O CI mantém o artefato protocol-evidence por 14 dias. Essas verificações usam fixtures
sintéticos e não estabelecem compatibilidade ao vivo com iCloud.
Documentação
| Documento | Propósito |
|---|---|
| Integração de host | Configuração YAML e JSON, processos multi-conta, comportamento do chamador |
| Códigos de erro | Regras de nova tentativa e recuperação de mutação |
| Arquitetura | Inicialização, limites de domínio, concorrência, idempotência de atualização |
| Compatibilidade CalDAV | Descoberta de calendário, escritas condicionais, recorrência, limites |
| Compatibilidade CardDAV | Descoberta de contatos, suporte vCard, busca, escritas condicionais |
| Compatibilidade de e-mail | Sessões IMAP, identidade de mensagem, mutação, envio SMTP |
| Política de segurança e implementação | Modelo de ameaça, relatórios e controles técnicos |
| Testes | Verificações locais, evidência de protocolo, CI e portões de integração ao vivo |
| Contribuição | Desenvolvimento, escrita, política de testes e suporte |
| Changelog | Histórico de releases |
Atribuição
A forma da ferramenta de calendário e vários padrões foram inspirados por
github.com/roygabriel/mcp-icloud-calendar
(MIT, copyright 2026 Gabe). O código foi reescrito, não copiado. Este servidor adiciona
egressão rígida por domínio, redação, parsers limitados, mutação condicional,
Contatos, E-mail e nenhuma telemetria.
Contribuição
Veja CONTRIBUTING.md. Execute gofmt, make test e make lint
antes de abrir um pull request.
Licença
MIT. Veja LICENSE e avisos de terceiros.