Evernote MCP 服务器

  
一个本地MCP服务器,用于将Claude Desktop(或任何兼容MCP的大型语言模型)与您的Evernote账户连接起来,使您能够使用自然语言对笔记进行上下文查询和搜索。
🎯 项目目标
启用本地、安全的AI辅助访问您的Evernote笔记。例如:
“总结我关于Sea Pro船的所有Evernote笔记。”
这个项目允许大型语言模型(LLM)发送MCP调用,例如 createSearch, getNote,和 getNoteContent这些内容被翻译成Evernote的API调用。响应以结构化格式返回给大型语言模型(LLM)。
🚀 v2.0+版本的新功能
v2.0.0:生产就绪的Docker部署
- 🐳 表示“海豚”或“鲸鱼”(取决于具体语境,有时也可泛指海洋哺乳动物)。 一键设置:
docker-compose up用于即时部署 - 🔐(锁形符号,常用于表示保密、安全或需要密码的界面) 持续认证OAuth令牌在容器重启后仍然有效
- 🛡️(盾牌符号,常用于表示保护、防御等含义) 安全至上Chainguard 无发行版基础镜像,零 CVE(无已知安全漏洞)
- ⚡(闪电符号,常用于表示速度、活力或紧急情况) 优化后的构建多阶段Docker构建,以最小化生产环境占用空间
- 🔧(扳手) 自动配置SSL证书和环境设置自动处理
v2.0.1:增强了MCP协议支持
- 🌐 代表“地球”或“互联网”的符号,可直接用作描述相关概念,无需额外翻译。 远程MCP服务器支持容器化Claude Desktop集成的HTTP/JSON-RPC 2.0
- 🔄 翻译成中文可以是“🔄”(这个符号本身在中文中通常表示“循环”或“重复”的意思,但直接翻译的话,由于它是一个特定的符号,所以通常保留原样或根据上下文解释其含义)。不过,如果非要给出一个更贴近其含义的中文表达,可以是“循环”或“重复”。但在这里,由于要求直接翻译这个符号,所以答案就是“🔄”。 双集成模式选择本地stdin/stdout或远程HTTPS集成
- 📋 代表“待办事项列表”或“清单”,在中文中可以翻译为“清单”或“待办事项”。 MCP规范符合性更新了工具定义和方法名称以符合官方MCP规范
- 🎯(瞄准靶心) 智能回复可读性强的摘要,而非原始的JSON数据导出
- 🌍 代表地球的符号,常用于表达全球、世界或地球相关的概念。 跨平台兼容性克服了Windows/Linux上Docker的stdin/stdout限制
v2.1.0:容器稳定性与错误容错性
- 🛡️ 译为中文是“盾牌”。 全局错误处理添加了未捕获异常和未处理拒绝的处理程序,以防止进程崩溃
- 🔄 旋转(循环) 集装箱稳定性在容器化部署(Podman/Docker)中消除了2-3分钟的重启周期
- 📊(表格) 增强的错误日志记录通过时间戳和PID追踪,提高了生产错误的可见性
- 🎯(目标) 优雅降级即使身份验证或API失败,服务器仍继续运行
- 🚫 禁止/禁止使用 移除了进程退出(或:进程终止)将致命的 process.exit() 调用替换为优雅的错误处理
- ⚡(闪电符号,无特定文字含义,常用于表示速度、能量或警示) 生产测试在生产模式下验证了容器的稳定性,未启用DEV_MODE调试日志记录
v2.1.1:生产日志优化
- 🧹(扫帚) 最小化生产测井清理了生产部署中的冗长调试代码
- 🎯 目标/靶心 基本稳定性组件维护了关键的信号处理程序和全局错误处理机制
- 📝(一个带有笔的图标,常用于表示笔记或待办事项) 开发模式(DEV_MODE)条件日志记录可选的调试输出仅在 DEV_MODE=true 时出现
- ⚡(闪电符号,无特定含义,常用于表示速度、能量或紧急情况) 事件循环稳定性最小化保持活动状态可防止 Node.js 在容器中进入非活动状态
- ✅ 验证集装箱稳定性10分钟以上的稳定性测试确认,在生产模式下未出现重启循环
✅ 特点
- 支持 仅读取权限的Evernote访问 (搜索、阅读并列出笔记)
- OAuth 1.0a 认证 浏览器自动启动以进行安全授权
- 自动令牌持久化 在 \
.env\文件中进行无缝重新认证 - 🆕 版本1.1.0:自动检测令牌过期 - 服务器在启动时检查令牌的有效性
- 🆕 版本1.1.0:交互式重新认证提示 - 代币过期时提供用户友好的提示
- 🆕 版本1.1.0:增强了错误处理功能 - 具体的EDAMUserException错误代码报告
- 🆕 版本1.1.0:主动式令牌管理 防止因凭证过期导致的API故障
- 🆕 v1.1.1:自动持久化 .env 文件中的令牌 - 令牌自动保存到 .env 文件中(替代 macOS 密钥链以实现跨平台兼容性)
- 🆕 版本1.1.2:安全加固 - 对于存在漏洞的依赖项,npm 替换方案中未发现任何 CVE(通用漏洞和暴露)
- 🆕 版本2.0.0:生产就绪的Docker部署 - 使用Chainguard安全镜像实现全面容器化
- 🆕 版本2.0.1:增强了MCP协议的合规性 - 支持远程HTTP/JSON-RPC服务器和智能响应格式化
- 🆕 版本2.1.0:容器稳定性增强 - 通过全局错误处理和优雅降级,消除了重启周期
- 🆕 版本2.1.1:生产日志优化 - 生产环境下的简洁最小化日志记录,支持DEV_MODE条件调试输出
- 仅支持HTTPS的服务器 使用自签名证书进行本地开发
- 设计为与……配合使用 Claude Desktop MCP 集成,同时为其他大型语言模型(如ChatGPT Desktop)做好未来兼容性准备
- 可配置的调试日志记录 通过
DEV_MODE用于安全目的的自动令牌屏蔽的环境变量 - 日后易于扩展,用于创建、更新或删除笔记
🛠 技术栈
- Node.js + Express 配合 HTTPS
- 印象笔记API(OAuth 1.0a + REST)
- 使用 dotenv 存储环境变量令牌
- MCP协议合规性
- 使用 Chainguard 安全基础镜像进行 Docker 容器化
🗝️ 认证
Evernote使用OAuth 1.0a(而非OAuth 2.0)进行API认证:
- 首次设置基于浏览器的OAuth 1.0a流程,支持自动令牌交换
- 令牌存储访问令牌自动保存到 .env 文件以实现持久化
- 自动重用存储的令牌会自动加载并用于后续的API调用
- 生产环境使用Evernote生产API(沙盒已停用)
- 跨平台兼容性在macOS、Linux和Windows系统上均可运行,采用基于文件的令牌存储方式
🔒 安全
漏洞管理
这个项目使用了npm overrides 确保所有依赖项使用安全版本,消除嵌套的漏洞包:
{
"overrides": {
"ws": "^8.18.3"
}
}为什么需要重写(或覆盖)方法依赖项如 thrift 可能会捆绑他们自己易受攻击的版本(例如。, ws@5.2.4) 在嵌套中 node_modules标准的npm更新仅影响顶层依赖,而留下易受攻击的嵌套包 overrides 强制所有包的实例使用安全版本。
安全特性:
- ✅ Docker漏洞扫描中未发现任何CVE(通用漏洞和披露)
- ✅ Chainguard 安全基础镜像(无发行版,最小攻击面)
- ✅ 仅使用HTTPS并进行证书验证
- ✅ 只读Evernote API访问
- ✅ 除Evernote外,不向第三方传输数据
- ✅ 调试日志中的自动令牌屏蔽
💻 设置
🐳 Docker 部署(推荐)
快速入门:
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你得到的是:
- ✅ 瞬间设置,无需本地依赖
- ✅ 准备就绪的Chainguard安全基础镜像,可用于生产
- ✅ 自动生成SSL证书
- ✅ OAuth令牌在容器重启后仍然保留
- ✅ 零CVE安全扫描
🛠️ 本地开发
要求:
- Node.js 18及以上版本
- 用于SSL证书生成的OpenSSL
- Evernote开发者账户和API凭证
- Docker Desktop(中文可译为“Docker 桌面版”) (用于容器化部署)
- 通过1Password配置的GitHub SSH密钥(用于开发)
- 带有GitHub Copilot和Copilot Chat扩展的Visual Studio Code(用于开发)
克隆并设置
git clone git@github.com:brentmid/evernote-mcp-server.git
cd evernote-mcp-server
npm install获取Evernote API凭据
- 注册您的应用程序 在 Evernote 开发者
- 创建一个新应用 并记下您的消费者密钥和消费者秘密
- 设置回调URL 到
https://localhost:3443/oauth/callback
配置环境变量
设置您的Evernote API凭据:
# 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生成SSL证书
服务器通过HTTPS运行,并且本地开发需要SSL证书:
# 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"启动服务器
npx node index.js服务器将在 https://localhost:3443您的浏览器将对自签名证书显示安全警告——这在本地开发环境中是正常的。
⏰ 令牌过期处理(v1.1.0+)
服务器现在会在启动时自动检查过期的身份验证令牌:
对于有效令牌:
🚀 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对于过期令牌:
🚀 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...如果你选择 N (不),服务器将优雅地退出,并给出重启和选择的指示 y 当准备重新进行身份验证时。
首次运行与OAuth流程
- 生成SSL证书 (见上方设置说明)
- 设置环境变量 使用您的Evernote API凭据
- 启动服务器:
npx node index.js - 完成OAuth认证:
- 服务器会自动打开您的浏览器,跳转到Evernote的授权页面 - 在您的浏览器中接受自签名证书的警告 - 登录您的Evernote账户并授权该应用程序 - 您将收到成功消息并被重定向回服务器 - 访问令牌会自动存储在.env文件中,以便将来使用
OAuth 流程详情
服务器实现了Evernote的OAuth 1.0a流程:
- 请求令牌服务器生成临时请求令牌
- 用户授权浏览器打开Evernote授权页面
- 回调用户授权应用后,Evernote 重定向到回调 URL
- 访问令牌服务器用请求令牌交换永久访问令牌
- 存储访问令牌安全地存储在 .env 文件中
注服务器使用的是Evernote的生产环境(Evernote已弃用沙盒环境)。
🐳 Docker 部署
快速入门Docker
运行Evernote MCP服务器的最简单方法是使用提供的基于Chainguard的安全容器镜像来运行Docker:
# 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服务器将在 https://localhost:3443。
Docker 架构
Docker 设置使用 Chainguard 的安全 Node.js 基础镜像 (cgr.dev/chainguard/node:latest) 提供:
- 无漏洞 - 最小攻击表面积,仅包含必要软件包
- 签名的容器镜像 - 所有镜像均使用Sigstore签名,以确保供应链安全
- 包含软件物料清单(SBOM) - 在构建时生成的软件物料清单
- 非root执行 - 容器以非root用户身份运行,以增强安全性
- 最小尺寸 - 仅145MB,相比之下标准Node.js镜像为1.12GB
Docker 文件概述
Docker 的设置包括几个关键文件:
Dockerfile
多阶段构建过程:
- 构建阶段用途
cgr.dev/chainguard/node:latest-dev使用 git 和 openssl 进行设置 - 生产阶段使用最少
cgr.dev/chainguard/node:latest用于运行时 - GitHub 集成直接从您的GitHub仓库克隆最新代码
- SSL证书自动为HTTPS生成自签名证书
- 安全以非root用户身份运行,依赖极少
docker-compose.yml
编排配置:
- 环境变量来自...的负载
.env文件或环境 - 端口映射将HTTPS端口3443暴露给主机
- 健康检查内置容器健康监控
- 重启策略在故障时自动重启
- 构建论点可配置的GitHub仓库URL
.dockerignore
通过排除以下内容来优化构建上下文:
- 节点模块、日志和开发文件
- Git仓库数据和文档
- 测试文件和配置
- SSL证书(在容器中生成)
.env.example
环境变量模板:
EVERNOTE_CONSUMER_KEY=your_consumer_key_here
EVERNOTE_CONSUMER_SECRET=your_consumer_secret_here
DEV_MODE=falseDocker 构建选项
选项1:Docker Compose(推荐)
# 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选项2:直接使用Docker构建
# 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自动容器更新
该存储库包括 evernote-mcp-daily-rebuild.sh一个用于日常自动化重建的shell脚本,以保持您的Chainguard基础镜像为最新状态:
# 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脚本的作用是:
- 拉取最新内容
cgr.dev/chainguard/node:latest基础镜像 - 使用(指定的配置或参数)重建容器
--no-cache确保依赖项为最新版本 - 使用 Docker Compose 无中断重启服务
安全优势:
- 确保您始终能从 Chainguard 获取最新的安全补丁
- 通过自动化基础镜像更新保持零CVE状态
- 安全更新无需手动干预
Docker 配置
环境变量
该容器接受以下环境变量:
EVERNOTE_CONSUMER_KEY- 您的Evernote API消费者密钥(必需)EVERNOTE_CONSUMER_SECRET您的Evernote API消费者密钥(必需)DEV_MODE- 启用调试日志记录(可选,默认:false)NODE_ENV- Node.js 环境(在容器中设置为生产环境)
卷挂载(可选)
对于跨容器重启时的持久令牌存储:
volumes:
- ./tokens:/app/tokens # If implementing file-based token storage健康检查
该容器内置了健康监控功能:
- 终点;端点在端口3443上进行内部HTTPS健康检查
- 间隔每30秒
- 超时10秒
- 重试在标记为不健康之前有3次尝试机会
- 开始时期初始启动需40秒
Docker 故障排除
常见问题
构建失败,提示“未找到 git”:
- 确保您的GitHub仓库是公开的,或者配置身份验证
- 检查一下
GITHUB_REPO_URL在 docker-compose.yml 中构建参数
SSL证书错误:
- 证书在容器中自动生成
- 您的浏览器将对自签名证书显示安全警告(正常现象)
- 接受证书警告以继续
容器健康检查失败:
- 检查容器日志:
docker-compose logs evernote-mcp-server - 验证环境变量是否设置正确
- 确保Evernote API凭证有效
容器重启循环(每2-3分钟一次):
- ✅ 已决定 (2025年8月5日):通过优化健康检查实现,解决了容器稳定性问题
- ✅ 已确定根本原因Node.js 健康检查命令在创建累积超时进程
- ✅ 解决方案简化后的Node.js健康检查,结合适当的超时处理,消除了进程累积问题
- 详情请参阅CLAUDE.md以获取完整的调查时间线和技术解决方案分析
- 诊断工具使用提供的调试脚本解决类似问题(见下文“调试”部分)
- 状态容器运行稳定,健康检查正常,未检测到重启周期
容器中的OAuth流程问题:
- 完整的OAuth流程可能需要先在本地运行服务器
- 如果使用卷挂载,容器会从主机继承令牌
- 考虑跑步
node index.js先本地化,再容器化
Docker 日志与调试
# 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安全考量
Docker设置实现了多项安全最佳实践:
- 最小基础镜像Chainguard 的无发行版 Node.js 镜像
- 非root执行容器作为……运行
node用户(非root用户) - 仅支持HTTPS所有通信均通过安全的HTTPS进行
- 环境隔离通过环境变量传递的秘密
- 网络安全仅暴露必要的端口(3443)
- 供应链安全带有软件物料清单(SBOM)的签名基础镜像
性能优化
Docker 部署提供了多项性能优势:
- 一致的环境在不同机器上运行时间相同
- 资源限制可以通过docker-compose设置CPU/内存限制
- 缓存Docker 层缓存加快了重建速度
- 扩展(或缩放)在负载均衡器后轻松运行多个实例
🔗 Claude 桌面集成
该服务器支持与Claude Desktop的两种集成方法:
方法1:本地stdin/stdout集成(原始方法)
完成上述服务器设置后,配置Claude Desktop以直接执行进程。
步骤1:定位Claude桌面配置
~/Library/Application Support/Claude/claude_desktop_config.json步骤2:配置本地MCP服务器
根据您的设置,选择以下配置中的一种:
选项A:直接执行Node.js(本地开发)
{
"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"
}
}
}
}选项B:Docker容器执行(推荐用于生产环境)
{
"mcpServers": {
"evernote": {
"command": "docker",
"args": [
"exec", "-i", "--tty=false",
"evernote-mcp-server-evernote-mcp-server-1",
"node", "mcp-server.js"
]
}
}
}选项C:使用Podman容器执行(Docker的替代方案)
{
"mcpServers": {
"evernote": {
"command": "podman",
"args": [
"exec", "-i", "--tty=false",
"evernote-mcp-server_evernote-mcp-server_1",
"node", "mcp-server.js"
]
}
}
}📁 示例配置文件
一个例子 claude_desktop_config.json 此文件已包含在本仓库中。要使用它:
- 复制示例:
cp claude_desktop_config.json ~/Library/Application\ Support/Claude/claude_desktop_config.json - 根据您的设置进行定制:
- Docker 用户如果不同,请更新容器名称(请核对 docker ps) - Podman 用户替换 docker 和,与,带有 podman 并更新容器名称(与……核对 podman ps) - 本地设置使用选项A配置
- 重启Claude桌面版 完全退出(⌘+Q 然后重新打开)
容器名称自定义:
- 默认的 Docker Compose:
evernote-mcp-server-evernote-mcp-server-1 - 默认的 Podman Compose:
evernote-mcp-server_evernote-mcp-server_1(注:使用下划线代替连字符) - 自定义容器名称检查您的正在运行的容器
docker ps或者podman ps - 不同的运行时替换
docker与;和;带着podman,nerdctl等。
方法2:远程HTTP/JSON-RPC集成(v2.0.1新功能)
适用于容器化部署或跨平台兼容性。
步骤1:启动容器化服务器
docker-compose up -d步骤2:配置远程MCP服务器
{
"mcpServers": {
"evernote": {
"command": "npx",
"args": [
"@modelcontextprotocol/server-everything",
"--url", "https://localhost:3443/mcp"
],
"env": {
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
}
}
}远程集成的优势:
- ✅ 与Docker容器兼容(克服了stdin/stdout的限制)
- ✅ 跨平台兼容性(Windows、Linux、macOS)
- ✅ 可以连接到远程服务器实例
- ✅ 更适合生产环境部署
重要的请将占位符值替换为您的实际Evernote API凭据。
步骤3:重启Claude桌面应用
- 退出 Claude 桌面版 完全退出(⌘+Q 或右键点击停靠图标 → 退出)
- 重新打开Claude桌面版
- 验证连接你应该能在界面上看到可用的Evernote工具
步骤4:测试集成
试着让Claude搜索你的Evernote笔记:
“在我的Evernote中搜索有关项目规划的笔记”
“在Evernote中查找我最近的会议记录”
“显示所有标记为‘重要’的Evernote笔记”
可用的Claude桌面工具
一旦连接成功,Claude Desktop 将能够访问这些 Evernote 工具:
createSearch使用自然语言查询搜索笔记getSearch检索缓存的搜索结果getNote获取特定笔记的详细元数据getNoteContent以文本、HTML 或 ENML 格式检索完整的笔记内容
解决Claude桌面连接问题
连接失败,提示“上游连接错误”:
- 完全重启Claude桌面版(⌘+Q然后重新打开)
- 检查凭据是否已正确设置
claude_desktop_config.json - 确保服务器路径在
args是绝对且正确的(mcp-server.js不是index.js) - 测试独立MCP服务器:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node mcp-server.js
不可见的工具:
- 在Claude Desktop重启后等待几秒钟
- 检查Claude Desktop控制台中的错误信息
- 通过运行来验证OAuth认证是否成功完成
node index.js首先
认证错误:
- 首先独立运行HTTPS服务器以完成OAuth流程:
node index.js - 🆕 版本1.1.0服务器现在会自动检测过期的令牌,并提示重新进行身份验证
- 检查令牌存储在 .env 文件或环境变量中
- 验证Evernote API凭证是否有效且处于激活状态
- 🆕 版本1.1.0如果你得到
EDAMUserException错误,重启服务器以检查令牌是否过期
配置选项
选项1:环境变量(推荐) 在你的shell环境中设置凭据并删除(相关配置或说明) env 来自Claude桌面配置的部分:
# In your ~/.zshrc or ~/.bashrc
export EVERNOTE_CONSUMER_KEY="your-consumer-key"
export EVERNOTE_CONSUMER_SECRET="your-consumer-secret"然后使用这个更简单的Claude Desktop配置:
{
"mcpServers": {
"evernote": {
"command": "node",
"args": ["/path/to/your/evernote-mcp-server/mcp-server.js"]
}
}
}选项2:从终端启动 从设置了环境变量的终端打开Claude桌面版:
# Set credentials
export EVERNOTE_CONSUMER_KEY="your-key"
export EVERNOTE_CONSUMER_SECRET="your-secret"
# Launch Claude Desktop
open -a "Claude"🐛 调试与开发
调试日志记录
服务器支持通过(某种方式)进行详细的调试日志记录 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调试功能:
- MCP 工具调用对所有工具调用进行详细记录,并附上时间戳
- Evernote API 请求完整的请求有效载荷和参数
- 印象笔记API响应响应摘要和错误详情
- 令牌遮蔽(或令牌编辑、令牌处理,具体翻译取决于上下文)自动遮蔽敏感信息(令牌、密钥、密钥)
- 错误详情增强错误日志记录功能,包含原始响应数据
- 标准错误日志记录所有调试信息都输出到标准错误流(stderr),以避免干扰JSON-RPC协议
正常模式与调试模式:
- 正常仅记录关键信息的基本日志(输出到标准错误流)
- 调试详细的JSON日志记录,敏感数据已做脱敏处理(输出到标准错误流)
重要的所有基于表情符号的调试信息均发送至标准错误输出(stderr),而非标准输出(stdout),以确保与Claude Desktop的JSON-RPC通信保持整洁。
示例调试输出:
🔧 [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]"
}容器调试工具
此存储库包含用于排查容器问题的全面诊断脚本。这些脚本是在调查容器重启循环问题时开发的,对未来的调试工作非常有用。
可用的诊断脚本
1. catch_sigterm_sender.sh - SIGTERM 源检测
./catch_sigterm_sender.sh- 目的确定是哪个进程向容器发送SIGTERM信号
- 主要特点实时进程监控、SIGTERM信号关联、系统日志分析
- 调查结果成功识别 podman-remote 作为健康检查执行器
- 使用方法当容器接收到意外的SIGTERM信号时运行
2. test_manual_healthcheck.sh - 健康检查可靠性测试
./test_manual_healthcheck.sh- 目的跨多种方法测试健康检查的可靠性
- 测试方法curl(主机→容器)、Node.js(主机→容器)、Node.js(容器内部)
- 关键发现基于主机的健康检查显示50%的失败率,而容器内部检查则100%成功
- 使用方法当容器显示“不健康”状态或健康检查失败时运行
3. monitor_app_failure.sh - 运行时应用程序监控
./monitor_app_failure.sh- 目的在容器故障周期中监控Node.js应用程序的行为
- 监测内存使用情况、进程状态、资源使用情况、应用程序日志
- 关键发现检测到累积的超时进程导致容器崩溃
- 用法在容器重启周期中运行以捕获详细的故障数据
4. analyze_app_code.sh - 应用程序代码分析
./analyze_app_code.sh- 目的应用程序代码的常见故障模式静态分析
- 分析内存泄漏、事件监听器、错误处理程序、SSL问题、Docker配置
- 关键特性自动扫描问题代码模式
- 使用方法用于识别潜在应用问题的一线分析工具
调试方法论
对于集装箱稳定性问题,请遵循以下系统化方法:
第一阶段:代码分析
./analyze_app_code.sh在运行时调查之前,检查应用程序代码中的明显问题。
第二阶段:健康检查验证
./test_manual_healthcheck.sh验证不同方法下的健康检查可靠性,以识别网络或实施问题。
第三阶段:检测SIGTERM信号源
./catch_sigterm_sender.sh如果容器正在重启,请确定是哪个进程在发送终止信号。
阶段4:运行时监控
./monitor_app_failure.sh对于持续存在的问题,在故障周期中捕获详细的运行时行为。
诊断脚本功能
所有脚本均包含:
- ✅ 全面的文档记录 带有目的、用途和调查结果
- ✅ 带时间戳的日志记录 用于精确事件关联
- ✅ 无敏感信息 - 对于公开的GitHub仓库是安全的
- ✅ 可配置参数 - 轻松适应不同的容器设置
- ✅ 背景监测 - 在不干扰正常操作的情况下捕获数据
- ✅ 翻译成中文是:对/正确/确认。 分析指南 - 内置结果解读提示
用于容器重启调查的示例用法:
# 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调查结果概要
容器重启循环问题(2025年8月5日):
- ✅ 根本原因Node.js 健康检查命令导致累积超时进程的创建
- ✅ 检测方法运行时监控脚本揭示了进程累积模式
- ✅ 解决方案简化健康检查并妥善处理超时
- ✅ 结果容器稳定性已恢复,无需重启循环
这些工具为容器调试提供了一种系统化的方法,并且可以适应其他基于Node.js的容器化应用程序。
🧪 测试
该项目包含一个全面的测试套件,其中 38项测试 涵盖所有关键功能:
测试命令
# 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测试结构
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测试覆盖率详情
🔐 auth.test.js 翻译为中文是:“认证测试文件(或:授权测试文件).js” - OAuth 认证(12 项测试)
- OAuth 参数生成验证必需的OAuth 1.0a参数
- HMAC-SHA1 签名生成使用已知的测试向量测试加密签名
- 令牌存储在 .env 文件和环境变量中存储/检索令牌
- 认证流程现有令牌重用与新OAuth流程启动
- 配置验证Evernote的终端节点和环境变量
- 错误处理网络故障和环境变量访问错误
🌐 代表“全球”或“互联网”的符号,可翻译为“🌐(全球/互联网)”。不过,单独使用时,通常直接用“🌐”表示其含义,无需额外翻译。如果要在句子中使用,可以结合上下文进行描述。 server.test.js 翻译成中文是:“服务器测试文件.js” - Express 服务器路由(15 个测试)
- 健康检查 (
GET /): 服务器状态和JSON响应 - OAuth 回调 (
GET /oauth/callback):
- 成功的代币交换 - 缺少参数验证 - 无效的OAuth状态处理 - 错误场景
- MCP 端点 (
POST /mcp):
- 已认证的请求处理 - 未认证请求被拒绝(401) - JSON体解析 - 内部错误处理
- 内容类型处理JSON验证和异常请求处理
- 路线验证对于未知路由和错误的HTTP方法返回404错误
🔄 旋转(循环) integration.test.js 翻译成中文是:“集成测试文件.js” - 端到端工作流程(11项测试)
- 完整的OAuth流程模拟请求令牌 → 授权 → 访问令牌交换
- OAuth 状态管理请求与回调阶段之间的状态保持
- 浏览器集成系统浏览器启动以进行授权
- 错误场景网络故障、无效响应、环境变量错误
- 配置验证终端点URL和凭证验证
- 代币生命周期存储、检索和重用模式
覆盖要求
测试套件保持高覆盖率标准:
- 分支最低70%的覆盖率
- 功能最低80%的覆盖率
- 线条最低80%的覆盖率
- 陈述;声明最低80%的覆盖率
测试功能
- 全面模拟所有外部依赖(环境变量、浏览器、SSL、网络)
- 环境隔离测试专用的环境变量可防止干扰
- 真实加密货币测试使用已知的测试向量进行实际的HMAC-SHA1签名验证
- 错误场景覆盖网络故障、响应格式错误、访问被拒绝
- 集成验证无需外部API调用的完整OAuth工作流程模拟
运行特定测试
# 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"测试套件确保OAuth 1.0a实现的正确性,验证所有服务器端点,并在测试过程中无需实际调用Evernote API或使用SSL证书,即可对认证流程提供信心。Claude Desktop还可用于验证您的MCP服务器是否能正确响应自然语言提示。
📋 更新日志
v2.1.3(最新版)
🛡️ 可靠的健康检查实施:
- 基于流程的健康检查 - 实施了简单(的方案/措施)
/proc/1/stat文件系统检查以避免gvproxy网络问题 - 100%健康检查可靠性 - 已验证20/20测试通过,无误报失败
- 集装箱稳定性已确认 - 稳定运行8+分钟,且已恢复适当的健康监测
- 宽容的重试配置 - 间隔45秒,超时15秒,重试5次,启动周期60秒以防止误报
- 兼容外部监控 - 为监控系统提供标准的 Docker/Podman “(健康)” 状态
- 网络无关的 - 消除了导致原始重启循环的gvproxy端口转发依赖
v2.1.2(版本2.1.2)
🔧 容器健康检查修复:
- 容器重启循环解决 - 通过识别不可靠的健康检查作为根本原因,修复了2-3分钟的重启周期问题
- 健康检查可靠性调查 - 综合诊断测试显示,偶尔的健康检查失败会触发容器重启
- 临时禁用健康检查 - 禁用有问题的健康检查以消除误报故障
- 集装箱稳定性已验证 - 连续8分钟稳定运行,无需重启周期(之前每2-3分钟就会失败)
- 生产影响 - 解决了频繁的容器重启问题,该问题曾影响服务可用性
- 诊断方法论 - 系统性的测试方法,以区分健康检查问题与应用程序问题
版本2.1.1
🧹 生产日志优化:
- 最小化生产测井 - 移除了冗长的调试代码(内存使用情况、私有 Node.js API)
- 基本稳定得以保持 - 保留了v2.1.0版本中的关键信号处理程序和全局错误处理
- DEV_MODE 条件编译 - 调试日志仅在以下情况下出现
DEV_MODE=true环境变量已设置 - 事件循环稳定性 - 最小化的保持活动功能防止Node.js在容器中处于非活动状态
- 生产测试 - 验证了无重启周期下集装箱的稳定性超过10分钟
- 清洁生产日志 - 在生产模式下,仅显示必要的启动信息和错误信息
🔧 技术实施:
- 用最小化的保活功能替换了冗长的30秒心跳检测
- 为生产环境调试维护了SIGTERM、SIGINT、SIGQUIT信号处理器
- 移除了内存使用日志记录和私有 Node.js API 调用(\_getActiveHandles, \_getActiveRequests)
- 增加了条件日志记录:
if (process.env.DEV_MODE === 'true')用于调试输出 - 从 v2.1.0 版本开始,保留了未捕获的异常和未处理的拒绝处理程序
✅ 测试结果:
- 容器稳定运行超过8分钟,未重启(目标:达到10分钟以上,已实现)
- 在生产模式下未检测到重启周期(DEV_MODE=false)
- 日志确认输出极少——仅包含启动信息,无详细心跳信息
- 在整个测试期间,容器保持“健康”状态
v2.0.1(版本2.0.1)
🆕 增强的MCP协议支持:
- 远程MCP服务器支持 - 添加了对HTTP/JSON-RPC 2.0协议的支持
/mcp终端节点 - 双集成模式 - 支持本地stdin/stdout以及远程HTTPS集成
- MCP规范符合性 - 更新了工具定义和方法名称,以符合官方MCP规范
- 增强的工具定义 - 已添加
type: 'tool'领域和变化inputSchema到;对于;给;向parameters - 智能响应格式化 - 提供可读性强的摘要,而非原始的JSON数据输出
- 跨平台Docker集成 - 克服了容器化部署中的stdin/stdout限制
- 跨源资源共享(CORS)支持 - 为远程服务器设置正确的CORS头部和处理OPTIONS请求
- 格式检测 - 自动检测传统请求格式与JSON-RPC请求格式之间的差异
🔧 技术改进:
- 双格式终端路由,支持向后兼容
- 带有错误处理的JSON-RPC 2.0协议实现
- 通过上下文响应摘要提升用户体验
- 必需参数验证(例如,createSearch的查询参数)
v2.0.0(版本2.0.0)
🐳 准生产环境的Docker部署:
- 使用 Chainguard 安全基础镜像实现全面容器化
- 零CVE安全扫描及npm覆盖配置
- 容器重启时OAuth令牌的持久性
- 多阶段Docker构建以优化生产镜像
版本1.1.0
🆕 新功能:
- 自动检测令牌过期 - 服务器在启动时检查令牌的有效性
- 交互式重新认证提示 - 对于过期令牌的用户友好提示
- 增强的错误处理 - 具体的EDAMUserException错误代码报告
- 主动的代币管理 - 防止因凭证过期导致的API故障
🔧 技术改进:
- 添加了
checkTokenExpiration()具有全面验证功能的函数 - 已添加
askUserConfirmation()用于交互式用户提示 - 添加
clearStoredTokens()用于安全地清理令牌 - 增强服务器启动流程,加入过期检查
- 在整个认证流程中改进了错误信息提示
🧪 测试:
- 所有38项现有测试均继续通过
- 令牌过期功能已测试并验证
v1.0.0
- 首次发布,完整实现OAuth 1.0a
- 完全集成Apache Thrift协议
- 四个MCP工具:createSearch(创建搜索)、getSearch(获取搜索)、getNote(获取笔记)、getNoteContent(获取笔记内容)
- 全面的测试套件(38项测试)
- Claude Desktop MCP 集成
- 跨平台的.env文件令牌存储
- 使用自签名证书的HTTPS服务器
🔒 安全
- 除通过HTTPS发送至Evernote外,不向任何第三方发送数据。
- 认证令牌安全地存储在.env文件和环境变量中。
- 所有提交均强制要求使用签名密钥(基于SSH的GPG)。
📄 许可证
根据MIT许可证授权。详见 LICENSE 请查阅完整条款文件。
🙋♂️ 作者
由……维护 @brentmid(这个标签或用户名直接翻译为中文仍为“@brentmid”,因为它是特定的用户名或标签,没有实际的中文含义,直接保留原样即可)。\ 这个项目既是一个功能集成,也是在MCP、Evernote的API、GitHub工作流程以及现代Node.js实践方面的一次教育体验。
______________________________________________________________________
在最小可行性产品(MVP)完成后,欢迎提交拉取请求和贡献。请查看“问题”标签页了解已知任务。
