Community写作与编辑github.com

DenshoApp/densho-skill

一个代理技能,教会AI助手如何通过MCP在Densho工作区中协作:搜索、读取、编写和评论页面。

densho-skill 是什么?

Densho是一个自托管的知识库,通过MCP协议与AI助手集成,提供结构化的工作区协作能力。该技能的核心功能包括搜索、读取、编写和评论页面,支持实时协作编辑,允许多人同时编辑同一个文档。对于AI代理而言,理解Densho的规则至关重要:`update_page`会替换整个页面内容而非追加,必须通过`expectedVersion`机制确保并发安全。AI助手需要先读取内容,合并修改后再写入,否则可能丢失数据。该技能支持多个AI平台如Claude Code、Cursor和Codex,通过MCP服务器提供标准化工具接口。最佳实践包括:创建页面前先搜索避免重复,使用`get_markdown_reference`获取正确的Markdown方言,优先使用评论而非直接编辑他人页面,以及根据工作区语言编写内容。工具分为读写两类,实际可用性取决于用户授权和实例版本。该技能还强调了团队协作中的注意事项,如实时编辑的干扰性、修改已验证页面会触发审查流程,以及评论文档作者应谨慎操作。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add DenshoApp/densho-skill

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Densho

Densho 是一个自托管的知识库。一个工作区包含空间,每个空间包含一个页面树,每个页面是一份实时协作文档,其他人可能正在与你同时编辑它。

你通过用户连接的 MCP 服务器访问它。你的访问权限与用户完全一致:如果某个工具返回空结果,通常意味着该空间不属于用户的阅读范围,而不是工作区为空。

关于编写的唯一规则

update_page 会替换整个正文。 它不是追加操作。未先读取就编写会破坏已有的内容。

较新的实例会强制执行此规则:替换内容需要 expectedVersion,即 get_page 返回的令牌。如果页面在你读取后发生了更改,或者 ID 错误,写入会被拒绝而不是静默应用。先读取,合并,再写入:

  1. get_page 返回 { version, title, content }
  2. 基于该内容构建完整的新正文
  3. 使用 content 和 expectedVersion: <version> 调用 update_page

如果返回消息说页面已更改,请重新读取并重新合并。切勿使用旧版本重试,也切勿通过丢弃未读取的内容来绕过保护。

较旧的实例没有这样的令牌:get_page 返回一个 Markdown 文档,标题以 # H1 的形式前置,而正文中不包含它。直接将此内容传回 update_page 会将标题写入正文,导致页面显示两次标题。在写入前,去掉那个首标题,并对其余部分同样小心:旧版本中没有任何机制可以阻止错误的写入,因此在写入前立即读取页面,并保留所有你无意更改的内容。

在触碰任何内容之前

  • 创建前先搜索。 先执行 search_pages。维基死于重复内容,而你要写的页面通常已经以另一个标题存在。
  • 在每个会话中调用一次 get_markdown_reference,然后再编写任何页面正文。它返回该实例渲染的确切方言,直接来自实例本身,因此永远不会过时。不要凭记忆猜测语法,也不要假设是 GitHub 风格的 Markdown。如果该工具未提供,说明实例较旧:遵循下面“无法生效的内容”中的限制,并引导用户前往其工作区中的 指南 > 编辑器 > “Markdown 输入和输出” 以获取完整语法。
  • 优先使用评论而非编辑那些你未被要求更改的页面。add_comment 将你的意见放在文本旁边并通知作者,这是对他人工作的礼貌行为。
  • 通过 list_pages 找到页面所属的位置,然后再创建页面。维基是一棵树,放在空间根目录的页面是没人能找到的页面。传递 parentPageId。
  • 使用周围页面的语言编写,而不是你自己的默认语言。一个工作区通常全程使用一种语言编写,使用另一种语言编写的页面会显得像个入侵者。

工具

读取。 list_spaces(用户所属的空间)、list_pages(空间的页面树,作为带有父节点的扁平列表)、search_pages(全文搜索,可选择限定到某个空间,最多 20 个匹配,无分页,因此优化查询而不是将列表视为全部真相)、get_page(标题和 Markdown 正文,以及版本令牌)、list_comments(线程及其解决状态)。

写入。 create_page(在空间中,可选择在父节点下,可选择带正文)、update_page(标题和/或完整正文)、add_comment(新线程或使用 parentCommentId 回复)、resolve_comment。

页面也作为 densho://page/{id} 资源暴露,因此客户端可以直接附加一个页面。

并非每个实例都提供所有这些工具。写入工具仅在用户在授权时授予了写入权限时才存在,而较旧的实例可能缺少评论列表、解决工具和 Markdown 参考。根据客户端实际向您展示的内容进行操作,并如实说明,而不是描述您无法执行的编辑。

编写人们会读的页面

像文档一样结构化,而不是像聊天回复。标题要说明章节内容,段落要简短,当内容适合列表形式时使用列表。

  • 使用 :::info、:::warning 和其他标注来表示真正打断读者的内容。连续三个标注会让人视而不见。
  • 使用 :::toggle 来呈现大多数读者会跳过的细节,而不是隐藏答案。
  • 使用 :::subpages 来创建子页面索引,而不是手写的链接列表,后者会在某天有人添加页面时过时。
  • 优先使用表格而不是用段落列举成对的内容。

编辑器支持的所有内容都可以通过 Markdown 进行往返转换,因此您写下的内容就是用户看到的内容,也是他们后来导出的内容。往返转换过程中会进行规范化:$$maths$$ 会以三行形式返回,块之间会添加空行。读取到与您发送的格式略有不同的内容是正常的,并非失败的迹象。

无法生效的内容

  • 原始 HTML 标签会被转义并以文本形式显示。使用带围栏的 ```htmlrender 块来渲染 HTML,且必须自包含:无网络、无外部资源。
  • GitHub 标注语法(> [!NOTE])不是该方言的一部分:方括号会被转义,读者会看到 \[!NOTE\] 在普通引用中。使用标注块代替。
  • 脚注在这里比无用更糟。text[^1] 与其 [^1]: note 定义会变成 [^1](note),一个指向空处的链接。将旁注内联写在文本中或放在标注块中。
  • ```math 围栏不会渲染。 块级数学公式使用 $$ ... $$。
  • 你不能上传任何东西。 没有文件或图片工具,因此永远不要编写指向本地路径或你声称已添加的文件的 Markdown 图片。已存在于页面中的图片会保持工作状态:在重写正文时,保持其链接不变。
  • 永远不要发明芯片标识符。 提及、页面链接和同步块编码了真实的 ID([@Name](mention:<userId>)、[label](page:<pageId>)、![[synced-blocks/...]])。虚构的 ID 会渲染为死芯片。使用从工具获得的真实 ID,或者编写普通链接。

对团队成员有影响的事情

  • 通过你编辑的页面会立即出现在任何打开该页面的人的编辑器中,位于他们的光标下。当有人在页面上工作时重写长页面,即使技术上安全,也会造成干扰。
  • 编辑标记为已验证的页面会将其状态重置为“待验证”,这会给管理员增加工作。这样做时请明确告知。
  • 评论会通知人们。不要为你能随手修复的问题开启新线程,也不要解决你未处理的线程。

报告反馈

向用户提供页面标题及其所在位置,而不是原始 ID。清楚地说明你更改了什么:完整的正文替换值得明确命名,如果你将文本合并到现有页面中,请说明你保留了哪些内容。

相关技能