Apple Reminders

Um servidor para integração nativa com o Apple Reminders no macOS.

Documentação

Servidor MCP de Eventos da Apple Version 1.5.0 License: MIT

X Follow

Inglês | 简体中文

Um servidor Model Context Protocol (MCP) que fornece integração nativa com Lembretes e Calendário da Apple no macOS por meio do framework EventKit. Expõe lembretes, listas, subtarefas e eventos de calendário por meio de uma interface padronizada com operações CRUD completas.

O backend EventKit é o event CLI Swift independente, incluído como submódulo git e compilado em bin/event durante pnpm install — nenhum brew install separado é necessário. Consulte docs/migration-to-event-cli.md para a troca de backend na v1.5.0 e a lista de campos de escrita ainda não expostos por event.

Sumário

Recursos

  • CRUD completo para lembretes, subtarefas, listas de lembretes e eventos de calendário
  • Prioridade (alta/média/baixa/nenhuma), tags e subtarefas de checklist com acompanhamento de progresso
  • Filtragem por múltiplos critérios: conclusão, intervalo de datas de vencimento, prioridade, tags, pesquisa de texto completo, recorrência, baseada em localização
  • Formatos de data flexíveis (YYYY-MM-DD, YYYY-MM-DD HH:mm:ss, ISO 8601) com suporte a fusos horários
  • Integração nativa com macOS via EventKit — valores configurados no app Lembretes / Calendário são refletidos nas respostas de leitura
  • Descoberta e solicitação automática de permissões do macOS
  • Suporte completo a Unicode com validação abrangente de entrada

Pré-requisitos

  • Node.js 20 ou posterior
  • macOS (necessário para EventKit)
  • Ferramentas de Linha de Comando do Xcode (apenas ao compilar a partir do código-fonte)
  • pnpm (recomendado)

O pacote npm publicado inclui um binário bin/event universal, pré-compilado e assinado digitalmente, portanto usuários de npx não precisam de Xcode nem de toolchain Swift. Compilar a partir de um clone do git requer os itens acima.

Início Rápido

npx mcp-server-apple-events

Configuração

Adicione o servidor ao seu cliente MCP. A forma npx funciona para todos os clientes abaixo; para uma compilação local, substitua command/args por node apontando para dist/index.js.

Cursor

Configurações → MCP → Adicionar novo servidor MCP global:

{
  "mcpServers": {
    "apple-reminders": {
      "command": "npx",
      "args": ["-y", "mcp-server-apple-events"]
    }
  }
}

ChatWise

Configurações → Ferramentas → "+", então:

  • Tipo: stdio
  • ID: apple-reminders
  • Comando: mcp-server-apple-events
  • Argumentos: (vazio)

Claude Desktop

Edite claude_desktop_config.json (abra via Configurações → Opção de Desenvolvedor → Editar Config, ou diretamente em ~/Library/Application Support/Claude/claude_desktop_config.json no macOS / %APPDATA%\Claude\claude_desktop_config.json no Windows):

{
  "mcpServers": {
    "apple-reminders": {
      "command": "npx",
      "args": ["-y", "mcp-server-apple-events"]
    }
  }
}

Para uma compilação local:

{
  "mcpServers": {
    "apple-reminders": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-server-apple-events/dist/index.js"]
    }
  }
}

Consulte a documentação oficial do MCP para conectar servidores locais. Reinicie o Claude Desktop completamente (saia, não apenas feche) para que as alterações tenham efeito.

Permissões do macOS

O event CLI incluído incorpora seu próprio Info.plist (bundle id me.frad.event) declarando todas as strings de privacidade de Lembretes e Calendário, e é iniciado por meio do shim bin/event-disclaim incluído, que isenta a responsabilidade TCC no momento da inicialização. Portanto, o macOS atribui a solicitação de permissão ao event em si, não ao aplicativo que iniciou o servidor MCP — assim, a primeira chamada EventKit solicita "evento", a concessão aparece em System Settings > Privacy & Security > Reminders / Calendars como event, e uma única concessão cobre todos os clientes MCP na máquina (Claude Desktop, Codex Desktop, Cursor, clientes de terminal, …). Consulte issue #93 para contexto.

Quando event detecta um status notDetermined, ele chama requestFullAccessToReminders / requestFullAccessToEvents, que exibem o prompt do sistema. Se o sistema operacional perder o controle das permissões, execute novamente ./check-permissions.sh para reabrir os diálogos.

Erros de leitura do Calendário

Se você vir Failed to read calendar events, defina o Calendário como Acesso Total ao Calendário em System Settings > Privacy & Security > Calendars, ou execute novamente ./check-permissions.sh (ele verifica tanto Lembretes quanto Calendários).

Recuperando um estado TCC travado (nenhum prompt aparece)

Se o diálogo de permissão nunca aparecer e event estiver ausente de System Settings → Privacy & Security → Reminders / Calendars, sua máquina está em um estado TCC obsoleto/atribuído incorretamente. A correção de isenção no lado do servidor evita isso em uma máquina limpa, mas não pode limpar entradas já corrompidas. Recuperação:

  1. Redefina as entradas TCC de Calendário e Lembretes globalmente (a redefinição por aplicativo frequentemente não funciona — a forma simples limpa todas as entradas, que é o que limpa o estado ruim):

    tccutil reset Calendar
    tccutil reset Reminders
    

    Isso limpa o acesso a Calendário/Lembretes para todos os aplicativos; outros aplicativos solicitarão permissão novamente na próxima vez.

  2. Reative a permissão de dentro de uma conversa no Claude (Claude Desktop ou Claude Code) pedindo, por exemplo, "Use AppleScript para verificar meu Calendário e Lembretes." Conceda o acesso e o servidor deve funcionar normalmente. Consulte issue #83.

Execuções headless / launchd travam em vez de falhar

Quando o servidor é executado em um contexto sem sessão GUI (SSH, agente/daemon launchd), a primeira chamada EventKit pode bloquear para sempre aguardando um prompt de permissão que nunca pode ser renderizado — a solicitação MCP nunca é concluída e um processo filho vaza a cada chamada. O servidor agora encerra qualquer chamada event que exceda 30 s (SIGKILL) e retorna um erro legível. Ajuste com a variável de ambiente EVENTKIT_CLI_TIMEOUT_MS (milissegundos; valores inválidos/zero voltam ao padrão — o timeout não pode ser desabilitado, embora valores grandes de até 2^31-1 ms sejam aceitos). O event CLI incluído (fixado via FradSer/event#15) adicionalmente falha rapidamente quando não há sessão GUI e desiste de um prompt sem resposta após 15 s (EVENT_PERMISSION_TIMEOUT_MS), relatando Permission denied: Timed out waiting for ... para que o host possa mostrar uma mensagem específica de permissão antes do encerramento do servidor (15 s < 30 s). Consulte issue #113.

macOS 26 (Tahoe) could not build module 'Foundation'

Se pnpm build falhar com could not build module 'Foundation' (ou SDK is not supported by the compiler), seu toolchain Swift é mais antigo do que o exigido pelo SDK do macOS 26 — ele precisa de Swift 6.3 ou mais recente, mas as Ferramentas de Linha de Comando incluídas nas primeiras versões do macOS 26 incluem Swift 6.2.x. pnpm build:event detecta isso e imprime a mesma correção; consulte issue #85. Corrija instalando o Xcode 26.x da App Store, ou atualizando as Ferramentas de Linha de Comando para uma versão Swift 6.3+:

softwareupdate --list
sudo softwareupdate -i "Command Line Tools for Xcode-<latest>"
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer   # if full Xcode is installed
xcrun swiftc --version    # should report Apple Swift version 6.3 or newer

Exemplos de Uso

Após configurado, peça ao Claude para interagir com seus Lembretes e Calendário da Apple. Exemplos de prompts:

Create a reminder to "Buy groceries" for tomorrow at 5 PM with tags shopping and errands.
Add a high-priority reminder to "Finish quarterly report" due Friday in my "Work" list.
Create "Grocery shopping" with subtasks: milk, eggs, bread, butter.
Show me all high-priority reminders due today tagged "urgent".
Show subtasks for my "Grocery shopping" reminder and mark "milk" as complete.
Update "Buy groceries" — change the title to "Buy organic groceries" and set priority to high.
Show reminders from my "Work" list, and list all my reminder lists.
Create a calendar event "Team standup" tomorrow from 9:00 to 9:30 in "Work".
Show my calendar events for the next week.
Invite alex@example.com to my "Team standup" event.
Cancel just the September 21 occurrence of my weekly "Team standup".

O servidor processa solicitações em linguagem natural, interage com os aplicativos nativos Lembretes e Calendário da Apple e retorna resultados formatados.

Alarmes, regras de recorrência e gatilhos de localização são somente leitura por meio deste servidor — configure-os no app Lembretes / Calendário. Eles ainda aparecem nos resultados de leitura com indicadores visuais.

Ferramentas MCP Disponíveis

As ferramentas com escopo de serviço espelham os domínios de Lembretes e Calendário da Apple. Todas aceitam um campo action além de parâmetros específicos da ação (o cliente MCP inspeciona o esquema Zod completo; apenas as ações são listadas aqui). Campos de data aceitam YYYY-MM-DD, YYYY-MM-DD HH:mm:ss (hora local) ou ISO 8601 com fuso horário.

FerramentaAçõesNotas
reminders_tasksread, create, update, deletePrioridade, tags, subtarefas. startDate é definido via update, não create; em read ele limita a janela de data de vencimento junto com endDate. Movimentação entre listas não suportada.
reminders_subtasksread, create, update, delete, toggle, reorderArmazenado no campo de notas (legível no app Lembretes).
reminders_listsread, create, update, deleteRenomear via name → newName.
calendar_eventsread, create, update, deleteDia inteiro inferido pelo formato da data. Movimentação entre calendários não suportada. span limita exclusões recorrentes. attendees (atualização) convida endereços; occurrenceDate (exclusão) excetua uma ocorrência de uma série — ambos precisam de configuração extra, consulte Participantes e ocorrências únicas.
calendar_calendarsreadCalendários com ≥1 evento na janela (opcional) startDate/endDate.

Exemplos de chamadas:

{
  "action": "create",
  "title": "Buy groceries",
  "dueDate": "2024-03-25 18:00:00",
  "targetList": "Shopping",
  "note": "Don't forget milk and eggs",
  "priority": 1,
  "tags": ["shopping", "errands"],
  "subtasks": ["Milk", "Eggs", "Bread"]
}
{ "action": "read", "filterList": "Work", "dueWithin": "today", "filterPriority": "high", "filterTags": ["urgent"] }
{ "action": "read", "startDate": "2026-08-01", "endDate": "2026-08-31" }
{ "action": "update", "id": "reminder-123", "completed": false, "addTags": ["followup"] }
{ "action": "toggle", "reminderId": "reminder-123", "subtaskId": "a1b2c3d4" }
{ "action": "create", "name": "Project Alpha" }
{ "action": "create", "title": "Team standup", "startDate": "2026-05-04 09:00:00", "endDate": "2026-05-04 09:30:00", "targetCalendar": "Work" }
{ "action": "update", "id": "event-123", "attendees": ["alex@example.com", "sam@example.com"] }
{ "action": "delete", "id": "event-123", "occurrenceDate": "2026-09-21T09:00:00" }

Participantes e ocorrências únicas

Estes dois parâmetros calendar_events são as únicas escritas que não passam pelo event CLI, porque o EventKit não pode expressar nenhum dos dois. Cada um precisa de configuração que o restante do servidor não faz.

attendees (atualização) — convida endereços de e-mail para um evento existente. EKCalendarItem.attendees é somente leitura no SDK do macOS e o EventKit não tem API de convite, então a escrita passa pela interface de script do app Calendário; adicionar o participante localmente é o que faz o iCloud enviar o convite.

  • Requer uma concessão de Automação: a primeira chamada solicita, e a entrada aparece em System Settings > Privacy & Security > Automation. Precisa de sessão GUI, portanto não funciona headless.
  • Os participantes devem ser atualizados sozinhos. Eles trafegam pelo app Calendário enquanto todos os outros campos trafegam pelo EventKit, e os dois não compartilham token de concorrência — uma atualização combinada não tem ordenação segura, então é recusada. Faça duas chamadas.
  • Dois eventos compartilhando título e data de início são recusados, não adivinhados. O app Calendário só pode ser consultado por título e data, e escrever no errado enviaria um convite real para ele.

occurrenceDate (exclusão) — excetua uma ocorrência de uma série recorrente. Cada ocorrência compartilha um identificador EventKit, então span: "this-event" só pode excetuar o início da série; direcionado a uma ocorrência posterior, não escreve nada e ainda relata sucesso. Fornecer occurrenceDate roteia a exclusão via CalDAV, que pode endereçar a instância diretamente.

  • Requer credenciais iCloud. Defina ICLOUD_APPLE_ID e ICLOUD_APP_PASSWORD, ou defina ICLOUD_APPLE_ID e armazene a senha no Keychain:

    security add-generic-password -a "you@icloud.com" -s "icloud-caldav-mcp" -w
    

    Use uma senha específica do app, nunca a senha da sua conta. As credenciais são lidas primeiro do ambiente, depois do Keychain, nunca da configuração do cliente MCP, e nunca são registradas em log.

  • Apenas eventos sincronizados com iCloud são elegíveis — um evento sem identificador externo não tem recurso CalDAV para localizar.

Formato da resposta de leitura

As respostas de leitura trazem indicadores visuais: 🔄 recorrente, 📍 baseado em localização, 🏷️ tem tags, 📋 tem subtarefas. Exemplo:

- [ ] Buy groceries 🏷️📋
  - List: Shopping
  - ID: reminder-123
  - Priority: high
  - Tags: #shopping #errands
  - Subtasks (1/3):
    - [x] Milk
    - [ ] Eggs
    - [ ] Bread
  - Due: 2024-03-25 18:00:00

O campo url é armazenado na propriedade nativa url (visível pelo ícone "i" no app Lembretes) e também anexado às notas em um bloco estruturado URLs: para análise e suporte a múltiplas URLs. As URLs aceitam qualquer esquema de URI válido (http, https, mailto, tel, obsidian, shortcuts, …); file, javascript, data e esquemas perigosos semelhantes são rejeitados, e nomes de host http(s) são verificados contra uma lista de bloqueio SSRF.

Campos somente leitura: alarmes, regras de recorrência, gatilhos de localização, localizações estruturadas, url/availability/isAllDay do calendário e movimentações entre calendários não são graváveis por meio deste servidor — eles refletem valores configurados no app Lembretes / Calendário. Consulte docs/migration-to-event-cli.md para a tabela completa de campos removidos e soluções alternativas.

Biblioteca de Prompts Estruturados

O servidor inclui um registro de prompts exposto via endpoints MCP ListPrompts / GetPrompt. Cada template compartilha uma missão, entradas de contexto, processo numerado, restrições, formato de saída e padrão de qualidade para que assistentes downstream obtenham scaffolding previsível.

  • daily-task-organizer — today_focus opcional; produz um blueprint de execução para o mesmo dia, equilibra trabalho prioritário com recuperação, cria automaticamente blocos de tempo no calendário para lembretes com vencimento hoje.
  • smart-reminder-creator — task_idea opcional; gera uma estrutura de lembretes com agendamento otimizado.
  • reminder-review-assistant — review_focus opcional (ex.: overdue ou um nome de lista); audita e otimiza lembretes existentes.
  • weekly-planning-workflow — user_ideas opcional; orienta um reset de segunda a domingo com blocos de tempo vinculados a listas existentes.

Os prompts são limitados aos recursos nativos do Apple Reminders e solicitam contexto ausente antes de ações irreversíveis. Execute pnpm test -- src/server/prompts.test.ts após alterar o texto do prompt.

Desenvolvimento

pnpm install        # postinstall builds bin/event from vendor/event on macOS
pnpm build          # TypeScript + vendored event CLI
pnpm test           # Jest suite: repositories, schemas, build script, prompt templates
pnpm exec biome check   # lint + format

O ponto de entrada da CLI percorre até dez diretórios para encontrar package.json, permitindo que o servidor inicie a partir de caminhos aninhados (ex.: dist/ ou executores de tarefas do editor) sem perder bin/event. Mantenha o manifesto acessível dentro dessa profundidade se você personalizar o layout de pastas.

Scripts

  • pnpm build — TypeScript + CLI event embutida (necessário antes de executar a partir do código-fonte)
  • pnpm build:ts — apenas TypeScript
  • pnpm build:event — apenas CLI event embutida (swift build -c release → bin/event)
  • pnpm build:release — build mais notarização (empacotamento de release)
  • pnpm test / pnpm test:ci — suíte Jest / com cobertura
  • pnpm lint — formatação/correção Biome + verificação de tipos TypeScript
  • pnpm check — lint + testes com cobertura

Licença

MIT

Contribuição

Contribuições são bem-vindas! Por favor, leia as diretrizes de contribuição primeiro.