productive-mcp
productive-mcp
Un servidor MCP para Productive.io: registra tiempo, inspecciona proyectos y gestiona entradas de tiempo desde cualquier cliente compatible con MCP (Claude Code, Claude Desktop, Cursor, etc.) usando inglés sencillo:
"log 2.5 hours on the Acme security review project"
"show me my time entries for last week"
"delete time entry 123456"
Construido sobre la API JSON:API v2 de Productive.io con coincidencia difusa de proyectos, caché de disco local y memoria de servicio predeterminado por proyecto, para que el caso común (registrar tiempo en un proyecto que usas regularmente) sea una sola frase.
Características
9 herramientas que cubren proyectos, servicios y entradas de tiempo (listar / crear / actualizar / eliminar)
Coincidencia difusa de proyectos:
"Acme","1099 Acme"o"1099"se resuelven en el mismo proyectoRecuerda tu servicio predeterminado por proyecto para que no tengas que especificarlo cada vez
Caché local para proyectos y servicios (TTL de 1 hora, actualizable manualmente)
Seguridad de credenciales: el token de API se lee del Llavero de macOS por defecto (se admiten variables de entorno como alternativa para Linux/WSL o uso sin interfaz gráfica)
Entrada en
hours, salida enhours: la API usa minutos internamente, pero tú nunca los vesAlcance "mío" por defecto:
list_time_entriessolo muestra tus propias entradas a menos que decidas lo contrario
Requisitos
Python 3.11+
Una cuenta de Productive.io con acceso a la API habilitado
macOS (recomendado, para la integración con el Llavero) — Linux / WSL funcionan mediante variables de entorno
Instalación
1. Clonar e instalar
git clone https://github.com/<you>/productive-mcp.git
cd productive-mcp
uv venv
uv pip install -e .(o python -m venv .venv && .venv/bin/pip install -e . si no usas uv)
2. Obtén tus credenciales de Productive
Necesitas tres valores:
Valor | Dónde encontrarlo |
Token de API | Productive → Ajustes → Integraciones de API → Generar nuevo token |
ID de organización | El segmento numérico en tu URL de Productive: |
ID de persona | Tu propio ID de usuario: abre tu perfil en Productive; es el segmento numérico en la URL |
3. Almacenar credenciales
Opción A — Llavero de macOS (recomendado en macOS)
security add-generic-password -s productive-mcp -a token -w "<token>" -U
security add-generic-password -s productive-mcp -a org_id -w "<org_id>" -U
security add-generic-password -s productive-mcp -a person_id -w "<person_id>" -UEl servidor busca estos valores al iniciar mediante la CLI security. Nunca se escriben en el disco por este proyecto.
Opción B — variables de entorno (Linux / WSL / CI / anulación)
export PRODUCTIVE_MCP_TOKEN="<token>"
export PRODUCTIVE_MCP_ORG_ID="<org_id>"
export PRODUCTIVE_MCP_PERSON_ID="<person_id>"Las variables de entorno tienen prioridad sobre las búsquedas en el Llavero, por lo que también son la forma más sencilla de probar cuentas alternativas temporalmente.
4. Registra el servidor con tu cliente MCP
Claude Code (~/.claude.json)
Añade bajo mcpServers:
{
"mcpServers": {
"productive": {
"type": "stdio",
"command": "/path/to/productive-mcp/.venv/bin/productive-mcp",
"args": []
}
}
}Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"productive": {
"command": "/path/to/productive-mcp/.venv/bin/productive-mcp"
}
}
}Reinicia el cliente después de editar su configuración.
5. (Opcional) Instalación global con el script de despliegue incluido
Si quieres una instalación compartida que no esté vinculada a un directorio de clonación:
bash scripts/install.shEsto crea ~/.local/share/productive-mcp/ conteniendo un venv nuevo y un lanzador run.sh. Apunta tu cliente MCP a ~/.local/share/productive-mcp/run.sh en lugar del binario del venv. Volver a ejecutar el script actualiza el venv en su lugar.
Herramientas
Todas las herramientas tienen el prefijo productive_ para que se agrupen limpiamente junto a otros servidores MCP.
Herramienta | Propósito |
| Listar todos los proyectos activos (id, nombre, número, empresa) |
| Búsqueda difusa de proyectos por nombre y/o número |
| Listar servicios (tipos de actividad facturables) en un proyecto dado |
| Crear una entrada de tiempo |
| Listar entradas de tiempo con filtros opcionales de fecha/proyecto/propietario |
| Editar horas / fecha / nota / servicio en una entrada existente |
| Eliminar permanentemente una entrada de tiempo |
| Forzar una actualización inmediata de la caché (después de crear nuevos proyectos/servicios) |
| Anular el servicio predeterminado recordado para un proyecto |
Referencia de herramientas
productive_log_time
project : str — Project name (fuzzy) or numeric id. e.g. "1099 Acme", "42"
hours : float — Hours worked (e.g. 2.5). Converted to minutes internally.
note : str? — Description of the work
date : str? — ISO date (YYYY-MM-DD). Defaults to today.
service_hint : str? — Service name or id (only needed when the project has
multiple services and no remembered default)Si tiene éxito, devuelve la entrada creada más una nota service_resolution explicando cómo se eligió el servicio ("auto-selected only service" / "used remembered default" / "matched by name" etc.).
Si el proyecto tiene solo un servicio, se selecciona automáticamente y se guarda como predeterminado para la próxima vez. Si tiene varios, el servidor devuelve un error accionable listando las opciones.
productive_find_project
query : str — Partial name or number (e.g. "Acme", "1099 acme", "1099")
limit : int — Max matches (default 5)Devuelve coincidencias puntuadas ordenadas de mejor a peor. El buscador difuso combina la coincidencia de subcadenas de tokens, una alternativa de coincidencia de secuencias para errores tipográficos y un impulso cuando la consulta contiene un número de proyecto exacto.
productive_list_time_entries
after : str? — Include entries on/after this ISO date
before : str? — Include entries on/before this ISO date
project : str? — Filter by project name or id
mine_only : bool — Default True; set False to see the whole team's entriesLas entradas se devuelven de más reciente a más antigua, con totales acumulados en total_hours.
Cómo funciona
Arquitectura
┌─────────────────────┐ stdio ┌──────────────────────┐ HTTPS ┌─────────────────┐
│ MCP client │ ─────────► │ productive-mcp │ ────────► │ Productive.io │
│ (Claude Code etc.) │ │ (FastMCP server) │ │ JSON:API v2 │
└─────────────────────┘ └──────────┬───────────┘ └─────────────────┘
│
▼
~/.config/productive-mcp/
├── cache.json (projects, services; 1h TTL)
└── preferences.json (per-project default service)Decisiones clave de diseño
Los servicios están vinculados a Deals, que pertenecen a Proyectos. El modelo de datos de Productive hace esto visible; el MCP recorre la jerarquía de forma transparente para que "servicios en el proyecto X" simplemente funcione.
Las horas son la única unidad orientada al usuario. La API almacena el tiempo en minutos; esta capa realiza la conversión en el límite.
Los valores predeterminados recordados reducen el ir y venir. Después de registrar tiempo en un proyecto una vez, las llamadas posteriores pueden omitir
service_hint: el valor predeterminado se recuerda por proyecto enpreferences.json.Coincidencia difusa sobre coincidencia exacta. La mayoría de las solicitudes de registro de tiempo dicen algo como "esa revisión de seguridad para Acme", no "proyecto #1099". El resolutor se inclina hacia el lenguaje natural.
Solo "mío" por defecto. Casi siempre estás registrando tiempo para ti mismo; la única persona que necesita visibilidad de todo el equipo puede pasar
mine_only=False.
Estado local
Dos archivos viven bajo ~/.config/productive-mcp/, ambos creados con permisos 0600:
cache.json: lista de proyectos recortada y búsqueda de servicios por proyecto. Se actualiza automáticamente al expirar el TTL o medianteproductive_refresh_cache.preferences.json:{ "default_services": { "<project_id>": "<service_id>" } }.
Ninguno de los archivos contiene credenciales.
Orden de búsqueda de credenciales
Variable de entorno (
PRODUCTIVE_MCP_TOKEN/_ORG_ID/_PERSON_ID)Llavero de macOS (
security find-generic-password -s productive-mcp -a <account>)Error: el servidor se niega a iniciar con un mensaje útil que apunta a ambas opciones.
Desarrollo
uv pip install -e ".[dev]"
# unit tests (no network required)
pytest
# integration tests (hit the real Productive API — requires credentials)
pytest -m integration
# lint + type check
ruff check .
mypy srcEjecuta el servidor directamente para depurar:
.venv/bin/productive-mcp
# or
python -m productive_mcpHabla JSON-RPC por stdio, así que para probarlo manualmente necesitarás un cliente MCP o mcp-inspector.
Diseño del proyecto
src/productive_mcp/
├── __main__.py Entrypoint (`python -m productive_mcp`)
├── server.py FastMCP tool definitions
├── client.py Async Productive.io API client + fuzzy matcher
├── auth.py Keychain / env-var credential loader
└── storage.py Local cache + preferences persistence
scripts/
└── install.sh One-shot deploy script for the global launcher
tests/
└── test_client.py Unit tests for trimming + fuzzy matchingSolución de problemas
"Keychain lookup failed"
O el elemento aún no existe (vuelve a ejecutar los comandos security add-generic-password en el paso 3) o no estás en macOS. Usa variables de entorno en su lugar.
"No project matches 'X'"
Tu caché puede estar desactualizada si el proyecto se creó recientemente. Llama a productive_refresh_cache e inténtalo de nuevo.
"Ambiguous project query" Dos proyectos obtuvieron una puntuación casi idéntica. Sé más específico: añade el número de proyecto o el nombre de la empresa.
"Project has multiple services; pass service_hint"
El proyecto aún no tiene un valor predeterminado establecido. Pasa service_hint="…" en esta llamada (se recordará) o llama a productive_set_default_service una vez por adelantado.
El servidor inicia, pero el cliente informa "no tools"
Asegúrate de que tu cliente MCP apunte al binario productive-mcp del venv (o al lanzador run.sh), no a un archivo fuente. FastMCP anuncia las herramientas en el momento del saludo: si el proceso no puede importar mcp, no aparecerá ninguna herramienta.
Notas de seguridad
Los tokens de API nunca son escritos en el disco por este proyecto. Solo viven en el Llavero o en variables de entorno.
Los archivos de caché y preferencias se crean con permisos
0600y no contienen credenciales.El token de la API de Productive otorga el mismo acceso que tiene tu usuario. Trátalo en consecuencia. Rótalo a través de Productive → Ajustes → Integraciones de API si sospechas de exposición.
Alternativas
Existen otros servidores MCP de Productive.io; vale la pena revisarlos antes de adoptar este:
berwickgeek/productive-mcp: el servidor de propósito general más completo (proyectos, tareas, tableros, personas, flujos de trabajo). Node.js. Sin seguimiento de tiempo.
adamchrabaszcz/productive-time-mcp: servidor de seguimiento de tiempo complementario para el anterior.
druellan/Productive-Simple-MCP: servidor Python/FastMCP de solo lectura que usa salida TOON para un bajo uso de tokens.
laurkee/productive-mcp (Codeberg): enfocado en tickets.
¿Por qué elegir este? Este servidor está estrechamente enfocado en el flujo de trabajo de "registrar tiempo y gestionar entradas", y la UX está construida en torno a tres decisiones:
Credenciales en el Llavero de macOS por defecto, no en un
.env: sin riesgo de que un token termine engit status.Coincidencia difusa de proyectos con impulso por número de proyecto: di
"1099 Acme"o solo"Acme"; ambos funcionan.Memoria de servicio predeterminado por proyecto: después del primer
productive_log_timeen un proyecto, las llamadas posteriores no necesitan especificar un servicio.
Si necesitas principalmente tareas/tableros/flujos de trabajo en lugar de registro de tiempo, usa berwickgeek/productive-mcp en su lugar, o ejecuta ambos lado a lado (usan prefijos de herramienta diferentes).
Licencia
MIT: consulta LICENSE.
Contribución
Las incidencias y PRs son bienvenidos. Este es un proyecto pequeño; por favor, mantén los cambios enfocados e incluye pruebas para cualquier comportamiento nuevo en client.py.
No afiliado a Productive.io. "Productive" es una marca comercial de sus respectivos propietarios.
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/cameronfairbairn/productive-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server