ToolBroker
by LankiYang
README.md
# notion-mcp2api
[](https://github.com/LankiYang/notion-mcp2api/actions/workflows/ci.yml)
[](LICENSE)
通过**已授权的 Notion 网页会话 + 隔离的双工具 MCP**,把外部会话中的动态函数 Schema 转换为 OpenAI Chat Completions `tool_calls`。
**An experimental OpenAI-compatible tool-call relay backed by an authorized Notion web session and an isolated two-tool MCP server.** It proposes calls; the external client executes them.
> **实验性项目,不是 Notion 官方 API / SDK,也不是公共多租户生产服务。** 使用非公开网页协议,可能随上游变更失效。需要自己合法授权的账号、可用的 MCP 功能和账户额度。提示词和事件白名单不是账号数据隔离;不要向陌生人开放现有个人账号。
## 核心思路
不是把模型的一段 JSON 文字猜成工具调用,也不是在服务器上执行客户提供的代码:
```text
OpenAI-compatible client: messages + tools JSON Schema
→ HTTP broker: auth, quota, task capability
→ existing Notion web session
→ native ToolBroker.claim_task(task_id, dispatch_token)
→ native ToolBroker.submit_decision(task_id, lease, proposal)
→ broker validates name/schema/tool_choice/lease
→ standard tool_calls returned to the client
→ client executes its own function or MCP tool
→ client sends role=tool + matching tool_call_id
→ a new request produces the next assistant response
```
Notion 只需连接固定的 `claim_task` / `submit_decision`。每次请求的工具名和参数定义都是任务数据,不需要逐个注册 MCP。
## 支持与边界
- `GET /v1/models`、`POST /v1/chat/completions`;默认模型 ID 为 `notion-mcp-broker`,与仓库名不同。
- 动态 `tools` JSON Schema、`tool_choice=auto/none/required`、指定函数、`parallel_tool_calls`、历史 `tool_call_id` 对应关系。
- JSON Schema 校验;不抓取远程 `$ref`;最多 128 个工具、请求体最多 512 KiB。
- 非流式 JSON,以及 **SSE 保活 + 经过校验后的结果分块**。不是模型逐 token 实时输出。
- 默认请求预算 **1000 秒**,SSE 立即及每 **15 秒**发注释保活;临时 Key 即将到期时会裁剪等待预算。
- 上游驱动单并发、无自动推理重试;到期、限额、失败明确返回错误,不伪造工具结果。
- 本地 owner pilot 与独立临时分享 Key;分享 Key 最长 1 小时、20 个聊天请求、单并发,另限每分钟 6 次。
**不支持:** Responses API、Anthropic Messages API、任意 MCP URL 的服务端自动发现/执行、浏览器跨域直连、账号权限沙箱、持久任务恢复、无人登录启动及 24/7 可用性承诺。上游模型目前固定验证 `claude-sonnet4.6`,不承诺其他模型等价兼容。
## 依赖
- Python 3.11+;Node.js 20+(本项目 CI 使用 Node 22)。
- 单独取得并配置 [notion2api](https://github.com/maverickxone/notion2api);本项目复用其已有登录和请求构造器,不附带、不替换、不上传任何账号。
- 上游适配参考提交 `5882102d019a9c8f2075fa357fe6a0c573c71af0` 的接口:`get_default_account`、`NotionOpusAPI`、`get_notion_model`。使用其他版本时需要自行验证。
- 一个供 Notion 访问的自有 HTTPS MCP 入口。外部 API 入口可选;安装时默认只监听本机。
- 原账号本来就允许自定义 MCP。遇到管理员审批或设备要求时停止,不绕过策略。
上游源码及其授权不包含在本仓库的 MIT 授权中,详见 [NOTICE](NOTICE)。
## 安装
```bash
git clone https://github.com/LankiYang/notion-mcp2api.git
cd notion-mcp2api
python -m venv .venv
```
Linux/macOS:
```bash
source .venv/bin/activate
```
Windows PowerShell:
```powershell
.\.venv\Scripts\Activate.ps1
```
安装本项目依赖,并按上游自己的说明安装它的依赖和配置登录:
```bash
python -m pip install -r requirements.txt
npm ci --ignore-scripts
```
本项目不重新分发上游源码;例如你可以将自己取得的上游放在同级 `../notion2api`。不要复制别人的 `accounts.json`。
## 初始化与接入
### 1. 生成自己的配置和独立密钥
以下域名为示例,必须替换为自己控制的入口:
```bash
python setup_project.py init --upstream-path ../notion2api --mcp-url https://mcp.example.com/mcp --api-url https://api.example.com/v1
```
- 写入本地 `settings.json`、`secrets/broker.json`、`secrets/broker-mcp.json`,不会打印密钥,不覆盖已有配置。
- 默认公开访问关闭;`automatic_enabled=false`、`private_test_until=0`。不要手工翻转旧开关来绕过准备检查。
- `settings.example.json` 只示意非秘密配置。网页 `notion_client_version` 必须与自己观察到的授权客户端协议兼容,初始参考值可能过期。
- `NOTION2API_PATH` 可覆盖上游目录;不读取或修改共用电脑远控 MCP。
### 2. 启动两个本机进程
分别在两个终端的项目目录执行:
```bash
python -B broker.py
```
```bash
npm run start:mcp
```
默认分别监听 `127.0.0.1:8002` 和 `127.0.0.1:8003`;可通过 `BROKER_PORT` / `BROKER_MCP_PORT` 调整,两进程必须配置同一个 `BROKER_PORT`。不要与已经运行的实例争抢端口。
将自己的 HTTPS MCP 入口转发到 8003,且只开放精确 `/mcp`;详情见 [部署指南](docs/DEPLOYMENT.md)。MCP 必须使用 `secrets/broker-mcp.json` 中的独立 Bearer,不是 HTTP client Key 或控制 Key。
### 3. 明确授权后连接隔离 MCP
```bash
python connect-upstream-mcp.py
```
默认仅检查现有账号与模块,不创建连接。确认账号、工作区政策和 HTTPS 入口均正确,再执行:
```bash
python connect-upstream-mcp.py --apply
```
仅为该账号保存名为 **ToolBroker** 的双工具连接并默认启用,保留其他模块。它会按已观察到的网页协议保存这两个元工具的自动运行设置;这不是给客户函数授权,更不是给 Notion 开放电脑的 shell/read/write。缺少政策许可或需要额外审批时停止,不自动绕过。
当前原生函数前缀固定适配 `connections.mcpServer_toolbroker`;不要随意改连接名称。
### 4. 显式验证一次真实原生调用
```bash
python web_isolated_mcp_probe.py --run
```
**这会消耗一次上游推理额度,无自动重试。** 它只让原生 MCP 领取一个故意不存在的任务;要求实际原生 applied 事件、隔离服务的 claim 审计和账号一致性均成立,才写入后续启动所需证明。不是客户工具完整闭环验收。原始流只写本地 `secrets/`,不要上传。
### 5. 开启本机短时 pilot
```bash
python setup_project.py pilot --minutes 15
```
客户端本机 Base URL 为 `http://127.0.0.1:8002/v1`。仅在自己的终端读取 `secrets/broker.json` 里的 `client_keys.pilot`;不要把文件或控制 Key 放到 issue、截图或公共仓库。
推荐客户端:`timeout=1000`、`stream=true`、自动重试 `0`。示例 [examples/client.py](examples/client.py) 演示两回合、客户端执行一个固定加法以及真实结果回传;运行它会产生两个聊天请求。
```bash
python setup_project.py close-pilot
```
### 6. 可选:仅给可信测试者临时分享
在了解账号数据/权限尚未隔离的风险后,由部署者明确执行:
```bash
python issue_public_trial.py --issue --confirmed-risk
```
临时凭据仅写入本地 `secrets/public-trial-share.json`。运行时只存 Key 的 SHA-256;默认 1 小时、20 个请求、单并发,不因重启续期或清零。已有活跃授权的替换需要额外明确的 `--replace-active`,不自动续期。两个工具回合消耗两次请求。
```bash
python issue_public_trial.py --revoke
```
撤销不重启服务、不改变上游登录。**不要把临时授权描述成安全的公开多租户服务。**
## 错误与流式处理
- 参数/鉴权/额度/准备检查发生在开始流式输出前:400 / 401 / 429 / 503。
- 非流式上游失败或超时:502 / 504。
- SSE 已发送 HTTP 200 后,失败通过 `data: {"error":{"code":502或504,...}}` 明确表示;客户端必须检查 `error`,不要只看 HTTP 200。
- `: keepalive` 是 SSE 注释,应忽略;真实工具决定尚未产生时不会输出假助手文字。
- 1000 秒是本机预算,不是整个公网的承诺。非流式无保活,可能遇到代理更短的空闲超时。
- 断开/撤销阻止新请求,但关闭本机流不能证明远端推理已即时取消或不再消耗额度。
## 测试与结构
```bash
python -B -m unittest discover -v
npm run check
npm test
python tools/check_release.py
```
默认测试使用模拟的 HTTP/网页驱动与临时本机 MCP 服务,不请求 Notion、不消耗上游额度。安装了单独上游时可额外测试其构造器的无网络捕获;未安装时该项跳过。CI 覆盖 Windows / Ubuntu、Python 3.11 / 3.12。
```text
broker.py OpenAI-compatible broker and native decision validation
web_automation.py retained web-session dispatcher, one POST, no inference retries
broker-mcp-http.mjs isolated Streamable HTTP MCP, exactly two tools
long_wait.py 1000s budget, SSE keepalive and explicit stream errors
project_config.py portable paths and non-secret deployment configuration
setup_project.py local initialization and bounded owner pilot
trial_access.py expiring hashed test keys and persistent request budgets
connect-upstream-mcp.py explicit owner-authorized connection setup
web_isolated_mcp_probe.py opt-in, one-inference native connection check
examples/client.py client-side fixed function + result roundtrip
```
## 安全、许可与贡献
- 详见 [SECURITY.md](SECURITY.md)、[贡献指南](CONTRIBUTING.md)、[部署指南](docs/DEPLOYMENT.md)。
- 本仓库不包含任何账号、Cookie、实际 API Key、Cloudflare Token、原始对话、个人域名、生产设置或历史 Git 数据。
- 协议适配来自一个实验部署的验证,不代表任意工具、任意账号或未来网页版本都兼容。
- 请仅使用自己有权访问的账号与连接,遵守服务条款、组织政策、隐私要求及适用法律;本项目不提供规避认证、收费、审批或权限限制的功能。
- 原创代码采用 [MIT License](LICENSE),第三方组件保留其各自许可。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues