Evernote
Conecta tu cuenta de Evernote a un LLM, permitiendo búsquedas y consultas en lenguaje natural sobre tus notas.
Documentación
Servidor MCP de Evernote
Un servidor MCP local que conecta Claude Desktop (o cualquier LLM compatible con MCP) con tu cuenta de Evernote, permitiendo consultas contextuales y búsquedas sobre tus notas usando lenguaje natural.
🎯 Objetivo del Proyecto
Habilitar acceso local, seguro y asistido por IA a tus notas de Evernote. Por ejemplo:
"Resume todas mis notas de Evernote sobre mi barco Sea Pro."
Este proyecto permite que el LLM envíe llamadas MCP como createSearch, getNote y getNoteContent, que se traducen en llamadas API a Evernote. La respuesta se devuelve al LLM en un formato estructurado.
🚀 Novedades en v2.0+
v2.0.0: Despliegue Docker listo para producción
- 🐳 Configuración con un solo comando:
docker-compose uppara despliegue instantáneo - 🔐 Autenticación persistente: Los tokens OAuth sobreviven a los reinicios del contenedor
- 🛡️ Seguridad primero: Imágenes base mínimas Red Hat Hummingbird con cero CVEs
- ⚡ Builds optimizados: Builds Docker multi-etapa para una huella de producción mínima
- 🔧 Auto-configuración: Certificados SSL y configuración del entorno manejados automáticamente
v2.0.1: Soporte mejorado del protocolo MCP
- 🌐 Servidor MCP remoto: Soporte HTTP/JSON-RPC 2.0 para integración con Claude Desktop en contenedores
- 🔄 Modos de integración dual: Elige entre integración local stdin/stdout o HTTPS remota
- 📋 Cumplimiento de la especificación MCP: Definiciones de herramientas y nombres de métodos actualizados para coincidir con la especificación oficial de MCP
- 🎯 Respuestas inteligentes: Resúmenes legibles para humanos en lugar de volcados JSON crudos
- 🌍 Compatibilidad multiplataforma: Supera las limitaciones de stdin/stdout de Docker en Windows/Linux
v2.1.0: Estabilidad del contenedor y resiliencia ante errores
- 🛡️ Manejo global de errores: Se agregaron manejadores de excepciones no capturadas y rechazos no manejados para prevenir caídas del proceso
- 🔄 Estabilidad del contenedor: Se eliminaron ciclos de reinicio de 2-3 minutos en despliegues containerizados (Podman/Docker)
- 📊 Registro de errores mejorado: Mayor visibilidad de errores en producción con marcas de tiempo y seguimiento de PID
- 🎯 Degradación gradual: El servidor continúa ejecutándose incluso con fallos de autenticación o API
- 🚫 Salidas de proceso eliminadas: Se reemplazaron las llamadas fatales process.exit() con manejo de errores gradual
- ⚡ Probado en producción: Estabilidad del contenedor verificada en modo producción sin registro de depuración DEV_MODE
v2.1.1: Optimización del registro en producción
- 🧹 Registro mínimo en producción: Se limpió el código de depuración verboso para despliegues de producción
- 🎯 Componentes esenciales de estabilidad: Se mantuvieron los manejadores de señales críticos y el manejo global de errores
- 📝 Registro condicional DEV_MODE: La salida de depuración opcional solo aparece cuando DEV_MODE=true
- ⚡ Estabilidad del bucle de eventos: Keepalive mínimo evita que Node.js se vuelva inactivo en contenedores
- ✅ Estabilidad del contenedor verificada: Pruebas de estabilidad de más de 10 minutos confirmaron que no hay ciclos de reinicio en modo producción
✅ Características
- Soporta acceso de solo lectura a Evernote (búsqueda, lectura y listado de notas)
- Autenticación OAuth 1.0a con apertura automática del navegador para autorización segura
- Persistencia automática de tokens en el archivo .env para re-autenticación sin interrupciones
- 🆕 v1.1.0: Detección automática de expiración de tokens - El servidor verifica la validez del token al iniciar
- 🆕 v1.1.0: Avisos interactivos de re-autenticación - Avisos amigables cuando los tokens expiran
- 🆕 v1.1.0: Manejo de errores mejorado - Reporte específico de códigos de error EDAMUserException
- 🆕 v1.1.0: Gestión proactiva de tokens - Previene fallos de API por credenciales expiradas
- 🆕 v1.1.1: Persistencia automática de tokens en .env - Los tokens se guardan automáticamente en el archivo .env (reemplazó macOS Keychain para compatibilidad multiplataforma)
- 🆕 v1.1.2: Endurecimiento de seguridad - Cero CVEs con overrides de npm para dependencias vulnerables
- 🆕 v2.0.0: Despliegue Docker listo para producción - Containerización completa con imágenes seguras Chainguard
- 🆕 v2.0.1: Cumplimiento mejorado del protocolo MCP - Soporte de servidor HTTP/JSON-RPC remoto y formato de respuesta inteligente
- 🆕 v2.1.0: Mejoras de estabilidad del contenedor - Se eliminaron ciclos de reinicio con manejo global de errores y degradación gradual
- 🆕 v2.1.1: Optimización del registro en producción - Registro mínimo y limpio para producción con salida de depuración condicional DEV_MODE
- Servidor solo HTTPS con certificados autofirmados para desarrollo local
- Diseñado para funcionar con integraciones MCP de Claude Desktop, con preparación para otros LLMs (por ejemplo, ChatGPT Desktop)
- Registro de depuración configurable mediante la variable de entorno
DEV_MODEcon redacción automática de tokens por seguridad - Fácil de extender posteriormente para creación, actualización o eliminación de notas
🧰 Stack Tecnológico
- Node.js + Express con HTTPS
- API de Evernote (OAuth 1.0a + REST)
- Almacenamiento de tokens en variables de entorno con dotenv
- Cumplimiento del protocolo MCP
- Containerización Docker con imágenes base seguras Chainguard
🗝️ Autenticación
Evernote utiliza OAuth 1.0a (no OAuth 2.0) para la autenticación de API:
- Configuración inicial: Flujo OAuth 1.0a basado en navegador con intercambio automático de tokens
- Almacenamiento de tokens: Los tokens de acceso se guardan automáticamente en el archivo .env para persistencia
- Reutilización automática: Los tokens almacenados se cargan y utilizan automáticamente para llamadas API posteriores
- Entorno de producción: Utiliza la API de producción de Evernote (sandbox retirado)
- Compatibilidad multiplataforma: Funciona en macOS, Linux y Windows con almacenamiento de tokens basado en archivos
🔒 Seguridad
Gestión de vulnerabilidades
Este proyecto utiliza npm overrides para garantizar que todas las dependencias usen versiones seguras, eliminando paquetes vulnerables anidados:
{
"overrides": {
"ws": "^8.18.3"
}
}
Por qué se necesitan overrides: Dependencias como thrift pueden incluir sus propias versiones vulnerables (por ejemplo, ws@5.2.4) en node_modules anidados. Las actualizaciones estándar de npm solo afectan las dependencias de nivel superior, dejando paquetes anidados vulnerables. El campo overrides fuerza a TODAS las instancias de un paquete a usar la versión segura.
Características de seguridad:
- ✅ Cero CVEs en escaneos de vulnerabilidad Docker
- ✅ Imágenes base seguras Chainguard (distroless, superficie de ataque mínima)
- ✅ Solo HTTPS con validación de certificados
- ✅ Acceso de solo lectura a la API de Evernote
- ✅ Sin transmisión de datos a terceros excepto a Evernote
- ✅ Redacción automática de tokens en registros de depuración
💻 Configuración
🐳 Despliegue Docker (Recomendado)
Inicio rápido:
git clone https://github.com/brentmid/evernote-mcp-server.git
cd evernote-mcp-server
cp .env.example .env
# Edit .env with your Evernote API credentials
docker-compose up --build
Lo que obtienes:
- ✅ Configuración instantánea con cero dependencias locales
- ✅ Imágenes base seguras Chainguard listas para producción
- ✅ Generación automática de certificados SSL
- ✅ Los tokens OAuth persisten entre reinicios del contenedor
- ✅ Escaneo de seguridad con cero CVEs
🛠️ Desarrollo local
Requisitos:
- Node.js 18+
- OpenSSL para generación de certificados SSL
- Cuenta de desarrollador de Evernote y credenciales de API
- Docker Desktop (para despliegue containerizado)
- Clave SSH de GitHub configurada mediante 1Password (para desarrollo)
- Visual Studio Code con extensiones GitHub Copilot y Copilot Chat (para desarrollo)
Clonar y configurar
git clone git@github.com:brentmid/evernote-mcp-server.git
cd evernote-mcp-server
npm install
Obtener credenciales de API de Evernote
- Registra tu aplicación en Evernote Developers
- Crea una nueva aplicación y anota tu Consumer Key y Consumer Secret
- Configura la URL de callback a
https://localhost:3443/oauth/callback
Configurar variables de entorno
Configura tus credenciales de API de Evernote:
# Add to your shell profile (.zshrc, .bashrc, etc.)
export EVERNOTE_CONSUMER_KEY="your-consumer-key-here"
export EVERNOTE_CONSUMER_SECRET="your-consumer-secret-here"
# Optional: Enable detailed debug logging for development
export DEV_MODE=true
# Reload your shell or run:
source ~/.zshrc
Generar certificados SSL
El servidor se ejecuta sobre HTTPS y requiere certificados SSL para desarrollo local:
# Create certificate directory
mkdir cert
# Generate self-signed certificate (valid for 365 days)
openssl req -x509 -newkey rsa:4096 -keyout cert/localhost.key -out cert/localhost.crt -days 365 -nodes -subj "/C=US/ST=Local/L=Local/O=Local/OU=Local/CN=localhost"
Iniciar el servidor
npx node index.js
El servidor se iniciará en https://localhost:3443. Tu navegador mostrará una advertencia de seguridad por el certificado autofirmado; esto es normal para desarrollo local.
⏰ Manejo de expiración de tokens (v1.1.0+)
El servidor ahora verifica automáticamente si los tokens de autenticación han expirado al iniciar:
Para tokens válidos:
🚀 Starting Evernote MCP Server...
🔍 Token status: Token valid until 8/21/2025, 1:20:00 AM
✅ Using existing valid authentication tokens
✅ Authentication ready
🌐 Evernote MCP Server listening on HTTPS port 3443
Para tokens expirados:
🚀 Starting Evernote MCP Server...
🔍 Token status: Token expired on 6/16/2025, 9:55:49 PM
⚠️ Your Evernote authentication tokens have expired.
Would you like to re-authenticate now? (y/N): y
🧹 Re-authenticating with Evernote...
🚀 Starting Evernote OAuth flow...
Si eliges N (no), el servidor saldrá de forma controlada con instrucciones para reiniciar y elegir y cuando estés listo para re-autenticarte.
Primera ejecución y flujo OAuth
- Genera certificados SSL (consulta las instrucciones de configuración anteriores)
- Configura variables de entorno con tus credenciales de API de Evernote
- Inicia el servidor:
npx node index.js - Completa la autenticación OAuth:
- El servidor abre automáticamente tu navegador en la página de autorización de Evernote
- Acepta la advertencia de certificado autofirmado en tu navegador
- Inicia sesión en tu cuenta de Evernote y autoriza la aplicación
- Serás redirigido de vuelta al servidor con un mensaje de éxito
- El token de acceso se almacena automáticamente en el archivo .env para uso futuro
Detalles del flujo OAuth
El servidor implementa el flujo OAuth 1.0a de Evernote:
- Token de solicitud: El servidor genera un token de solicitud temporal
- Autorización del usuario: El navegador abre la URL de autorización de Evernote
- Callback: El usuario autoriza la aplicación, Evernote redirige a la URL de callback
- Token de acceso: El servidor intercambia el token de solicitud por un token de acceso permanente
- Almacenamiento: El token de acceso se almacena de forma segura en el archivo .env
Nota: El servidor utiliza el entorno de producción de Evernote (el sandbox ha sido retirado por Evernote).
🐳 Despliegue Docker
Inicio rápido con Docker
La forma más fácil de ejecutar el servidor MCP de Evernote es usando Docker con la imagen de contenedor segura basada en Chainguard proporcionada:
# Clone the repository
git clone https://github.com/brentmid/evernote-mcp-server.git
cd evernote-mcp-server
# Copy environment template
cp .env.example .env
# Edit .env with your Evernote API credentials
vim .env
# Build and run the container
docker-compose up --build
El servidor estará disponible en https://localhost:3443.
Arquitectura Docker
La configuración Docker utiliza la imagen base segura de Node.js de Chainguard (cgr.dev/chainguard/node:latest) que proporciona:
- Cero vulnerabilidades - Superficie de ataque mínima con solo paquetes esenciales
- Imágenes de contenedor firmadas - Todas las imágenes firmadas con Sigstore para seguridad de la cadena de suministro
- SBOM incluido - Lista de materiales de software generada en tiempo de compilación
- Ejecución sin root - Los contenedores se ejecutan como usuario no root para mayor seguridad
- Tamaño mínimo - Solo 145MB en comparación con 1.12GB de las imágenes estándar de Node.js
Resumen de archivos Docker
La configuración Docker incluye varios archivos clave:
Dockerfile
Proceso de compilación multi-etapa:
- Etapa de compilación: Utiliza
cgr.dev/chainguard/node:latest-devcon git y openssl para la configuración - Etapa de producción: Utiliza
cgr.dev/chainguard/node:latestmínimo para el tiempo de ejecución - Integración con GitHub: Clona el código más reciente directamente desde tu repositorio de GitHub
- Certificados SSL: Genera automáticamente certificados autofirmados para HTTPS
- Seguridad: Se ejecuta como usuario no root con dependencias mínimas
docker-compose.yml
Configuración de orquestación:
- Variables de entorno: Se cargan desde el archivo
.envo del entorno - Mapeo de puertos: Expone el puerto HTTPS 3443 al host
- Comprobaciones de salud: Monitoreo de salud del contenedor integrado
- Política de reinicio: Se reinicia automáticamente en caso de fallo
- Argumentos de compilación: URL del repositorio de GitHub configurable
.dockerignore
Optimiza el contexto de compilación excluyendo:
- Módulos de Node, registros y archivos de desarrollo
- Datos del repositorio Git y documentación
- Archivos de prueba y configuraciones
- Certificados SSL (generados en el contenedor)
.env.example
Plantilla para variables de entorno:
EVERNOTE_CONSUMER_KEY=your_consumer_key_here
EVERNOTE_CONSUMER_SECRET=your_consumer_secret_here
DEV_MODE=false
Opciones de compilación Docker
Opción 1: Docker Compose (Recomendado)
# Build and run with compose
docker-compose up --build
# Run in background
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop and remove
docker-compose down
Opción 2: Compilación Docker directa
# Build image
docker build \
--build-arg GITHUB_REPO_URL=https://github.com/yourusername/evernote-mcp-server.git \
-t evernote-mcp-server .
# Run container
docker run -d \
--name evernote-mcp \
-p 3443:3443 \
-e EVERNOTE_CONSUMER_KEY=your_key \
-e EVERNOTE_CONSUMER_SECRET=your_secret \
evernote-mcp-server
# View logs
docker logs -f evernote-mcp
Actualizaciones automatizadas del contenedor
El repositorio incluye evernote-mcp-daily-rebuild.sh, un script de shell diseñado para reconstrucciones automatizadas diarias para mantener tus imágenes base Chainguard actualizadas:
# Set up daily rebuild (example cron job)
0 2 * * * /path/to/your/evernote-mcp-server/evernote-mcp-daily-rebuild.sh >> /tmp/evernote-mcp-rebuild.log 2>&1
Lo que hace el script:
- Obtiene la imagen base
cgr.dev/chainguard/node:latestmás reciente - Reconstruye el contenedor con
--no-cachepara garantizar dependencias frescas - Reinicia el servicio con cero tiempo de inactividad usando Docker Compose
Beneficios de seguridad:
- Garantiza que siempre tengas los últimos parches de seguridad de Chainguard
- Mantiene el estado de cero CVEs con actualizaciones automatizadas de la imagen base
- No se requiere intervención manual para actualizaciones de seguridad
Configuración Docker
Variables de Entorno
El contenedor acepta estas variables de entorno:
EVERNOTE_CONSUMER_KEY- Tu clave de consumidor de la API de Evernote (requerida)EVERNOTE_CONSUMER_SECRET- Tu secreto de consumidor de la API de Evernote (requerido)DEV_MODE- Habilitar registro de depuración (opcional, predeterminado: false)NODE_ENV- Entorno de Node.js (configurado como production en el contenedor)
Montajes de Volumen (Opcional)
Para almacenamiento persistente de tokens entre reinicios del contenedor:
volumes:
- ./tokens:/app/tokens # If implementing file-based token storage
Verificaciones de Salud
El contenedor incluye monitoreo de salud integrado:
- Endpoint: Verificación de salud HTTPS interna en el puerto 3443
- Intervalo: Cada 30 segundos
- Tiempo de espera: 10 segundos
- Reintentos: 3 intentos antes de marcarlo como no saludable
- Período de inicio: 40 segundos para el arranque inicial
Solución de Problemas de Docker
Problemas Comunes
La compilación falla con "git not found":
- Asegúrate de que tu repositorio de GitHub sea público o configura la autenticación
- Verifica el argumento de compilación
GITHUB_REPO_URLen docker-compose.yml
Errores de certificado SSL:
- Los certificados se generan automáticamente en el contenedor
- Tu navegador mostrará advertencias de seguridad para certificados autofirmados (normal)
- Acepta la advertencia del certificado para continuar
Fallos en la verificación de salud del contenedor:
- Revisa los registros del contenedor:
docker-compose logs evernote-mcp-server - Verifica que las variables de entorno estén configuradas correctamente
- Asegúrate de que las credenciales de la API de Evernote sean válidas
Bucles de reinicio del contenedor (cada 2-3 minutos):
- ✅ RESUELTO (5 de agosto de 2025): Problema de estabilidad del contenedor corregido mediante una implementación optimizada de verificación de salud
- ✅ Causa raíz identificada: El comando de verificación de salud de Node.js estaba creando procesos de tiempo de espera acumulativos
- ✅ Solución: La verificación de salud simplificada de Node.js con manejo adecuado de tiempo de espera elimina la acumulación de procesos
- Detalles: Consulta CLAUDE.md para conocer la cronología completa de la investigación y el análisis de la resolución técnica
- Herramientas de diagnóstico: Utiliza los scripts de depuración proporcionados para problemas similares (consulta la sección de Depuración a continuación)
- Estado: Contenedor funcionando de manera estable con verificaciones de salud adecuadas, sin ciclos de reinicio detectados
Problemas de flujo OAuth en el contenedor:
- Completar el flujo OAuth puede requerir ejecutar el servidor localmente primero
- El contenedor hereda los tokens del host si se utilizan montajes de volumen
- Considera ejecutar
node index.jslocalmente primero y luego contenerizarlo
Registros de Docker y Depuración
# View container logs
docker-compose logs -f evernote-mcp-server
# Enable debug mode
echo "DEV_MODE=true" >> .env
docker-compose up --build
# Execute commands in running container
docker-compose exec evernote-mcp-server sh
# Check container health
docker-compose ps
Consideraciones de Seguridad
La configuración de Docker implementa varias mejores prácticas de seguridad:
- Imagen base mínima: Imagen distroless de Node.js de Chainguard
- Ejecución sin root: El contenedor se ejecuta como usuario
node(sin root) - Solo HTTPS: Toda la comunicación a través de HTTPS seguro
- Aislamiento del entorno: Secretos pasados a través de variables de entorno
- Seguridad de red: Solo se expone el puerto necesario (3443)
- Seguridad de la cadena de suministro: Imágenes base firmadas con SBOM
Optimización del Rendimiento
La implementación de Docker ofrece varios beneficios de rendimiento:
- Entorno consistente: Tiempo de ejecución idéntico en diferentes máquinas
- Límites de recursos: Se pueden establecer límites de CPU/memoria a través de docker-compose
- Caché: El caché de capas de Docker acelera las reconstrucciones
- Escalado: Fácil de ejecutar múltiples instancias detrás de un balanceador de carga
🔗 Integración con Claude Desktop
El servidor admite dos métodos de integración con Claude Desktop:
Método 1: Integración Local stdin/stdout (Original)
Después de completar la configuración del servidor anterior, configura Claude Desktop para la ejecución directa del proceso.
Paso 1: Localiza la Configuración de Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json
Paso 2: Configura el Servidor MCP Local
Elige una de estas configuraciones según tu configuración:
Opción A: Ejecución directa de Node.js (desarrollo local)
{
"mcpServers": {
"evernote": {
"command": "node",
"args": ["/path/to/your/evernote-mcp-server/mcp-server.js"],
"env": {
"EVERNOTE_CONSUMER_KEY": "your-actual-consumer-key",
"EVERNOTE_CONSUMER_SECRET": "your-actual-consumer-secret"
}
}
}
}
Opción B: Ejecución en contenedor Docker (recomendado para producción)
{
"mcpServers": {
"evernote": {
"command": "docker",
"args": [
"exec", "-i", "--tty=false",
"evernote-mcp-server-evernote-mcp-server-1",
"node", "mcp-server.js"
]
}
}
}
Opción C: Ejecución en contenedor Podman (alternativa a Docker)
{
"mcpServers": {
"evernote": {
"command": "podman",
"args": [
"exec", "-i", "--tty=false",
"evernote-mcp-server_evernote-mcp-server_1",
"node", "mcp-server.js"
]
}
}
}
📁 Archivo de Configuración de Ejemplo
Se incluye un archivo de ejemplo claude_desktop_config.json en este repositorio. Para usarlo:
- Copia el ejemplo:
cp claude_desktop_config.json ~/Library/Application\ Support/Claude/claude_desktop_config.json - Personalízalo para tu configuración:
- Usuarios de Docker: Actualiza el nombre del contenedor si es diferente (verifica con
docker ps) - Usuarios de Podman: Reemplaza
dockerconpodmany actualiza el nombre del contenedor (verifica conpodman ps) - Configuración local: Usa la configuración de la Opción A en su lugar
- Usuarios de Docker: Actualiza el nombre del contenedor si es diferente (verifica con
- Reinicia Claude Desktop por completo (⌘+Q y luego vuelve a abrirlo)
Personalización del Nombre del Contenedor:
- Docker Compose predeterminado:
evernote-mcp-server-evernote-mcp-server-1 - Podman Compose predeterminado:
evernote-mcp-server_evernote-mcp-server_1(nota: guiones bajos en lugar de guiones) - Nombre de contenedor personalizado: Verifica tus contenedores en ejecución con
docker psopodman ps - Diferente tiempo de ejecución: Reemplaza
dockerconpodman,nerdctl, etc.
Método 2: Integración Remota HTTP/JSON-RPC (Nuevo en v2.0.1)
Para implementaciones contenerizadas o compatibilidad multiplataforma.
Paso 1: Inicia el Servidor Contenerizado
docker-compose up -d
Paso 2: Configura el Servidor MCP Remoto
{
"mcpServers": {
"evernote": {
"command": "npx",
"args": [
"@modelcontextprotocol/server-everything",
"--url", "https://localhost:3443/mcp"
],
"env": {
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
}
}
}
Beneficios de la Integración Remota:
- ✅ Funciona con contenedores Docker (supera las limitaciones de stdin/stdout)
- ✅ Compatibilidad multiplataforma (Windows, Linux, macOS)
- ✅ Puede conectarse a instancias de servidor remoto
- ✅ Mejor para implementaciones de producción
Importante: Reemplaza los valores de marcador de posición con tus credenciales reales de la API de Evernote.
Paso 3: Reinicia Claude Desktop
- Sal de Claude Desktop por completo (⌘+Q o clic derecho en el ícono del dock → Salir)
- Vuelve a abrir Claude Desktop
- Verifica la conexión: Deberías ver las herramientas de Evernote disponibles en la interfaz
Paso 4: Prueba la Integración
Intenta pedirle a Claude que busque en tus notas de Evernote:
"Busca en mi Evernote notas sobre planificación de proyectos"
"Encuentra mis notas de reunión más recientes en Evernote"
"Muéstrame todas las notas de Evernote etiquetadas con 'importante'"
Herramientas Disponibles de Claude Desktop
Una vez conectado, Claude Desktop tendrá acceso a estas herramientas de Evernote:
createSearch: Busca notas usando consultas en lenguaje naturalgetSearch: Recupera resultados de búsqueda en cachégetNote: Obtén metadatos detallados para una nota específicagetNoteContent: Recupera el contenido completo de la nota en formato texto, HTML o ENML
Solución de Problemas de Conexión con Claude Desktop
La conexión falla con "upstream connect error":
- Reinicia Claude Desktop por completo (⌘+Q y luego vuelve a abrirlo)
- Verifica que las credenciales estén configuradas correctamente en
claude_desktop_config.json - Asegúrate de que la ruta del servidor en
argssea absoluta y correcta (mcp-server.jsnoindex.js) - Prueba el servidor MCP de forma independiente:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node mcp-server.js
Herramientas no visibles:
- Espera unos segundos después de reiniciar Claude Desktop
- Revisa la consola de Claude Desktop para ver mensajes de error
- Verifica que la autenticación OAuth se haya completado correctamente ejecutando
node index.jsprimero
Errores de autenticación:
- Completa el flujo OAuth ejecutando el servidor HTTPS de forma independiente primero:
node index.js - 🆕 v1.1.0: El servidor ahora detecta automáticamente tokens caducados y solicita reautenticación
- Verifica que los tokens estén almacenados en el archivo .env o en variables de entorno
- Asegúrate de que las credenciales de la API de Evernote sean válidas y estén activas
- 🆕 v1.1.0: Si recibes errores de
EDAMUserException, reinicia el servidor para verificar la caducidad del token
Alternativas de Configuración
Opción 1: Variables de Entorno (Recomendado)
Configura las credenciales en tu entorno de shell y elimina la sección env de la configuración de Claude Desktop:
# In your ~/.zshrc or ~/.bashrc
export EVERNOTE_CONSUMER_KEY="your-consumer-key"
export EVERNOTE_CONSUMER_SECRET="your-consumer-secret"
Luego usa esta configuración más simple de Claude Desktop:
{
"mcpServers": {
"evernote": {
"command": "node",
"args": ["/path/to/your/evernote-mcp-server/mcp-server.js"]
}
}
}
Opción 2: Iniciar desde la Terminal Abre Claude Desktop desde una terminal donde estén configuradas las variables de entorno:
# Set credentials
export EVERNOTE_CONSUMER_KEY="your-key"
export EVERNOTE_CONSUMER_SECRET="your-secret"
# Launch Claude Desktop
open -a "Claude"
🐛 Depuración y Desarrollo
Registro de Depuración
El servidor admite registro de depuración detallado a través de la variable de entorno DEV_MODE:
# Enable detailed debug logging
export DEV_MODE=true
# Or run with debug mode for a single session
DEV_MODE=true npx node index.js
Características de Depuración:
- Invocaciones de Herramientas MCP: Registro detallado de todas las llamadas a herramientas con marcas de tiempo
- Solicitudes a la API de Evernote: Cargas útiles y parámetros completos de las solicitudes
- Respuestas de la API de Evernote: Resúmenes de respuestas y detalles de errores
- Redacción de Tokens: Redacción automática de información sensible (tokens, secretos, claves)
- Detalles de Errores: Registro de errores mejorado con datos de respuesta sin procesar
- Registro en stderr: Todos los mensajes de depuración van a stderr para evitar interferir con el protocolo JSON-RPC
Modo Normal vs Modo Depuración:
- Normal: Registro básico solo con información clave (a stderr)
- Depuración: Registro JSON detallado con datos sensibles redactados (a stderr)
Importante: Todos los mensajes de depuración basados en emojis se envían a stderr, no a stdout, lo que garantiza una comunicación JSON-RPC limpia con Claude Desktop.
Ejemplo de salida de depuración:
🔧 [2025-06-17T00:07:56.351Z] MCP Tool Invocation: createSearch
📥 Args: {
"query": "Sea Pro boat",
"authenticationToken": "[REDACTED:19chars]"
}
🌐 [2025-06-17T00:07:57.123Z] Evernote API Request: /findNotesMetadata
📤 Request: {
"filter": { "words": "Sea Pro boat" },
"authenticationToken": "[REDACTED:19chars]"
}
Herramientas de Depuración de Contenedores
Este repositorio incluye scripts de diagnóstico completos para solucionar problemas de contenedores. Estos se desarrollaron durante la investigación de los bucles de reinicio de contenedores y son útiles para futuras depuraciones.
Scripts de Diagnóstico Disponibles
1. catch_sigterm_sender.sh - Detección de Fuente de SIGTERM
./catch_sigterm_sender.sh
- Propósito: Identifica qué proceso envía señales SIGTERM a los contenedores
- Características clave: Monitoreo de procesos en tiempo real, correlación de SIGTERM, análisis de registros del sistema
- Resultados de la investigación: Identificó con éxito a podman-remote como ejecutor de la verificación de salud
- Uso: Ejecuta cuando los contenedores reciben señales SIGTERM inesperadas
2. test_manual_healthcheck.sh - Pruebas de Fiabilidad de Verificación de Salud
./test_manual_healthcheck.sh
- Propósito: Prueba la fiabilidad de la verificación de salud en múltiples métodos
- Métodos de prueba: curl (host→contenedor), Node.js (host→contenedor), Node.js (interno al contenedor)
- Descubrimiento clave: Reveló una tasa de fallo del 50% en verificaciones de salud basadas en el host frente a un 100% de éxito para verificaciones internas al contenedor
- Uso: Ejecuta cuando los contenedores muestran estado "no saludable" o fallos en la verificación de salud
3. monitor_app_failure.sh - Monitoreo de Aplicaciones en Tiempo de Ejecución
./monitor_app_failure.sh
- Propósito: Monitorea el comportamiento de la aplicación Node.js durante ciclos de fallo del contenedor
- Monitoreo: Uso de memoria, estado del proceso, uso de recursos, registros de la aplicación
- Descubrimiento clave: Detectó procesos de tiempo de espera acumulativos que causaban fallos en el contenedor
- Uso: Ejecuta para capturar datos detallados de fallos durante ciclos de reinicio del contenedor
4. analyze_app_code.sh - Análisis de Código de Aplicación
./analyze_app_code.sh
- Propósito: Análisis estático del código de la aplicación para patrones de fallo comunes
- Análisis: Fugas de memoria, listeners de eventos, manejadores de errores, problemas de SSL, configuración de Docker
- Características clave: Escaneo automatizado de patrones de código problemáticos
- Uso: Herramienta de análisis de primera línea para identificar posibles problemas de la aplicación
Metodología de Depuración
Para problemas de estabilidad del contenedor, sigue este enfoque sistemático:
Fase 1: Análisis de Código
./analyze_app_code.sh
Verifica si hay problemas obvios en el código de la aplicación antes de la investigación en tiempo de ejecución.
Fase 2: Validación de Verificación de Salud
./test_manual_healthcheck.sh
Valida la fiabilidad de la verificación de salud en diferentes métodos para identificar problemas de red o implementación.
Fase 3: Detección de Fuente de SIGTERM
./catch_sigterm_sender.sh
Si los contenedores se están reiniciando, identifica qué proceso está enviando señales de terminación.
Fase 4: Monitoreo en Tiempo de Ejecución
./monitor_app_failure.sh
Para problemas continuos, captura el comportamiento detallado en tiempo de ejecución durante los ciclos de fallo.
Características de los Scripts de Diagnóstico
Todos los scripts incluyen:
- ✅ Documentación completa con propósito, uso y resultados de la investigación
- ✅ Registro con marcas de tiempo para una correlación precisa de eventos
- ✅ Sin información sensible - seguro para repositorios públicos de GitHub
- ✅ Parámetros configurables - fácilmente adaptables a diferentes configuraciones de contenedores
- ✅ Monitoreo en segundo plano - captura datos sin interferir con la operación normal
- ✅ Guía de análisis - consejos integrados para interpretar resultados
Ejemplo de uso para la investigación de reinicios de contenedores:
# Quick health check validation
./test_manual_healthcheck.sh
# If health checks are failing, identify the SIGTERM sender
./catch_sigterm_sender.sh
# For deeper analysis, monitor runtime behavior
./monitor_app_failure.sh
Resumen de Resultados de la Investigación
Problema de bucle de reinicio de contenedor (5 de agosto de 2025):
- ✅ Causa raíz: El comando de verificación de salud de Node.js crea procesos de tiempo de espera acumulativos
- ✅ Método de detección: El script de monitoreo en tiempo de ejecución reveló un patrón de acumulación de procesos
- ✅ Solución: Verificación de salud simplificada con manejo adecuado de tiempo de espera
- ✅ Resultado: Estabilidad del contenedor restaurada, sin ciclos de reinicio
Estas herramientas proporcionan un enfoque sistemático para la depuración de contenedores y pueden adaptarse a otras aplicaciones Node.js contenerizadas.
🧪 Pruebas
El proyecto incluye una suite de pruebas completa con 38 pruebas que cubren toda la funcionalidad crítica:
Comandos de prueba
# Run all tests
npm test
# Run tests with coverage report
npm run test:coverage
# Run tests in watch mode (for development)
npm run test:watch
Estructura de pruebas
tests/
├── auth.test.js # OAuth 1.0a authentication tests
├── server.test.js # Express server route tests
├── integration.test.js # End-to-end workflow tests
├── setup.js # Global test configuration
└── jest.config.js # Jest configuration
Detalles de cobertura de pruebas
🔐 auth.test.js - Autenticación OAuth (12 pruebas)
- Generación de parámetros OAuth: Valida los parámetros requeridos de OAuth 1.0a
- Generación de firma HMAC-SHA1: Prueba firmas criptográficas con vectores de prueba conocidos
- Almacenamiento de tokens: Almacena/recupera tokens en el archivo .env y variables de entorno
- Flujo de autenticación: Reutilización de token existente vs inicio de nuevo flujo OAuth
- Validación de configuración: Endpoints de Evernote y variables de entorno
- Manejo de errores: Fallos de red y errores de acceso a variables de entorno
🌐 server.test.js - Rutas del servidor Express (15 pruebas)
- Verificación de salud (
GET /): Estado del servidor y respuestas JSON - Callback OAuth (
GET /oauth/callback):- Intercambio de token exitoso
- Validación de parámetros faltantes
- Manejo de estado OAuth inválido
- Escenarios de error
- Endpoint MCP (
POST /mcp):- Manejo de solicitudes autenticadas
- Rechazo de solicitudes no autenticadas (401)
- Análisis del cuerpo JSON
- Manejo de errores internos
- Manejo de Content-Type: Validación JSON y manejo de solicitudes malformadas
- Validación de rutas: Errores 404 para rutas desconocidas y métodos HTTP incorrectos
🔄 integration.test.js - Flujos de trabajo de extremo a extremo (11 pruebas)
- Flujo OAuth completo: Token de solicitud simulado → autorización → intercambio de token de acceso
- Gestión de estado OAuth: Preservación del estado entre las fases de solicitud y callback
- Integración del navegador: Lanzamiento del navegador del sistema para autorización
- Escenarios de error: Fallos de red, respuestas inválidas, errores de variables de entorno
- Validación de configuración: URLs de endpoints y validación de credenciales
- Ciclo de vida del token: Patrones de almacenamiento, recuperación y reutilización
Requisitos de cobertura
La suite de pruebas mantiene altos estándares de cobertura:
- Ramas: 70% de cobertura mínima
- Funciones: 80% de cobertura mínima
- Líneas: 80% de cobertura mínima
- Declaraciones: 80% de cobertura mínima
Características de las pruebas
- Simulación integral: Todas las dependencias externas (variables de entorno, navegador, SSL, red)
- Aislamiento del entorno: Variables de entorno específicas de prueba evitan interferencias
- Pruebas criptográficas reales: Validación real de firma HMAC-SHA1 con vectores de prueba conocidos
- Cobertura de escenarios de error: Fallos de red, respuestas malformadas, denegaciones de acceso
- Validación de integración: Simulación completa del flujo OAuth sin llamadas API externas
Ejecución de pruebas específicas
# Run only authentication tests
npm test auth.test.js
# Run only server tests
npm test server.test.js
# Run only integration tests
npm test integration.test.js
# Run tests matching a pattern
npm test -- --testNamePattern="OAuth"
La suite de pruebas garantiza la correcta implementación de OAuth 1.0a, valida todos los endpoints del servidor y brinda confianza en el flujo de autenticación sin requerir llamadas reales a la API de Evernote ni certificados SSL durante las pruebas. Claude Desktop también se puede utilizar para validar que su servidor MCP responda correctamente a indicaciones de lenguaje natural.
📋 Registro de cambios
v2.2.1 (Última versión)
- Se migraron las imágenes base del contenedor de Chainguard a Red Hat Project Hummingbird
v2.2.0
- Se corrigió el análisis de la fecha de expiración del token (se eliminó la multiplicación errónea por *1000)
- Se corrigió la vulnerabilidad de inyección de comandos en la función openBrowser
v2.1.3
🛡️ Implementación de verificación de salud confiable:
- Verificación de salud basada en procesos - Se implementó una verificación simple del sistema de archivos
/proc/1/statevitando problemas de red de gvproxy - Confiabilidad del 100% en la verificación de salud - Se verificaron 20/20 pruebas exitosas con cero fallos falsos positivos
- Estabilidad del contenedor confirmada - Más de 8 minutos de operación estable con monitoreo de salud adecuado restaurado
- Configuración generosa de reintentos - Intervalo de 45s, tiempo de espera de 15s, 5 reintentos, período de inicio de 60s para evitar falsos positivos
- Compatible con monitoreo externo - Proporciona estado "(healthy)" estándar de Docker/Podman para sistemas de monitoreo
- Independiente de la red - Elimina las dependencias de reenvío de puertos de gvproxy que causaron los bucles de reinicio originales
v2.1.2
🔧 Corrección de verificación de salud del contenedor:
- Resolución del bucle de reinicio del contenedor - Se corrigieron los ciclos de reinicio de 2-3 minutos al identificar las verificaciones de salud no confiables como causa raíz
- Investigación de confiabilidad de la verificación de salud - Pruebas de diagnóstico exhaustivas revelaron fallos ocasionales de verificación de salud que provocaban reinicios del contenedor
- Desactivación temporal de la verificación de salud - Se desactivaron las verificaciones de salud problemáticas para eliminar fallos falsos positivos
- Estabilidad del contenedor verificada - Más de 8 minutos de operación estable sin ciclos de reinicio (anteriormente fallaba cada 2-3 minutos)
- Impacto en producción - Resuelve los reinicios frecuentes del contenedor que afectaban la disponibilidad del servicio
- Metodología de diagnóstico - Enfoque de pruebas sistemático para aislar problemas de verificación de salud vs problemas de aplicación
v2.1.1
🧹 Optimización de registro en producción:
- Registro mínimo en producción - Se eliminó el código de depuración verboso (uso de memoria, APIs privadas de Node.js)
- Estabilidad esencial mantenida - Se conservaron los manejadores de señales críticos y el manejo global de errores de v2.1.0
- Condicional DEV_MODE - El registro de depuración solo aparece cuando la variable de entorno
DEV_MODE=trueestá configurada - Estabilidad del bucle de eventos - La función keepalive mínima evita que Node.js se vuelva inactivo en contenedores
- Pruebas en producción - Se verificó estabilidad del contenedor por más de 10 minutos sin ciclos de reinicio
- Registros de producción limpios - Solo aparecen mensajes esenciales de inicio y error en modo producción
🔧 Implementación técnica:
- Se reemplazó el heartbeat verboso de 30 segundos con una función keepalive mínima
- Se mantuvieron los manejadores de señales SIGTERM, SIGINT, SIGQUIT para depuración en producción
- Se eliminó el registro de uso de memoria y las llamadas a APIs privadas de Node.js (_getActiveHandles, _getActiveRequests)
- Se agregó registro condicional:
if (process.env.DEV_MODE === 'true')para salida de depuración - Se conservaron los manejadores de excepciones no capturadas y rechazos no manejados de v2.1.0
✅ Resultados de las pruebas:
- El contenedor funcionó de manera estable durante más de 8 minutos sin reinicios (objetivo: más de 10 minutos logrado)
- No se detectaron ciclos de reinicio en modo producción (DEV_MODE=false)
- Los registros confirmaron salida mínima - solo mensajes de inicio, sin heartbeat verboso
- El contenedor mantuvo el estado "healthy" durante todo el período de pruebas
v2.0.1
🆕 Soporte mejorado del protocolo MCP:
- Soporte de servidor MCP remoto - Se agregó soporte del protocolo HTTP/JSON-RPC 2.0 en el endpoint
/mcp - Modos de integración dual - Soporte tanto para integración local stdin/stdout como para integración HTTPS remota
- Cumplimiento de la especificación MCP - Se actualizaron las definiciones de herramientas y nombres de métodos para coincidir con la especificación oficial de MCP
- Definiciones de herramientas mejoradas - Se agregó el campo
type: 'tool'y se cambióinputSchemaaparameters - Formato de respuesta inteligente - Resúmenes legibles por humanos en lugar de volcados JSON crudos
- Integración Docker multiplataforma - Supera las limitaciones de stdin/stdout para implementaciones contenerizadas
- Soporte CORS - Cabeceras CORS adecuadas y manejo de OPTIONS para servidores remotos
- Detección de formato - Detección automática entre formatos de solicitud heredados y JSON-RPC
🔧 Mejoras técnicas:
- Enrutamiento de endpoint de doble formato con compatibilidad hacia atrás
- Implementación del protocolo JSON-RPC 2.0 con manejo de errores
- Experiencia de usuario mejorada con resúmenes de respuesta contextuales
- Validación de parámetros requeridos (por ejemplo, parámetro de consulta para createSearch)
v2.0.0
🐳 Implementación Docker lista para producción:
- Contenerización completa con imágenes base seguras de Chainguard
- Escaneo de seguridad Zero-CVE y overrides de npm
- Persistencia de tokens OAuth entre reinicios del contenedor
- Construcciones Docker de múltiples etapas para imágenes de producción optimizadas
v1.1.0
🆕 Nuevas características:
- Detección automática de expiración de token - El servidor verifica la validez del token al inicio
- Indicaciones interactivas de re-autenticación - Indicaciones amigables para tokens expirados
- Manejo de errores mejorado - Reporte específico de códigos de error EDAMUserException
- Gestión proactiva de tokens - Previene fallos de API por credenciales expiradas
🔧 Mejoras técnicas:
- Se agregó la función
checkTokenExpiration()con validación integral - Se agregó
askUserConfirmation()para indicaciones interactivas de usuario - Se agregó
clearStoredTokens()para limpieza segura de tokens - Se mejoró el flujo de inicio del servidor con verificaciones de expiración
- Se mejoraron los mensajes de error en todo el flujo de autenticación
🧪 Pruebas:
- Las 38 pruebas existentes continúan pasando
- Funcionalidad de expiración de token probada y validada
v1.0.0
- Lanzamiento inicial con implementación completa de OAuth 1.0a
- Integración completa del protocolo Apache Thrift
- Cuatro herramientas MCP: createSearch, getSearch, getNote, getNoteContent
- Suite de pruebas integral (38 pruebas)
- Integración MCP de Claude Desktop
- Almacenamiento de tokens en archivo .env multiplataforma
- Servidor HTTPS con certificados autofirmados
🔒 Seguridad
- No se envían datos de terceros a ningún lugar excepto a Evernote a través de HTTPS.
- Los tokens de autenticación se almacenan de forma segura en archivos .env y variables de entorno.
- El uso de claves de firma (GPG basado en SSH) se aplica en todos los commits.
📄 Licencia
Licenciado bajo la Licencia MIT. Consulte el archivo LICENSE para conocer los términos completos.
🙋♂️ Autor
Mantenido por @brentmid.
Este proyecto es tanto una integración funcional como una experiencia educativa en MCP, la API de Evernote, flujos de trabajo de GitHub y prácticas modernas de Node.js.
Las solicitudes de extracción y contribuciones son bienvenidas después de completar el MVP. Consulte la pestaña de Issues para conocer las tareas pendientes.