
Lexiang Knowledge Base
- 8 installs
- 33 repo stars
- Updated April 26, 2026
- bighardperson/computer-science-skills-collection
lexiang-knowledge-base is a Claude skill for accessing the Lexiang (乐享) knowledge-base platform, supporting document fetch, search, create, edit, move, tags, comments, and attachments.
About
lexiang-knowledge-base lets an agent access the Lexiang (乐享) knowledge-base platform. It can fetch document content and metadata, search documents, query knowledge-base and directory structure, create, edit, and move documents, manage tags and comments, and upload and maintain attachments. A developer uses it when a task references Lexiang or a lexiangla.com link. It requires the LEXIANG_TOKEN and COMPANY_FROM environment variables.
- Dedicated skill for the Lexiang (乐享) knowledge-base platform at lexiangla.com
- Fetches, searches, creates, edits, and moves documents plus manages tags, comments, and attachments
- Triggers on keywords 乐享/lexiang/知识库/文档 or lexiangla.com links; needs LEXIANG_TOKEN and COMPANY_FROM
Lexiang Knowledge Base by the numbers
- 8 all-time installs (skills.sh)
- Ranked #1,167 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Jul 30, 2026 (Skillselion catalog sync)
lexiang-knowledge-base capabilities & compatibility
Requires a LEXIANG_TOKEN and COMPANY_FROM for the Lexiang account.
- Capabilities
- search documents · fetch documents · manage documents
- Use cases
- research · documentation · web search
- Pricing
- Bring your own API key
What lexiang-knowledge-base says it does
homepage: https://lexiangla.com
version: 2.0.0
npx skills add https://github.com/bighardperson/computer-science-skills-collection --skill lexiang-knowledge-baseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8 |
|---|---|
| repo stars | ★ 33 |
| Last updated | April 26, 2026 |
| Repository | bighardperson/computer-science-skills-collection ↗ |
What it does
Read, search, and manage documents in the Lexiang (lexiangla.com) knowledge base from an agent using a token.
Who is it for?
Teams using the Lexiang knowledge base who want an agent to read and maintain their documents.
Skip if: Anyone not on the Lexiang (lexiangla.com) platform, or without a LEXIANG_TOKEN.
When should I use this skill?
The user mentions 乐享, lexiang, 知识库, or 文档, or provides a lexiangla.com link or a space_id/entry_id.
What you get
The agent can fetch, search, create, and organize Lexiang documents directly.
- fetched documents
- search results
- created or edited knowledge-base entries
By the numbers
- 2 required env vars (LEXIANG_TOKEN, COMPANY_FROM)
Files
乐享 MCP 服务
触发场景:当用户明确提到「乐享」「lexiang」「知识」「文档」,或提供lexiangla.com链接,或给出space_id、entry_id、team_id、/spaces/、/pages/等乐享标识时,应使用本服务。
>
优先级:处理乐享相关操作时,优先使用本 Skill 提供的能力,而非直接调用 MCP。本 Skill 封装了最佳实践和完整的使用说明。
>
需要调用 MCP 时,请以 MCP 服务端返回的最新的 schema 为准。
---
⛔ 必读(调用前必须理解):
>
1. 本服务直接暴露所有业务工具(如team_list_teams、search_kb_search等),可直接调用
2. 调用前先确认工具参数定义,以 MCP 返回的 schema 为准
3. 不确定参数时,使用 get_tool_schema(tool_name="xxx") 获取最新定义---
🔑 AccessToken 生命周期管理
阶段 1:未配置 Token
当调用 MCP 连接失败或无认证信息时:
1. 告知用户需要获取乐享 MCP 的 access_token 2. 引导用户打开 https://lexiangla.com/mcp 获取配置信息 3. 用户获取后,帮助完成 mcp.json 配置(参见「快速开始」)
阶段 2:Token 即将过期
当 MCP 返回正常结果但附带过期预警信息时:
1. 先正常返回本次结果 2. 在结果末尾附加提醒,引导用户续期:
⚠️ 您的乐享访问令牌即将过期。请打开以下链接自动续期(需已登录):
https://lexiangla.com/mcp?action=renew&company_from={company_from}阶段 3:Token 已过期(401 响应)
当 MCP 返回 401 未授权时:
1. 不要反复重试 2. 引导用户重新创建会话:
🔒 您的乐享访问令牌已过期。请打开以下链接创建新会话:
https://lexiangla.com/mcp?action=recreate&company_from={company_from}
创建后请将新的 access_token 提供给我进行更新。租户隔离规则
company_from和access_token必须属于同一租户,不同租户的 token 不能混用- OAuth 不支持跨租户授权
- 续期或重建 token 时,URL 中的
company_from必须与当前配置一致 - 如果用户切换了企业/租户,必须重新获取对应租户的 token
---
📊 数据模型
核心概念
| 概念 | 说明 |
|---|---|
| Team(团队) | 顶级组织单元,一个团队下可以有多个知识库(Space) |
| Space(知识库) | 知识的容器,属于某个团队,包含多个条目(Entry),有 root_entry_id 作为根节点 |
| Entry(条目) | 知识库中的内容单元,可以是页面(page)、文件夹(folder)或文件(file),支持树形结构(parent_id) |
| File(文件) | 附件类型的条目,如 PDF、Word、图片等 |
层级关系
Team → Space → Entry(树形结构,root_entry_id 为根)
├── page(页面)
├── folder(文件夹)
└── file(文件)URL 规则
域名固定为 https://lexiangla.com——即 {domain} = https://lexiangla.com
⛔ `company_from` 不是子域名,只能作为 URL 查询参数使用!
>
❌ 错误:https://km.lexiangla.com/pages/xxx(把 company_from 当子域名)❌ 错误:https://abc.lexiangla.com/pages/xxx✅ 正确:https://lexiangla.com/pages/xxx?company_from=km✅ 正确:https://lexiangla.com/pages/xxx(无 company_from 时)链接拼接规则:
https://lexiangla.com/pages/{entry_id}?company_from={company_from}如果没有 company_from,直接使用 https://lexiangla.com/pages/{entry_id}(不加查询参数)。
`company_from` 获取方式(按优先级): 1. MCP 连接 URL 中的 company_from 查询参数(如 mcp?company_from=km 中的 km) 2. 环境变量 COMPANY_FROM 3. 用户提供的 URL 中已有的 company_from 查询参数 4. 如果均不可用,省略该参数
⛔ 严禁使用 `mcp.lexiang-app.com` 拼接任何用户可访问的链接! 该域名仅用于 MCP 接口调用,不是用户访问地址。
⛔ 严禁将 `company_from` 拼接为子域名!company_from只能作为 URL 查询参数(?company_from=xxx),不能拼成https://{company_from}.lexiangla.com。
| 资源 | URL 格式 |
|---|---|
| 团队首页 | {domain}/t/{team_id}/spaces |
| 知识库 | {domain}/spaces/{space_id} |
| 知识条目 | {domain}/pages/{entry_id} |
URL 解析规则
当用户提供链接时,从 URL 路径中提取 ID(忽略查询参数):
| URL 路径 | 提取方式 |
|---|---|
/spaces/{space_id} | 取 spaces/ 后面的部分作为 space_id |
/pages/{entry_id} | 取 pages/ 后面的部分作为 entry_id |
/t/{team_id}/spaces | 取 t/ 后面的部分作为 team_id |
---
🛡️ 写入操作安全规则
核心原则:写入、修改、删除操作 必须基于用户明确提供的目标信息,禁止 Agent 自行选择或猜测目标。
🚫 绝对禁止
1. 禁止遍历团队/知识库列表后自行选择写入目标 2. 禁止根据名称"看起来合适"就决定写入 3. 禁止在未确认时执行写入
✅ 允许写入的条件(满足之一即可)
| 条件 | 示例 |
|---|---|
| 用户提供了明确 URL | "写到这里:https://lexiangla.com/spaces/xxx" |
| 用户提供了明确 ID | "写入 space_id 为 xxx 的知识库" |
| 用户指定名称 + Agent 回显确认 | Agent 搜到后展示详情,用户确认 |
写入操作涉及的工具
entry_create_entry、entry_import_content、entry_import_content_to_entry、block_update_block、block_update_blocks、block_create_block_descendant、block_delete_block、block_delete_block_children、block_move_blocks、entry_rename_entry、entry_move_entry、file_apply_upload、file_commit_upload、file_create_hyperlink
读取操作不受此限制
team_list_teams、team_describe_team、team_list_frequent_teams、space_list_spaces、space_describe_space、entry_list_children、block_list_block_children、search_kb_search、search_kb_embedding_search、space_list_recently_spaces、entry_list_latest_entries、entry_describe_ai_parse_content、file_describe_file、file_download_file 等只读操作可正常执行。
---
🔍 工具发现与调用
本服务直接暴露所有业务工具,可直接调用(如 team_list_teams()、search_kb_search(keyword="xxx"))。
同时提供以下辅助元工具,帮助发现和理解工具:
| 元工具 | 用途 |
|---|---|
list_tool_categories | 列出所有工具分类及其工具列表 |
search_tools | 按关键词或分类搜索工具 |
get_tool_schema | 获取具体工具的完整参数定义 |
标准工作流
1. 直接调用已知工具:team_list_teams()、search_kb_search(keyword="xxx") 等
2. 不确定参数时:get_tool_schema(tool_name="xxx") → 获取参数定义
3. 不确定工具名时:search_tools(query="关键词") → 找到工具名大多数常用工具已在本 Skill 中列出,可直接使用;遇到新工具或不确定的参数时,再用 get_tool_schema 查询。---
🚀 快速开始
获取配置参数
访问:https://lexiangla.com/mcp
登录后获取:
- company_from:你的企业标识
- access_token:访问令牌(格式
lxmcp_xxx)
配置方式
方式1:自动配置(推荐)
请阅读 setup.md 中的步骤说明,按指引完成配置。
方式2:环境变量
export COMPANY_FROM="your_company"
export LEXIANG_TOKEN="lxmcp_YOUR_TOKEN_HERE"方式3:直接修改 mcp.json
编辑 mcp.json,将 ${COMPANY_FROM} 和 ${LEXIANG_TOKEN} 替换为实际值。
mcp.json 配置模板
{
"mcpServers": {
"lexiang": {
"enabled": true,
"url": "https://mcp.lexiang-app.com/mcp?company_from=${COMPANY_FROM}",
"transportType": "streamable-http",
"headers": {
"Authorization": "Bearer ${LEXIANG_TOKEN}"
}
}
}
}安装后验证
配置完成后,立即调用 whoami() 进行连通性检查并获取用户身份信息:
1. 调用 whoami() 2. 成功(返回用户信息)→ 向用户展示欢迎消息:
✅ 乐享 MCP 连接成功!
👤 当前用户:{用户姓名}
🏢 绑定乐享:{企业/租户名称}
🎉 配置已就绪,你现在可以这样使用乐享知识库:
💡 试试这样提问:
• "看看我最近访问的知识库有什么更新"
• "我要记录今天的工作内容,为我创建一个乐享文档并拟写一个模版"
• "搜索关于 XXX 的知识文档"
• "帮我总结一下这个知识库的内容:{知识库链接}"根据 whoami 返回的实际字段灵活调整展示内容。3. 401 错误 → token 无效或已过期,引导用户重新获取(参见「AccessToken 生命周期管理」) 4. 连接超时/其他错误 → 检查 mcp.json 配置是否正确
遇到问题?
| 问题 | 解决方案 |
|---|---|
| 连接无响应 | 确认 mcp.json 中 URL 包含 company_from 且格式正确 |
| 401 未授权 | token 过期或租户不匹配,参见「AccessToken 生命周期管理」 |
| 参数报错 | 执行 get_tool_schema(tool_name="xxx") 获取最新参数定义 |
---
🎯 意图识别与澄清
明确使用本 Skill 的场景
1. 关键词触发:用户提到「乐享」「lexiang」「知识库」「知识」「文档」 2. 链接触发:用户提供的链接 host 为 lexiangla.com 3. 上下文延续:用户之前已明确使用乐享,后续操作默认继续
🛡️ 写入安全提醒
- ❌ 禁止遍历团队/知识库列表后自行选择写入目标
- ✅ 用户提供了 URL / ID / 精确名称 + 确认后方可写入
- ✅ 写入目标不明确时(如"帮我写到乐享""执行吧"但未指定知识库),需要求用户提供具体写入位置
- ✅ 读取操作(搜索、浏览、查看)不受此限制
---
工具概述
本 MCP 服务提供以下工具,可直接调用。参数不确定时以 get_tool_schema 返回为准。
📚 知识库管理
entry_create_entry— 创建文档/文件夹entry_import_content— 导入 Markdown/HTML 创建新文档(⚠️ 仅新建)entry_import_content_to_entry— 导入内容到已有页面(支持覆盖/追加)entry_list_latest_entries— 获取最近更新条目entry_rename_entry— 重命名条目
📎 文件管理
file_apply_upload— 申请文件上传(返回 upload_url 和 session_id)file_commit_upload— 确认上传完成
🧩 Block 操作
block_convert_content_to_blocks— Markdown/HTML 转 Block 结构block_create_block_descendant— 创建 Block 结构block_update_block— 单块更新block_update_blocks— 批量更新block_move_blocks— 移动 Blockblock_delete_block_children— 删除子节点block_delete_block— 删除指定 Block(含子孙)block_describe_block— 获取单个 Block 详情block_list_block_children— 读取 Block 内容
🔍 搜索与发现
search_kb_search— 关键词搜索search_kb_embedding_search— 语义向量搜索team_list_teams— 获取团队列表team_describe_team— 获取团队详情team_list_frequent_teams— 获取常用团队列表space_list_spaces— 获取知识库列表space_describe_space— 获取知识库详情(返回root_entry_id)space_list_recently_spaces— 获取最近访问知识库
📖 条目与结构浏览
entry_list_children— 浏览目录结构entry_describe_entry— 获取条目元信息(不含正文)entry_describe_ai_parse_content— 获取 AI 解析内容(含正文)entry_list_parents— 获取父级路径(面包屑)
🔗 外部内容导入
file_create_hyperlink— 导入公众号文章等外部链接
---
内容搜索
关键词搜索 vs 语义搜索
| 工具 | 适用场景 |
|---|---|
search_kb_search | 精确关键词匹配 |
search_kb_embedding_search | 模糊查询、"记得大意但忘了标题" |
建议:语义搜索召回后,再用 entry_describe_entry 或 entry_describe_ai_parse_content 精确读取。
搜索结果链接格式
根据返回的 target_type 拼接链接:
| target_type | URL 格式 |
|---|---|
kb_page | {domain}/pages/<target_id> |
kb_file / kb_video | {domain}/teams/<team_id>/docs/<target_id> |
---
🔗 结果链接生成规则(通用)
适用于所有返回 `entry_id` 的操作,包括但不限于:entry_import_content、entry_create_entry、entry_import_content_to_entry、file_commit_upload、搜索结果等。
拼接规则
当操作成功返回了 entry_id(或 target_id),向用户展示访问链接时,使用上方「URL 规则」中定义的 {domain} 拼接:
{domain}/pages/{entry_id}⛔ 禁止
- 禁止使用
mcp.lexiang-app.com拼接用户访问链接 - 禁止使用 MCP 连接 URL(
mcp.lexiang-app.com)的域名作为用户访问域名 - 禁止将
company_from拼接为子域名(如https://{company_from}.lexiangla.com是错误的) - 禁止编造或猜测域名,必须严格使用上方定义的
{domain}
---
📖 内容读取
| 工具 | 返回内容 | 用途 |
|---|---|---|
entry_describe_entry | 条目元信息(ID、名称、类型等) | 获取基本信息 |
entry_describe_ai_parse_content | 条目正文内容 | 读取实际内容进行分析 |
---
常见操作流程
从知识库链接写入文档
⚠️ 仅在用户主动提供了知识库链接时执行。详见下方「常见使用场景 > 场景0」。
核心步骤:提取 space_id → space_describe_space 获取 root_entry_id → entry_import_content 写入 → 用 {domain}/pages/{entry_id} 拼接访问链接返回给用户。
微信公众号导入
当用户提供 mp.weixin.qq.com 链接且意图是"导入/收藏/保存到乐享"时,使用 file_create_hyperlink。
如果用户只是想阅读或总结内容,不要默认导入。
---
常见使用场景
场景0: 用户给了知识库链接,写入文档
用户:"把报告写入乐享,链接是 https://lexiangla.com/spaces/16c4224607ea45ebacce6c15130a4957"
Step 1: 从 URL 提取 space_id = "16c4224607ea45ebacce6c15130a4957"
Step 2: call_tool("space_describe_space", {"space_id": "..."}) → 获取 root_entry_id
Step 3: call_tool("entry_import_content", {"space_id": "...", "parent_id": root_entry_id, "name": "报告", "content": "...", "content_type": "markdown"})
Step 4: 从返回结果取 entry_id,向用户展示访问链接:{domain}/pages/{entry_id}要点:space_id和parent_id要同时传;parent_id用root_entry_id表示写入根目录;链接中{domain}见上方 URL 规则定义。
场景1: 创建文档
call_tool("entry_create_entry", {"name": "技术文档", "parent_entry_id": "abc123", "entry_type": "page"})场景2: 导入 Markdown
call_tool("entry_import_content", {"parent_id": "folder123", "name": "技术文档", "content": "...", "content_type": "markdown"})场景3: 创建结构化 Block 文档
call_tool("block_create_block_descendant", {
"entry_id": "doc123",
"descendant": [
{"block_id": "h1", "block_type": "h1", "heading1": {"elements": [{"text_run": {"content": "项目文档"}}]}},
{"block_id": "tip", "block_type": "callout", "callout": {"color": "#FFF3E0"}, "children": ["tip_p"]},
{"block_id": "tip_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "重要提示内容"}}]}},
{"block_id": "li1", "block_type": "bulleted_list", "bulleted": {"elements": [{"text_run": {"content": "功能一"}}]}}
],
"children": ["h1", "tip", "li1"]
})场景4: 上传文件(3 步)
Step 1: call_tool("file_apply_upload", {"parent_entry_id": "folder123", "name": "README.md", "size": 1024})
→ 返回 upload_url, session_id
Step 2: HTTP PUT upload_url(上传文件内容,非 MCP 调用)
Step 3: call_tool("file_commit_upload", {"session_id": "..."})场景5: 读取 Block 内容
call_tool("block_list_block_children", {"entry_id": "abc123", "with_descendants": true})场景6: 批量更新 Block
call_tool("block_update_blocks", {
"entry_id": "abc123",
"updates": {
"actual_block_id": {
"update_text_elements": {
"elements": [{"text_run": {"content": "更新后的内容"}}]
}
}
}
})---
Block 结构核心规则
🍃 叶子节点(不能有 children)
- 标题块:h1, h2, h3, h4, h5
- 代码块:code
- 图片块:image
- 分割线:divider
- 图表块:mermaid, plantuml
📦 容器节点(必须指定 children)
- 提示框:callout
- 表格:table, table_cell
- 分栏布局:column_list, column
- 折叠块:toggle
详细说明:完整 Block 类型和字段定义见 references/block-schema.md。---
⚠️ 核心注意事项
1. Block ID 映射:block_id 为客户端临时 ID,服务端返回实际 ID 映射 2. 叶子节点限制:标题、代码块、图片等不支持 children 字段 3. 容器节点要求:callout、table、column_list 等必须指定 children 4. 文件上传大小:必须获取准确的文件大小(字节数) 5. `_mcp_fields` 优化:所有工具支持 _mcp_fields 参数选择返回字段,减少 token 消耗
更多细节:见references/common-errors.md和references/markdown-import.md。
---
辅助资源
参考文档(references/ 目录)
| 文档 | 说明 |
|---|---|
block-schema.md | Block 类型完整说明 |
mcp-examples.md | 复杂 Block 结构示例 |
markdown-to-block.md | Markdown 转 Block 指南 |
block-update.md | 批量更新 Block 方法 |
content-reorganize.md | 文档结构重组 |
folder-sync.md | 文件夹同步方案 |
markdown-import.md | Markdown 导入详解 |
common-errors.md | 常见错误排查 |
skill-maintenance.md | 维护与反馈流程 |
辅助脚本(scripts/ 目录)
| 脚本 | 说明 |
|---|---|
sync-folder.ts | 文件夹增量同步 |
block-helper.ts | Block 构建辅助工具 |
mcp-validator.ts | MCP 参数校验 |
---
❓ 问题与排查
遇到问题时,请先查阅 references/common-errors.md。
---
📮 维护与反馈
Issue 反馈流程和 Skill 自我进化机制见 references/skill-maintenance.md。
---
相关链接
- 乐享平台:https://lexiangla.com
- MCP 协议:https://modelcontextprotocol.io
{
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "h2_compare",
"block_type": "h2",
"heading2": {"elements": [{"text_run": {"content": "对比效果", "text_style": {}}}]}
},
{
"block_id": "table_compare",
"block_type": "table",
"table": {"row_size": 4, "column_size": 2, "column_width": [400, 500], "header_row": true},
"children": ["c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"]
},
{"block_id": "c1", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["c1_p"]},
{"block_id": "c1_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "传统方式", "text_style": {"bold": true}}}]}},
{"block_id": "c2", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["c2_p"]},
{"block_id": "c2_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "新方案", "text_style": {"bold": true}}}]}},
{"block_id": "c3", "block_type": "table_cell", "table_cell": {"background_color": "#FFEBEE"}, "children": ["c3_p"]},
{"block_id": "c3_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "手动操作,耗时 2-3 小时", "text_style": {}}}]}},
{"block_id": "c4", "block_type": "table_cell", "table_cell": {"background_color": "#E8F5E9"}, "children": ["c4_p"]},
{"block_id": "c4_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "自动化执行,秒级完成", "text_style": {}}}]}},
{"block_id": "c5", "block_type": "table_cell", "table_cell": {"background_color": "#FFEBEE"}, "children": ["c5_p"]},
{"block_id": "c5_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "容易出错,需要多次检查", "text_style": {}}}]}},
{"block_id": "c6", "block_type": "table_cell", "table_cell": {"background_color": "#E8F5E9"}, "children": ["c6_p"]},
{"block_id": "c6_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "标准化流程,零出错率", "text_style": {}}}]}},
{"block_id": "c7", "block_type": "table_cell", "table_cell": {"background_color": "#FFEBEE"}, "children": ["c7_p"]},
{"block_id": "c7_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "格式不统一,维护困难", "text_style": {}}}]}},
{"block_id": "c8", "block_type": "table_cell", "table_cell": {"background_color": "#E8F5E9"}, "children": ["c8_p"]},
{"block_id": "c8_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "风格一致,模板可复用", "text_style": {}}}]}}
],
"children": ["h2_compare", "table_compare"]
}
{
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "intro",
"block_type": "callout",
"callout": {"color": "#E3F2FD", "icon": "1f680"},
"children": ["intro_p"]
},
{
"block_id": "intro_p",
"block_type": "p",
"text": {"elements": [{"text_run": {"content": "本文档介绍 XXX 功能的使用方法和最佳实践", "text_style": {}}}]}
},
{
"block_id": "h2_overview",
"block_type": "h2",
"heading2": {"elements": [{"text_run": {"content": "概述", "text_style": {}}}]}
},
{
"block_id": "p_overview",
"block_type": "p",
"text": {"elements": [{"text_run": {"content": "功能描述内容...", "text_style": {}}}]}
},
{
"block_id": "divider_1",
"block_type": "divider",
"divider": {}
},
{
"block_id": "h2_quickstart",
"block_type": "h2",
"heading2": {"elements": [{"text_run": {"content": "快速开始", "text_style": {}}}]}
},
{
"block_id": "code_example",
"block_type": "code",
"code": {
"elements": [{"text_run": {"content": "// 示例代码\nfunc main() {\n fmt.Println(\"Hello\")\n}", "text_style": {}}}],
"style": {"language": "go"}
}
},
{
"block_id": "divider_2",
"block_type": "divider",
"divider": {}
},
{
"block_id": "h2_params",
"block_type": "h2",
"heading2": {"elements": [{"text_run": {"content": "参数说明", "text_style": {}}}]}
},
{
"block_id": "table_params",
"block_type": "table",
"table": {"row_size": 3, "column_size": 4, "column_width": [150, 100, 80, 270], "header_row": true},
"children": ["tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7", "tc8", "tc9", "tc10", "tc11", "tc12"]
},
{"block_id": "tc1", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["tc1_p"]},
{"block_id": "tc1_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "参数名", "text_style": {"bold": true}}}]}},
{"block_id": "tc2", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["tc2_p"]},
{"block_id": "tc2_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "类型", "text_style": {"bold": true}}}]}},
{"block_id": "tc3", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["tc3_p"]},
{"block_id": "tc3_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "必填", "text_style": {"bold": true}}}]}},
{"block_id": "tc4", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["tc4_p"]},
{"block_id": "tc4_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "说明", "text_style": {"bold": true}}}]}},
{"block_id": "tc5", "block_type": "table_cell", "table_cell": {}, "children": ["tc5_p"]},
{"block_id": "tc5_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "name", "text_style": {"inline_code": true}}}]}},
{"block_id": "tc6", "block_type": "table_cell", "table_cell": {}, "children": ["tc6_p"]},
{"block_id": "tc6_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "string", "text_style": {}}}]}},
{"block_id": "tc7", "block_type": "table_cell", "table_cell": {}, "children": ["tc7_p"]},
{"block_id": "tc7_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "是", "text_style": {}}}]}},
{"block_id": "tc8", "block_type": "table_cell", "table_cell": {}, "children": ["tc8_p"]},
{"block_id": "tc8_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "名称", "text_style": {}}}]}},
{"block_id": "tc9", "block_type": "table_cell", "table_cell": {}, "children": ["tc9_p"]},
{"block_id": "tc9_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "timeout", "text_style": {"inline_code": true}}}]}},
{"block_id": "tc10", "block_type": "table_cell", "table_cell": {}, "children": ["tc10_p"]},
{"block_id": "tc10_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "int", "text_style": {}}}]}},
{"block_id": "tc11", "block_type": "table_cell", "table_cell": {}, "children": ["tc11_p"]},
{"block_id": "tc11_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "否", "text_style": {}}}]}},
{"block_id": "tc12", "block_type": "table_cell", "table_cell": {}, "children": ["tc12_p"]},
{"block_id": "tc12_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "超时时间(秒),默认 30", "text_style": {}}}]}},
{
"block_id": "divider_3",
"block_type": "divider",
"divider": {}
},
{
"block_id": "tip_callout",
"block_type": "callout",
"callout": {"color": "#FFF3E0", "icon": "1f4a1"},
"children": ["tip_p"]
},
{
"block_id": "tip_p",
"block_type": "p",
"text": {"elements": [{"text_run": {"content": "提示:建议在生产环境设置合理的超时时间", "text_style": {}}}]}
}
],
"children": ["intro", "h2_overview", "p_overview", "divider_1", "h2_quickstart", "code_example", "divider_2", "h2_params", "table_params", "divider_3", "tip_callout"]
}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://lexiangla.com/schemas/lexiang-block-schema.json",
"title": "乐享 Block JSON Schema",
"description": "乐享在线文档 Block 类型的完整 JSON Schema 定义",
"version": "1.0.0",
"definitions": {
"CommonBlock": {
"type": "object",
"properties": {
"block_id": {
"type": "string",
"description": "创建嵌套块时指定临时 ID;创建简单块时可留空"
},
"block_type": {
"type": "string",
"enum": [
"p",
"h1",
"h2",
"h3",
"h4",
"h5",
"bulleted_list",
"numbered_list",
"code",
"divider",
"callout",
"toggle",
"task",
"column_list",
"column",
"table",
"table_cell",
"mermaid",
"plantuml",
"image",
"video",
"attachment"
],
"description": "块类型枚举值"
},
"children": {
"type": "array",
"items": {
"type": "string"
},
"description": "子块的临时 ID 列表(仅容器类块使用)"
},
"parent_id": {
"type": "string",
"description": "父块 ID(响应中返回,创建时无需指定)"
}
},
"required": [
"block_type"
]
},
"Text": {
"description": "文本内容,适用于:text, heading1-heading5, bulleted, numbered, code, toggle",
"type": "object",
"properties": {
"elements": {
"type": "array",
"items": {
"$ref": "#/definitions/TextElement"
}
},
"style": {
"$ref": "#/definitions/BlockStyle"
}
}
},
"TextElement": {
"type": "object",
"oneOf": [
{
"properties": {
"text_run": {
"$ref": "#/definitions/TextRun"
}
},
"required": [
"text_run"
]
},
{
"properties": {
"mention_staff": {
"type": "object",
"properties": {
"staff_id": {
"type": "string"
}
},
"required": [
"staff_id"
]
}
},
"required": [
"mention_staff"
]
},
{
"properties": {
"mention_entry": {
"type": "object",
"properties": {
"entry_id": {
"type": "string"
}
},
"required": [
"entry_id"
]
}
},
"required": [
"mention_entry"
]
},
{
"properties": {
"mention_date": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"time": {
"type": "string",
"pattern": "^\\d{2}:\\d{2}:\\d{2}$"
}
},
"required": [
"date",
"time"
]
}
},
"required": [
"mention_date"
]
}
]
},
"TextRun": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"text_style": {
"$ref": "#/definitions/TextStyle"
}
},
"required": [
"content"
]
},
"TextStyle": {
"type": "object",
"properties": {
"bold": {
"type": "boolean"
},
"italic": {
"type": "boolean"
},
"underline": {
"type": "boolean"
},
"strikethrough": {
"type": "boolean"
},
"inline_code": {
"type": "boolean"
},
"text_color": {
"type": "string",
"pattern": "^#[0-9A-Fa-f]{6}$"
},
"background_color": {
"type": "string",
"pattern": "^#[0-9A-Fa-f]{6}$"
},
"link": {
"type": "string",
"format": "uri"
}
}
},
"BlockStyle": {
"type": "object",
"properties": {
"align": {
"enum": [
"left",
"center",
"right"
]
},
"background_color": {
"type": "string",
"pattern": "^#[0-9A-Fa-f]{6}$"
},
"language": {
"type": "string"
},
"wrap": {
"type": "boolean"
}
}
},
"Paragraph": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "p"
},
"text": {
"$ref": "#/definitions/Text"
}
},
"required": [
"text"
]
}
]
},
"Heading": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"enum": [
"h1",
"h2",
"h3",
"h4",
"h5"
]
},
"heading1": {
"$ref": "#/definitions/Text"
},
"heading2": {
"$ref": "#/definitions/Text"
},
"heading3": {
"$ref": "#/definitions/Text"
},
"heading4": {
"$ref": "#/definitions/Text"
},
"heading5": {
"$ref": "#/definitions/Text"
}
}
}
]
},
"BulletedList": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "bulleted_list"
},
"bulleted": {
"$ref": "#/definitions/Text"
}
},
"required": [
"bulleted"
]
}
]
},
"NumberedList": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "numbered_list"
},
"numbered": {
"$ref": "#/definitions/Text"
}
},
"required": [
"numbered"
]
}
]
},
"CodeBlock": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "code"
},
"code": {
"$ref": "#/definitions/Text"
}
},
"required": [
"code"
]
}
]
},
"Divider": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "divider"
},
"divider": {
"type": "object"
}
},
"required": [
"divider"
]
}
]
},
"Callout": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "callout"
},
"callout": {
"type": "object",
"properties": {
"icon": {
"type": "string",
"description": "Emoji Unicode,如 1f680 = 🚀"
},
"color": {
"type": "string",
"pattern": "^#[0-9A-Fa-f]{6}$",
"description": "背景色 Hex 值"
}
},
"required": [
"icon",
"color"
]
}
},
"required": [
"callout"
]
}
]
},
"Toggle": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "toggle"
},
"toggle": {
"$ref": "#/definitions/Text"
}
},
"required": [
"toggle"
]
}
]
},
"Task": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "task"
},
"task": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"done": {
"type": "boolean"
},
"due_at": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"time": {
"type": "string",
"pattern": "^\\d{2}:\\d{2}:\\d{2}$"
}
},
"required": [
"date",
"time"
]
},
"assignees": {
"type": "array",
"items": {
"type": "object",
"properties": {
"staff_id": {
"type": "string"
}
},
"required": [
"staff_id"
]
}
}
},
"required": [
"name"
]
}
},
"required": [
"task"
]
}
]
},
"ColumnList": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "column_list"
},
"column_list": {
"type": "object",
"properties": {
"column_size": {
"type": "number",
"minimum": 1
}
},
"required": [
"column_size"
]
}
},
"required": [
"column_list"
]
}
]
},
"Column": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "column"
},
"column": {
"type": "object",
"properties": {
"width_ratio": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"width_ratio"
]
}
},
"required": [
"column"
]
}
]
},
"Table": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "table"
},
"table": {
"type": "object",
"properties": {
"row_size": {
"type": "number",
"minimum": 1
},
"column_size": {
"type": "number",
"minimum": 1
},
"column_width": {
"type": "array",
"items": {
"type": "number",
"minimum": 0
}
},
"header_row": {
"type": "boolean"
},
"header_column": {
"type": "boolean"
}
},
"required": [
"row_size",
"column_size"
]
}
},
"required": [
"table"
]
}
]
},
"TableCell": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "table_cell"
},
"table_cell": {
"type": "object",
"properties": {
"background_color": {
"type": "string",
"pattern": "^#[0-9A-Fa-f]{6}$"
},
"align": {
"enum": [
"left",
"center",
"right"
]
},
"vertical_align": {
"enum": [
"top",
"middle",
"bottom"
]
},
"row_span": {
"type": "number",
"minimum": 1
},
"col_span": {
"type": "number",
"minimum": 1
}
}
}
},
"required": [
"table_cell"
]
}
]
},
"Mermaid": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "mermaid"
},
"mermaid": {
"type": "object",
"properties": {
"content": {
"type": "string"
}
},
"required": [
"content"
]
}
},
"required": [
"mermaid"
]
}
]
},
"PlantUML": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "plantuml"
},
"plantuml": {
"type": "object",
"properties": {
"content": {
"type": "string"
}
},
"required": [
"content"
]
}
},
"required": [
"plantuml"
]
}
]
},
"Image": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "image"
},
"image": {
"type": "object",
"properties": {
"file_id": {
"type": "string"
},
"width": {
"type": "number",
"minimum": 0
},
"height": {
"type": "number",
"minimum": 0
},
"align": {
"enum": [
"left",
"center",
"right"
]
},
"caption": {
"type": "string"
}
},
"required": [
"file_id"
]
}
},
"required": [
"image"
]
}
]
},
"Video": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "video"
},
"video": {
"type": "object",
"properties": {
"file_id": {
"type": "string"
},
"name": {
"type": "string"
},
"width": {
"type": "number",
"minimum": 0
},
"height": {
"type": "number",
"minimum": 0
},
"align": {
"enum": [
"left",
"center",
"right"
]
}
},
"required": [
"file_id"
]
}
},
"required": [
"video"
]
}
]
},
"Attachment": {
"allOf": [
{
"$ref": "#/definitions/CommonBlock"
},
{
"properties": {
"block_type": {
"const": "attachment"
},
"attachment": {
"type": "object",
"properties": {
"file_id": {
"type": "string"
},
"name": {
"type": "string"
},
"view_type": {
"enum": [
"text",
"card",
"preview"
]
}
},
"required": [
"file_id"
]
}
},
"required": [
"attachment"
]
}
]
},
"Block": {
"oneOf": [
{
"$ref": "#/definitions/Paragraph"
},
{
"$ref": "#/definitions/Heading"
},
{
"$ref": "#/definitions/BulletedList"
},
{
"$ref": "#/definitions/NumberedList"
},
{
"$ref": "#/definitions/CodeBlock"
},
{
"$ref": "#/definitions/Divider"
},
{
"$ref": "#/definitions/Callout"
},
{
"$ref": "#/definitions/Toggle"
},
{
"$ref": "#/definitions/Task"
},
{
"$ref": "#/definitions/ColumnList"
},
{
"$ref": "#/definitions/Column"
},
{
"$ref": "#/definitions/Table"
},
{
"$ref": "#/definitions/TableCell"
},
{
"$ref": "#/definitions/Mermaid"
},
{
"$ref": "#/definitions/PlantUML"
},
{
"$ref": "#/definitions/Image"
},
{
"$ref": "#/definitions/Video"
},
{
"$ref": "#/definitions/Attachment"
}
]
}
},
"anyOf": [
{
"$ref": "#/definitions/Paragraph"
},
{
"$ref": "#/definitions/Heading"
},
{
"$ref": "#/definitions/BulletedList"
},
{
"$ref": "#/definitions/NumberedList"
},
{
"$ref": "#/definitions/CodeBlock"
},
{
"$ref": "#/definitions/Divider"
},
{
"$ref": "#/definitions/Callout"
},
{
"$ref": "#/definitions/Toggle"
},
{
"$ref": "#/definitions/Task"
},
{
"$ref": "#/definitions/ColumnList"
},
{
"$ref": "#/definitions/Column"
},
{
"$ref": "#/definitions/Table"
},
{
"$ref": "#/definitions/TableCell"
},
{
"$ref": "#/definitions/Mermaid"
},
{
"$ref": "#/definitions/PlantUML"
},
{
"$ref": "#/definitions/Image"
},
{
"$ref": "#/definitions/Video"
},
{
"$ref": "#/definitions/Attachment"
}
]
}{
"$schema": "lexiang-doc-theme/v1",
"name": "默认主题",
"description": "适用于技术文档、功能说明、开发指南等",
"version": "1.0.0",
"callout": {
"primary": {
"color": "#E3F2FD",
"icon": "1f680",
"usage": "开篇引导、核心价值、重要说明"
},
"tip": {
"color": "#FFF3E0",
"icon": "1f4a1",
"usage": "提示信息、注意事项、小技巧"
},
"success": {
"color": "#E8F5E9",
"icon": "2705",
"usage": "成功、完成、总结确认"
},
"warning": {
"color": "#FFF8E1",
"icon": "26a0",
"usage": "警告、风险提示"
},
"error": {
"color": "#FFEBEE",
"icon": "274c",
"usage": "错误、禁止、危险操作"
},
"info": {
"color": "#E8EAF6",
"icon": "2139",
"usage": "补充说明、背景信息"
}
},
"table": {
"header": {
"background_color": "#F5F5F5",
"text_style": {
"bold": true
}
},
"cell": {
"success": {"background_color": "#E8F5E9"},
"warning": {"background_color": "#FFF8E1"},
"error": {"background_color": "#FFEBEE"},
"highlight": {"background_color": "#E3F2FD"},
"neutral": {"background_color": "#FAFAFA"}
},
"default_column_width": [300, 400],
"compare_table": {
"column_width": [400, 550],
"left_header": "传统方式",
"right_header": "新方案"
}
},
"text": {
"emphasis": {
"keyword": {"bold": true},
"important": {"bold": true, "underline": true},
"highlight": {"bold": true, "background_color": "#FFF59D"}
},
"code": {"inline_code": true}
},
"code_block": {
"default_language": "go",
"wrap": false
},
"structure": {
"use_divider_between_sections": true,
"callout_at_start": true,
"callout_at_end": true
},
"semantic_mapping": {
"markdown_to_callout": {
"> 核心": "primary",
"> 重要": "primary",
"> 提示": "tip",
"> 建议": "tip",
"> 注意": "warning",
"> 警告": "warning",
"> 成功": "success",
"> 完成": "success",
"> 错误": "error",
"> 危险": "error",
"> 信息": "info",
"> ": "primary"
},
"table_cell_keywords": {
"success": ["完成", "成功", "推荐", "支持", "是", "✓", "✅"],
"error": ["失败", "不支持", "否", "✗", "❌", "危险"],
"warning": ["注意", "警告", "待定", "可选"]
}
}
}
{
"mcpServers": {
"lexiang": {
"enabled": true,
"url": "https://mcp.lexiang-app.com/mcp?company_from=${COMPANY_FROM}",
"transportType": "streamable-http",
"headers": {
"Authorization": "Bearer ${LEXIANG_TOKEN}"
}
}
}
}
乐享 MCP - ClawHub 外部版本
适用于外部 ClawHub / mcporter 用户
认证方式
需要用户自行配置:
COMPANY_FROM:企业标识(从 https://lexiangla.com/mcp 获取)LEXIANG_TOKEN:访问令牌(格式lxmcp_xxx)
配置方式
方式1:环境变量(推荐)
export COMPANY_FROM="your_company"
export LEXIANG_TOKEN="lxmcp_YOUR_TOKEN_HERE"方式2:直接修改 mcp.json
将 ${COMPANY_FROM} 和 ${LEXIANG_TOKEN} 替换为实际值。
快速配置
阅读 setup.md 中的配置步骤,按指引完成配置。适用于所有操作系统(macOS / Linux / Windows)。
使用说明
详细工具文档请参考 lexiang-base/SKILL.md
Block 类型速查
支持的块类型
| 类型 | block_type | 说明 | 支持 children |
|---|---|---|---|
| 段落 | p | 普通文本段落 | ✓ |
| 一级标题 | h1 | 标题 | ✗ |
| 二级标题 | h2 | 标题 | ✗ |
| 三级标题 | h3 | 标题 | ✗ |
| 四级标题 | h4 | 标题 | ✗ |
| 五级标题 | h5 | 标题 | ✗ |
| 无序列表 | bulleted_list | 项目符号列表 | ✓ |
| 有序列表 | numbered_list | 数字编号列表 | ✓ |
| 代码块 | code | 代码 | ✗ |
| 分割线 | divider | 水平分割线 | ✗ |
| 折叠块 | toggle | 可展开/折叠内容 | ✓ |
| 高亮块 | callout | 带颜色和图标的提示框 | ✓ (必填) |
| 任务 | task | 任务项 | ✓ |
| 分栏容器 | column_list | 多列布局容器 | ✓ (必填) |
| 分栏列 | column | 单列内容 | ✓ (必填) |
| 表格 | table | 表格 | ✓ (必填) |
| 表格单元格 | table_cell | 表格单元格 | ✓ (必填) |
| Mermaid | mermaid | Mermaid 图表 | ✗ |
| PlantUML | plantuml | PlantUML 图表 | ✗ |
---
文本结构
{
"elements": [
{
"text_run": {
"content": "文本内容",
"text_style": {
"bold": true,
"italic": false,
"underline": false,
"strikethrough": false,
"inline_code": false,
"link": "https://example.com",
"text_color": "#333333",
"background_color": "#FFFFFF"
}
}
}
],
"style": {
"align": "left",
"background_color": "#FFFFFF",
"language": "javascript",
"wrap": false
}
}---
块字段映射
| block_type | 内容字段 |
|---|---|
| p | text |
| h1 | heading1 |
| h2 | heading2 |
| h3 | heading3 |
| h4 | heading4 |
| h5 | heading5 |
| bulleted_list | bulleted |
| numbered_list | numbered |
| code | code |
| toggle | toggle |
| callout | callout |
| task | task |
| table | table |
| table_cell | table_cell |
| column_list | column_list |
| column | column |
| divider | divider |
| mermaid | mermaid |
| plantuml | plantuml |
---
特殊块结构
callout
{
"callout": {
"color": "#E3F2FD",
"icon": "1f680"
}
}table
{
"table": {
"row_size": 3,
"column_size": 2,
"column_width": [300, 400],
"header_row": true,
"header_column": false
}
}table_cell
{
"table_cell": {
"background_color": "#F5F5F5",
"align": "left",
"vertical_align": "middle",
"row_span": 1,
"col_span": 1
}
}column_list / column
{
"column_list": {"column_size": 2}
}
{
"column": {"width_ratio": 0.5}
}mermaid / plantuml
{
"mermaid": {
"content": "graph TD\n A --> B"
}
}
{
"plantuml": {
"content": "@startuml\nA -> B\n@enduml"
}
}task
{
"task": {
"name": "任务名称",
"done": false,
"assignees": [{"staff_id": "user_123"}],
"due_at": {"date": "2026-01-25", "time": "18:00"}
}
}---
注意事项
1. 容器类块必须指定 children: callout, table, table_cell, column_list, column 2. 表格 children 顺序: 从左到右、从上到下 3. block_id 为临时 ID: 服务端返回实际 ID 映射 4. 叶子节点不支持 children: h1-h5, code, divider, mermaid, plantuml
场景:Block 增量更新
批量更新已有文档中的多个块内容或样式。
批量更新 API
MCP Tool: lexiang.block_update_blocks
Arguments: {
"entry_id": "<entry_id>",
"updates": {
"<block_id_1>": { <更新操作> },
"<block_id_2>": { <更新操作> },
...
}
}限制: 单次最多更新 20 个块
---
更新操作类型
更新文本内容
{
"update_text": {
"text": {
"elements": [
{"text_run": {"content": "新内容", "text_style": {"bold": true}}}
]
}
}
}更新块样式
{
"update_style": {
"style": {
"background_color": "#FFF8E1",
"align": "center"
}
}
}更新任务状态
{
"update_task": {
"done": true,
"name": "任务名称"
}
}插入文本
{
"insert_text": {
"position": {"index": 5},
"text": "插入的文本",
"text_style": {"italic": true}
}
}删除文本
{
"delete_text": {
"range": {"start_index": 0, "end_index": 10}
}
}---
完整示例
MCP Tool: lexiang.block_update_blocks
Arguments: {
"entry_id": "abc123",
"updates": {
"block_001": {
"update_text": {
"text": {
"elements": [{"text_run": {"content": "更新后的标题", "text_style": {"bold": true}}}]
}
}
},
"block_002": {
"update_style": {
"style": {"background_color": "#E8F5E9"}
}
},
"block_003": {
"update_task": {"done": true}
}
}
}---
使用辅助工具
import { UpdateBlocksBuilder } from './scripts/block-helper';
const updater = new UpdateBlocksBuilder()
.updateText('block_1', '新标题', { bold: true })
.updateStyle('block_2', { background_color: '#E8F5E9' })
.updateTask('block_3', true)
.insertText('block_4', 0, '前缀: ')
.deleteText('block_5', 0, 5);
const mcpCall = updater.toMCPCall(entryId);
// { tool: 'lexiang.block_update_blocks', args: {...} }---
注意事项
1. 每个块在单次请求中只能执行一种更新操作 2. 如需同时更新文本和样式,使用 update_text 并在 text.style 中指定样式 3. 更新前需先获取 block_id,可通过 list_block_children 获取
乐享 MCP 常见错误和修复
本文档列出 Agent 调用乐享 MCP 时的常见错误和修复方法。
---
⚠️ 高频错误速查
| 错误 | 原因 | 修复 |
|---|---|---|
| 文件上传失败 | 缺少 size 参数 | 必须指定文件大小(字节数) |
| 更新文件失败 | file_id 未传或 parent_entry_id 错误 | 更新时 parent_entry_id = 当前文件 entry_id |
| 块创建报错 | h1/h2/code 等叶子节点包含 children | 标题、代码块等不支持 children |
| 块创建不完整 | 缺少顶层 children | 确保 children 包含所有顶层块 ID |
---
错误一:文件上传缺少 size
错误表现
调用 apply_upload 后返回错误或上传失败错误参数
{
"parent_entry_id": "abc123",
"name": "document.md",
"mime_type": "text/markdown",
"upload_type": "PRE_SIGNED_URL"
// ❌ 缺少 size
}正确参数
{
"parent_entry_id": "abc123",
"name": "document.md",
"mime_type": "text/markdown",
"size": 1234, // ✅ 必须指定文件大小(字节数)
"upload_type": "PRE_SIGNED_URL"
}如何获取文件大小
// TypeScript/JavaScript
const fs = require('fs');
const size = fs.statSync(filePath).size;# Python
import os
size = os.path.getsize(file_path)---
错误二:更新文件时参数混淆
错误表现
更新文件时创建了新文件,或报参数错误关键区别
| 场景 | parent_entry_id | file_id |
|---|---|---|
| 新建文件 | 父目录的 entry_id | 不传 |
| 更新文件 | 当前文件自己的 entry_id | 必传(从 describe_entry 获取) |
新建文件
{
"parent_entry_id": "<父目录 entry_id>",
"name": "new-doc.md",
"mime_type": "text/markdown",
"size": 1234,
"upload_type": "PRE_SIGNED_URL"
// 不传 file_id
}更新文件
{
"parent_entry_id": "<当前文件自己的 entry_id>", // ⚠️ 注意:不是父目录!
"name": "existing-doc.md",
"mime_type": "text/markdown",
"size": 5678,
"file_id": "<从 describe_entry 获取的 target_id>", // ⚠️ 必传
"upload_type": "PRE_SIGNED_URL"
}获取 file_id 的方法
Step 1: 调用 describe_entry 获取条目详情
MCP Tool: lexiang.entry_describe_entry
Arguments: { "entry_id": "<文件条目 entry_id>" }
Step 2: 从返回值中提取
返回: { "entry": { "target_id": "<这就是 file_id>", ... } }---
错误三:叶子节点包含 children
错误表现
块创建失败,或文档结构异常叶子节点类型(不支持 children)
h1,h2,h3,h4,h5- 标题块code- 代码块divider- 分割线image- 图片块attachment- 附件块video- 视频块mermaid- Mermaid 图表plantuml- PlantUML 图表
错误示例
{
"block_id": "h2_1",
"block_type": "h2",
"heading2": {"elements": [{"text_run": {"content": "标题"}}]},
"children": ["para_1", "para_2"] // ❌ 标题块不支持 children!
}正确示例
// 标题块(叶子节点,无 children)
{
"block_id": "h2_1",
"block_type": "h2",
"heading2": {"elements": [{"text_run": {"content": "标题"}}]}
// ✅ 不要 children
}
// 段落块作为顶层块排列
{
"block_id": "para_1",
"block_type": "p",
"text": {"elements": [{"text_run": {"content": "段落内容"}}]}
}正确的文档结构
标题和其下的内容应该是平级的,通过顶层 children 的顺序来体现层级:
{
"entry_id": "xxx",
"descendant": [
{"block_id": "h2_1", "block_type": "h2", "heading2": {...}},
{"block_id": "para_1", "block_type": "p", "text": {...}},
{"block_id": "para_2", "block_type": "p", "text": {...}},
{"block_id": "h2_2", "block_type": "h2", "heading2": {...}},
{"block_id": "para_3", "block_type": "p", "text": {...}}
],
"children": ["h2_1", "para_1", "para_2", "h2_2", "para_3"] // ✅ 顺序体现结构
}---
错误四:容器块缺少 children
容器块类型(必须有 children)
callout- 高亮块table- 表格(children 是 table_cell)table_cell- 表格单元格(children 是内容块)column_list- 分栏容器(children 是 column)column- 分栏列(children 是内容块)toggle- 折叠块
错误示例
{
"block_id": "callout_1",
"block_type": "callout",
"callout": {"color": "#E3F2FD", "icon": "1f680"}
// ❌ 缺少 children
}正确示例
// Callout 必须有内容子块
{
"block_id": "callout_1",
"block_type": "callout",
"callout": {"color": "#E3F2FD", "icon": "1f680"},
"children": ["callout_1_p"] // ✅ 指向内容块
},
{
"block_id": "callout_1_p",
"block_type": "p",
"text": {"elements": [{"text_run": {"content": "提示内容"}}]}
}---
使用校验工具
导入校验器
import {
validateApplyUpload,
validateCreateBlockDescendant,
fixApplyUploadArgs,
fixCreateBlockDescendantArgs,
formatValidationResult
} from './scripts/mcp-validator';校验上传参数
const result = validateApplyUpload(
{ parent_entry_id: 'abc', name: 'doc.md' },
{ isUpdate: false }
);
console.log(formatValidationResult(result));
// 输出错误列表和修复建议校验块创建参数
const result = validateCreateBlockDescendant({
entry_id: 'xxx',
descendant: [
{ block_id: 'h1', block_type: 'h1', heading1: {...}, children: ['p1'] } // 错误
]
});
console.log(formatValidationResult(result));
// 🔴 [descendant[0].children] 【关键】h1 是叶子节点,不能包含 children自动修复
// 自动修复块创建参数
const fixed = fixCreateBlockDescendantArgs(originalArgs);
// 自动修复上传参数
const fixedUpload = fixApplyUploadArgs(args, {
path: '/docs/readme.md',
size: 1234,
entryId: 'xxx',
fileId: 'yyy' // 如果是更新
});---
块类型速查
支持 children 的块
| 类型 | children 内容 |
|---|---|
p | 可选,嵌套内容 |
bulleted_list | 可选,嵌套列表 |
numbered_list | 可选,嵌套列表 |
callout | 必须,内容块 |
toggle | 必须,折叠内容 |
table | 必须,table_cell |
table_cell | 必须,内容块 |
column_list | 必须,column |
column | 必须,内容块 |
task | 可选,子任务 |
不支持 children 的块(叶子节点)
| 类型 | 说明 |
|---|---|
h1 - h5 | 标题 |
code | 代码块 |
divider | 分割线 |
image | 图片 |
attachment | 附件 |
video | 视频 |
mermaid | Mermaid 图表 |
plantuml | PlantUML 图表 |
---
常见问题 (FAQ)
Q: 如何选择 Markdown 导入方式?
A: 根据需求选择:
- 作为文件上传(
apply_upload→ PUT →commit_upload):保留原始格式,支持版本管理,适合文档归档 - 转为在线文档(
import_content):转换为 Block 结构,可在线编辑,适合协作场景
Q: Block ID 如何管理?
A: 客户端传入的 block_id 是临时标识,用于在单次调用中建立关系。服务端返回实际 ID 映射,后续更新操作使用服务端返回的 ID。
Q: 表格单元格如何排序?
A: children 数组按从左到右、从上到下顺序排列。例如 2x2 表格:
[row1_col1, row1_col2, row2_col1, row2_col2]Q: 如何实现文档版本控制?
A: 文件上传方式(apply_upload)支持版本管理。更新已有文件时,parent_entry_id 传文件自身的 entry_id。
Q: 为什么 entry_describe_entry 不返回文档正文内容?
A: entry_describe_entry 设计用于获取条目的元信息(如ID、名称、类型、创建时间等),不包含实际内容。要读取文档的正文内容,请使用 entry_describe_ai_parse_content 工具。
Q: 什么时候使用 entry_describe_entry,什么时候使用 entry_describe_ai_parse_content?
A:
- 使用
entry_describe_entry:当您需要获取文档的基本信息用于后续操作时(如获取ID、确认文档类型) - 使用
entry_describe_ai_parse_content:当您需要读取文档的实际内容进行摘要、分析或处理时
场景:内容重组
使用 MoveBlocks 调整文档结构,将块移动到新位置。
移动块 API
MCP Tool: lexiang.block_move_blocks
Arguments: {
"entry_id": "<entry_id>",
"block_ids": ["block_1", "block_2", "block_3"],
"parent_block_id": "<目标父块 ID>",
"after": "<插入位置,某块之后,可选>"
}限制: 单次最多移动 20 个块
---
参数说明
| 参数 | 说明 |
|---|---|
entry_id | 文档 entry_id |
block_ids | 要移动的块 ID 数组,按顺序移动 |
parent_block_id | 目标父节点块 ID |
after | 插入到此块之后,为空则插入到开头 |
---
使用场景
将分散内容整合到同一章节
MCP Tool: lexiang.block_move_blocks
Arguments: {
"entry_id": "doc123",
"block_ids": ["para_1", "para_2", "list_1"],
"parent_block_id": "section_h2",
"after": "intro_callout"
}调整段落顺序
MCP Tool: lexiang.block_move_blocks
Arguments: {
"entry_id": "doc123",
"block_ids": ["para_3"],
"parent_block_id": "root_block",
"after": "para_1"
}---
使用辅助工具
import { ContentReorganizer } from './scripts/block-helper';
const reorganizer = new ContentReorganizer()
.move(['para_1', 'para_2'], 'section_h2', 'intro_callout')
.move(['list_1', 'list_2'], 'section_h2');
const mcpCalls = reorganizer.toMCPCalls(entryId);
// 返回多个 MCP 调用---
注意事项
1. 所有块只能移动到同一个目标父节点 2. 目标父节点不能是叶子节点类型,包括:
- h1, h2, h3, h4, h5(标题块)
- code(代码块)
- image(图片块)
- attachment(附件块)
- video(视频块)
- divider(分割线)
- mermaid、plantuml(图表块)
3. 移动操作会保持块的子孙结构 4. 建议移动前先获取文档结构确认 block_id
---
获取文档结构
MCP Tool: lexiang.block_list_block_children
Arguments: {
"entry_id": "<entry_id>",
"with_descendants": true
}返回完整的块树结构,包含所有 block_id。
文档类型与大纲规范
写入文档前,先确定文档类型,按对应大纲组织内容。
---
类型一:推广文案型
适用场景: 功能推广、工具介绍、方案宣传
1. [callout:primary] 一句话核心价值
2. [h2] 你是否遇到这些问题?
- [bulleted_list] 痛点场景
3. [divider]
4. [h2] 解决方案
- [callout:tip] 核心能力
- [numbered_list] 功能列表
5. [divider]
6. [h2] 对比效果
- [table] 传统方式 vs 新方案
7. [divider]
8. [h2] 快速上手
- [h3] 步骤一
- [code] 配置代码
9. [divider]
10. [h2] 最佳实践
- [numbered_list] 实践建议
11. [divider]
12. [callout:success] 总结 + 行动召唤---
类型二:技术文档型
适用场景: API 文档、开发指南、技术规范
1. [h1] 文档标题
2. [h2] 概述
- [p] 功能描述
- [callout:tip] 适用场景
3. [h2] 快速开始
- [code] 最小示例
4. [h2] 详细说明
- [h3] 参数说明
- [table] 参数名 | 类型 | 必填 | 说明
- [h3] 返回值
- [code] 返回结构
5. [h2] 示例
6. [h2] 注意事项
- [callout:warning] 重要提醒---
类型三:操作指南型
适用场景: 使用教程、操作手册、配置指南
1. [callout:primary] 本指南帮你实现 XXX
2. [h2] 前置准备
- [bulleted_list] 环境要求
- [callout:warning] 注意事项
3. [h2] 操作步骤
- [h3] 步骤 1:XXX
- [numbered_list] 详细操作
- [code] 命令/代码
- [callout:tip] 小技巧
4. [h2] 验证结果
5. [h2] 常见问题
6. [callout:success] 完成确认---
Callout 语义映射
| 关键词模式 | Callout 类型 | 配色 |
|---|---|---|
| 核心/重要/价值 | primary | #E3F2FD |
| 提示/建议/tips | tip | #FFF3E0 |
| 成功/完成/搞定 | success | #E8F5E9 |
| 警告/注意/风险 | warning | #FFF8E1 |
| 错误/禁止/危险 | error | #FFEBEE |
场景:文件夹同步到知识库
将本地文件夹(如项目文档目录)增量同步到乐享知识库,保持目录结构。
使用脚本
npx ts-node scripts/sync-folder.ts --local ./docs --entry-id <parent_entry_id> [--dry-run]同步流程
1. 扫描本地目录: 递归扫描文件和目录,计算文件 hash 2. 加载同步状态: 从 .lexiang-sync-state.json 读取上次同步状态 3. 计算差异: 比对本地和远程,确定创建/更新操作 4. 生成 MCP 调用: 输出需要执行的 MCP 调用序列
增量同步逻辑
| 场景 | 操作 |
|---|---|
| 新文件 | apply_upload + HTTP PUT + commit_upload |
| 文件内容变更 | 使用 file_id 更新文件版本 |
| 新目录 | create_entry (type=folder) |
| 文件删除 | 暂不自动删除,需手动处理 |
同步状态文件
位置: .lexiang-sync-state.json
{
"version": "1.0.0",
"lastSyncAt": "2026-01-22T10:00:00Z",
"files": {
"docs/readme.md": {
"localPath": "docs/readme.md",
"entryId": "abc123",
"fileId": "file_xyz",
"contentHash": "d41d8cd98f00b204e9800998ecf8427e",
"lastModified": "2026-01-22T10:00:00Z",
"syncedAt": "2026-01-22T10:00:00Z"
}
}
}MCP 调用示例
创建文件夹
MCP Tool: lexiang.entry_create_entry
Arguments: {
"parent_entry_id": "<父节点 entry_id>",
"name": "子目录名",
"entry_type": "folder"
}上传文件 (3步)
Step 1: lexiang.file_apply_upload
Arguments: {
"parent_entry_id": "<父节点 entry_id>",
"name": "document.md",
"mime_type": "text/markdown",
"size": 1234,
"upload_type": "PRE_SIGNED_URL"
}
Step 2: HTTP PUT 上传到 upload_url
Step 3: lexiang.file_commit_upload
Arguments: { "session_id": "xxx" }命令行参数
| 参数 | 说明 |
|---|---|
--local | 本地目录路径 |
--entry-id | 目标父节点 entry_id |
--space-id | 知识库 ID(可选) |
--state-file | 同步状态文件路径 |
--dry-run | 仅生成计划不执行 |
场景:Markdown 导入知识库
将 Markdown 文件导入到乐享知识库。
导入策略
方式一:文件上传(推荐)
- 优点: 保留文件版本历史,后续更新只需上传新版本
- 适用: 需要版本管理的文档
- 后续更新: 使用
file_id上传新版本
方式二:转换为 Block
- 优点: 内容直接转换为可编辑的 Block 结构
- 缺点: 后续更新需要操作 Block,较复杂
- 适用: 需要在乐享中直接编辑的文档
---
文件上传流程 (3步)
Step 1: 申请上传凭证
MCP Tool: lexiang.file_apply_upload
Arguments: {
"parent_entry_id": "<父节点 entry_id>",
"name": "document.md",
"mime_type": "text/markdown",
"size": 1234,
"upload_type": "PRE_SIGNED_URL"
}
返回: { "session": { "session_id": "xxx", "upload_url": "https://..." } }Step 2: HTTP PUT 上传
curl -X PUT -H "Content-Type: text/markdown" \
--data-binary @document.md \
"$upload_url"Step 3: 确认上传
MCP Tool: lexiang.file_commit_upload
Arguments: { "session_id": "xxx" }
返回: { "entry": { "id": "new_entry_id", ... } }---
更新已有文件
更新时需要提供 file_id:
MCP Tool: lexiang.file_apply_upload
Arguments: {
"parent_entry_id": "<当前文件的 entry_id>", // 注意:更新时填自己的 entry_id
"name": "document.md",
"mime_type": "text/markdown",
"size": 5678,
"file_id": "<describe_entry 返回的 target_id>", // 必填
"upload_type": "PRE_SIGNED_URL"
}获取 file_id
MCP Tool: lexiang.entry_describe_entry
Arguments: { "entry_id": "<文件条目 entry_id>" }
返回: { "entry": { "target_id": "<这就是 file_id>", ... } }---
使用 import_content 转换为 Block
MCP Tool: lexiang.entry_import_content
Arguments: {
"parent_id": "<父节点 entry_id>",
"name": "文档标题",
"content": "# 标题\n\n正文内容...",
"content_type": "markdown"
}---
辅助脚本
# 单文件上传
python scripts/upload-files.py --files doc.md --entry-id <parent_entry_id>
# 文件夹批量上传(并行)
python scripts/upload-files.py --folder ./docs --entry-id <parent_entry_id> --parallel 5
# 生成上传计划
python scripts/upload-files.py --folder ./docs --entry-id <entry_id> --output plan.json --dry-run场景:Markdown 转 Block 写入
将 Markdown 内容解析并转换为乐享 Block 结构写入文档。
使用辅助工具
import { MarkdownToBlocks } from './scripts/block-helper';
import theme from './themes/default.json';
const converter = new MarkdownToBlocks(theme);
const mcpCall = converter.toMCPCall(entryId, markdownContent);---
支持的 Markdown 语法
| Markdown | Block 类型 | 说明 |
|---|---|---|
# 标题 | h1 | 一级标题 |
## 标题 | h2 | 二级标题 |
### 标题 | h3-h5 | 三到五级标题 |
| 普通段落 | p | 段落文本 |
> 引用 | callout | 根据关键词自动选择类型 |
- 列表 | bulleted_list | 无序列表 |
1. 列表 | numbered_list | 有序列表 |
`` code `` | code | 代码块 |
--- | divider | 分割线 |
---
Callout 语义映射
引用块会根据内容关键词自动映射到对应的 Callout 类型:
| 关键词 | Callout 类型 | 颜色 |
|---|---|---|
| 核心、重要、价值 | primary | #E3F2FD |
| 提示、建议、tips | tip | #FFF3E0 |
| 成功、完成、搞定 | success | #E8F5E9 |
| 警告、注意、风险 | warning | #FFF8E1 |
| 错误、禁止、危险 | error | #FFEBEE |
---
示例
输入 Markdown
# 产品介绍
> 核心价值:提升 10 倍效率
## 功能特性
- 自动化处理
- 智能分析
- 实时同步
## 快速开始
npm install lexiang-sdk
---
> 提示:更多信息请查阅文档生成的 MCP 调用
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "<entry_id>",
"descendant": [
{"block_id": "blk_1", "block_type": "h1", "heading1": {"elements": [{"text_run": {"content": "产品介绍"}}]}},
{"block_id": "blk_2", "block_type": "callout", "callout": {"color": "#E3F2FD", "icon": "1f680"}, "children": ["blk_3"]},
{"block_id": "blk_3", "block_type": "p", "text": {"elements": [{"text_run": {"content": "核心价值:提升 10 倍效率"}}]}},
{"block_id": "blk_4", "block_type": "h2", "heading2": {"elements": [{"text_run": {"content": "功能特性"}}]}},
{"block_id": "blk_5", "block_type": "bulleted_list", "bulleted": {"elements": [{"text_run": {"content": "自动化处理"}}]}},
{"block_id": "blk_6", "block_type": "bulleted_list", "bulleted": {"elements": [{"text_run": {"content": "智能分析"}}]}},
{"block_id": "blk_7", "block_type": "bulleted_list", "bulleted": {"elements": [{"text_run": {"content": "实时同步"}}]}},
{"block_id": "blk_8", "block_type": "h2", "heading2": {"elements": [{"text_run": {"content": "快速开始"}}]}},
{"block_id": "blk_9", "block_type": "code", "code": {"elements": [{"text_run": {"content": "npm install lexiang-sdk"}}], "style": {"language": "bash"}}},
{"block_id": "blk_10", "block_type": "divider", "divider": {}},
{"block_id": "blk_11", "block_type": "callout", "callout": {"color": "#FFF3E0", "icon": "1f4a1"}, "children": ["blk_12"]},
{"block_id": "blk_12", "block_type": "p", "text": {"elements": [{"text_run": {"content": "提示:更多信息请查阅文档"}}]}}
],
"children": ["blk_1", "blk_2", "blk_4", "blk_5", "blk_6", "blk_7", "blk_8", "blk_9", "blk_10", "blk_11"]
}---
使用 BlockBuilder 手动构建
import { BlockBuilder } from './scripts/block-helper';
const builder = new BlockBuilder();
builder.heading(1, '文档标题');
builder.callout('#E3F2FD', '1f680', '核心价值描述');
builder.paragraph('正文内容...');
builder.divider();
builder.bulletedList(['功能1', '功能2', '功能3']);
builder.codeBlock('console.log("hello")', 'javascript');
builder.table([
['特性', '说明'],
['功能A', '描述A']
], { headerRow: true, headerBgColor: '#F5F5F5' });
const mcpCall = builder.toMCPCall(entryId);MCP 调用完整示例
创建完整文档结构
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "intro",
"block_type": "callout",
"callout": {"color": "#E3F2FD", "icon": "1f680"},
"children": ["intro_p"]
},
{
"block_id": "intro_p",
"block_type": "p",
"text": {"elements": [{"text_run": {"content": "核心价值描述", "text_style": {"bold": true}}}]}
},
{
"block_id": "h2_1",
"block_type": "h2",
"heading2": {"elements": [{"text_run": {"content": "功能特性", "text_style": {}}}]}
},
{
"block_id": "divider_1",
"block_type": "divider",
"divider": {}
}
],
"children": ["intro", "h2_1", "divider_1"]
}---
创建对比表格
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "table_1",
"block_type": "table",
"table": {"row_size": 3, "column_size": 2, "column_width": [400, 500], "header_row": true},
"children": ["c1", "c2", "c3", "c4", "c5", "c6"]
},
{"block_id": "c1", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["c1_p"]},
{"block_id": "c1_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "传统方式", "text_style": {"bold": true}}}]}},
{"block_id": "c2", "block_type": "table_cell", "table_cell": {"background_color": "#F5F5F5"}, "children": ["c2_p"]},
{"block_id": "c2_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "新方案", "text_style": {"bold": true}}}]}},
{"block_id": "c3", "block_type": "table_cell", "table_cell": {"background_color": "#FFEBEE"}, "children": ["c3_p"]},
{"block_id": "c3_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "手动操作", "text_style": {}}}]}},
{"block_id": "c4", "block_type": "table_cell", "table_cell": {"background_color": "#E8F5E9"}, "children": ["c4_p"]},
{"block_id": "c4_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "自动化", "text_style": {}}}]}},
{"block_id": "c5", "block_type": "table_cell", "table_cell": {}, "children": ["c5_p"]},
{"block_id": "c5_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "耗时长", "text_style": {}}}]}},
{"block_id": "c6", "block_type": "table_cell", "table_cell": {}, "children": ["c6_p"]},
{"block_id": "c6_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "秒级完成", "text_style": {}}}]}}
],
"children": ["table_1"]
}---
创建代码块
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "code_1",
"block_type": "code",
"code": {
"elements": [{"text_run": {"content": "const config = {\n apiKey: 'xxx',\n endpoint: 'https://api.example.com'\n};"}}],
"style": {"language": "javascript", "wrap": false}
}
}
],
"children": ["code_1"]
}---
创建列表
无序列表
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{"block_id": "li_1", "block_type": "bulleted_list", "bulleted": {"elements": [{"text_run": {"content": "功能一"}}]}},
{"block_id": "li_2", "block_type": "bulleted_list", "bulleted": {"elements": [{"text_run": {"content": "功能二"}}]}},
{"block_id": "li_3", "block_type": "bulleted_list", "bulleted": {"elements": [{"text_run": {"content": "功能三"}}]}}
],
"children": ["li_1", "li_2", "li_3"]
}有序列表
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{"block_id": "ni_1", "block_type": "numbered_list", "numbered": {"elements": [{"text_run": {"content": "步骤一"}}]}},
{"block_id": "ni_2", "block_type": "numbered_list", "numbered": {"elements": [{"text_run": {"content": "步骤二"}}]}},
{"block_id": "ni_3", "block_type": "numbered_list", "numbered": {"elements": [{"text_run": {"content": "步骤三"}}]}}
],
"children": ["ni_1", "ni_2", "ni_3"]
}---
创建分栏布局
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "col_list",
"block_type": "column_list",
"column_list": {"column_size": 2},
"children": ["col_1", "col_2"]
},
{
"block_id": "col_1",
"block_type": "column",
"column": {"width_ratio": 0.5},
"children": ["col_1_p"]
},
{"block_id": "col_1_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "左侧内容"}}]}},
{
"block_id": "col_2",
"block_type": "column",
"column": {"width_ratio": 0.5},
"children": ["col_2_p"]
},
{"block_id": "col_2_p", "block_type": "p", "text": {"elements": [{"text_run": {"content": "右侧内容"}}]}}
],
"children": ["col_list"]
}---
创建 Mermaid 图表
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "mermaid_1",
"block_type": "mermaid",
"mermaid": {
"content": "graph TD\n A[开始] --> B{判断}\n B -->|是| C[执行]\n B -->|否| D[结束]"
}
}
],
"children": ["mermaid_1"]
}---
创建任务块
MCP Tool: lexiang.block_create_block_descendant
Arguments: {
"entry_id": "{entry_id}",
"descendant": [
{
"block_id": "task_1",
"block_type": "task",
"task": {
"name": "完成文档编写",
"done": false,
"assignees": [{"staff_id": "user_123"}],
"due_at": {"date": "2026-01-25"}
}
}
],
"children": ["task_1"]
}Skill 维护与反馈指南
本文档包含乐享知识库 Skill 的维护机制和反馈流程,用于指导 Skill 的自我进化和问题反馈。
---
📮 Issue 反馈 - 主动帮助用户改进平台
当发现 Skill 存在问题或有改进建议时,可以主动建议用户反馈给维护者;但真正创建 Issue、提交反馈或修改仓库内容前,必须先获得用户确认。
不要等用户明确说"提交 Issue"才提醒;但在未确认前,只整理问题、影响范围和改进建议,不要直接执行提交。
🎯 适合建议反馈的场景
1. 功能缺失场景
用户:"最近访问的知识库有哪些更新?"
AI 判断:需要遍历所有团队(20+ 次 API 调用)才能实现
↓
→ 主动建议:"这个需求目前需要 20+ 次 API 调用,效率较低。我建议向乐享团队反馈增加「最近访问历史」接口。需要的话,我可以先帮您整理一份 Issue 草稿。"2. 性能问题场景
用户:"批量导出所有知识库的文档"
AI 判断:当前方案效率低下
↓
→ 主动建议:"当前批量操作效率有限,我可以先帮您整理优化建议和复现步骤,确认后再提交反馈。"3. 用户体验问题
用户:"为什么搜索结果没有高亮显示?"
AI 判断:这是平台功能缺失,不是用户操作问题
↓
→ 主动建议:"这确实是个实用的功能。我可以先帮您整理一份功能需求草稿,您确认后我再继续反馈。"4. 重复遇到的障碍
用户第 3 次问类似问题(从 memory 判断)
↓
→ 主动建议:"我注意到您多次遇到类似问题,这可能是平台需要改进的地方。要不要我先帮您整理一份反馈草稿?"主动反馈的触发关键词
除了明确的"提交 Issue""反馈问题"等关键词,还应识别隐含意图:
| 用户表达 | 隐含意图 | AI 响应 |
|---|---|---|
| "为什么不能..." | 期望功能不存在 | 主动建议整理反馈草稿 |
| "太麻烦了..." | 操作体验差 | 建议优化并询问是否需要整理反馈 |
| "能不能支持..." | 功能需求 | 主动帮助整理需求,但提交前先确认 |
| "每次都要..." | 重复低效操作 | 识别痛点并建议反馈 |
| "其他平台可以..." | 对比发现差距 | 主动提出改进建议 |
原则:做用户的产品顾问,主动发现问题、提炼需求、推动改进;但对外提交动作必须由用户确认后再执行。
反馈渠道
以当前 runtime 文档指定的渠道为准:
| 场景 | 渠道 |
|---|---|
| 内部运行时 | 使用当前 runtime 文档指定的内部仓库或反馈流程 |
| 外部公开版 | https://github.com/tencent-lexiang/lexiang-skill |
反馈流程
Step 1:先征得用户确认是否需要正式反馈 Step 2:整理标题、问题描述、复现步骤、影响范围和建议修复方案 Step 3:按当前 runtime 对应渠道创建 Issue 或输出反馈草稿 Step 4:通知用户反馈已记录或草稿已准备完成
---
🧬 Skill 自我进化
本 Skill 支持自查和校验,但默认目标是发现差异、解释原因、给出修正建议。只有在用户明确要求"修 Skill""更新文档"或"维护仓库"时,才进入实际修改流程。
触发时机
当出现以下情况时,应主动执行进化检查:
1. 调用 MCP 工具时报参数错误或工具不存在 2. 用户反馈文档中的示例无法正常工作 3. 用户主动要求检查或更新 Skill
进化流程
1. 调用 list_tool_categories 获取最新工具列表
↓
2. 对比本 Skill 中记录的工具名和参数
↓
3. 对有疑问的工具,调用 get_tool_schema 获取最新 schema
↓
4. 对比 SKILL.md 和 SLOT_EXAMPLES.md 中的参数定义
↓
5. 输出差异、影响范围和建议修正文案
↓
6. 仅在用户明确要求维护 Skill 时,修改对应文件
↓
7. 向用户说明修改内容,并建议按当前 runtime 渠道同步维护者校验要点
| 检查项 | 方法 |
|---|---|
| 工具名称 | list_tool_categories 返回值 vs SKILL.md 中的名称 |
| 参数名和类型 | get_tool_schema 返回值 vs SKILL.md 中的参数表 |
| 示例代码 | 对比 SLOT_EXAMPLES.md 中的调用参数是否与 schema 一致 |
注意事项
- 默认先做差异说明和修正建议,不要在未获确认时直接修改 Skill 文件
- 修改 Skill 文件后,应保持各变体(SLOT_EXAMPLES.md)的一致性
- 进化修改仅限于参数修正、工具名更新、明确性改进,不要随意改变文档结构
- 若当前运行时无写权限,则只输出修正建议或补丁内容
theme.json 配置说明
主题配置文件定义文档的视觉和结构规范。
文件位置
.codebuddy/themes/lexiang-{template-name}.json默认主题: skills/lexiang-doc-writer/themes/default.json
---
配置结构
{
"$schema": "lexiang-doc-theme/v1",
"name": "主题名称",
"source": "https://lexiangla.com/pages/{entry_id}",
"extracted_at": "2026-01-22T10:00:00Z",
"callout": { ... },
"table": { ... },
"text": { ... },
"code_block": { ... },
"structure": { ... },
"semantic_mapping": { ... }
}---
callout 配置
{
"callout": {
"primary": {
"color": "#E3F2FD",
"icon": "1f680",
"usage": "开篇引导、核心价值、重要说明"
},
"tip": {
"color": "#FFF3E0",
"icon": "1f4a1",
"usage": "提示信息、注意事项、小技巧"
},
"success": {
"color": "#E8F5E9",
"icon": "2705",
"usage": "成功、完成、总结确认"
},
"warning": {
"color": "#FFF8E1",
"icon": "26a0",
"usage": "警告、风险提示"
},
"error": {
"color": "#FFEBEE",
"icon": "274c",
"usage": "错误、禁止、危险操作"
},
"info": {
"color": "#E8EAF6",
"icon": "2139",
"usage": "补充说明、背景信息"
}
}
}---
table 配置
{
"table": {
"header": {
"background_color": "#F5F5F5",
"text_style": {"bold": true}
},
"cell": {
"success": {"background_color": "#E8F5E9"},
"warning": {"background_color": "#FFF8E1"},
"error": {"background_color": "#FFEBEE"},
"highlight": {"background_color": "#E3F2FD"},
"neutral": {"background_color": "#FAFAFA"}
},
"default_column_width": [300, 400],
"compare_table": {
"column_width": [400, 550],
"left_header": "传统方式",
"right_header": "新方案"
}
}
}---
text 配置
{
"text": {
"emphasis": {
"keyword": {"bold": true},
"important": {"bold": true, "underline": true},
"highlight": {"bold": true, "background_color": "#FFF59D"}
},
"code": {"inline_code": true}
}
}---
code_block 配置
{
"code_block": {
"default_language": "go",
"wrap": false
}
}---
structure 配置
{
"structure": {
"use_divider_between_sections": true,
"callout_at_start": true,
"callout_at_end": true
}
}---
semantic_mapping 配置
语义映射,用于自动识别内容类型:
{
"semantic_mapping": {
"markdown_to_callout": {
"> 核心": "primary",
"> 重要": "primary",
"> 提示": "tip",
"> 建议": "tip",
"> 注意": "warning",
"> 警告": "warning",
"> 成功": "success",
"> 完成": "success",
"> 错误": "error",
"> 危险": "error",
"> 信息": "info",
"> ": "primary"
},
"table_cell_keywords": {
"success": ["完成", "成功", "推荐", "支持", "是", "✓", "✅"],
"error": ["失败", "不支持", "否", "✗", "❌", "危险"],
"warning": ["注意", "警告", "待定", "可选"]
}
}
}---
提取主题
从现有文档提取主题:
MCP Tool: lexiang.block_list_block_children
Arguments: {"entry_id": "{entry_id}", "with_descendants": true}提取内容:
| 块类型 | 提取字段 |
|---|---|
| callout | color, icon |
| table | header_row, column_width |
| table_cell | background_color |
| text/heading | style.align, style.background_color |
| code | style.language, style.wrap |
稳定性规则
- 同一文档多次提取产生相同 theme.json
- 只提取显式设置的样式,未设置使用 null
- 不依赖块顺序或内容
Lexiang Scripts
乐享文档写入辅助脚本集合。
安装依赖
TypeScript 脚本
npm install -g ts-node typescript
npm install @types/nodePython 脚本
pip install aiohttp requests脚本列表
sync-folder.ts
本地文件夹增量同步到乐享知识库。
# Dry run 模式(仅生成计划)
npx ts-node sync-folder.ts --local ./docs --entry-id abc123 --dry-run
# 完整参数
npx ts-node sync-folder.ts \
--local ./docs \
--entry-id <parent_entry_id> \
--space-id <space_id> \
--state-file .sync-state.json \
--dry-runupload-files.py
并行上传文件到乐享。
# 单文件上传
python upload-files.py --files doc1.md doc2.pdf --entry-id abc123
# 文件夹批量上传
python upload-files.py --folder ./docs --entry-id abc123 --parallel 5
# 输出上传计划到 JSON
python upload-files.py --folder ./docs --entry-id abc123 --output plan.json --dry-run工作流示例
1. 项目文档同步
# 1. 首次同步(dry run 检查)
npx ts-node sync-folder.ts --local ./project-docs --entry-id root123 --dry-run
# 2. 执行同步
# 将生成的 MCP 调用序列提供给 AI 助手执行
# 3. 后续增量同步
# 脚本会自动检测变更,只同步修改的文件2. Markdown 文档导入
# 1. 生成上传计划
python upload-files.py --folder ./markdown-docs --entry-id target123 --output plan.json
# 2. 查看计划
cat plan.json
# 3. 执行上传(通过 AI 助手)
# 将 plan.json 中的 MCP 调用提供给 AI 助手注意事项
1. MCP 调用需要通过 AI 助手执行:脚本生成 MCP 调用参数,实际执行需要 AI 助手的 MCP 能力 2. 文件上传是 3 步流程:apply_upload → HTTP PUT → commit_upload 3. 同步状态文件:.lexiang-sync-state.json 记录同步状态,请勿删除 4. 大文件建议分批:单次 MCP 调用的数据量有限制 5. Block 写入使用 MCP 工具:直接调用 block_convert_content_to_blocks 将 Markdown/HTML 转换为块结构,无需手动构建
/**
* 乐享知识库文件夹同步脚本
* 支持将本地文件夹增量同步到乐享知识库
*
* 使用方式:
* npx ts-node sync-folder.ts --local ./docs --entry-id <parent_entry_id> [--dry-run]
*/
import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
// ============ 类型定义 ============
interface SyncConfig {
localPath: string;
parentEntryId: string;
spaceId?: string;
dryRun: boolean;
syncStateFile: string;
ignoredPatterns: string[];
supportedExtensions: string[];
}
interface SyncState {
version: string;
lastSyncAt: string;
files: Record<string, FileState>;
}
interface FileState {
localPath: string;
entryId: string;
fileId?: string;
contentHash: string;
lastModified: string;
syncedAt: string;
}
interface LocalFile {
relativePath: string;
absolutePath: string;
isDirectory: boolean;
contentHash?: string;
lastModified: Date;
}
interface SyncAction {
type: 'create_folder' | 'create_file' | 'update_file' | 'delete';
localPath: string;
entryId?: string;
fileId?: string;
reason: string;
}
interface LexiangEntry {
id: string;
name: string;
entry_type: 'page' | 'folder' | 'file';
target_id?: string;
has_children: boolean;
}
// ============ MCP 调用封装 ============
/**
* 乐享 MCP 调用包装器
* 实际使用时通过 AI 助手的 MCP 调用能力执行
*/
class LexiangMCPClient {
/**
* 生成 MCP 调用参数(供 AI 助手使用)
*/
static listChildren(parentId: string): { tool: string; args: object } {
return {
tool: 'lexiang.entry_list_children',
args: { parent_id: parentId, limit: 100 }
};
}
static describeEntry(entryId: string): { tool: string; args: object } {
return {
tool: 'lexiang.entry_describe_entry',
args: { entry_id: entryId }
};
}
static createEntry(params: {
parentEntryId: string;
name: string;
entryType: 'page' | 'folder';
}): { tool: string; args: object } {
return {
tool: 'lexiang.entry_create_entry',
args: {
parent_entry_id: params.parentEntryId,
name: params.name,
entry_type: params.entryType
}
};
}
static applyUpload(params: {
parentEntryId: string;
name: string;
mimeType: string;
size: number;
fileId?: string;
}): { tool: string; args: object } {
return {
tool: 'lexiang.file_apply_upload',
args: {
parent_entry_id: params.parentEntryId,
name: params.name,
mime_type: params.mimeType,
size: params.size,
file_id: params.fileId,
upload_type: 'PRE_SIGNED_URL'
}
};
}
static commitUpload(sessionId: string): { tool: string; args: object } {
return {
tool: 'lexiang.file_commit_upload',
args: { session_id: sessionId }
};
}
static importContent(params: {
parentId: string;
name: string;
content: string;
contentType: 'markdown' | 'html';
}): { tool: string; args: object } {
return {
tool: 'lexiang.entry_import_content',
args: {
parent_id: params.parentId,
name: params.name,
content: params.content,
content_type: params.contentType
}
};
}
}
// ============ 工具函数 ============
/**
* 计算文件内容 hash
*/
function computeFileHash(filePath: string): string {
const content = fs.readFileSync(filePath);
return crypto.createHash('md5').update(content).digest('hex');
}
/**
* 获取 MIME 类型
*/
function getMimeType(filePath: string): string {
const ext = path.extname(filePath).toLowerCase();
const mimeTypes: Record<string, string> = {
'.md': 'text/markdown',
'.markdown': 'text/markdown',
'.txt': 'text/plain',
'.json': 'application/json',
'.pdf': 'application/pdf',
'.doc': 'application/msword',
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'.xls': 'application/vnd.ms-excel',
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'.ppt': 'application/vnd.ms-powerpoint',
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.zip': 'application/zip'
};
return mimeTypes[ext] || 'application/octet-stream';
}
/**
* 检查路径是否匹配忽略模式
*/
function shouldIgnore(relativePath: string, patterns: string[]): boolean {
for (const pattern of patterns) {
if (pattern.startsWith('*')) {
// 扩展名匹配
if (relativePath.endsWith(pattern.slice(1))) return true;
} else if (pattern.endsWith('/')) {
// 目录匹配
if (relativePath.includes(pattern) || relativePath.startsWith(pattern)) return true;
} else {
// 精确匹配或包含匹配
if (relativePath === pattern || relativePath.includes(pattern)) return true;
}
}
return false;
}
/**
* 递归扫描本地目录
*/
function scanLocalDirectory(
basePath: string,
config: SyncConfig,
currentPath: string = ''
): LocalFile[] {
const files: LocalFile[] = [];
const absolutePath = path.join(basePath, currentPath);
if (!fs.existsSync(absolutePath)) {
return files;
}
const entries = fs.readdirSync(absolutePath, { withFileTypes: true });
for (const entry of entries) {
const relativePath = path.join(currentPath, entry.name);
// 检查是否应该忽略
if (shouldIgnore(relativePath, config.ignoredPatterns)) {
continue;
}
const entryAbsolutePath = path.join(basePath, relativePath);
const stats = fs.statSync(entryAbsolutePath);
if (entry.isDirectory()) {
files.push({
relativePath,
absolutePath: entryAbsolutePath,
isDirectory: true,
lastModified: stats.mtime
});
// 递归扫描子目录
files.push(...scanLocalDirectory(basePath, config, relativePath));
} else {
// 检查是否是支持的文件类型
const ext = path.extname(entry.name).toLowerCase();
if (config.supportedExtensions.length > 0 &&
!config.supportedExtensions.includes(ext)) {
continue;
}
files.push({
relativePath,
absolutePath: entryAbsolutePath,
isDirectory: false,
contentHash: computeFileHash(entryAbsolutePath),
lastModified: stats.mtime
});
}
}
return files;
}
/**
* 加载同步状态
*/
function loadSyncState(stateFile: string): SyncState {
if (fs.existsSync(stateFile)) {
const content = fs.readFileSync(stateFile, 'utf-8');
return JSON.parse(content);
}
return {
version: '1.0.0',
lastSyncAt: '',
files: {}
};
}
/**
* 保存同步状态
*/
function saveSyncState(stateFile: string, state: SyncState): void {
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
}
// ============ 同步逻辑 ============
/**
* 计算需要执行的同步操作
*/
function computeSyncActions(
localFiles: LocalFile[],
syncState: SyncState,
remoteEntries: Map<string, LexiangEntry>
): SyncAction[] {
const actions: SyncAction[] = [];
// 按目录层级排序,确保父目录先创建
localFiles.sort((a, b) => {
const depthA = a.relativePath.split(path.sep).length;
const depthB = b.relativePath.split(path.sep).length;
if (depthA !== depthB) return depthA - depthB;
if (a.isDirectory !== b.isDirectory) return a.isDirectory ? -1 : 1;
return a.relativePath.localeCompare(b.relativePath);
});
for (const file of localFiles) {
const existingState = syncState.files[file.relativePath];
const remoteName = path.basename(file.relativePath);
const remoteEntry = remoteEntries.get(remoteName);
if (file.isDirectory) {
if (!existingState && !remoteEntry) {
actions.push({
type: 'create_folder',
localPath: file.relativePath,
reason: '新目录'
});
}
} else {
if (!existingState) {
// 新文件
actions.push({
type: 'create_file',
localPath: file.relativePath,
reason: '新文件'
});
} else if (existingState.contentHash !== file.contentHash) {
// 文件内容变更
actions.push({
type: 'update_file',
localPath: file.relativePath,
entryId: existingState.entryId,
fileId: existingState.fileId,
reason: `内容变更 (hash: ${existingState.contentHash.slice(0, 8)} -> ${file.contentHash?.slice(0, 8)})`
});
}
}
}
return actions;
}
/**
* 生成同步操作的 MCP 调用序列
*/
function generateMCPCalls(
actions: SyncAction[],
config: SyncConfig,
localFiles: LocalFile[]
): Array<{ action: SyncAction; mcpCall: { tool: string; args: object }; note: string }> {
const calls: Array<{ action: SyncAction; mcpCall: { tool: string; args: object }; note: string }> = [];
// 记录目录路径到 entry_id 的映射(需要在实际执行时更新)
const pathToEntryId: Record<string, string> = {
'': config.parentEntryId
};
for (const action of actions) {
const parentPath = path.dirname(action.localPath);
const parentEntryId = pathToEntryId[parentPath] || config.parentEntryId;
const name = path.basename(action.localPath);
switch (action.type) {
case 'create_folder':
calls.push({
action,
mcpCall: LexiangMCPClient.createEntry({
parentEntryId,
name,
entryType: 'folder'
}),
note: `创建目录: ${action.localPath}`
});
// 占位,实际 entry_id 需要从返回值获取
pathToEntryId[action.localPath] = `<待获取:${action.localPath}>`;
break;
case 'create_file':
const localFile = localFiles.find(f => f.relativePath === action.localPath);
if (localFile) {
const stats = fs.statSync(localFile.absolutePath);
const isMarkdown = ['.md', '.markdown'].includes(
path.extname(action.localPath).toLowerCase()
);
if (isMarkdown) {
// Markdown 优先使用文件上传方式(便于后续版本更新)
calls.push({
action,
mcpCall: LexiangMCPClient.applyUpload({
parentEntryId,
name,
mimeType: 'text/markdown',
size: stats.size
}),
note: `上传 Markdown 文件: ${action.localPath} (第1步: 申请上传)`
});
} else {
calls.push({
action,
mcpCall: LexiangMCPClient.applyUpload({
parentEntryId,
name,
mimeType: getMimeType(action.localPath),
size: stats.size
}),
note: `上传文件: ${action.localPath} (第1步: 申请上传)`
});
}
}
break;
case 'update_file':
const updateFile = localFiles.find(f => f.relativePath === action.localPath);
if (updateFile && action.fileId) {
const stats = fs.statSync(updateFile.absolutePath);
calls.push({
action,
mcpCall: LexiangMCPClient.applyUpload({
parentEntryId: action.entryId!, // 更新时使用当前文件的 entry_id
name: path.basename(action.localPath),
mimeType: getMimeType(action.localPath),
size: stats.size,
fileId: action.fileId
}),
note: `更新文件: ${action.localPath} (第1步: 申请上传, file_id=${action.fileId})`
});
}
break;
}
}
return calls;
}
// ============ 主入口 ============
/**
* 文件夹同步主函数
*/
export async function syncFolder(config: SyncConfig): Promise<{
actions: SyncAction[];
mcpCalls: Array<{ action: SyncAction; mcpCall: { tool: string; args: object }; note: string }>;
summary: string;
}> {
console.log('📁 开始扫描本地目录:', config.localPath);
// 1. 扫描本地文件
const localFiles = scanLocalDirectory(config.localPath, config);
console.log(` 找到 ${localFiles.length} 个文件/目录`);
// 2. 加载同步状态
const syncState = loadSyncState(config.syncStateFile);
console.log(` 同步状态文件: ${config.syncStateFile}`);
console.log(` 上次同步: ${syncState.lastSyncAt || '从未同步'}`);
// 3. 计算同步操作
const remoteEntries = new Map<string, LexiangEntry>();
// 注意:实际执行时需要先调用 list_children 获取远程条目
const actions = computeSyncActions(localFiles, syncState, remoteEntries);
console.log(`\n📋 同步计划:`);
console.log(` 创建目录: ${actions.filter(a => a.type === 'create_folder').length}`);
console.log(` 新建文件: ${actions.filter(a => a.type === 'create_file').length}`);
console.log(` 更新文件: ${actions.filter(a => a.type === 'update_file').length}`);
// 4. 生成 MCP 调用
const mcpCalls = generateMCPCalls(actions, config, localFiles);
// 5. 生成摘要
const summary = `
同步摘要
========
本地目录: ${config.localPath}
目标节点: ${config.parentEntryId}
文件总数: ${localFiles.length}
同步操作: ${actions.length}
操作详情:
${actions.map(a => ` - [${a.type}] ${a.localPath} (${a.reason})`).join('\n')}
MCP 调用序列:
${mcpCalls.map((c, i) => ` ${i + 1}. ${c.note}`).join('\n')}
`;
if (config.dryRun) {
console.log('\n🔍 Dry Run 模式,不执行实际操作');
console.log(summary);
}
return { actions, mcpCalls, summary };
}
// ============ CLI ============
function parseArgs(): SyncConfig {
const args = process.argv.slice(2);
const config: SyncConfig = {
localPath: '',
parentEntryId: '',
dryRun: false,
syncStateFile: '.lexiang-sync-state.json',
ignoredPatterns: [
'node_modules/',
'.git/',
'.DS_Store',
'*.log',
'.lexiang-sync-state.json'
],
supportedExtensions: ['.md', '.markdown', '.txt', '.json', '.pdf', '.doc', '.docx']
};
for (let i = 0; i < args.length; i++) {
switch (args[i]) {
case '--local':
config.localPath = args[++i];
break;
case '--entry-id':
config.parentEntryId = args[++i];
break;
case '--space-id':
config.spaceId = args[++i];
break;
case '--dry-run':
config.dryRun = true;
break;
case '--state-file':
config.syncStateFile = args[++i];
break;
}
}
if (!config.localPath || !config.parentEntryId) {
console.error('用法: npx ts-node sync-folder.ts --local <路径> --entry-id <entry_id> [--dry-run]');
process.exit(1);
}
return config;
}
// 如果直接运行脚本
if (require.main === module) {
const config = parseArgs();
syncFolder(config).catch(console.error);
}
export { SyncConfig, SyncState, SyncAction, LocalFile, LexiangMCPClient };
Setup Guide - Lexiang MCP Skill (ClawHub Edition)
本文档描述配置步骤,AI Agent 应读取后自动完成配置。
前置条件
用户需要提供两个参数(如果用户未提供,引导用户访问 https://lexiangla.com/mcp 获取):
| 参数 | 说明 | 格式示例 |
|---|---|---|
company_from | 企业标识 | your_company |
access_token | 访问令牌 | lxmcp_xxx |
配置步骤
Step 1: 获取用户参数
向用户询问 company_from 和 access_token。如果用户不清楚,引导其访问:
https://lexiangla.com/mcp登录后即可看到配置信息。
校验规则:两个参数都不能为空。
Step 2: 确定配置文件路径
配置文件路径为:
| 操作系统 | 路径 |
|---|---|
| macOS / Linux | ~/.mcporter/mcporter.json |
| Windows | %USERPROFILE%\.mcporter\mcporter.json |
| WSL | ~/.mcporter/mcporter.json(Linux 侧路径) |
Step 3: 检查已有配置
如果配置文件已存在,提示用户确认是否覆盖,不要静默覆盖。
Step 4: 创建目录并写入配置
1. 如果 .mcporter 目录不存在,创建它 2. 将以下 JSON 写入配置文件(替换 {company_from} 和 {access_token} 为用户提供的实际值):
{
"mcpServers": {
"lexiang": {
"url": "https://mcp.lexiang-app.com/mcp?company_from={company_from}",
"transportType": "streamable-http",
"headers": {
"Authorization": "Bearer {access_token}"
}
}
}
}安全说明:access_token 通过 HTTP Authorization header 传递,避免在 URL 中暴露(URL 可能被记录到日志、Referer 头中)。
编码要求:文件必须以 UTF-8 无 BOM 编码保存。
Step 5: 确认结果
配置写入后,告知用户配置文件的完整路径,并提示配置完成。
Step 6: 身份验证与欢迎引导
配置完成后,立即调用 MCP 工具 whoami() 获取当前用户信息。
成功时(返回用户信息),向用户展示欢迎消息,格式参考:
✅ 乐享 MCP 连接成功!
👤 当前用户:{用户姓名}
🏢 绑定乐享:{企业/租户名称}
🎉 配置已就绪,你现在可以这样使用乐享知识库:
💡 试试这样提问:
• "看看我最近访问的知识库有什么更新"
• "我要记录今天的工作内容,为我创建一个乐享文档并拟写一个模版"
• "搜索关于 XXX 的知识文档"
• "帮我总结一下这个知识库的内容:{知识库链接}"根据 whoami 返回的实际字段灵活调整展示内容。如果返回了额外有用的信息(如用户角色、头像等),可酌情展示。401 错误 → token 无效或已过期,引导用户重新获取(参见 SKILL.md「AccessToken 生命周期管理」)
连接超时/其他错误 → 检查 mcp.json 配置是否正确
注意事项
- 不要在输出中回显 access_token 的完整值(安全考虑)
- 如果已有配置文件包含其他 mcpServers 条目,应合并而非覆盖整个文件
- Windows 环境下注意路径分隔符使用
\
Related skills
FAQ
What platform does this skill target?
It targets the Lexiang (乐享) knowledge-base platform at lexiangla.com.
What can it do with documents?
It can fetch content and metadata, search, query structure, and create, edit, and move documents, plus manage tags, comments, and attachments.
What credentials does it need?
It requires the LEXIANG_TOKEN and COMPANY_FROM environment variables.