Core operation pattern:locate first (outline / search) → then read (read) → finally edit (write). All content is exchanged in semantic XML format, and all locating is based on block_id(10-character alphanumeric).
When to use
- The user mentions WPS Notes, WPS Note, cloud notes, or Kingsoft Notes
- The user asks to read, edit, search, summarize, or translate note content
- The user needs to create notes, manage tags, or organize the note library
- Need to troubleshoot MCP tool call failures (
BLOCK_NOT_FOUND、EDITOR_NOT_READYand other errors)
Not applicable to: local Markdown file operations, other products such as WPS Documents/Spreadsheets/Presentations, and purely conceptual discussions.
Core concepts
Block model
- A note is composed of blocks, and each block has a unique
block_id。 - block types:
paragraph、heading、blockquote、code_block、list、table、image(single image/image column),horizontal_rule、highlight_block、columns、embed、note_audio_card。 embedblocks (spreadsheets, videos, LaTeX, countdowns, etc.) areread-only placeholders, and cannot be edited.note_audio_cardblocks are voice recording cards (read-only), displayed in XML as<NoteAudioCard/>, use theget_audio_transcripttool to obtain the transcript content.- Tables must bereplaced as a whole table, and individual cells cannot be edited. Table cells only support simple blocks (paragraphs, headings, quotes, code blocks, dividers, images),container blocks such as highlight blocks, columns, and tables cannot be nested within cells.
- Container nesting restrictions:
<highlightBlock>only supports simple blocks (paragraphs, headings, quotes, code blocks, dividers, images) inside,cannot nest<highlightBlock>、<columns>、<table>。<columns>each<column>inside supports simple blocks and<highlightBlock>,cannot nest<table>or<columns>。
note_id
- Most tools require
note_idto specify the note to operate on. - Obtain
list_notesorsearch_notesvianote_id; if the user wants to operate on the currently open note, they can directly callget_current_noteto obtain it. get_note_infocan obtain note metadata (including tags), supporting three modes: singlenote_idquery, batchnote_idsquery (up to 100), and full paginated browsing (page/page_size/limit), without needing to read the full content.
XML input and output
- All content is sent and received in semantic XML format, using tags such as
<p>、<h1>-<h6>、<blockquote>、<codeblock>、<table>、<highlightBlock>、<columns>etc. - Each block-level tag is identified by the
idattribute as block_id, such as<p id="aB3kLm9xZq">内容</p>。 - Important: write operations (
edit_blocketc.)'sblock_id/anchor_idonly accept top-level block IDs (returned byget_note_outline).read_noteIn XML, containers (<highlightBlock>、<columns>、<table>) internal paragraphs'idare for reading reference only and cannot be used for write operations. - Provide content in XML format when writing; the system automatically converts it to the internal block model.
replaceThe target block ofblock_idis specified by the tool parametercontent, it is recommended not to writeid; if the root blockidis explicitly written, it must match the targetblock_id.insertWhen inserting, block-level tags in the new content should omitid; the system automatically assigns a newblock_id。 - Inline marks use semantic tags:
<strong>粗体</strong>、<em>斜体</em>、<s>删除线</s>、<u>下划线</u>、<a href="url">链接</a>。 - Tag management: use the
manage_note_tagstool to manage note tags—directly add/remove file-level tags without editing document content. After creating a note, callmanage_note_tags({ note_id, add: ["标签名"] })to assign tags; use/for multi-level tags, and do not include the#prefix in the call parameters; after editing an existing note, if it has no tags, they should also be added. - Inline self-closing elements:
<emoji value="😀"/>(emoji),<latex formula="E=mc^2"/>(inline formula),<br/>(hard line break). - Style attributes are passed via
<span>:<span fontColor="#C21C13">红色文字</span>、<span fontHighlightColor="#FBF5B3">高亮文字</span>、<span fontSize="16">大号文字</span>。 - Colors are constrained by the preset color palette; any hex color value will be silently discarded by the editor. Preset values for various colors:
fontColor(12 colors):#080F17#C21C13#DB7800#078654#0E52D4#0080A0#757575#DA326B#D1A300#58A401#116AF0#A639D7fontHighlightColor(9 colors):#FBF5B3#F8D7B7#F7C7D3#DFF0C4#C6EADD#D9EEFB#D5DCF7#E6D6F0#E6E6E6highlightBlockcolors (6 pairs bg→border):#FAF1E6→#FEC794、#FAE6E6→#F2A7A7、#E6FAEB→#AFE3BB、#E6EEFA→#98C1FF、#F5EBFA→#E5B5FD、#EBEBEB→#C5C5C5columnBackgroundColor(42 colors, including solid colors and gradients):- 6 basic colors:
#FFF5EB#FFECEB#E8FCEF#EBF2FF#FAF0FF#F2F2F2 - 18 extended solid colors:
#FCFAE1#FEF6E7#FFF5ED#FFF2F0#FFF2F4#FFF0F7#EEFFEB#EBFFF5#E8FCFC#EBF8FF#EBF1FF#F0EDFF#F2E7E4#F0E6DA#F5EEDA#EDF0EB#EDEEF0#F0E4DD - 6 saturated colors:
#FEF49C#BCFAAF#ADF4FF#C2D3FF#FFC7C7#E0E0E0 - 12 gradient colors: use CSS
linear-gradient()syntax, e.g.linear-gradient(133deg,#FFFAF7 2.14%,#FFEDFE 96.88%)
- 6 basic colors:
- The complete XML format reference has been integrated into the MCP Server Instructions and is automatically injected (depending on client support). If not injected, you can call
get_xml_referencetool to get it on demand.
Read-only Token
- Some note tokens are read-only; write tools will return
DOCUMENT_READ_ONLY。 - At this point
retryable: false—do not retry, inform the user. Read operations are unaffected.
Response format
All tools return a unified standard envelope:
{ "ok": true, "code": "OK", "message": "...", "retryable": false, "data": { ... }, "hints": [] }
ok—whether the call succeeded.code—machine-readable status code (see error recovery).retryable—whentrue, you can retry directly.hints—suggested follow-up tools or actions.
Workflow
1. Read and understand notes
get_current_note() → 获取 note_id + word_count + size_category(决定后续策略)
list_notes / search_notes → 按条件查找 note_id
get_note_outline(note_id) → 查看结构和 block ID(超大文档自动分页)
get_cursor_block() → 获取当前光标所在顶层 block_id
read_section(note_id, heading_id) → 读取某个章节
read_blocks(note_id, block_ids) → 批量读取指定 block
read_blocks(note_id, block_id, before, after) → 读取单个 block 及上下文
search_note_content(note_id, q) → 在笔记内搜索文本
read_image(note_id, block_id) → 读取图片 block 的实际内容(base64)
get_audio_transcript(shorthand_id) → 获取语音录音的转写内容
get_xml_reference() → 获取 XML 格式完整参考文档
For long notes, prefer using get_note_outline → read_section, rather than read_note, to reduce token overhead.
Read large documents in pages
When a note exceeds 200 blocks,read_note and get_note_outline returns are automatically paginated—use the offset and block_limit parameters to switch between pages to view different parts. The note itself has no block count limit; these parameters only control the amount returned in a single read.
read_note example:
read_note({ note_id })
→ pagination: { total_blocks: 350, has_more: true, next_offset: 100 }
read_note({ note_id, offset: 100 })
→ pagination: { has_more: true, next_offset: 200 }
read_note({ note_id, offset: 200 })
→ pagination: { has_more: false } ← 读完
You can also manually control the page size:read_note({ note_id, offset: 0, block_limit: 50 })
get_note_outline similarly—has_more: true when using next_offset to continue reading:get_note_outline({ note_id, offset: next_offset })
read_section similarly—when truncated, returns next_block_offset, pass in block_offset to continue reading:
read_section({ note_id, heading_block_id, max_blocks: 50 })
→ truncated: true, next_block_offset: 50
read_section({ note_id, heading_block_id, block_offset: 50 })
→ truncated: false ← 读完
Document size strategy
get_current_note and get_note_outline both return word_count、size_category and estimated_xml_chars, based on which you choose the reading strategy:
| size_category | Word count range | Strategy |
|---|---|---|
small |
<5K words | read_note Read the full text directly |
medium |
5K-20K characters | get_note_outline → read_section Read by chapter |
large |
20K-80K characters | search_note_content Precise targeting → read_blocks Read target + context → edit |
very_large |
>80K characters | Same as large, precise targeting takes priority search_note_content;get_note_outline Supports paginated reading (offset/block_limit) to retrieve structure as needed |
Principle: The larger the document, the more you should use search to locate rather than reading sequentially. For large/very_large documents, prioritize using search_note_content to find the target block, then use read_blocks to read its context.When operating on the current note, first call get_current_note to get size_category, then decide the path。
2. Edit note content
get_note_outline(note_id) → 获取最新 block ID
get_cursor_block() → 当前围绕光标位置编辑时,获取锚点 block
read_blocks(note_id, [target_id]) → 确认当前内容
insert_image(note_id, anchor_id, pos, src) → 插入图片(独立工具,不走 XML,当前需联网)
generate_image(prompt, width?, height?) → AI 文生图,返回图片 URL(配合 insert_image 插入笔记)
edit_block(note_id, op, ...) → 单个编辑操作(替换、插入、删除、更新属性、移动)
batch_edit(note_id, operations) → 多个操作合并为一次原子事务
Key: After editing, block IDs may change. For consecutive inserts, you can directly use the returned last_block_id as an anchor; before operating on other blocks, refresh via get_note_outline .
Parameter constraints:edit_block / batch_edit Only pass the current op required fields.replace / insert 's content must directly contain the complete XML string; you cannot pass plain text, Markdown, or "把第二段改成……" such natural language editing instructions.
Correct approach for consecutive inserts(to avoid disorder):
- Preferred: In a single
insert, concatenate all content into complete XML (e.g.,"<h2>A</h2><p>...</p><h2>B</h2><p>...</p>"), and insert them in XML order; no need to call multiple times. - Chained: If you must split into multiple
insert, each time use thelast_block_idreturned from the previous call as theanchor_idfor the next call, or callget_note_outlineafter each write to refresh the ID.
3. Batch editing (atomic transaction)
Use edit_blockfor a single operation, and batch_edit for multiple operations merged into an atomic transaction:
# 单个操作
edit_block(note_id, op: "replace", block_id: "id1", content: "<p>...</p>")
edit_block(note_id, op: "insert", anchor_id: "id2", position: "after", content: "<h2>...</h2><p>...</p>")
# 多个操作(原子事务)
batch_edit(note_id, operations: [
{ op: "delete", block_ids: ["id1"] },
{ op: "replace", block_id: "id2", content: "<p>...</p>" },
{ op: "update_attrs", block_id: "id3", attrs: { level: 2 } },
{ op: "move", block_id: "id5", anchor_id: "id2", position: "after" },
{ op: "insert", anchor_id: "id4", position: "after", content: "<h2>...</h2><p>...</p>" }
])
Execution order is fixed(batch_edit): delete → replace → update_attrs → move → insert (independent of array order).
4. Manage notes and tags
get_note_info(note_id) → 获取单个笔记元数据(含标签)
get_note_info(note_ids: [...]) → 批量获取多个笔记元数据(最多 100 个)
get_note_info(page, page_size) → 分页浏览所有笔记元数据
search_notes(keyword, tags, since, before) → 搜索笔记(也可按标签筛选笔记)
create_note(title) → 创建空白笔记(需用 edit_block 添加内容)
import_web_page(url) → 从白名单域名导入网页为笔记(微信公众号、知乎、豆瓣等)
delete_note(note_id) → 不可恢复——必须与用户确认
sync_note(note_id) → 触发同步
find_tags() → 列出所有标签
find_tags(keyword) → 搜索标签
manage_note_tags(note_id, add, remove) → 添加/移除笔记的文件级标签
get_note_stats(detailed) → 使用统计
Tool quick reference
Read/locate tools
| Tool | Purpose | Key parameters |
|---|---|---|
get_note_outline |
Get the structural outline (including title, word_count, block_count, size_category, estimated_xml_chars, blocks list, pagination)—the main way to get block_id and document scale; very large documents are automatically paginated | note_id、max_depth?、include_preview?、offset?、block_limit? |
get_cursor_block |
Get the block_id、block_type and note_idof the top-level block where the current cursor is located; not supported when the cursor is inside a highlight block or column |
(no parameters) |
read_blocks |
Batch read the XML content and attributes of blocks by ID, or read a single block and its surrounding context | note_id、block_ids(batch) or block_id+before?+after?(context) |
read_note |
Read the full text or read in pages (XML); very large documents are automatically paginated and return pagination (including has_more + next_offset) | note_id、max_length?、offset?、block_limit? |
search_note_content |
Search for text within the note, returning the block_id/type/preview of matching blocks, used for locating before editing | note_id、query、max_results? |
read_section |
Read the complete chapter by heading (until the next heading of the same level); when truncated, returns next_block_offset for continued reading | note_id、heading_block_id、max_blocks?、block_offset? |
read_image |
Read the actual content of an image block (base64), available for visual understanding | note_id、block_id |
get_audio_transcript |
Get the transcription text of a voice recording (NoteAudioCard), returning a list of sentences (including speaker and timestamps) | shorthand_id(from outline's note_audio_card block attrs) |
get_xml_reference |
Get the complete reference documentation in XML format (all tags, attributes, and write examples) | (no parameters) |
Example:
get_note_outline({ note_id: "abc123" })
get_note_outline({ note_id: "abc123", offset: 100 }) // 分页续读
get_cursor_block()
read_blocks({ note_id: "abc123", block_ids: ["aB3kLm9xZq", "xY7nPq2wRt"] })
read_blocks({ note_id: "abc123", block_id: "xY7nPq2wRt", before: 2, after: 3 })
read_note({ note_id: "abc123" })
read_note({ note_id: "abc123", offset: 100 }) // 分页续读
read_note({ note_id: "abc123", offset: 0, block_limit: 50 }) // 手动控制每页大小
search_note_content({ note_id: "abc123", query: "季度总结" })
read_section({ note_id: "abc123", heading_block_id: "aB3kLm9xZq" })
read_section({ note_id: "abc123", heading_block_id: "aB3kLm9xZq", block_offset: 50 }) // 续读截断章节
read_image({ note_id: "abc123", block_id: "imgBlock01" })
get_audio_transcript({ shorthand_id: "sh_abc123" })
get_xml_reference()
Write tools
| Tool | Purpose | Key parameters |
|---|---|---|
edit_block |
A single edit operation (recommended entry point); after editing, block_id may change and needs to be re-fetched. The insert operation returns new_block_ids and last_block_id. After a move operation, block_id does not change |
note_id、op(replace/insert/delete/update_attrs/move)、block_id/anchor_id/block_ids、content/attrs |
batch_edit |
An atomic transaction of multiple operations (all succeed or all roll back), with a fixed execution order. Returns new_block_ids and last_block_id |
note_id、operations[] |
insert_image |
Insert an image (images cannot be created via XML and must use this tool); currently uses online upload, returns block_id and dimensions | note_id、anchor_id、position、src、alt? |
generate_image |
AI text-to-image, returns the image URL (use with insert_image to insert into a note). Limited to once per minute per user, takes 30-120 seconds |
prompt、width?(default 2688),height?(default 1536) |
import_web_page |
Import web content as a note from whitelisted domains (WeChat Official Accounts, Zhihu, Douban, etc.), returning the note ID, title, and summary. Takes 5-30 seconds | url |
edit_block / batch_edit operation type:
op |
Required fields |
|---|---|
"replace" |
block_id、content |
"insert" |
anchor_id、position("before"/"after")、content |
"delete" |
block_ids |
"update_attrs" |
block_id、attrs |
"move" |
block_id、anchor_id、position("before"/"after") |
content appears only in replace / insert and must be a complete XML string, not natural language, plain text, or Markdown.
File reference parameters(CLI and script scenarios): when content or operations content is too large and causes command-line truncation, file references can be used instead—content_file(pass in a file path; Electron reads it and fills in content)、operations_file(similarly fills in operations)、__args_file(read all parameters from a JSON file). File references are ignored when an explicit value already exists. See references/CLI_REFERENCE.md。
Example:
// 单个操作 — edit_block
edit_block({ note_id: "abc123", op: "replace", block_id: "xY7nPq2wRt", content: "<p>更新后的段落文本</p>" })
edit_block({ note_id: "abc123", op: "insert", anchor_id: "aB3kLm9xZq", position: "after", content: "<h2>新章节</h2><p>这里是新内容。</p>" })
edit_block({ note_id: "abc123", op: "delete", block_ids: ["xY7nPq2wRt", "kL5mNp8vBc"] })
edit_block({ note_id: "abc123", op: "update_attrs", block_id: "aB3kLm9xZq", attrs: { level: 2 } })
edit_block({ note_id: "abc123", op: "move", block_id: "imgBlock01", anchor_id: "aB3kLm9xZq", position: "after" })
// 多个操作(原子事务) — batch_edit
batch_edit({ note_id: "abc123", operations: [
{ op: "replace", block_id: "xY7nPq2wRt", content: "<p>更新后的段落文本</p>" },
{ op: "insert", anchor_id: "aB3kLm9xZq", position: "after", content: "<h2>新章节</h2>" }
]})
// 图片
insert_image({ note_id: "abc123", anchor_id: "aB3kLm9xZq", position: "after", src: "https://example.com/photo.png", alt: "示意图" })
// AI 文生图 → 插入笔记
generate_image({ prompt: "一只橘猫坐在窗台上,水彩画风格,暖色调" })
→ { image_url: "https://...", task_id: "...", width: 2688, height: 1536 }
// 然后用 insert_image 将返回的 image_url 插入笔记
// 导入网页为笔记
import_web_page({ url: "https://mp.weixin.qq.com/s/xxx" })
→ { fileId: "123456", title: "文章标题", intro: "摘要...", linkUrl: "https://xxx/note/123456" }
Hidden write tools
The following tools are still available but not shown by default, suitable for scenarios that require calling them individually:
| Tool | Purpose | Key parameters |
|---|---|---|
replace_block |
Replace the content of a single block | note_id、block_id、content |
insert_block |
Insert before or after a specified position | note_id、anchor_id、position、content |
delete_blocks |
Delete a block | note_id、block_ids |
update_block_attrs |
Modify block attributes | note_id、block_id、attrs |
Management tools
| Tool | Purpose | Key parameters |
|---|---|---|
list_notes |
List notes, supports sorting and pagination, returns { notes, meta } | limit?、sort?、direction?、since?、before?、page?、page_size?、starred? |
create_note |
Create a blank note (containing only an empty paragraph), returns { fileId, title } | title? |
get_note_info |
Get note metadata (without reading the full text), returns title, time, intro, tags, starred | note_id(single),note_ids(batch),limit?、page+page_size(pagination) |
get_current_note |
Get the current note ID, metadata, and document statistics (including word_count, size_category) | (no parameters) |
get_cursor_block |
Get the current cursor's block's block_id、block_type and note_id; not supported when inside a highlight block/column layout |
(no parameters) |
search_notes |
Search notes (keyword + tag intersection + time range); you can also pass only tags to browse by tag | keyword?、tags?、since?、before?、sort?、direction?、limit?、starred? |
find_tags |
List or search tags, returning an array of { id, name } | keyword?(if not provided, list all; if provided, search) |
manage_note_tags |
Manage file-level tags of a note (add/remove) | note_id、add?(array of tag names),remove?(array of tag names or IDs) |
sync_note |
Trigger sync between note and cloud | note_id |
delete_note |
Permanently delete note (unrecoverable), must first confirm with user | note_id or note_ids(batch, up to 100) |
get_note_stats |
Usage statistics (total notes, tag count, distribution, etc.) | detailed? |
get_mcp_logs |
MCP call logs, used for diagnosing INTERNAL_ERROR |
limit? |
Example:
list_notes({ sort: "update_time", direction: "desc", limit: 10 })
list_notes({ starred: true }) // 仅列出已收藏笔记
search_notes({ keyword: "项目方案", tags: ["工作"], since: "2025-01-01T00:00:00Z" })
search_notes({ tags: ["工作"] }) // 按标签筛选笔记(替代原 list_tag_notes)
search_notes({ starred: true }) // 仅在已收藏笔记中搜索
create_note({ title: "会议记录 2025-03-03" })
get_current_note()
get_cursor_block()
get_note_info({ note_id: "abc123" }) // 单个笔记元数据(含标签)
get_note_info({ note_ids: ["abc123", "def456"] }) // 批量查询
get_note_info({ page: 1, page_size: 20 }) // 分页浏览所有笔记
get_note_info({ limit: 5 }) // 仅获取前 5 条
find_tags() // 列出所有标签
find_tags({ keyword: "工作" }) // 搜索标签
manage_note_tags({ note_id: "abc123", add: ["工作", "项目"] }) // 为笔记添加标签
manage_note_tags({ note_id: "abc123", remove: ["草稿"] }) // 移除笔记标签
manage_note_tags({ note_id: "abc123" }) // 查看当前标签
delete_note({ note_id: "abc123" }) // 不可恢复——必须先与用户确认!
get_mcp_logs({ limit: 20 }) // 查看最近的工具调用日志
Block types and XML tags
| Block type | XML tag | Description |
|---|---|---|
paragraph |
<p> |
Supports inline mark (<strong>、<em>、<s>、<u>、<a>) and inline nodes (<emoji/>、<latex/>、<br/>) |
heading |
<h1>-<h6> |
level is controlled by tag name or attrs.level Control |
blockquote |
<blockquote> |
Supports inline mark and <br/> line break |
code_block |
<codeblock lang="..."> |
Pure text content; language is specified via the lang attribute |
list |
<p listType="bullet|ordered|todo"> |
Controlled via the listType、listLevel、checked attribute; ordered lists additionally support listId and listValue |
table |
<table> |
<tr> → <td> structure; must replace the whole table. Cells only support simple blocks (<p>、<h1>-<h6>、<blockquote>、<codeblock>、<hr/>、<img/>), cannot nest <highlightBlock>、<columns>、<table> and other containers |
highlight_block |
<highlightBlock> |
Highlight block, only supports simple blocks (<p>、<h1>-<h6>、<blockquote>、<codeblock>、<hr/>、<img/>), cannot nest <highlightBlock>、<columns>、<table> and other containers |
columns |
<columns> → <column> |
Column layout, each column supports simple blocks and <highlightBlock>, cannot nest <table> or <columns> |
image |
<img/> |
Read-only——cannot be created or modified via XML, use the insert_image tool to insert a single image |
image_column |
<imageColumn> |
Read-only——images displayed in columns, cannot be created via XML |
horizontal_rule |
<hr/> |
Divider |
embed |
<embed type="..."/> |
Read-only——cannot be edited or replaced |
note_audio_card |
<NoteAudioCard/> |
Read-only——audio recording card, use get_audio_transcript to get the transcript |
update_block_attrs supported attributes
| Block type | Attribute | Optional values |
|---|---|---|
heading |
level |
1–6 |
heading |
textAlign |
"left"、"center"、"right" |
paragraph |
textAlign |
"left"、"center"、"right" |
code_block |
language |
Language identifier string |
todo_list sub-items |
checked |
true / false |
Troubleshooting
block ID invalid (BLOCK_NOT_FOUND)
Symptom: write operation reports BLOCK_NOT_FOUND, even if the block was just read previously.
Cause: editing operations cause block IDs to change, and the cached ID has expired.
Solution: always first get_note_outline or search_note_content to refresh the ID before writing; or use the last_block_id returned by the last insert as the next anchor_id。
Table editing fails
Symptom: an error or content loss occurs when trying to edit a table cell.
Cause: tables only support whole-table replacement and cannot edit individual cells.
Solution: use edit_block 's replace operation to pass in the complete XML table (including the header separator row).
embed block is not writable
Symptom: calling edit_block of the replace operation returns an error.
Cause: embedded content such as spreadsheets, videos, audio, and LaTeX are read-only placeholders.
Solution: skip embed blocks and only operate on other editable block types.
Note is read-only (DOCUMENT_READ_ONLY)
Symptom: all write operations return DOCUMENT_READ_ONLY。
Cause: the current note token has read-only permission and cannot be retried.
Solution: inform the user that this note is read-only. Read operations still work normally.
Editor not ready (EDITOR_NOT_READY)
Symptom: the operation returns EDITOR_NOT_READY。
Cause: the note editor is still initializing, usually recovering in 1-2 seconds.
Solution: wait a moment and retry. If it still fails after 3 attempts, ask the user to check the notes app.
WebSocket not connected (WEBSOCKET_NOT_CONNECTED)
Symptom:get_audio_transcript returns WEBSOCKET_NOT_CONNECTED。
Cause: the network is disconnected or the WebSocket connection is interrupted.
Solution: check the network connection, wait for the WebSocket to reconnect automatically, then retry.
Other notes
- Images must use the
insert_imagetool: images cannot be created via XML (the<img/>tag is read-only).insert_imagecurrently uploads online, requiring internet access when called. Supports HTTP/HTTPS URLs and base64 data URIs.Local file paths are not supported for direct input; you must first read them and convert them to base64 data URIs。The URL must point directly to an image resource (returning image/ content type), and cannot be an HTML page link*. If the URL returns 404, is offline, or contains non-image content, it will report theIMAGE_FETCH_FAILEDerror.edit_block's replace/insert/update_attrs do not support images (but move can move image blocks)。 generate_imageis AI text-to-image: returns an image URL rather than inserting it directly into the note. Must be used withinsert_image. Limited to 1 time per user per minute; generation takes about 30-120 seconds.import_web_pageonly supports whitelisted domains: whitelisted domains such as WeChat Official Accounts, Zhihu, and Douban can be imported; non-whitelisted domains will returnINVALID_PARAMS. Conversion takes about 5-30 seconds. After import completes, a new note is automatically created and opened.batch_edithas a fixed execution order: delete → replace → update_attrs → move → insert, regardless of array order.moveoperations support all block types: including images (<img/>), embedded content (<embed/>), and other read-only tags that cannot be created via XML. After moving, block_id remains unchanged, so there is no need to refresh the outline. Suitable for adjusting content order and reorganizing document structure.create_notecreates a blank note: initial content is not supported; useedit_blockto fill it.read_sectionis limited to headings:heading_block_idmust point to aheadingblock, otherwise it reportsINVALID_BLOCK_TYPE。get_cursor_blockonly supports top-level blocks: when the cursor is inside a highlight block (subdoc) or columns, it returnsUNSUPPORTED_POSITION。delete_noteis unrecoverable: you must first confirm with the user.- When the response contains
hints,follow its suggestions—they indicate the fastest recovery path.
Error Code Quick Reference
| Error Code | Retryable | Recovery Method |
|---|---|---|
INVALID_PARAMS |
No | Fix the parameters according to inputSchema |
EDITOR_NOT_READY |
Yes | Wait and retry |
NO_ACTIVE_EDITOR_WINDOW |
Yes | Ask the user to open the note window |
BLOCK_NOT_FOUND |
No | Refresh the outline to get a valid ID |
INVALID_BLOCK_TYPE |
No | Check the block type |
INVALID_CONTENT |
No | Fix the content format |
DOCUMENT_READ_ONLY |
No | Inform the user |
FRONTEND_TIMEOUT |
Yes | Narrow the scope or retry |
IMAGE_FETCH_FAILED |
Yes | Check whether the image URL points directly to an image resource, fix it, and retry |
GENERATE_IMAGE_FAILED |
No | Fix the prompt or check the whitelist/login status |
RATE_LIMITED |
Yes | Wait 60 seconds and retry |
WEBSOCKET_NOT_CONNECTED |
Yes | Check the network, wait for the WebSocket to reconnect, and retry |
INTERNAL_ERROR |
Yes | Retry; check get_mcp_logs(hidden tool) |
For full error details, see references/ERROR_CODES.md。
Common Orchestration Patterns
The most frequent multi-tool combinations, usable without consulting the full use case manual.
Pattern 1: Search and locate → Read in sections(preferred for long documents)
search_notes({ keyword }) → note_id
get_note_outline({ note_id }) → heading block ID
read_section({ note_id, heading_block_id }) → 按需读取章节
Pattern 2: Batch search and replace within a note
search_note_content({ note_id, query }) → 匹配的 block_id 列表
read_blocks({ note_id, block_ids }) → 读取完整内容
batch_edit({ note_id, operations: [{ op: "replace", ... }, ...] }) → 原子替换
Pattern 3: Create → Fill template
create_note({ title }) → note_id(空白笔记)
manage_note_tags({ note_id, add: ["标签名"] }) → 分配标签
get_note_outline({ note_id }) → 获取空 block ID
batch_edit({ note_id, operations: [
{ op: "replace", block_id, content: "<h1>标题</h1>" },
{ op: "insert", anchor_id, position: "after", content: "<p>模板内容...</p>" }
]})
Pattern 4: Continuously append multiple sections(avoid out-of-order)
# 方式 A(推荐):单次 insert 拼接完整 XML
edit_block({ note_id, op: "insert", anchor_id: "last_id", position: "after",
content: "<h2>第一部分</h2><p>内容 A</p><h2>第二部分</h2><p>内容 B</p>" })
# 方式 B:链式 insert,用上次返回的 last_block_id 做锚点
edit_block({ ..., anchor_id: "id1", position: "after", content: "<h2>第一部分</h2><p>内容 A</p>" })
→ { last_block_id: "new_id_1" }
edit_block({ ..., anchor_id: "new_id_1", position: "after", content: "<h2>第二部分</h2><p>内容 B</p>" })
→ { last_block_id: "new_id_2" }
Pattern 5: Move blocks (images, embedded content, etc.)
get_note_outline({ note_id }) → 找到源 block 和目标位置
edit_block({ note_id, op: "move", block_id: "img_id", anchor_id: "target_heading", position: "after" })
→ block_id 不变,无需刷新 outline
Pattern 6: Manage note tags
find_tags() → 查看已有标签名
manage_note_tags({ note_id, add: ["工作", "项目"] }) → 添加标签
manage_note_tags({ note_id, remove: ["草稿"] }) → 移除标签
manage_note_tags({ note_id }) → 查看当前标签
Pattern 7: Read oversized documents in pages(preferred when there is no heading structure; paging only controls the read amount, and notes have no block limit)
read_note({ note_id })
→ pagination: { total_blocks: 350, has_more: true, next_offset: 100 }
read_note({ note_id, offset: 100 })
→ pagination: { has_more: true, next_offset: 200 }
read_note({ note_id, offset: 200 })
→ pagination: { has_more: false } ← 读完
For more combination patterns and end-to-end scenarios, see references/USE_CASES.md。
Full Examples
User says: "Help me find the Q1 report, update the summary section, and add a conclusion"
Step 1: Locate the note
search_notes({ keyword: "Q1 报告" })
→ data.notes[0].note_id = "note_xyz"
Step 2: Read the structure
get_note_outline({ note_id: "note_xyz" })
→ blocks: [
{ id: "h1abc", type: "heading", preview: "Q1 报告" },
{ id: "p1def", type: "paragraph", preview: "执行摘要..." },
{ id: "h2ghi", type: "heading", preview: "营收" },
{ id: "h2jkl", type: "heading", preview: "下一步计划" },
{ id: "p3mno", type: "paragraph", preview: "继续监控..." }
]
Step 3: Confirm the current content
read_blocks({ note_id: "note_xyz", block_ids: ["p1def"] })
→ "本季度各部门..."
Step 4: Atomic edit (replace the summary + insert the conclusion)
batch_edit({ note_id: "note_xyz", operations: [
{ op: "replace", block_id: "p1def",
content: "<p>本报告涵盖 2025 年 Q1 各部门业绩表现。营收超出目标 15%。</p>" },
{ op: "insert", anchor_id: "p3mno", position: "after",
content: "<h2>总结</h2><p>2025 年 Q1 是强劲的一个季度,所有关键指标均实现显著增长。</p>" }
]})
→ ok: true, last_block_id: "new_conclusion_id"
Tip:
batch_edit/edit_blockIn the insert operation of , content can contain multiple block-level XML elements (such as<h2>+<p>in the example above), which are inserted in XML order without needing multiple calls. The returnedlast_block_idcan be used directly for subsequent operations.
Step 5: Verify the result
read_section({ note_id: "note_xyz", heading_block_id: "h1abc", max_blocks: 5 })
→ 确认摘要已更新、结论已添加
Result: The note summary has been replaced with the new content, and a "Conclusion" section has been added at the end.
Reference Documentation
- API Reference—Complete inputSchema for all tools
- CLI Reference——
wpsnote-clicanonical command surface, CLI-specific behavior, and JSON output format - Error Codes—Detailed error codes, the hints system, and recovery patterns
- Use Case Manual—A complete set of use cases progressing by complexity (including end-to-end workflow examples), Prompt templates, and a quick reference for exception handling