Skip to main content
Glama
estrenuo

OmniFocus MCP Server

by estrenuo

OmniFocus MCP Server

Un servidor del Model Context Protocol (MCP) que permite a los asistentes de IA interactuar con OmniFocus en macOS mediante JXA (JavaScript for Automation).

Características

Este servidor MCP proporciona acceso a funcionalidad de OmniFocus:

Gestión de tareas

  • Listar tareas de la bandeja de entrada — Ver y filtrar tareas en tu bandeja de entrada (incluido el filtrado por varias etiquetas)

  • Crear tareas — Añadir nuevas tareas con soporte completo de propiedades (fechas de vencimiento, fechas planificadas, etiquetas, notas, subtareas, recurrencia)

  • Actualizar tareas — Cambiar el nombre, la nota, las fechas, el marcado, la estimación, la recurrencia o mover una tarea a otro proyecto

  • Completar/Descartar tareas — Marcar tareas como completadas o descartadas, individualmente o en lote

  • Eliminar tareas — Quitar una tarea de forma permanente

  • Actualizar notas de tarea — Reemplazar, vaciar o añadir texto a la nota de una tarea

  • Obtener tareas vencidas — Encontrar tareas cuyo vencimiento cae dentro de un período

  • Obtener tareas planificadas — Encontrar tareas planificadas dentro de un período

  • Obtener tareas marcadas — Listar todos los elementos marcados

  • Añadir/quitar etiquetas a tareas — Gestionar las etiquetas de una tarea, individualmente o en lote

Gestión de proyectos

  • Listar proyectos — Ver proyectos con filtrado por estado

  • Obtener tareas del proyecto — Listar todas las tareas pertenecientes a un proyecto

  • Crear proyectos — Nuevos proyectos con ubicación en carpeta, estado, fechas, modo secuencial, intervalo de revisión

  • Actualizar proyectos — Cambiar el nombre, la nota, el estado, el marcado, las fechas, el modo secuencial, el intervalo de revisión

  • Eliminar proyectos — Eliminar un proyecto y sus tareas

  • Actualizar notas del proyecto — Reemplazar, vaciar o actualizar el texto de la nota de un proyecto

  • Obtener proyectos para revisar — Encontrar proyectos que necesitan revisión, opcionalmente con sus tareas incompletas

  • Marcar proyecto revisado — Actualizar el estado de revisión de un proyecto y su próxima fecha de revisión

  • Marcar revisados en lote — Revisar eficientemente varios proyectos a la vez

Organización

  • Listar carpetas — Ver la jerarquía de carpetas

  • Crear/renombrar/eliminar carpetas — Gestionar el árbol de carpetas (incluidas las carpetas anidadas)

  • Listar etiquetas — Ver todas las etiquetas

  • Listar perspectivas — Ver perspectivas integradas y personalizadas

  • Obtener tareas de una perspectiva — Listar las tareas que muestra una perspectiva concreta

Búsqueda

  • Búsqueda universal — Buscar en tareas, proyectos, carpetas y etiquetas

Propiedades de seguridad

  • Sin ganador silencioso con nombres duplicados. OmniFocus permite que dos proyectos (o tareas) compartan nombre. Las búsquedas por nombre recopilan todas las coincidencias y fallan con los IDs coincidentes cuando hay más de una, de modo que un renombrado, una reubicación o un borrado nunca puede dar en el elemento equivocado y al mismo tiempo informar de un éxito.

  • Las mutaciones se verifican. Las operaciones en las que JXA puede fallar silenciosamente (en particular mover una tarea entre proyectos) releen el resultado dentro del mismo script, de forma que un movimiento fallido se notifica como error y no como éxito.

Related MCP server: OmniFocus MCP Server

Requisitos

  • macOS (OmniFocus solo está disponible para macOS/iOS, y este servidor usa JXA)

  • OmniFocus 3+ instalado

  • Node.js 18+

  • Permisos de automatización habilitados para tu terminal/aplicación cliente

Instalación

  1. Clona o descarga este repositorio:

    cd omnifocus-mcp-server
  2. Instala las dependencias:

    npm install
  3. Compila el TypeScript:

    npm run build
  4. Configura tu cliente MCP para usar el servidor (consulta Configuración abajo)

Configuración

Claude Desktop

Añade al archivo de configuración de Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "omnifocus": {
      "command": "/opt/homebrew/bin/node",
      "args": ["/path/to/omnifocus-mcp-server/dist/index.js"]
    }
  }
}

Usa una ruta absoluta al binario node. Un "node" a secas se resuelve usando el PATH de la sesión gráfica, que no incluye Homebrew ni los shims de un gestor de versiones, por lo que el servidor no arranca y aparece un error del estilo «server unreachable», aunque desde tu terminal funcione correctamente. Encuentra la tuya con which node.

Otros clientes MCP

El servidor usa transporte stdio por defecto, así que configura tu cliente para lanzar:

node /path/to/omnifocus-mcp-server/dist/index.js

Acceso remoto (transporte HTTP)

Para clientes remotos — los más importantes son los conectores personalizados de claude.ai, que es como la app de Claude para iOS llega a los servidores MCP — el servidor puede ejecutarse como un endpoint HTTP Streamable:

MCP_TRANSPORT=http \
MCP_AUTH_TOKEN="$(openssl rand -hex 32)" \
node /path/to/omnifocus-mcp-server/dist/index.js

Variables de entorno:

Variable

Default

Propósito

MCP_TRANSPORT

stdio

Ponlo a http para habilitar el transporte HTTP

MCP_HTTP_PORT

3000

Puerto de escucha

MCP_HTTP_HOST

127.0.0.1

Dirección de enlace (mantén loopback; expónlo mediante un túnel)

MCP_AUTH_TOKEN

Secreto compartido necesario; el servidor no arranca sin él

MCP_PUBLIC_URL

Origen público HTTPS en el que el servidor es accesible (p. ej. https://your-tunnel-host). Ajústalo para activar la capa OAuth que necesitan la interfaz de “Connectors” de claude.ai / Claude Desktop. Déjalo sin definir para clientes directos/programáticos, que solo necesitan el token estático.

OMNIFOCUS_SCRIPT_TIMEOUT_MS

60000

Rompe un script JXA que se cuelgue (aplica a ambos transportes)

El endpoint MCP es /mcp. La autenticación acepta una cabecera Authorization: Bearer <token>, o el token como segmento de ruta (/mcp/<token>) para clientes que no puedan enviar cabeceras personalizadas. GET /health no requiere autenticación.

Llegar a él desde claude.ai / la app de iOS. Los conectores personalizados se conectan desde la nube de Anthropic (no desde tu dispositivo), por lo que el endpoint debe ser accesible públicamente por HTTPS. Para esto sirven tanto un Clodeflare Tunnel como un Tailscale Funnel; en cualquier caso, un proceso local realiza una conexión saliente, así que no necesitas abrir puertos. (El Tailscale normal, sin Funnel, no: solo alcanza tu propia tailnet, en la que la nube de Anthropic no está.) Opcionalmente puedes restringir el acceso al rango de IP de salida de Anthropic (160.79.104.0/21) en una regla WAF de Cloudflare.

La interfaz de “Connectors” de claude.ai y de Claude Desktop (a diferencia de una configuración MCP en bruto o de un cliente API directo) siempre exige un handshake OAuth completo antes de llamar a un servidor remoto; no acepta el token estático por sí solo, ni siquiera incrustado en la URL. Ajusta MCP_PUBLIC_URL al origen público de tu túnel para activar una capa OAuth autoemitida que cumpla este requisito y que todas las características sigan estando protegidas con el mismo secreto estático (consulta oauth.ts / CLAUDE.md para más detalle). Con esto ajustado, añade el conector en Settings → Connectors mediante la URL con el token en la ruta (https://your-tunnel-host/mcp/<token>) — el paso “Connect” completará automáticamente el handshake OAuth. Si tu túnel también proxía / a otro servicio local, asegúrate de que /authorize, /token, /register y /.well-known/* estén también mapeados a este servidor; de lo contrario las peticiones OAuth nunca llegarán aquí.

El Mac debe permanecer despierto y con OmniFocus en ejecución (caffeinate -s o Amphetamine).

Semántica de sesión: solo un cliente. El transporte HTTP atiende una sola sesión por vez: una nueva initialize reemplaza la sesión anterior. Cada llamada a una herramienta es sin estado, y un cliente que cumple la especificación vuelve a inicializarse al recibir 404 para una sesión que ya no existe, por lo que un único cliente con llamadas secuenciales funciona bien. Esto también cubre el caso de que el servidor no tiene sesión en absoluto, que es lo que los pasa a todos los clientes después que el servidor se reinicia — se reinicializan en vez de tratar la punto como muerto.

Con dos clientes a la vez no. Se reproduce lanzando dos secuencias concurrentes initializetools/list hacia el endpoint público: una siempre recibe 404. El SDK de MCP subyacente vincula un único transporte a la instancia compartida del servidor, con lo cual la sesión perdedora es expulsada y su solicitud en curso recibe 404 o se queda colgada. Arreglar eso requiere una instancia de McpServer por sesión en lugar de patrón actual de registro sobre un singleton; no está planificado. Véanse los detalles en CLAUDE.md.

Solucionar problemas de un cliente que «no puede conectarse». Los clientes resumen cualquier fallo remoto en un único mensaje vago, así que lee el log de este servidor (StandardErrorPath de agente de tu inicio) en lugar de lo que dice el cliente: el código de estado indica cuál de tres cosas no relacionadas ha ocurrido:

Qué muestra el log

Significado

Solución

↳ path token rejected: got N chars …

El token de la URL delquiero es incorrecto o llega truncado

Vuelve a copiar entero <MCP_PUBLIC_URL>/mcp/<token>; no lo teclees nunca

↳ authorize rejected: resource … !== …

La misma causa, vista desde el lado de OAuth. Un /authorize → 302 sin un /token posterior siempre significa esto

Igual que arriba

[…] → 404 y luego un initialize nuevo

Recuperación normal después de un reinicio o de una sesión secuestrada

Nada; el cliente se re-inicializa

[initialize] → 200 — client: …

Funcionando. El nombre del cliente identifica cuál cliente es.

Si el log no muestra nada en absoluto, la petición nunca llegó a este servidor: comprueba los mapas de rutas del túnel y no este código.

Permisos

En el primer uso, macOS te pedirá que permitas el acceso de automatización:

  1. Ve a Preferencias del SistemaSeguridad y PrivacidadPrivacidadAutomatización

  2. Activa el permiso para que tu terminal o Claude Desktop controle OmniFocus

Reference de herramientas

Todas las 31 herramientas se listan abajo, agrupadas por área.

omnifocus_list_inbox

Lista las tareas de la bandeja de entrada, opcionalmente filtradas por etiquetas.

{
  "includeCompleted": false,
  "limit": 50,
  "tags": ["Work", "Urgent"],
  "tagMatchMode": "all"
}

tagMatchMode es "all" (la tarea tiene todas las etiquetas listadas; por defecto), "any" (al menos una) o "none" (ninguna de ellas). Solo se aplica cuando se proporciona tags. Los mismos dos parámetros funcionan en omnifocus_get_due_tasks, omnifocus_get_flagged_tasks y omnifocus_get_planned_tasks.

omnifocus_list_projects

Lista proyectos con filtrado.

{
  "status": "active",
  "folderName": "Work",
  "limit": 50
}

omnifocus_get_project_tasks

Obtiene todas las tareas pertenecientes a un solo proyecto.

{
  "projectId": "abc123",
  "includeCompleted": false,
  "limit": 100
}

omnifocus_create_project

Crea un proyecto, opcionalmente dentro de una carpeta.

{
  "name": "Website redesign",
  "note": "Q1 initiative",
  "folderName": "Work",
  "dueDate": "2024-03-31T17:00:00",
  "deferDate": "2024-01-15T09:00:00",
  "flagged": false,
  "sequential": false,
  "status": "active",
  "reviewIntervalDays": 7
}

status es "active" (predeterminado), "on hold", "done" o "dropped". sequential: false (predeterminado) crea un proyecto paralelo.

omnifocus_update_project

Actualiza las propiedades de un proyecto. Identifícalo por projectId o projectName (el ID tiene prioridad).

{
  "projectId": "abc123",
  "name": "Website redesign v2",
  "status": "on hold",
  "flagged": true,
  "dueDate": null,
  "sequential": true,
  "reviewIntervalDays": 14
}

Pasa null para note, dueDate o deferDate para borrarlos. Un proyecto no puede moverse a otra carpeta (limitación de JXA).

omnifocus_delete_project

Elimina un proyecto y sus tareas. Identifícalo por projectId o projectName (el ID tiene prioridad).

{
  "projectId": "abc123"
}

omnifocus_list_folders

Lista todas las carpetas.

{
  "status": "active",
  "limit": 50
}

omnifocus_create_folder

Crea una carpeta, de nivel superior o anidada.

{
  "name": "Clients",
  "parentFolderName": "Work"
}

omnifocus_update_folder

Cambia el nombre de una carpeta. Identifícala por folderId o folderName (el ID tiene prioridad). Una carpeta no puede moverse dentro de otra carpeta (limitación de JXA).

{
  "folderName": "Clients",
  "name": "Key clients"
}

omnifocus_delete_folder

Elimina una carpeta y todo su contenido. Identifícala por folderId o folderName (el ID tiene prioridad).

{
  "folderId": "abc123"
}

omnifocus_list_tags

Lista todas las etiquetas.

{
  "status": "active",
  "limit": 50
}

omnifocus_list_perspectives

Lista las perspectivas (integradas y personalizadas).

{
  "limit": 50
}

omnifocus_get_perspective_tasks

Obtiene las tareas que se muestran en una perspectiva concreta.

{
  "perspectiveName": "Next",
  "limit": 50
}

omnifocus_create_task

Crea una nueva tarea.

{
  "name": "Review quarterly report",
  "note": "Check all sections",
  "projectName": "Work",
  "dueDate": "2024-12-31T17:00:00",
  "deferDate": "2024-12-01T09:00:00",
  "plannedDate": "2024-12-15T09:00:00",
  "flagged": true,
  "estimatedMinutes": 60,
  "tagNames": ["Review", "Important"],
  "parentTaskId": "xyz789",
  "recurrence": {
    "frequency": "weekly",
    "interval": 1,
    "daysOfWeek": ["Monday", "Thursday"],
    "repeatFrom": "due-date"
  }
}

Fecha planificada frente a fecha de vencimiento:

  • dueDate: cuándo debe completarse la tarea (fecha límite)

  • plannedDate: cuándo tienes previsto trabajar en la tarea (planificación)

  • Esta distinción es crucial para separar las fechas límite del tiempo de trabajo programado

Recurrencia: frequency es "daily", "weekly", "monthly" o "yearly". Usa daysOfWeek para semanal, dayOfMonth (1-31) para mensual, monthOfYear (1-12) para anual. repeatFrom es "due-date" (predeterminado) o "completion-date".

Subtareas: pasa parentTaskId para crear la tarea como hija de una tarea existente.

omnifocus_update_task

Actualiza una tarea existente. Identifícala por taskId o taskName (el ID tiene prioridad).

{
  "taskId": "abc123",
  "name": "Review quarterly report (final)",
  "note": null,
  "dueDate": "2024-12-20T17:00:00",
  "flagged": true,
  "estimatedMinutes": 45,
  "projectName": "Work"
}
  • Pasa null para note, dueDate, deferDate o plannedDate para borrarlos; estimatedMinutes: 0 borra la estimación.

  • projectId / projectName mueve la tarea a ese proyecto (las subtareas van con ella). El movimiento se verifica después, por lo que un fallo se notifica como error en lugar de un falso éxito.

  • recurrence acepta el mismo objeto que create_task; recurrence: null o clearRecurrence: true desactiva la repetición.

omnifocus_delete_task

Elimina una tarea. Identifícala por taskId o taskName (el ID tiene prioridad).

{
  "taskId": "abc123"
}

omnifocus_update_task_note

Reemplaza, borra o añade contenido a la nota de una tarea. Identifícala por taskId o taskName (el ID tiene prioridad).

{
  "taskId": "abc123",
  "note": "Added after the call.",
  "append": true
}

Una cadena note vacía borra la nota.

omnifocus_complete_task

Marca una tarea como completada o descartada. Puedes identificar la tarea por ID o por nombre.

{
  "taskId": "abc123",
  "action": "complete"
}

O usando el nombre de la tarea:

{
  "taskName": "Write documentation",
  "action": "complete"
}

La acción puede ser "complete" (predeterminado) o "drop". Si se proporcionan tanto taskId como taskName, taskId tiene prioridad.

Descartar una tarea repetitiva borra primero su regla de repetición, de modo que la serie realmente se detiene en lugar de avanzar a la siguiente ocurrencia.

omnifocus_batch_complete_task

Completa o descarta hasta 100 tareas por ID en una sola llamada.

{
  "taskIds": ["id1", "id2", "id3"],
  "action": "complete"
}

omnifocus_add_tag_to_task

Añade una etiqueta a una tarea. Puedes identificar la tarea por ID o por nombre.

{
  "taskId": "abc123",
  "tagName": "Urgent"
}

O usando el nombre de la tarea:

{
  "taskName": "Write report",
  "tagName": "Urgent"
}

Si se proporcionan tanto taskId como taskName, taskId tiene prioridad.

omnifocus_remove_tag_from_task

Elimina una etiqueta de una tarea. Puedes identificar la tarea por ID o por nombre.

{
  "taskId": "abc123",
  "tagName": "Urgent"
}

O usando el nombre de la tarea:

{
  "taskName": "Old task",
  "tagName": "Done"
}

Si se proporcionan tanto taskId como taskName, taskId tiene prioridad.

omnifocus_batch_add_tag

Añade una etiqueta existente a hasta 100 tareas por ID.

{
  "taskIds": ["id1", "id2", "id3"],
  "tagName": "Urgent"
}

omnifocus_batch_remove_tag

Elimina una etiqueta de hasta 100 tareas por ID.

{
  "taskIds": ["id1", "id2", "id3"],
  "tagName": "Urgent"
}

omnifocus_update_project_note

Reemplaza, borra o añade contenido a la nota de un proyecto. Identifícalo por projectId o projectName (el ID tiene prioridad).

{
  "projectName": "Website redesign",
  "note": "Kickoff moved to March.",
  "append": false
}

omnifocus_search

Busca en OmniFocus.

{
  "query": "report",
  "searchType": "all",
  "limit": 20
}

omnifocus_get_due_tasks

Obtiene las tareas que vencen dentro de un período de tiempo.

{
  "daysAhead": 7,
  "includeOverdue": true,
  "limit": 50
}

omnifocus_get_flagged_tasks

Obtiene las tareas marcadas con bandera.

{
  "includeCompleted": false,
  "limit": 50
}

omnifocus_get_planned_tasks

Obtiene las tareas planificadas dentro de un período de tiempo.

{
  "daysAhead": 7,
  "includeOverdue": true,
  "limit": 50
}

omnifocus_get_projects_for_review

Obtiene los proyectos que necesitan revisión según su próxima fecha de revisión. Perfecto para practicantes de GTD que siguen el flujo de trabajo de revisión.

{
  "daysAhead": 0,
  "status": "active",
  "limit": 50,
  "includeTasks": true,
  "taskLimit": 50
}

Parámetros:

  • daysAhead: cuántos días hacia adelante mirar (0 = solo revisiones atrasadas)

  • status: filtra por estado del proyecto ("active", "done", "dropped", "onHold", "all")

  • limit: número máximo de proyectos a devolver (1-500)

  • includeTasks: incluye las tareas incompletas de cada proyecto en el resultado (predeterminado false) — esto convierte una pasada de revisión en una sola llamada en lugar de una llamada de seguimiento por proyecto

  • taskLimit: número máximo de tareas por proyecto cuando includeTasks es true (1-200, predeterminado 50)

Cada proyecto también devuelve reviewInterval y lastReviewDate.

omnifocus_mark_project_reviewed

Marca un proyecto como revisado y actualiza su próxima fecha de revisión. Puedes identificar el proyecto por ID o por nombre.

{
  "projectId": "abc123"
}

O usando el nombre del proyecto:

{
  "projectName": "Weekly Review"
}

Con intervalo de revisión personalizado:

{
  "projectName": "Work Project",
  "reviewIntervalDays": 14
}

Parámetros:

  • projectId o projectName: identifica el proyecto (el ID tiene prioridad)

  • reviewIntervalDays (opcional): intervalo de revisión personalizado en días. Si no se proporciona, usa el intervalo de revisión existente del proyecto.

omnifocus_batch_mark_reviewed

Marca varios proyectos como revisados en una sola operación eficiente.

{
  "projectIds": ["id1", "id2", "id3"]
}

Con intervalo de revisión personalizado para todos:

{
  "projectIds": ["id1", "id2", "id3"],
  "reviewIntervalDays": 7
}

Parámetros:

  • projectIds: matriz de IDs de proyectos para marcar como revisados (1-100 proyectos)

  • reviewIntervalDays (opcional): intervalo de revisión personalizado para aplicar a todos los proyectos

Devuelve un resumen con:

  • Número de revisiones correctas

  • Número de fallos

  • Datos completos de los proyectos con revisión correcta

  • Detalles del error para cualquier fallo

Formatos de fecha

Todas las fechas usan el formato ISO 8601: YYYY-MM-DDTHH:mm:ss

Ejemplos:

  • 2024-12-31T17:00:00 - 31 de diciembre de 2024 a las 17:00

  • 2024-06-15T09:00:00 - 15 de junio de 2024 a las 9:00

Gestión de errores

El servidor proporciona mensajes de error claros para problemas comunes:

  • OmniFocus no está en ejecución: inicia OmniFocus primero

  • Permiso denegado: activa los permisos de automatización en Preferencias del Sistema

  • Elemento no encontrado: el ID especificado no existe

  • Parámetros no válidos: comprueba el formato y los valores de los parámetros

Desarrollo

Compilación

npm run build

Modo de vigilancia

npm run dev

Pruebas

npm test              # All unit tests
npm run test:watch    # Watch mode
npm run test:coverage # Coverage report (thresholds enforced: 80% lines, 75% branches)

Las pruebas de integración en src/__tests__/integration.test.ts están omitidas por defecto: requieren una instancia de OmniFocus en ejecución y modifican tu base de datos real.

Prueba manual

Después de compilar, puedes probar con:

echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node dist/index.js

Aplicar cambios a un servidor en ejecución (importante)

Los clientes MCP obtienen la lista de herramientas una vez cuando se conectan y la almacenan en caché durante la sesión. npm run build por sí solo no actualiza un cliente que ya está conectado — Node no recarga en caliente y el cliente no volverá a obtener el esquema. Después de cambiar herramientas/esquemas debes reiniciar el servidor y hacer que cada cliente se reconecte:

  1. Recompilar: npm run build

  2. Reiniciar el proceso del servidor para que cargue el nuevo dist/:

    • LaunchAgent (transporte HTTP): launchctl kickstart -k gui/$(id -u)/com.sanderrobijns.omnifocus-mcp

    • Verifica que sirve el nuevo esquema: lsof -nP -iTCP:3000 -sTCP:LISTEN debería mostrar un PID recién iniciado.

  3. Reconectar cada cliente para que vuelva a obtener tools/list:

    • Claude Code / Cowork: inicia una nueva sesión (una sesión en ejecución mantiene su esquema en caché durante toda su vida).

    • Claude Desktop: sal y vuelve a abrir la aplicación (o activa/desactiva el servidor).

    • claude.ai / conector personalizado de Claude iOS: vuelve a sincronizar el conector en Configuración → Conectores (almacena en caché la lista de herramientas a nivel del conector).

Hasta que el cliente se reconecte, seguirá mostrando el esquema antiguo, aunque el servidor ya sirva el nuevo.

Licencia

MIT

Créditos

Construido con:

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity
Issues opened vs closed

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

View all related MCP servers

Related MCP Connectors

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…

  • Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.

  • MCP connector that lets ChatGPT list, search, and run your Apple Shortcuts via a local Mac agent

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/estrenuo/omnifocus-mcp-server'

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