Skip to main content
Glama
martijnstegink

apple-notes-reminders-mcp

apple-notes-reminders-mcp

Un servidor MCP (Model Context Protocol) que expone Apple Notes y Apple Reminders a clientes compatibles con MCP (p. ej. Claude Desktop) en macOS.

Qué hace

El servidor registra un conjunto de herramientas para leer y escribir Notas y Recordatorios. Las herramientas de Notas cubren listar, buscar (incluyendo texto reconocido dentro de archivos adjuntos de imagen), leer, crear, actualizar, mover y eliminar notas y carpetas, además de etiquetas, estado de fijado, archivos adjuntos de imagen y Eliminados recientemente. Las herramientas de Recordatorios cubren las operaciones equivalentes más subtareas, creación por lotes, finalización, fechas de vencimiento, banderas, recurrencia, alarmas de ubicación/tempranas, vistas de filtro guardadas, plantillas y filtros basados en palabras clave masivos.

Related MCP server: apple-reminders-mcp

Arquitectura

Los dos dominios se leen y escriben mediante diferentes mecanismos:

Lecturas se realizan a través de SQLite cuando es posible. Las notas se leen directamente de la base de datos NoteStore en disco:

~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite

La base de datos se copia a una ubicación temporal y se abre en modo solo lectura, por lo que el almacenamiento activo nunca se toca ni se bloquea. Los cuerpos de las notas se almacenan como un blob protobuf comprimido con gzip en ZICNOTEDATA.ZDATA; el decodificador descomprime esto y navega por la estructura protobuf de manera determinista para extraer texto y metadatos de formato.

Escrituras se realizan a través de AppleScript (osascript). La base de datos NoteStore es propiedad de Notes.app y no se puede escribir de forma segura desde fuera, por lo que las operaciones de crear/actualizar/eliminar/mover se delegan a Notes.app a través de AppleScript. Las subtareas de Recordatorios también usan AppleScript, porque la API pública de EventKit no las expone.

Decodificación del cuerpo de la nota

Leer correctamente el cuerpo de una nota es la parte sutil de este proyecto. El cuerpo no es texto plano — es un mensaje protobuf dentro del blob comprimido con gzip. El decodificador:

  1. Descomprime ZDATA y navega de forma determinista hasta el mensaje de texto de la nota (document → field 2 → field 3), luego lee la cadena de texto (field 2). Esto reemplazó una heurística anterior que escaneaba en busca del candidato de cadena "más limpio" y devolvía datos binarios corruptos para notas que contenían listas de verificación.

  2. Recorre los metadatos de párrafo por intervalo repetido para detectar elementos de lista de verificación y su estado completado/no completado, prefijando los elementos marcados con - [x] y los no marcados con - [ ] .

Dos detalles son importantes para la corrección:

  • Varints se acumulan con multiplicación (* 2 ** shift) en lugar del operador <<, porque el desplazamiento bit a bit de JavaScript se trunca a 32 bits y corrompe los desplazamientos grandes.

  • Las longitudes de los intervalos se miden en unidades de código UTF-16, coincidiendo con cómo las almacena Apple, para que los marcadores de lista de verificación permanezcan alineados incluso cuando el texto contiene caracteres multibyte o emojis.

Si la decodificación de SQLite falla por cualquier motivo, notes_get recurre a leer el cuerpo de la nota a través de AppleScript, que devuelve texto limpio pero no puede recuperar el estado de las casillas de verificación (la propiedad body de AppleScript de Apple no lo codifica).

Archivos adjuntos

Los archivos adjuntos de imagen se leen de las filas ICAttachment/ICMedia de ZICCLOUDSYNCINGOBJECT (resueltas dinámicamente mediante Z_PRIMARYKEY/Z_ENT, no codificadas de forma fija, ya que los identificadores de entidad numéricos y los nombres de columna ZACCOUNT*/ZPARENT cambian entre versiones de macOS). El archivo real reside en disco en:

~/Library/Group Containers/group.com.apple.notes/Accounts/{account}/Media/{media id}/{generation}/{filename}

notes_get devuelve el id, nombre de archivo, tipo, ruta de archivo resuelta y cualquier texto OCR reconocido de cada adjunto; notes_get_attachment obtiene un archivo adjunto de imagen como un bloque de contenido de imagen MCP. notes_search incorpora el texto OCR en el corpus de búsqueda, por lo que el texto que solo aparece dentro de una captura de pantalla se puede encontrar. Agregar un archivo adjunto no es compatible — consulte "Limitaciones conocidas" a continuación.

flagged de Recordatorios y otras lecturas solo de AppleScript

La API pública de EventKit no tiene una propiedad flagged, por lo que se lee y escribe completamente a través de AppleScript y se fusiona en los objetos Reminder obtenidos de EventKit por id. Un escaneo de elementos marcados de toda la biblioteca es comparativamente lento (la sobrecarga de IPC por propiedad de AppleScript), por lo que reminders_list/reminders_search solo incluyen flagged cuando se limitan a una sola lista; use reminders_query_where/reminders_view con un filtro flagged explícito cuando lo necesite en todas las listas.

Almacenamiento en caché

notesStore.ts almacena en caché la conexión SQLite abierta, el esquema detectado y el cuerpo decodificado de cada nota, todo invalidado al comparar las marcas de tiempo de modificación del archivo fuente (y sus archivos secundarios -wal/-shm) en cada llamada — una escritura en el NoteStore activo siempre invalida la caché, por lo que esto es una ganancia de rendimiento pura, no un riesgo de obsolescencia. Los cuerpos decodificados también se indexan por (Z_PK, fecha de modificación), por lo que una nota editada obtiene una nueva entrada de caché en lugar de un acierto obsoleto.

Requisitos y permisos

  • macOS (probado en macOS 26 / Tahoe)

  • Node.js 18+ (usa better-sqlite3 para acceso a SQLite)

  • Notes.app y Reminders.app configurados e iniciados sesión en una cuenta

  • Permiso de Automatización: la aplicación anfitriona (p. ej. Claude Desktop) debe tener permiso para controlar Notas y Recordatorios — macOS lo solicitará en el primer uso, o puede concederse en Configuración del Sistema › Privacidad y Seguridad › Automatización

  • Acceso total al disco: necesario para que la aplicación anfitriona lea la base de datos NoteStore en ~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite — concédalo en Configuración del Sistema › Privacidad y Seguridad › Acceso total al disco

Notas sobre la versión de macOS

Los nombres de columna y los identificadores de entidad numéricos dentro de ZICCLOUDSYNCINGOBJECT cambian entre versiones de macOS/Notes.app (por ejemplo, se han visto ZACCOUNT1 hasta ZACCOUNT8 como la clave foránea carpeta→cuenta activa en diferentes sistemas, y los valores de Z_ENT para ICAccount/ICAttachment/ICMedia no son estables). detectSchema() de notesStore.ts vuelve a detectarlos en cada fallo de caché en lugar de codificarlos de forma fija — consulte los comentarios allí antes de codificar un nuevo nombre de columna. Esto se desarrolló y probó con macOS 26 (Tahoe); la lógica de detección está escrita para tolerar versiones anteriores pero no se ha verificado con ellas.

Instalar

npm install
npm run build

Ejecutar

npm start

O registre dist/index.js como un comando de servidor MCP en la configuración de su cliente.

Estructura del proyecto

src/
  index.ts        MCP server + tool registrations
  notes.ts        Notes tool implementations (SQLite reads, AppleScript writes)
  notesStore.ts   NoteStore SQLite access + protobuf body decoder
  reminders.ts    Reminders tool implementations + local template/saved-view storage
  applescript.ts  Shared runAppleScript() helper (argv-only, never string-spliced)
  markdown.ts     Markdown -> Notes-compatible HTML converter
swift/
  reminders-daemon.swift  Persistent EventKit daemon (NDJSON over stdio)
scripts/
  test-phase2.mjs           Protobuf/checklist decoder tests (+ pinned full-pipeline fixtures)
  test-markdown.mjs         Markdown -> HTML converter tests
  test-schema-detection.mjs Schema-detection sanity checks against the live DB
dist/             Compiled output (generated by `npm run build`)

Las plantillas de Recordatorios y las vistas de filtro guardadas (reminders_save_template, reminders_save_view) se almacenan como JSON en ~/.apple-notes-reminders-mcp/ — no hay una base de datos del servidor para estas, ya que EventKit no tiene ese concepto propio.

Notas sobre permisos y privacidad

Todas las lecturas se realizan localmente contra una copia temporal de la base de datos NoteStore local. El servidor en sí mismo no envía nada fuera del dispositivo. El servidor requiere el mismo acceso que un usuario ya tiene a sus propias Notas y Recordatorios.

Pruebas

npm run build && node scripts/test-phase2.mjs           # protobuf/checklist decoder
npm run build && node scripts/test-markdown.mjs          # markdown -> Notes-HTML converter
npm run build && node scripts/test-schema-detection.mjs  # schema detection sanity (live DB)

test-markdown.mjs es completamente determinista. Las secciones de prueba unitaria de test-phase2.mjs (seguridad de varint, casos extremos de listas de verificación, fixtures de canalización completa de notas fijadas) son autónomas; su sección final "Real DB notes" y todo test-schema-detection.mjs leen la base de datos de Notas real y activa y solo pasarán con Acceso total al disco y datos de notas reales presentes — espere fallos/errores allí en una máquina que no sea la del autor original (la sección de BD de test-phase2.mjs hace referencia específicamente a identificadores de nota que solo existen en esa biblioteca).

Limitaciones conocidas

  • No se ha implementado el cambio de carpeta principal. Se ha confirmado en vivo que el AppleScript move <folder> to <folder> de Notes.app no es fiable — de forma intermitente lanza un error (item N of every folder kan niet worden opgevraagd) o no hace nada silenciosamente, independientemente de si la referencia a la carpeta proviene de folder id, un filtro whose o un escaneo hecho a mano. Cambiar el nombre y eliminar carpetas es fiable y está implementado; re-parentar una carpeta debajo de otra no lo está, ya que enviar una herramienta que falla de forma impredecible es peor que no tenerla. Cambiar el nombre/eliminar una carpeta anidada (creada a través de la interfaz de usuario de Notes.app, no por este servidor) es compatible — pase su ruta completa "Padre/Hijo".

  • No hay forma de agregar un archivo adjunto a través de este servidor. La lectura de archivos adjuntos es totalmente compatible (ver arriba). Agregar uno requiere la interfaz de usuario de Notes.app — se investigó un puente basado en Atajos-CLI (shortcuts run <name> -i <path>) y se consideró no viable como herramienta de configuración cero: acepta exactamente un archivo de entrada sin forma de pasar también una nota de destino, y la CLI de shortcuts solo puede ejecutar un atajo que ya existe, no crear uno. Consulte el comentario al principio de notes.ts para obtener el informe completo.

  • Las transcripciones de audio no se muestran. El texto OCR de los archivos adjuntos de imagen sí se muestra (notes_get, notes_search). La base de datos también tiene una columna con forma de transcripción de audio (ZTEMPORARYTRANSCRIPTDATA), pero es un blob opaco y no había archivos adjuntos de audio disponibles para aplicar ingeniería inversa a su formato — se deja para un futuro colaborador que tenga datos de fixture reales.

  • Una carpeta eliminada puede tardar más de un minuto en desaparecer de notes_list_folders. Confirmado en vivo: la eliminación es instantánea en Notes.app (e instantáneamente visible para AppleScript), pero el indicador de eliminación suave de la fila de SQLite puede retrasarse 60 segundos o más, aparentemente pendiente de un viaje de ida y vuelta de sincronización de iCloud — mucho más que el retraso típico de ~5 segundos de SQLite observado para cambios de nombre/creación en otros lugares. No es algo que este servidor pueda acortar; documentado en notesStore.ts para cualquiera que busque lo que parece un error de caché.

  • Las "carpetas inteligentes" (frase original de PLAN) realmente no existen como una característica general de Notes.app de la manera en que Recordatorios las tiene — el ZFOLDERTYPE=1 de la base de datos distingue solo la carpeta incorporada "Eliminados recientemente" de las carpetas normales. El soporte de solo lectura para ese indicador existe (isSmartFolder en notes_list_folders); la agrupación por etiquetas (notes_list_tags) es el análogo más cercano a una "lista inteligente guardada" para Notas.

  • Las "secciones de lista" de Recordatorios (una característica de agrupación más reciente de Reminders.app) no se leen — EventKit no las expone, y hacerlo implicaría aplicar ingeniería inversa al almacenamiento en disco separado de Recordatorios, lo que no se intentó en esta iteración.

Herramientas

Notas

Herramienta

Propósito

notes_list_folders

Listar todas las carpetas — id, nombre, ruta anidada, cuenta, indicador de carpeta inteligente, recuento de notas

notes_list

Listar notas, filtro opcional de carpeta, con ordenación + paginación por límite/desplazamiento

notes_get

Obtener una nota por nombre o id, incluidos metadatos de archivos adjuntos

notes_get_attachment

Obtener una imagen adjunta como bloque de imagen de MCP

notes_get_folder

Obtener todas las notas de una carpeta con cuerpos decodificados en una sola lectura, con ordenación + paginación

notes_search

Buscar en título/cuerpo/texto OCR en todas las carpetas, con ordenación + paginación

notes_create

Crear una nota (cuerpo markdown/html/texto)

notes_update

Actualizar una nota (reemplazar/añadir/preponer; protección contra adjuntos)

notes_delete

Eliminar una nota

notes_create_folder

Crear una carpeta

notes_rename_folder

Renombrar una carpeta (raíz o anidada, por ruta)

notes_delete_folder

Eliminar una carpeta (sus notas se mueven a Eliminados recientemente)

notes_move

Mover una nota a otra carpeta

notes_list_tags

Listar #hashtags usados en notas, con recuentos de notas

notes_recently_deleted

Listar notas en Eliminados recientemente

notes_restore_note

Restaurar una nota desde Eliminados recientemente

notes_query_where

Contar/listar notas que coinciden con un filtro basado en palabras (carpeta, búsqueda, etiqueta)

notes_delete_where

Eliminación masiva de notas coincidentes (con confirmación)

notes_move_where

Movimiento masivo de notas coincidentes (con confirmación)

Recordatorios

Herramienta

Propósito

reminders_list_lists

Listar todas las listas de recordatorios

reminders_list

Listar recordatorios, filtro opcional de lista, con ordenación + paginación por límite/desplazamiento

reminders_get

Obtener un recordatorio por nombre o id

reminders_search

Buscar recordatorios por nombre/notas/lista

reminders_view

Listas inteligentes estilo Reminders.app: hoy/planificadas/atrasadas/urgentes/marcadas/completadas

reminders_create

Crear un recordatorio (fecha de vencimiento en lenguaje natural, marca, repetición, alarmas tempranas/de ubicación)

reminders_create_batch

Crear varios recordatorios en una sola llamada nativa (una única confirmación de BD)

reminders_update

Actualizar un recordatorio

reminders_complete

Marcar como completado/incompleto

reminders_delete

Eliminar un recordatorio

reminders_create_list

Crear una lista

reminders_rename_list

Renombrar una lista

reminders_delete_list

Eliminar una lista y sus recordatorios

reminders_add_subtask

Añadir una subtarea (AppleScript — EventKit no tiene API pública de subtareas)

reminders_complete_subtask

Completar/restaurar una subtarea

reminders_delete_completed

Eliminación masiva de recordatorios completados, opcionalmente limitada a una lista

reminders_query_where

Contar/listar recordatorios que coinciden con un filtro basado en palabras

reminders_delete_where

Eliminación masiva de recordatorios coincidentes (con confirmación)

reminders_complete_where

Completar/incompletar masivamente recordatorios coincidentes (con confirmación)

reminders_move_where

Mover masivamente recordatorios coincidentes a otra lista (con confirmación)

reminders_save_template

Guardar una plantilla de recordatorio con nombre

reminders_list_templates

Listar plantillas guardadas

reminders_delete_template

Eliminar una plantilla guardada

reminders_create_from_template

Crear un recordatorio a partir de una plantilla, con anulaciones por llamada

reminders_save_view

Guardar un filtro basado en palabras con nombre como vista reutilizable

reminders_list_views

Listar vistas guardadas

reminders_delete_view

Eliminar una vista guardada

reminders_run_view

Ejecutar una vista guardada y devolver los recordatorios coincidentes

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    C
    maintenance
    An MCP server that enables AI assistants like Claude to access and manipulate Apple Notes on macOS, allowing for retrieving, creating, and managing notes through natural language interactions.
    82
    MIT
  • F
    license
    -
    quality
    C
    maintenance
    An MCP server that gives AI assistants access to your Apple Notes, Reminders, and Contacts — with optional BERT-powered semantic search.
    2

View all related MCP servers

Related MCP Connectors

  • Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.

  • MCP connector for Apple Reminders — search, create, complete, and edit via your own Mac.

  • MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/martijnstegink/apple-notes-reminders-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server