Prime Agent Notion 集成指南:在 Python 内核中通过官方 MCP 服务器搜索与读写页面
【免费下载链接】prime-agentA self-improving RLM agent for coding workflows and long-running autonomous tasks.项目地址: https://gitcode.com/GitHub_Trending/pr/prime-agent
在 Prime Agent 的 Python 内核中,Notion 是通过其官方托管的 MCP(Model Context Protocol)服务器接入的:Agent 只需import notion,就能在代码里搜索页面、读取内容、创建/更新 page 与 database,而工具清单由服务器在运行时动态下发。本文以 Notion skill 文档 为主体,结合内核源码讲解登录、发现工具、调用工具与排查问题的完整流程。读完你既能直接上手使用,也能理解这套"MCP 集成 = Python skill"机制在 Prime Agent 中的底层实现。
Notion skill 是什么
packages/coding-agent/skills/notion/SKILL.md的 frontmatter 给出了它的定位:
--- name: notion description: Search Notion and read/create/update pages and databases via Notion's official hosted MCP server. Tools are auto-discovered from the server at runtime. ---即:通过 Notion 官方托管的 MCP 服务器,从 Python 内核中搜索 Notion、读取/创建/更新页面与数据库;工具在运行时由服务器自动发现。这句话里有三个关键点:
- 连接对象是官方托管服务器,不是自建代理。源码中 notion/init.py 直接声明了服务器名与端点:
class Notion(McpIntegration): server = "notion" url = "https://mcp.notion.com/mcp"skill 只是薄封装。整个包只有寥寥几十行:
Notion继承内核提供的McpIntegration基类,再导出一个模块级单例notion = Notion(),所有工具行为都来自McpIntegration。工具集合由服务器决定,而不是由本 skill 决定。这意味着你不能假设工具名和参数名,必须先"发现"再"调用"——这是全文最重要的使用准则。
连接:通过 OAuth 登录启用
使用 Notion 前必须先完成一次交互式登录,方式有两种,效果等价:
- 在 TUI 中执行
/login,切到Services选项卡,选择Notion,在浏览器中完成 OAuth 授权; - 或者直接在命令行执行
/mcp login notion。
登录完成后本 skill 会被自动启用,无需手动配置任何环境变量。这一点是设计上的硬约束:如果某次调用抛出了NotEnabled,说明当前用户尚未登录——正确的做法是引导用户走/login流程,而不是让用户去设置环境变量。
这条约束在内核代码里也有呼应。NotEnabled异常定义于 mcp_base.py,它的消息本身就写明了指引:
class NotEnabled(RuntimeError): """Raised when an integration has no usable credentials...""" def __init__(self, server: str): super().__init__( f"The '{server}' integration is not enabled: no credentials found. " f"Tell the user to run `/mcp login {server}` in Prime Agent to connect it. " f"Do not ask them to set environment variables." )从源码可以看到启用判定的具体逻辑(mcp_base.py):_token()优先读静态 Bearer Token 环境变量,否则读取auth.json中mcp:notion条目下的 OAuth 凭据(含access、refresh、expires字段);凭据过期或缺失时再请求宿主刷新;刷新也失败且本就没有凭据时才抛出NotEnabled。登录后凭据统一落在~/.prime/agent/auth.json中,由宿主在浏览器侧完成 OAuth 与 token 铸造/刷新,内核只负责"读取 + 过期时请求刷新"。
另外注意:登录发生在对话回合中间时,集成不会立刻生效——资源重载会被推迟,需要在本回合结束后执行/reload才能激活。完整的"以登录即启用"生命周期(enable-by-login)可参见 mcp-integrations.md:内置 skill 出厂时处于禁用状态(不进入 prompt、不导入内核),一旦检测到auth.json中出现mcp:<server>凭据,重载后即启用;登出或凭据丢失则再次禁用。
使用:先发现,再调用
工具集合由服务器定义而非本 skill 定义,所以调用前必须先发现,不能想当然地写工具名和参数名。官方文档给出了标准的发现流程:
import notion # 1. Discover available tools (returns names + schemas) for tool in await notion.list_tools(): print(tool["name"], "-", tool["description"]) # 2. Call by exact name; the second arg matches the tool's input schema result = await notion.call_tool("notion-search", {"query": "roadmap"}) print(result)为什么必须用 call_tool
Notion 官方 MCP 服务器的工具名普遍带连字符,例如notion-search、notion-fetch。连字符不是合法的 Python 标识符,所以await notion.notion-search(...)这类写法根本编译不过;而getattr式动态属性访问也无法用于带连字符的名字。因此对这类工具,必须使用显式的逃生通道:
await notion.call_tool("notion-search", {"query": "roadmap"})call_tool的第二个参数是一个 dict,直接对应服务器下发的工具 JSON Schema 输入。
合法标识符工具名的写法
如果某个工具名本身是合法的 Python 标识符(例如不含连字符、不以数字开头),那么它也可以直接作为属性调用:
await notion.<tool>(**args)而且一旦执行过list_tools(),help(notion.<tool>)就能展示该工具的完整 schema,方便你在交互式环境中查参数。
从源码看,这套"属性即工具"的机制由McpIntegration.__getattr__实现(mcp_base.py):访问未定义的属性名时,它会被绑定成一个异步工具调用函数,并在工具已发现的情况下把工具的description与 JSON Schema 写进该函数的__doc__,这就是help()有内容的来源。若目标工具不存在,__getattr__会抛出带可用工具列表的AttributeError,方便自查。
调用语义速查
官方文档强调的三条注意事项,逐条对应实现细节:
- 每个调用都是
async,必须await:call_tool与list_tools均返回协程; - 返回结果已经是解析好的 Python 对象:结构化输出是
dict,否则是字符串,无需再json.loads。这一点由_parse_result(mcp_base.py)保证:优先提取structuredContent/structured_content作为结构化结果;无结构化内容时把多个文本块拼接为字符串;图片等非文本内容则转换为普通 dict 列表返回; - 在依赖
help()或假定某个工具存在之前,先跑一次list_tools():服务器下发的 schema 才是工具名与参数的唯一事实来源。
底层原理:McpIntegration 基类如何工作
Notion skill 只是McpIntegration的一个子类,理解这个基类就理解了整个调用链。它定义在 mcp_base.py,核心职责有三块:
- 凭据解析:
_resolve_token()决定当前可用 token(静态环境变量 >auth.json中的 OAuth 凭据),过期则请求宿主执行mcp.refresh,并在彻底无凭据时抛NotEnabled(见上文); - 连接与会话:
_open_session()通过官方mcpPython SDK 的 streamable HTTP 传输层连接https://mcp.notion.com/mcp,携带Authorization: Bearer <token>头并完成 MCP 握手(session.initialize())。需要注意 SDK 签名在不同版本间有差异(headers=或http_client=两种形态),源码对此做了兼容处理;同时关闭了重定向跟随,避免配置的凭据头被重定向端点截获; - 工具发现与调用:
list_tools()首次调用时经_ensure_tools()拉取服务器工具清单并缓存为{name, description, inputSchema}列表;call_tool()每次调用都新建一个会话——原因是 MCP 会话无法安全地跨越内核的 snapshot/restore,逐次连接也能对空闲会话与 token 轮换保持健壮,代价只是少量延迟。
另外,Notion模块还定义了一个模块级__getattr__转发器(notion/init.py),把裸模块属性访问转发到单例实例上,所以import notion; await notion.notion_search(...)(对标识符合法的工具名)无需显式写.notion。它专门保留了run、__wrapped__、__call__这几个名字——内核引导程序会探测这些名字来判断模块是否为"可调用 skill",如果被转发成 MCP 工具桩,模块就会被错误地包装成可调用对象,从而破坏await notion.<tool>()的分发。
包结构与运行时环境
Notion skill 作为独立 Python 包发布,其 pyproject.toml 声明了运行时依赖:
[project] name = "prime-agent-skill-notion" version = "0.1.0" description = "Notion integration skill for Prime Agent (Notion's official hosted MCP server)." requires-python = ">=3.10" dependencies = ["mcp", "httpx", "prime-agent-runtime"]也就是说:除了官方的mcpSDK 与httpx之外,它还依赖本仓库的 prime-agent-runtime,其中rlm包以懒加载方式再导出McpIntegration、McpToolError、NotEnabled(见 rlm/init.py),保证普通import rlm不会因缺少可选依赖mcp而硬失败。
官方文档特别提醒了一个环境陷阱:内核导入名是notion。如果你自定义了PRIME_AGENT_KERNEL_PYTHON,而该环境里恰好安装了 PyPI 上那个与本主题无关的notion客户端库,import notion可能解析到那个库而不是本集成。规避办法是使用默认的受管内核 venv,从而避免命名冲突。
错误处理与边界情况
调用 Notion 工具时可能遇到两类内核级异常,均定义在 mcp_base.py:
NotEnabled:集成已安装但未登录,凭据缺失。按异常消息指引用户执行/login或/mcp login notion,不要尝试设置环境变量;McpToolError:工具调用返回了被服务器标记为错误的结果(is_error/isError为真)。_parse_result会把这类结果转成异常,避免"失败的工具调用看起来像成功"。
此外还有几个值得注意的行为边界:
- 工具名是连字符形态时必须走
call_tool,这在"先发现,再调用"一节已详述; - 调用前务必先
list_tools(),因为服务器 schema 是工具名与参数的唯一事实来源,help()的内容也依赖它; - 登录后需重载才生效:若在对话中段登录,本回合结束后执行
/reload激活集成; - 内置集成名(
linear、notion等)是保留字:mcp add会拒绝同名条目,手工编辑一个同名mcpServers条目只会禁用内置 skill 而非重配它(详见 mcp-integrations.md)。
结语
Notion skill 是 Prime Agent "MCP 集成 = Python skill"设计的一个典型样本:skill 侧只声明服务器端点,工具清单完全交给官方 MCP 服务器在运行时下发,内核的McpIntegration基类统一负责凭据解析、会话建立、工具发现与结果归一化。实战中你只需要记住四件事:先/login或/mcp login notion登录、import 后先list_tools()发现、连字符工具名一律走call_tool、所有调用都要await。掌握了这套模式,Linear(同构实现于 linear/init.py)乃至自建的 MCP 服务器接入,对你来说都只是换个server和url的事。
【免费下载链接】prime-agentA self-improving RLM agent for coding workflows and long-running autonomous tasks.项目地址: https://gitcode.com/GitHub_Trending/pr/prime-agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考