icloud-mcp

MCP stdio para iCloud Calendar com Contatos e Mail opcionais

Documentação

icloud-mcp

CI Release License: MIT

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.

A stdio MCP client connects to capability gates and four separate iCloud protocol clients.

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ínioProtocoloPadrão
CalendárioCalDAV HTTPSSempre ativo (leitura + escrita, exceto em modo somente leitura global)
ContatosCardDAV HTTPSDesativado até ICLOUD_MCP_ENABLE_CONTACTS
Leitura de e-mailIMAP TLSDesativado até ICLOUD_MCP_ENABLE_MAIL
Mutação de e-mailIMAPDesativado até E-mail + ICLOUD_MCP_ENABLE_MAIL_WRITE
Envio de e-mailSMTP STARTTLSDesativado 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
  1. Crie uma senha específica de app. Nunca use a senha principal da Conta Apple.
  2. Armazene a identidade e a senha em arquivos regulares separados, fora do repositório.
  3. Dê a cada arquivo modo 0600 ou mais restritivo e um tamanho máximo de 4 KiB.
  4. 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
  1. Registre o caminho absoluto do binário e o ambiente no seu host MCP.
  2. 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.

ContagemQuando
10Padrão: leitura+escrita de Calendário + icloud_capabilities
7Somente leitura global, domínios opcionais desativados (recomendado para a primeira execução)
23Contatos + 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.

GrupoFerramentas
Globalicloud_capabilities
Leitura de Calendáriolist_calendars, search_events, get_event, find_free_slots, validate_event, calendar_capabilities
Escrita de Calendáriocreate_event, update_event, delete_event
Leitura de Contatoslist_address_books, search_contacts, get_contact
Escrita de Contatoscreate_contact, update_contact, delete_contact
Leitura de E-maillist_mailboxes, search_messages, get_message
Mutação de E-mailset_message_flags, move_message, trash_message
Envio de E-mailsend_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ávelPadrãoContrato
ICLOUD_EMAILnenhumIdentidade obrigatória de Calendário/Contatos. file:// suportado (arquivo regular, <=4 KiB, modo 0600+).
ICLOUD_PASSWORDnenhumSenha específica de app obrigatória. O E-mail a usa como fallback. file:// como acima.
ICLOUD_MCP_READ_ONLYfalseInterruptor global de mutação.
ICLOUD_MCP_LOG_LEVELinfoNível de stderr. Consulte os formatos aceitos abaixo.
ICLOUD_MCP_DEFAULT_TZUTCFuso IANA para entradas de Calendário sem offset e fallback de escrita recorrente.
ICLOUD_MCP_ENABLE_CONTACTSfalseFerramentas de Contatos. Escritas exigem que o modo somente leitura esteja desativado.
ICLOUD_MCP_ENABLE_MAILfalseLeituras de E-mail. Exige um endereço e senha de E-mail.
ICLOUD_MAIL_ADDRESSnenhumEndereço IMAP/SMTP completo quando o E-mail está ativo. file:// como acima.
ICLOUD_MAIL_PASSWORDICLOUD_PASSWORDSenha de E-mail dedicada opcional. file:// como acima.
ICLOUD_MCP_ENABLE_MAIL_WRITEfalseTrês ferramentas de mutação IMAP.
ICLOUD_MCP_ENABLE_MAIL_SENDfalsesend_message (independente da escrita de E-mail).
ICLOUD_MCP_SMTP_ALLOWED_RECIPIENTSnenhumObrigató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 start e end aceitam RFC3339 com offset. Elas também aceitam valores de hora local sem offset em ICLOUD_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 UTC Z por padrão no fio. Criações de dia inteiro usam VALUE=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, nunca Z puro. Datas de dia inteiro usam YYYY-MM-DD. Consulte calendar_capabilities.outputFormat.
  • Aniversários de Contatos: grave apenas YYYY-MM-DD.
  • Pesquisa de E-mail: since inclusivo, before exclusivo (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.com e hosts p[0-9]{1,3}-caldav.icloud.com:443 correspondentes. Contatos usa hosts de Contatos correspondentes. IMAP usa imap.mail.me.com:993. SMTP usa smtp.mail.me.com:587 com 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 usa os/exec nem telemetria. Ele não grava em disco após a inicialização.
  • Auditoria: logs de mutação incluem domain, resourceType e o HMAC resourceToken local 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 ferramenta25s (DAV HTTP 30s)
Resultado Stdio / MCPQuadro de 1 MiB. Resultado de 256 KiB. Erros de protocolo refletidos têm um limite.
CalendárioIntervalo 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.
Contatos100 livros. 100 resumos. 2.000 cartões verificados. Taxa: 60 leituras e 20 escritas por minuto. Concorrência: 4.
E-mailTaxa: 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.
EscritasSem 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ênciaVersão exataJustificativa
github.com/emersion/go-webdavv0.7.0Primitivas CalDAV. Descoberta e operações condicionais permanecem escritas manualmente.
github.com/emersion/go-icalv0.0.0-20250609112844-439c63cef608Parse/encode iCalendar
github.com/mark3labs/mcp-gov1.2.0MCP stdio, schemas, JSON-RPC
github.com/teambition/rrule-gov1.8.2Recorrência limitada com preservação de fuso horário
golang.org/x/timev0.16.0Limitadores de taxa por domínio
github.com/emersion/go-vcardv0.1.0Leitura vCard 3.0/4.0, escrita 3.0
github.com/emersion/go-imap/v2v2.0.0-beta.8IMAP por trás de internal/mail/imapadapter
github.com/emersion/go-messagev0.18.2Limites MIME / texto simples
github.com/emersion/go-smtpv0.25.0SMTP + STARTTLS
github.com/emersion/go-saslv0.0.0-20241020182733-b788ff22d5a6SASL 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

DocumentoPropósito
Integração de hostConfiguração YAML e JSON, processos multi-conta, comportamento do chamador
Códigos de erroRegras de nova tentativa e recuperação de mutação
ArquiteturaInicialização, limites de domínio, concorrência, idempotência de atualização
Compatibilidade CalDAVDescoberta de calendário, escritas condicionais, recorrência, limites
Compatibilidade CardDAVDescoberta de contatos, suporte vCard, busca, escritas condicionais
Compatibilidade de e-mailSessões IMAP, identidade de mensagem, mutação, envio SMTP
Política de segurança e implementaçãoModelo de ameaça, relatórios e controles técnicos
TestesVerificações locais, evidência de protocolo, CI e portões de integração ao vivo
ContribuiçãoDesenvolvimento, escrita, política de testes e suporte
ChangelogHistó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.