内容
# easy-notion-mcp
面向生产的MCP服务器,通过标准markdown连接AI代理到Notion,而不是原始API JSON。
代理读取和写入GFM markdown。服务器处理块转换、数据库模式映射、OAuth和可选的Redis支持持久化,以实现多实例部署。
## 功能亮点
| 功能 | 详情 |
| --- | --- |
| **Markdown优先的输入/输出** | 42种MCP工具;代理永远不会构造Notion块JSON |
| **往返保真度** | 24种块类型,包括切换、列、标注、表格、上传 |
| **数据库人体工程学** | 编写 `{ "状态": "完成" }` — 模式转换是自动的 |
| **双重传输** | 标准输入输出(API令牌)和HTTP(OAuth或承载保护的静态令牌) |
| **安全默认值** | 内容通知前缀、URL净化、工作区根文件包含 |
| **可选Redis** | 共享模式缓存和OAuth令牌持久化,带有优雅的故障转移 |
| **CLI配置文件** | 通过`easy-notion`进行低上下文Notion访问,具有只读/读写模式 |
## 架构
```mermaid
flowchart TB
subgraph clients [MCP客户端]
CC[Claude 代码 / 光标]
HTTP[HTTP MCP客户端]
end
subgraph transport [传输层]
STDIO[index.ts — 标准输入输出]
HTTP_SRV[http.ts — Express]
end
subgraph core [应用核心]
SRV[server.ts — MCP工具和资源]
NC[notion-client.ts — Notion SDK包装器]
MD[markdown转换器]
end
subgraph persistence [持久化 — 可选]
MEM[(内存缓存)]
REDIS[(Redis)]
FS[(加密令牌文件)]
end
CC --> STDIO
HTTP --> HTTP_SRV
STDIO --> SRV
HTTP_SRV --> SRV
SRV --> NC
SRV --> MD
NC --> MEM
NC --> REDIS
HTTP_SRV --> FS
HTTP_SRV --> REDIS
```
### 请求工作流(工具调用)
```mermaid
sequenceDiagram
participant 代理
participant MCP as MCP服务器
participant 缓存 as 缓存存储
participant Notion as Notion API
代理->>MCP: 工具/调用(例如read_page)
MCP->>Notion: blocks.children.list(分页)
Notion-->>MCP: 块树
MCP->>MCP: 块 → markdown
MCP-->>代理: { markdown, 警告? }
代理->>MCP: 工具/调用(add_database_entry)
MCP->>缓存: 获取模式:dbId
alt 缓存未命中
缓存->>Notion: dataSources.retrieve
Notion-->>缓存: 模式
缓存-->>MCP: 模式
else 缓存命中
缓存-->>MCP: 模式
end
MCP->>MCP: 转换属性值
MCP->>Notion: pages.create
Notion-->>MCP: 页面
MCP-->>代理: { id, url }
```
## 项目结构
```
easy-notion-mcp/
├── src/
│ ├── index.ts # 标准输入输出入口点
│ ├── http.ts # HTTP/OAuth入口点
│ ├── cli.ts # 基于配置文件的CLI
│ ├── server.ts # MCP工具和资源处理程序
│ ├── notion-client.ts # Notion SDK集成
│ ├── config/env.ts # 类型环境解析
│ ├── logging/logger.ts # 结构化日志记录
│ ├── persistence/ # 缓存 + Redis集成
│ │ ├── cache-store.ts
│ │ ├── init.ts
│ │ └── redis/
│ └── auth/ # OAuth令牌存储
├── tests/ # Vitest单元测试和集成测试
├── docs/AUDIT.md # 工程审计笔记
├── skills/ # 代理技能定义
└── dist/ # 编译输出(生成)
```
## 设计决策
- **单一服务器模块** — 工具处理程序保留在`server.ts`中,以保持稳定的公共MCP合同;支持模块处理横切关注点。
- **可插拔缓存** — `CacheStore`抽象允许内存(默认)或Redis后端,而无需更改Notion客户端逻辑。
- **故障开放Redis** — 如果配置了Redis但无法访问,服务器记录警告并继续使用内存/文件持久化。
## 安装
### 先决条件
- Node.js 20+
- 一个[Notion集成](https://www.notion.so/my-integrations),并与之共享页面
### 从源代码
```bash
git clone https://github.com/Grey-Iris/easy-notion-mcp.git
cd easy-notion-mcp
npm install
npm run build
```
### 通过npx(已发布包)
```bash
npx -y easy-notion-mcp
```
### MCP客户端配置(stdio)
```json
{
"mcpServers": {
"notion": {
"command": "npx",
"args": ["-y", "easy-notion-mcp"],
"env": {
"NOTION_TOKEN": "ntn_您的集成令牌"
}
}
}
}
```
## 配置
复制`.env.example`到`.env`以便从克隆的检出中运行:
```bash
cp .env.example .env
```
### 核心变量
| 变量 | 必需 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `NOTION_TOKEN` | 是(stdio) | — | Notion集成令牌 |
| `NOTION_ROOT_PAGE_ID` | 否 | — | `create_page`的默认父级 |
| `NOTION_TRUST_CONTENT` | 否 | `false` | 读取时禁用内容通知前缀 |
| `NOTION_MCP_WORKSPACE_ROOT` | 否 | `cwd` | 本地`file://`上传的根目录 |
| `LOG_LEVEL` | 否 | `info` | 日志记录详细程度 |
### Redis持久化(可选)
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `REDIS_ENABLED` | `false` | 启用Redis时为`true`或设置`REDIS_URL`时为`true` |
| `REDIS_URL` | — | 完整连接URL |
| `REDIS_HOST` | `127.0.0.1` | 主机(当未设置URL时) |
| `REDIS_PORT` | `6379` | 端口 |
| `REDIS_PASSWORD` | — | 认证密码 |
| `REDIS_DB` | `0` | 数据库索引 |
| `REDIS_KEY_PREFIX` | `easy-notion:` | 键命名空间前缀 |
| `REDIS_CONNECT_TIMEOUT_MS` | `10000` | 连接超时 |
| `REDIS_MAX_RETRIES` | `3` | 失败前重试次数 |
使用本地Redis示例:
```bash
REDIS_ENABLED=true REDIS_URL=redis://127.0.0.1:6379/0 npm start
```
### HTTP传输
| 变量 | 必需 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `NOTION_MCP_BEARER` | 是(静态HTTP) | — | `/mcp`请求的共享密钥 |
| `NOTION_OAUTH_CLIENT_ID` | OAuth模式 | — | 公共集成客户端ID |
| `NOTION_OAUTH_CLIENT_SECRET` | OAuth模式 | — | OAuth客户端密钥 |
| `PORT` | 否 | `3333` | 监听端口 |
| `NOTION_MCP_BIND_HOST` | 否 | `127.0.0.1` | 绑定地址 |
## 开发
```bash
# 安装依赖
npm install
# 监视模式
npm run dev
# 在本地运行stdio服务器
NOTION_TOKEN=ntn_... npm start
# 运行HTTP服务器
NOTION_TOKEN=ntn_... NOTION_MCP_BEARER=$(openssl rand -hex 32) npm run start:http
```
### 质量门控
```bash
npm run build # 编译TypeScript
npm run typecheck # 类型检查,无需发出
npm run lint # ESLint
npm test # Vitest单元测试
```
## 测试
```bash
# 完整的单元测试套件(~850个测试)
npm test
# 监视模式
npm run test:watch
# Live Notion E2E(需要专用的测试工作区)
cp .env.example .env # 设置E2E_ROOT_PAGE_ID
npm run test:e2e
```
依赖于符号链接的安全测试在无法创建符号链接的平台上会自动跳过(Windows上常见,无需开发者模式)。
## 故障排除
| 症状 | 可能原因 | 修复方法 |
| --- | --- | --- |
| `NOTION_TOKEN is required` | 缺少环境变量 | 在MCP配置`env`块或`.env`中设置令牌 |
| `401 invalid_token`(HTTP) | 缺少/错误的承载令牌 | 设置`NOTION_MCP_BEARER`在服务器上;发送`Authorization: Bearer …` |
| `outside the allowed workspace root` | 文件路径逸出根目录 | 设置`NOTION_MCP_WORKSPACE_ROOT`或使用其内部的绝对路径 |
| 启动时的Redis警告 | Redis无法访问 | 启动Redis或设置`REDIS_ENABLED=false` |
| 未知属性名称 | 过时/错误的模式 | 首先调用`get_database`;检查大小写敏感性 |
| 符号链接测试跳过 | 操作系统限制 | 启用Windows开发者模式或在Linux/macOS上运行 |
启用调试日志:
```bash
LOG_LEVEL=debug npm start
```
## 贡献
1. 复刻仓库并从`main`创建功能分支
2. 进行带有测试的聚焦更改(如果行为更改)
3. 运行`npm run build && npm run lint && npm test`
4. 打开带有清晰描述和测试计划的拉取请求
参见[docs/AUDIT.md](docs/AUDIT.md)获取架构上下文和已知的改进区域。
## 常见问题
**这与官方Notion MCP服务器有何不同?**
官方服务器返回原始Notion JSON(~6–7倍每页更多令牌)。该服务器转换为代理已经理解的markdown,具有24种块类型的往返保真度。
**我需要Redis吗?**
不需要。Redis是可选的,它改进了水平扩展(共享模式缓存,跨HTTP实例的OAuth令牌)。单进程stdio部署在没有它的情况下工作良好。
**markdown往返是否无损?**
对于支持的块类型,是的。原生不支持的块(例如`synced_block`,嵌入式数据库)会发出警告,以便代理避免破坏性重写。
**文件上传是否通过HTTP工作?**
否。`file://`上传仅限stdio出于安全考虑。使用HTTPS URL或stdio传输本地文件。
**需要哪个Node版本?**
Node.js 20或更高版本。
## 许可证
MIT — 参见 [LICENSE](LICENSE)。