使用说明
OneNote MCP服务器
OneNote MCP服务器是一个功能强大的模型上下文协议(MCP)服务器 使AI助手能够安全地与您的Microsoft OneNote数据进行交互。它 允许阅读、写作、搜索和全面编辑您的 OneNote笔记本、分区和页面直接通过您的AI界面。
此服务器为高级OneNote管理提供了一套丰富的工具, 包括健壮的文本提取、HTML内容处理和细粒度页面 操纵。
特性
- 身份验证: 用于Microsoft Graph API访问的安全设备代码流。
- 读取操作:
- 列出笔记本、分区、分区组和分区内的页面。
- 使用高级过滤功能按名称搜索部分,按标题搜索页面。
- 按修改日期范围和特定笔记本筛选页面。
- 获取各种格式的页面内容(完整HTML、可读文本、摘要)。
- 笔记本和章节管理:
- 创建新的笔记本、分区和分区组。
- 以编程方式构建和组织OneNote结构。
- 写入和编辑操作:
- 使用自定义HTML或markdown内容创建新的OneNote页面。
- 更新整个页面内容,保留或替换标题。
- 使用可选的时间戳和分隔符将内容附加到现有页面。
- 更新页面标题。
- 查找和替换页面中的文本(区分大小写或不区分大小写)。
- 在页面上添加格式化的笔记(如标注或待办事项)。
- 将结构化表格从CSV数据插入页面。
- 页面管理:
- 在各部分之间复制页面。
- 高级内容处理:
- 复杂的HTML到可读文本提取。
- 页面内容的Markdown到HTML转换。
- 稳健的错误处理:
- 针对瞬态故障,采用指数回退的自动重试(速率 限制、服务器错误、超时)。
- 详细的、可操作的错误消息,并为每个错误提供具体指导 类型。
- 智能处理身份验证、权限和网络问题。
- 安全与验证:
- 输入验证和消毒,以防止注射攻击。
- 使用Zod定义和验证工具输入模式。
- 性能优化:
- 对于频繁访问的资源(笔记本电脑, 部分)。
- 并行API调用多部分查询以减少延迟。
- 批处理资源验证,以最大限度地减少多余的API请求。
- 结构化日志记录:
- 使用Pino进行高性能、结构化的JSON日志记录。
- 可配置的日志级别(跟踪、调试、信息、警告、错误、致命)。
- 开发中的打印输出很漂亮,生产中的JSON。
先决条件
- Node.js: 建议使用18.x或更高版本。(从安装 nodejs.org)
- npm: 通常与Node.js捆绑在一起。
- Git
- Microsoft帐户: 具有OneNote访问权限的活动Microsoft帐户。
- Azure应用程序注册(建议用于生产/共享):
- 而服务器默认使用Microsoft Graph Explorer的公共 客户端ID便于测试,可供常规或共享使用,它是 强烈地 推荐 创建自己的Azure应用程序注册。
- 确保您的应用注册具有以下授权的Microsoft Graph API
权限:
Notes.Read,Notes.ReadWrite,Notes.Create,User.Read. - 您需要从应用程序注册中获得“应用程序(客户端)ID”。
安装
-
克隆存储库:
git clone https://github.com/IAmKSquared/onenotemcp.git cd onenotemcp -
安装依赖关系:
npm install
项目结构
为了可维护性和清晰性,代码库遵循模块化架构:
onenote-mcp-server/
├── src/
│ ├── auth/ # Authentication modules
│ │ ├── device-code-flow.mjs # OAuth device code flow
│ │ ├── token-manager.mjs # Token file operations
│ │ ├── encryption.mjs # AES-256-GCM authenticated encryption
│ │ └── key-storage.mjs # OS keychain integration
│ ├── api/ # API infrastructure
│ │ ├── cache.mjs # Caching layer with TTL
│ │ └── retry.mjs # Retry logic with exponential backoff
│ ├── tools/ # MCP tool definitions
│ │ ├── auth-tools.mjs # Authentication tools
│ │ ├── read-tools.mjs # Read operations (list, search, get)
│ │ ├── write-tools.mjs # Edit operations (update, append, replace)
│ │ ├── create-tools.mjs # Creation tools (notebooks, sections, pages)
│ │ └── delete-tools.mjs # Delete operations (pages)
│ ├── utils/ # Shared utilities
│ │ ├── common.mjs # Core utilities (validation, conversion, cache)
│ │ ├── html.mjs # HTML formatting helpers
│ │ ├── logger.mjs # Pino structured logging
│ │ └── validation.mjs # Resource validation and fetching
│ ├── config/ # Configuration
│ │ └── constants.mjs # Centralized constants (no magic numbers)
│ ├── session.mjs # Session state management
│ └── server.mjs # Main entry point
├── test/ # Test suite
│ ├── test_unit.mjs # 132 unit tests
│ ├── test_smoke.mjs # Server startup verification
│ └── test_integration.mjs # 55 integration tests
└── package.json
主要架构特征:
- 模块化设计: 明确分离关注点(auth、API、工具、实用程序)
- 会话管理: 封装状态通过
OneNoteSession类(否 全局变量) - 集中配置: 所有幻数都替换为命名常量
- 综合测试: 187多项测试,涵盖安全性、功能性和 整合
配置
-
Azure客户端ID: 此服务器需要Azure应用程序客户端ID才能 使用Microsoft Graph进行身份验证。
- 建议用于生产/共享用途: 设置
AZURE_CLIENT_ID将环境变量设置为您自己的Azure应用程序的“应用程序(客户端)ID”。(在Windows上,使用export AZURE_CLIENT_ID="your-actual-azure-app-client-id"set AZURE_CLIENT_ID=your-actual-azure-app-client-id) - 快速测试: 如果
AZURE_CLIENT_ID环境变量为 如果未设置,服务器将默认使用Microsoft Graph Explorer的 公共客户端ID。这适用于初始测试,但不建议使用 用于长期或共享使用。 - 或者,您可以修改
clientId变量直接在src/auth/device-code-flow.mjs,但使用环境变量 首选。
- 建议用于生产/共享用途: 设置
-
日志记录配置(可选): 服务器使用Pino进行结构化 登录中。您可以使用环境变量配置日志记录行为:
-
LOG_LEVEL: 设置要输出的最小日志级别(默认值:
info). 可用级别:trace,debug,info,warn,error,fatalexport LOG_LEVEL=debug # Enable debug-level logging(在Windows上:
set LOG_LEVEL=debug) -
NODE_ENV: 吃起来
production为了更好地输出JSON格式的日志 解析/分析。在开发中(默认),日志打印得很漂亮 颜色和时间戳。export NODE_ENV=production
-
-
.gitignore: 该项目包括.gitignore文件。确保它 至少包含以下内容以防止提交敏感文件:node_modules/ .DS_Store *.log .access-token.txt .env这
.access-token.txt服务器将创建文件来存储您的 身份验证令牌。
运行MCP服务器
配置后,从项目的根目录启动服务器:
npm start
或者直接:
node src/server.mjs
您应该看到控制台输出,指示服务器已启动,并列出 可用工具类别。
连接到MCP客户端
您可以将此服务器连接到任何兼容MCP的客户端,例如Claude 桌面。
Claude桌面或光标示例:
-
打开MCP客户端的配置文件。
- 克劳德桌面(macOS):
~/Library/Application Support/Claude/claude_desktop_config.json - 克劳德桌面(Windows):
%APPDATA%\Claude\claude_desktop_config.json - 光标: 首选项->MCP选项卡。
- 克劳德桌面(macOS):
-
添加或更新
mcpServers配置:基本配置(使用默认客户端ID):
{ "mcpServers": { "onenote": { "command": "node", "args": ["/full/path/to/your/onenotemcp/src/server.mjs"] } } }使用自定义Azure客户端ID(可选):
{ "mcpServers": { "onenote": { "command": "node", "args": ["/full/path/to/your/onenotemcp/src/server.mjs"], "env": { "AZURE_CLIENT_ID": "YOUR_AZURE_APP_CLIENT_ID_HERE" } } } }- 替换
/full/path/to/your/onenotemcp/随着 绝对路径 到 在那里克隆了存储库。 - 注意:路径应指向
src/server.mjs在项目目录中。 - 这
env部分是 可选的 只有在以下情况下才需要:- 您想使用自定义Azure应用程序客户端ID,并且
- 您尚未设置
AZURE_CLIENT_ID作为系统范围的环境变量
- 如果省略,服务器将使用Microsoft Graph Explorer的公共客户端 ID(适用于测试和个人使用)。
- 替换
-
重新启动MCP客户端(克劳德桌面/光标)。
身份验证流程
您第一次尝试通过人工智能助手或通过以下方式使用OneNote工具
明确调用 authenticate 工具:
- 调用
authenticate工具: 您的AI助手将呼叫authenticate服务器上的工具。 - 设备代码提示: 服务器将输出一个URL(通常
https://microsoft.com/devicelogin)并为其添加用户代码stderr.你的 MCP客户端(例如Claude Desktop)应向您显示此信息。 - 浏览器身份验证: 在web浏览器中打开提供的URL并输入 用户代码。
- 登录并授予权限: 使用您的Microsoft帐户登录 具有OneNote访问权限,并授予请求的权限。
- 已保存令牌: 浏览器身份验证成功后,服务器将
自动接收访问令牌并将其保存到
.access-token.txt文件在其目录中。 - 验证(可选但推荐): 调用
saveAccessToken工具 通过你的AI助手。这个工具实际上并没有保存(因为它已经保存了 由后台进程保存),而是加载和验证令牌, 确认身份验证成功并显示您的帐户信息。
保存的令牌将用于后续会话,直到到期,届时 您可能需要重新进行身份验证。
可用的MCP工具
此服务器向您的AI助手公开以下工具:
身份验证:
authenticate:启动与Microsoft的设备代码身份验证流程 图表。saveAccessToken:加载并验证本地保存的访问令牌。
正在读取OneNote数据:
listNotebooks:列出所有OneNote笔记本。listSections:列出分区,可选择按笔记本或分区筛选 集团。(Args:notebookId(可选字符串),sectionGroupId(可选 字符串)listSectionGroups:列出分区组,可选择按笔记本或 父节组。(Args:notebookId(可选字符串),sectionGroupId(可选字符串))searchSections:按名称搜索节。(Arg:query(字符串)listPagesInSection:列出特定部分中的所有页面。(Arg:sectionId(字符串)searchPages:按标题搜索页面,可选择日期和笔记本 过滤。(Args:query(可选字符串),modifiedAfter(可选ISO 8601年日期),modifiedBefore(可选ISO 8601日期),notebookId(可选 字符串)getRecentPages:检索笔记本中最近修改的页面。(Args:notebookId(字符串),limit(可选数字,默认值:10,最大值:50)getPageContent:检索特定OneNote页的内容。(Args:pageId(字符串),format(枚举:“文本”、“html”、“摘要”,可选, 默认值:“文本”)getPageByTitle:按页面标题查找页面并检索其内容。(Args:title(字符串),format(枚举:“文本”、“html”、“摘要”,可选, 默认值:“文本”)getPageLink:获取在浏览器或桌面应用程序中打开页面的直接链接。 (Arg:pageId(字符串)
创建和管理结构:
createNotebook:创建新的OneNote笔记本。(Arg:displayName(字符串)createSection:在笔记本中创建新分区。(Args:notebookId(字符串),displayName(字符串)createSectionGroup:在笔记本中创建新的分区组。(Args:notebookId(字符串),displayName(字符串)
编辑和创建OneNote页面:
createPage:在第一个可用分区中创建新的OneNote页。 (Args:title(字符串),content(字符串-HTML或markdown)createPageInSection:在特定分区中创建新的OneNote页。 (Args:sectionId(字符串),title(字符串),content(字符串-HTML或 降价)updatePageContent:替换现有页面的全部内容。(Args:pageId(字符串),content(字符串),preserveTitle(布尔值,可选, 默认值:true))appendToPage:将新内容添加到现有页面的末尾。(Args:pageId(字符串),content(字符串),addTimestamp(布尔值,可选, 默认值:true),addSeparator(布尔值,可选,默认值:true)updatePageTitle:更改现有页面的标题。(Args:pageId(字符串),newTitle(字符串)replaceTextInPage:查找并替换页面中的文本。(Args:pageId(字符串),findText(字符串),replaceText(字符串),caseSensitive(布尔值,可选,默认值:false)addNoteToPage:向页面添加格式化的带时间戳的注释/评论。(Args:pageId(字符串),note(字符串),noteType(enum: “注意”, “所有”, “重要”、“问题”、可选、默认:“注意”),position(枚举:“top”, “bottom”,可选,默认值:“bottle”)addTableToPage:从CSV数据向页面添加格式化表。(Args:pageId(字符串),tableData(字符串-CSV),title(字符串,可选),position(枚举:“top”,“bottom”,可选,默认值:“bottle”)
页面管理:
copyPage:将页面复制到其他部分(异步操作)。 (Args:pageId(字符串),targetSectionId(字符串)
删除资源:
deletePage:永久删除页面。(Args:pageId(字符串),confirmDelete(布尔值,必须为true)
与AI交互示例
一旦连接并通过身份验证,您就可以让您的AI助手执行任务 比如:
- “列出我的OneNote笔记本。”
- “创建一个名为‘Work 2025’的新笔记本电脑。”
- “在我的工作笔记本中创建一个名为“每周报告”的部分。”
- “显示笔记本中的所有部分。”
- 搜索包含“Project”的节
- “显示“会议笔记”部分中的所有页面。”
- “查找2024-01-01之后修改的所有页面。”
- “搜索上次修改过的标题中包含“预算”的页面 周。"
- “显示特定笔记本中包含“会议”的所有页面 标题。"
- “创建一个名为“会议想法”的新OneNote页面,内容为“头脑风暴” 新的营销策略”。"
- 在“工作项目”部分创建一个标题为“行动项”的页面
- “将此页面复制到“存档”部分。”
- “你能找到我关于‘凤凰计划’的OneNote页面并告诉我吗 总结?"
- 将“跟进John Doe”添加到带有ID的OneNote页面 “您的页面id在这里”。"
- “在我的OneNote页面“配方创意”中,将所有“糖”实例替换为 “甜味剂”。"
测试
该项目包括一个全面的测试套件,以确保可靠性和捕获能力 回归。
运行测试
运行所有测试:
npm test
运行特定测试类型:
npm run test:unit # Unit tests (132 tests for utility functions)
npm run test:smoke # Smoke test (verifies server starts and tools are registered)
npm run test:integration # Integration tests (55 tests for core functionality)
测试结构
- test/test_unit.mjs -实用功能单元测试(132次测试) (escapeODataString、sanitizeUrl、validateId、extractReadableText、, extractTextSummary、textToHtml、Cache类、CSV验证)
- test/test_smoke.mjs -烟雾测试,验证MCP服务器启动和 所有25个工具都已正确注册
- test/test_integration.mjs -验证的集成测试(55个测试) 加密、重试逻辑、错误处理和格式化功能
测试覆盖率
- ✅ 安全功能: OData注入预防、XSS保护、ID 验证
- ✅ 内容处理: HTML到文本转换,markdown到HTML 转换
- ✅ 缓存: TTL过期,模式无效
- ✅ 服务器启动: MCP协议合规性、工具注册
- ✅ API集成: 部分查询、带过滤器的页面搜索
代码质量和工具
该项目使用现代代码质量工具来保持一致性、安全性和 记录良好的代码:
装订和格式化
- ESLint:静态代码分析,具有全面的代码质量规则, 最佳实践和安全
- 更漂亮:自动代码格式化,确保整个系统风格一致 代码库
- JSDoc验证:确保所有导出的函数都有适当的文档
可用命令:
npm run lint # Check for code issues
npm run lint:fix # Auto-fix linting issues
npm run format # Format all code files
npm run format:check # Check if files are formatted
npm run quality # Run linting, formatting, and all tests
预提交钩子
该项目使用 哈士奇 和 皮棉上演 自动执行代码 质量:
- 自动植绒:ESLint在所有舞台上运行
.js和.mjs文件 - 自动格式化:在提交之前对所有暂存文件进行预格式化
- 零配置:运行时会自动设置挂钩
npm install
这确保了每个提交都能保持项目的质量标准,而无需 手动干预。
配置文件
eslint.config.js-带安全规则和JSDoc的ESLint配置 验证.prettierrc.json-预处理格式规则.prettierignore-从格式化中排除的文件.husky/pre-commit-Git预提交钩子配置package.json(lint分段部分)-分段文件处理规则
故障排除
- 身份验证问题:
- 确保您的
AZURE_CLIENT_ID(如果设置)是正确的,并且具有所需的API 权限。 - 如果设备代码流失败,请在其他浏览器或 匿名/私人窗口。
- 令牌到期:如果工具停止工作,您可能需要重新运行
authenticate工具。
- 确保您的
- 服务器未启动:
- 检查Node.js版本(
node -v). - 确保安装了所有依赖项(
npm install).
- 检查Node.js版本(
- MCP客户端问题(例如,克劳德桌面、光标):
- 验证
command和args(尤其是通往src/server.mjs)客户端的MCP服务器配置是正确的。 - 更改配置后重新启动MCP客户端。
- 检查MCP客户端的日志和服务器的控制台输出是否有错误。
- 验证
安全说明
- 加密密钥存储: 服务器使用操作系统本机安全存储
加密密钥:
- 视窗:Windows凭据管理器(DPAPI)
- macOS:钥匙扣服务
- Linux:特勤局API(gnome-keyring/KWallet)
- 后备方案:如果操作系统密钥链不可用,则使用加密文件存储 带有警告信息。
- 迁移:现有的基于文件的密钥会自动迁移到操作系统 首次启动时使用钥匙扣。
- 访问令牌安全: 这
.access-token.txt文件包含加密 根据定义的范围授予对OneNote数据访问权限的令牌。 令牌使用AES-256-GCM(经过身份验证的加密)和密钥进行加密 安全地存储在您的操作系统钥匙链中。像保护任何文件一样保护此文件 敏感凭证。确保它包含在您的.gitignore文件。 - Azure客户端ID: 如果您创建了自己的Azure应用程序注册,请保留其 客户端机密(如果为其他流生成)是安全的。对于此设备代码 流,此脚本不使用客户端机密。
- 权限: 此服务器请求
Notes.ReadWrite和Notes.Create权限。请注意您授予的访问权限。
已知限制
以下操作是 不支持 由于Microsoft Graph API 限制:
重命名节或节组
Microsoft Graph API不支持修改节或节组 创建后的属性。正在尝试对这些资源使用PATCH操作 返回“找不到资源”错误。
解决方法: 使用所需名称创建新部分并手动复制 使用OneNote应用程序访问它的页面。
在节之间移动页面
Microsoft Graph API仅提供 copyToSection 端点--没有
moveToSection 操作。虽然我们理论上可以复制一页,然后
删除原始文件,这是不安全的,因为:
- 异步操作: 复制操作是异步的,没有完成 回调
- 数据丢失风险: 如果在复制完成之前删除了原件,或 如果复制失败,页面将永久丢失
- 无原子性: 无法确保这两项行动同时成功
解决方法: 使用 copyPage 要手动将页面复制到目标部分
验证复制成功,然后使用删除原始页面 deletePage.
删除章节、章节组和笔记本
Microsoft Graph API仅支持删除 页面。没有DELETE 分区、分区组或笔记本的端点。
解决方法: 使用OneNote桌面或web应用程序删除分区, 分区组或笔记本。
为什么存在这些限制
这些限制是由Microsoft的OneNote API设计施加的,而不是由此MCP施加的 服务器。OneNote API将数据安全置于破坏性数据的便利性之上 操作。有关API的最新功能,请参阅 Microsoft Graph OneNote API文档.
致谢
该项目最初源于 onenotemcp 由Ehsan Shahabi撰写,但已经 由于已经用新的架构、特征和功能进行了实质性的重写和扩展, 以及工具。
许可证
此项目根据MIT许可证获得许可-请参阅 许可证 文件 了解详情。