From c2add31bd8fe81f42c6b5df6324e2ee6dcbbb345 Mon Sep 17 00:00:00 2001 From: xiaolai Date: Wed, 28 Jan 2026 18:04:29 +0800 Subject: [PATCH] feat: add vmark-mcp plugin for VMark markdown editor Add AI writing assistant skill for VMark editor that provides: - Comprehensive skill with writer-centric workflows - tools-by-intent.md: Maps writer intents to 76 MCP tools - workflows.md: 9 detailed step-by-step patterns - examples.md: Real tool calls with parameters Key features: - Read-before-write workflow pattern - Suggestion-first approach for content changes - Conflict handling with revision management - Multi-document workflow support Homepage: https://github.com/xiaolai/vmark --- .claude-plugin/marketplace.json | 12 + plugins/vmark-mcp/.claude-plugin/plugin.json | 18 + plugins/vmark-mcp/README.md | 64 ++ plugins/vmark-mcp/skills/vmark-mcp/SKILL.md | 200 +++++ .../skills/vmark-mcp/references/examples.md | 733 ++++++++++++++++++ .../vmark-mcp/references/tools-by-intent.md | 264 +++++++ .../skills/vmark-mcp/references/workflows.md | 506 ++++++++++++ 7 files changed, 1797 insertions(+) create mode 100644 plugins/vmark-mcp/.claude-plugin/plugin.json create mode 100644 plugins/vmark-mcp/README.md create mode 100644 plugins/vmark-mcp/skills/vmark-mcp/SKILL.md create mode 100644 plugins/vmark-mcp/skills/vmark-mcp/references/examples.md create mode 100644 plugins/vmark-mcp/skills/vmark-mcp/references/tools-by-intent.md create mode 100644 plugins/vmark-mcp/skills/vmark-mcp/references/workflows.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4e22718..1950b17 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -32,6 +32,18 @@ "homepage": "https://github.com/EveryInc/compound-engineering-plugin", "tags": ["coding", "programming", "tutorial", "learning", "spaced-repetition", "education"], "source": "./plugins/coding-tutor" + }, + { + "name": "vmark-mcp", + "description": "AI writing assistant for VMark markdown editor. Comprehensive skills and workflows for 76 MCP tools - write, edit, reorganize, and format documents with AI assistance. Includes 1 skill with detailed references.", + "version": "0.3.10", + "author": { + "name": "xiaolai", + "url": "https://github.com/xiaolai" + }, + "homepage": "https://github.com/xiaolai/vmark", + "tags": ["markdown", "editor", "mcp", "writing", "ai-assistant", "vmark"], + "source": "./plugins/vmark-mcp" } ] } diff --git a/plugins/vmark-mcp/.claude-plugin/plugin.json b/plugins/vmark-mcp/.claude-plugin/plugin.json new file mode 100644 index 0000000..2202a52 --- /dev/null +++ b/plugins/vmark-mcp/.claude-plugin/plugin.json @@ -0,0 +1,18 @@ +{ + "name": "vmark-mcp", + "version": "0.3.10", + "description": "AI writing assistant for VMark markdown editor. Provides comprehensive skills and workflows for interacting with VMark through 76 MCP tools - write, edit, reorganize, and format documents with AI assistance. Includes 1 skill with detailed reference documentation.", + "author": { + "name": "xiaolai", + "url": "https://github.com/xiaolai" + }, + "repository": "https://github.com/xiaolai/vmark", + "keywords": [ + "vmark", + "markdown", + "editor", + "mcp", + "writing", + "ai-assistant" + ] +} diff --git a/plugins/vmark-mcp/README.md b/plugins/vmark-mcp/README.md new file mode 100644 index 0000000..866d396 --- /dev/null +++ b/plugins/vmark-mcp/README.md @@ -0,0 +1,64 @@ +# VMark MCP Plugin + +AI writing assistant for the VMark markdown editor. This plugin provides skills and workflows for Claude Code to interact with VMark through MCP tools. + +## What's Included + +### Skills + +- **vmark-mcp** — Comprehensive writing assistant skill with workflows for: + - Continuing/expanding text at cursor + - Improving and refining sections + - Reorganizing document structure + - Find and replace operations + - Converting notes to prose + - Multi-document workflows + - Table and list manipulation + +### MCP Server + +The plugin includes the VMark MCP server which exposes 76 tools for document manipulation: +- Structure tools (AST, digest, sections) +- Mutation tools (batch edit, find/replace) +- Formatting tools (marks, blocks, lists, tables) +- Workspace tools (windows, tabs, documents) + +## Installation + +### For Claude Code Users + +```bash +# Install the plugin +claude plugins install github:xiaolai/vmark +``` + +### For VMark Developers + +The skill is already available in the vmark repository at `plugins/vmark-mcp/skills/`. + +## Usage + +Once installed, use the skill via: + +``` +/vmark-mcp +``` + +Or let Claude Code auto-detect when you're working with VMark documents. + +## Key Workflows + +1. **Read before write** — Always understand document structure first +2. **Suggest, don't force** — Use suggestion mode for content changes +3. **Work with structure** — Target nodes by ID, not character positions + +See the skill's reference files for detailed workflows and examples. + +## Requirements + +- VMark editor running with MCP enabled +- Claude Code CLI + +## License + +Same as VMark (see root LICENSE file). diff --git a/plugins/vmark-mcp/skills/vmark-mcp/SKILL.md b/plugins/vmark-mcp/skills/vmark-mcp/SKILL.md new file mode 100644 index 0000000..26e1767 --- /dev/null +++ b/plugins/vmark-mcp/skills/vmark-mcp/SKILL.md @@ -0,0 +1,200 @@ +--- +name: vmark-mcp +description: AI writing assistant for VMark editor. Use when helping users write, edit, reorganize, or format markdown documents through the VMark MCP tools. +--- + +# VMark MCP Writing Assistant + +## When to Use This Skill + +Use this skill when the user wants AI help with: +- Writing or expanding content in VMark +- Editing, refining, or improving existing text +- Reorganizing document structure (moving sections, reordering) +- Formatting (headings, lists, tables, emphasis) +- Multi-document workflows (working across tabs/windows) + +## Core Principles + +### 1. Read Before Write + +**Always** understand the document before making changes: + +``` +get_document_digest → understand structure +get_section → read specific content +THEN propose changes +``` + +Never edit blind. The digest gives you: title, word count, outline, block counts. + +### 2. Suggest, Don't Force + +Use `mode: "suggest"` for content changes. Let the writer decide: + +``` +batch_edit( + mode: "suggest", ← Writer reviews before applying + operations: [...] +) +``` + +The writer sees highlighted suggestions and accepts/rejects them. + +### 3. Respect Revision History + +Every mutation needs `baseRevision` for conflict detection: + +``` +1. get_document_revision → "rev_abc123" +2. batch_edit(baseRevision: "rev_abc123", ...) + → If doc changed: CONFLICT (re-read and retry) + → If unchanged: SUCCESS +``` + +### 4. Work with Structure, Not Positions + +Target nodes by ID, not character offsets: + +``` +✓ batch_edit(operations: [{nodeId: "node_123", ...}]) +✗ "Replace characters 450-500" +``` + +Use `list_blocks` or `get_document_ast` to find node IDs. + +## Quick Reference: Intent → Tool + +| You Want To... | Use This Tool | Mode | +|----------------|---------------|------| +| Understand the document | `get_document_digest` | - | +| Find specific content | `list_blocks` with query | - | +| Read a section | `get_section` | - | +| Insert/update/delete content | `batch_edit` | suggest | +| Find and replace | `apply_diff` | suggest | +| Replace with context anchors | `replace_text_anchored` | suggest | +| Move a section | `move_section` | apply | +| Toggle formatting | `format_toggle` | apply | +| Change block type | `block_set_type` | apply | +| Work with lists | `list_toggle`, `list_modify` | apply | +| Work with tables | `table_modify` | apply | +| Check pending suggestions | `suggestion_list` | - | +| Preview changes | Any mutation tool | dryRun | + +## The Fundamental Workflow + +Every AI writing task follows this cycle: + +``` +┌─────────────────────────────────────────────────────────┐ +│ 1. READ get_document_digest / get_section │ +│ Understand what exists │ +├─────────────────────────────────────────────────────────┤ +│ 2. LOCATE list_blocks / resolve_targets │ +│ Find the nodes you'll modify │ +├─────────────────────────────────────────────────────────┤ +│ 3. PLAN (AI reasoning) │ +│ Decide what changes to make │ +├─────────────────────────────────────────────────────────┤ +│ 4. PREVIEW batch_edit with mode: "dryRun" │ +│ (Optional) Verify targets are correct │ +├─────────────────────────────────────────────────────────┤ +│ 5. SUGGEST batch_edit with mode: "suggest" │ +│ Propose changes for writer approval │ +├─────────────────────────────────────────────────────────┤ +│ 6. WAIT Writer accepts/rejects suggestions │ +│ Don't assume acceptance │ +└─────────────────────────────────────────────────────────┘ +``` + +## Common Workflows + +### Expand/Continue Writing + +``` +1. cursor_get_context → Get text around cursor +2. (AI generates continuation) +3. document_insert_at_cursor(text, mode: "suggest") +4. Tell writer: "I've suggested a continuation. Press Tab to accept or Escape to reject." +``` + +### Improve a Section + +``` +1. get_document_digest → Find section heading +2. get_section("Introduction") → Read full content +3. (AI analyzes and improves) +4. update_section(heading: "Introduction", content: "...", mode: "suggest") +5. Tell writer what you changed and why +``` + +### Reorganize Document + +``` +1. get_document_digest → See outline +2. move_section(heading: "Conclusion", before: "Methods") +3. Confirm new structure to writer +``` + +### Find and Replace + +``` +1. apply_diff( + original: "old phrase", + replacement: "new phrase", + matchPolicy: "all", + mode: "suggest" + ) +2. Report: "Found X occurrences. Review suggestions to accept." +``` + +### Format Content + +``` +1. list_blocks(query: {contains: "important term"}) +2. batch_edit(operations: [ + {type: "format", nodeId: "...", marks: [{type: "bold"}]} + ]) +``` + +## What This Skill Cannot Do + +Be honest about limitations: + +| Request | Reality | +|---------|---------| +| "Type along with me" | No real-time streaming. AI responds to requests. | +| "Show me 3 alternatives" | One suggestion at a time. Iterate if needed. | +| "Watch for errors as I type" | No document events. Must be asked to check. | +| "Track all my changes" | Suggestions are accept/reject, not diff view. | + +## Handling Conflicts + +If `batch_edit` returns a conflict error: + +``` +1. Re-read: get_document_digest or get_section +2. Re-analyze: the content may have changed +3. Re-propose: new batch_edit with fresh baseRevision +4. Tell writer: "The document changed. Here's my updated suggestion." +``` + +## Multi-Document Workflows + +When working across files: + +``` +1. workspace_list_windows → See all open windows +2. tabs_list(windowId) → See tabs in a window +3. tabs_switch(tabId) → Switch to target document +4. (Perform operations) +5. tabs_switch back if needed +``` + +Always specify `windowId` when not working in the focused window. + +## References + +- `references/tools-by-intent.md` — Complete tool mapping by writer intent +- `references/workflows.md` — Detailed step-by-step patterns +- `references/examples.md` — Real tool call examples with parameters diff --git a/plugins/vmark-mcp/skills/vmark-mcp/references/examples.md b/plugins/vmark-mcp/skills/vmark-mcp/references/examples.md new file mode 100644 index 0000000..56a57a7 --- /dev/null +++ b/plugins/vmark-mcp/skills/vmark-mcp/references/examples.md @@ -0,0 +1,733 @@ +# VMark MCP Tool Examples + +Real tool call examples with parameters and expected responses. + +--- + +## Reading the Document + +### get_document_digest + +**Call:** +```json +{ + "tool": "get_document_digest" +} +``` + +**Response:** +```json +{ + "title": "My Research Paper", + "wordCount": 2450, + "charCount": 14230, + "outline": [ + { "level": 1, "text": "My Research Paper", "nodeId": "node_1" }, + { "level": 2, "text": "Introduction", "nodeId": "node_5" }, + { "level": 2, "text": "Methods", "nodeId": "node_23" }, + { "level": 3, "text": "Data Collection", "nodeId": "node_31" }, + { "level": 2, "text": "Results", "nodeId": "node_45" }, + { "level": 2, "text": "Conclusion", "nodeId": "node_67" } + ], + "blockCounts": { + "paragraph": 28, + "heading": 6, + "bulletList": 3, + "codeBlock": 2, + "table": 1 + }, + "flags": { + "hasImages": true, + "hasTables": true, + "hasCode": true, + "hasMath": false + }, + "revision": "rev_a7b3c9" +} +``` + +### get_section + +**Call:** +```json +{ + "tool": "get_section", + "heading": "Introduction" +} +``` + +**Response:** +```json +{ + "heading": { + "nodeId": "node_5", + "level": 2, + "text": "Introduction" + }, + "content": [ + { "nodeId": "node_6", "type": "paragraph", "text": "This paper explores..." }, + { "nodeId": "node_7", "type": "paragraph", "text": "Previous research has..." } + ], + "markdown": "## Introduction\n\nThis paper explores...\n\nPrevious research has...", + "wordCount": 156, + "revision": "rev_a7b3c9" +} +``` + +### list_blocks + +**Call:** +```json +{ + "tool": "list_blocks", + "query": { + "type": "paragraph", + "contains": "important" + }, + "limit": 10 +} +``` + +**Response:** +```json +{ + "revision": "rev_a7b3c9", + "blocks": [ + { + "id": "node_12", + "type": "paragraph", + "text": "This is an important finding that...", + "position": { "from": 450, "to": 520 } + }, + { + "id": "node_34", + "type": "paragraph", + "text": "Another important consideration is...", + "position": { "from": 890, "to": 945 } + } + ], + "hasMore": false +} +``` + +### cursor_get_context + +**Call:** +```json +{ + "tool": "cursor_get_context", + "charsBefore": 200, + "charsAfter": 50 +} +``` + +**Response:** +```json +{ + "before": "...the data shows a clear trend toward increased adoption. The implications of this finding are significant for practitioners who need to", + "after": " make informed decisions about...", + "position": 1234, + "currentBlock": { + "nodeId": "node_28", + "type": "paragraph", + "text": "The implications of this finding are significant for practitioners who need to make informed decisions about implementation strategies." + }, + "revision": "rev_a7b3c9" +} +``` + +--- + +## Making Edits + +### batch_edit - Insert content + +**Call:** +```json +{ + "tool": "batch_edit", + "baseRevision": "rev_a7b3c9", + "mode": "suggest", + "operations": [ + { + "type": "insert", + "after": "node_12", + "content": "Furthermore, this finding aligns with recent studies by Smith et al. (2023) which demonstrated similar patterns in controlled environments." + } + ] +} +``` + +**Response:** +```json +{ + "success": true, + "mode": "suggest", + "operationResults": [ + { + "type": "insert", + "suggestionId": "sug_x7y8z9", + "insertedNodeId": "node_13_new" + } + ], + "newRevision": "rev_b8c4d0" +} +``` + +### batch_edit - Update content + +**Call:** +```json +{ + "tool": "batch_edit", + "baseRevision": "rev_a7b3c9", + "mode": "suggest", + "operations": [ + { + "type": "update", + "nodeId": "node_12", + "text": "This is a critically important finding that demonstrates a clear correlation between the variables studied." + } + ] +} +``` + +**Response:** +```json +{ + "success": true, + "mode": "suggest", + "operationResults": [ + { + "type": "update", + "nodeId": "node_12", + "suggestionId": "sug_a1b2c3" + } + ], + "newRevision": "rev_b8c4d0" +} +``` + +### batch_edit - Multiple operations + +**Call:** +```json +{ + "tool": "batch_edit", + "baseRevision": "rev_a7b3c9", + "mode": "suggest", + "operations": [ + { + "type": "update", + "nodeId": "node_12", + "text": "Improved paragraph one..." + }, + { + "type": "update", + "nodeId": "node_13", + "text": "Improved paragraph two..." + }, + { + "type": "delete", + "nodeId": "node_14" + } + ] +} +``` + +### batch_edit - Dry run + +**Call:** +```json +{ + "tool": "batch_edit", + "baseRevision": "rev_a7b3c9", + "mode": "dryRun", + "operations": [ + { + "type": "update", + "nodeId": "node_12", + "text": "New content..." + } + ] +} +``` + +**Response:** +```json +{ + "success": true, + "mode": "dryRun", + "preview": { + "operationCount": 1, + "affectedNodes": ["node_12"], + "estimatedChanges": { + "deletions": 45, + "insertions": 52 + } + } +} +``` + +### apply_diff - Find and replace + +**Call:** +```json +{ + "tool": "apply_diff", + "baseRevision": "rev_a7b3c9", + "original": "machine learning", + "replacement": "ML", + "matchPolicy": "all", + "mode": "suggest" +} +``` + +**Response:** +```json +{ + "success": true, + "matchCount": 7, + "suggestionIds": ["sug_1", "sug_2", "sug_3", "sug_4", "sug_5", "sug_6", "sug_7"], + "newRevision": "rev_c9d5e1" +} +``` + +### apply_diff - Scoped replacement + +**Call:** +```json +{ + "tool": "apply_diff", + "baseRevision": "rev_a7b3c9", + "scopeQuery": { + "type": "heading", + "level": 2 + }, + "original": "Section", + "replacement": "Chapter", + "matchPolicy": "all", + "mode": "suggest" +} +``` + +### replace_text_anchored + +**Call:** +```json +{ + "tool": "replace_text_anchored", + "baseRevision": "rev_a7b3c9", + "anchor": { + "text": "machine learning", + "beforeContext": "advances in the field of ", + "afterContext": " have revolutionized", + "maxDistance": 50 + }, + "replacement": "artificial intelligence", + "mode": "suggest" +} +``` + +**Response:** +```json +{ + "success": true, + "matched": true, + "confidence": 0.95, + "suggestionId": "sug_d4e5f6", + "matchPosition": { "from": 234, "to": 250 } +} +``` + +--- + +## Section Operations + +### update_section + +**Call:** +```json +{ + "tool": "update_section", + "heading": "Introduction", + "content": "## Introduction\n\nThis completely rewritten introduction provides a clearer overview of the research objectives.\n\nThe study aims to investigate three key areas...", + "mode": "suggest" +} +``` + +### move_section + +**Call:** +```json +{ + "tool": "move_section", + "heading": "Conclusion", + "before": "Methods" +} +``` + +**Response:** +```json +{ + "success": true, + "movedSection": "Conclusion", + "newPosition": "before Methods", + "newRevision": "rev_e0f6g2" +} +``` + +### insert_section + +**Call:** +```json +{ + "tool": "insert_section", + "heading": "Literature Review", + "level": 2, + "content": "Previous studies have examined...", + "after": "Introduction" +} +``` + +--- + +## Formatting + +### format_toggle + +**Call:** +```json +{ + "tool": "format_toggle", + "mark": "bold" +} +``` + +**Response:** +```json +{ + "success": true, + "mark": "bold", + "applied": true +} +``` + +### format_set_link + +**Call:** +```json +{ + "tool": "format_set_link", + "url": "https://example.com/paper", + "title": "Reference Paper" +} +``` + +### block_set_type + +**Call:** +```json +{ + "tool": "block_set_type", + "type": "heading", + "attrs": { + "level": 2 + } +} +``` + +### block_set_type - Code block + +**Call:** +```json +{ + "tool": "block_set_type", + "type": "codeBlock", + "attrs": { + "language": "python" + } +} +``` + +--- + +## Lists + +### list_toggle + +**Call:** +```json +{ + "tool": "list_toggle", + "type": "bulletList" +} +``` + +### list_modify - Batch operations + +**Call:** +```json +{ + "tool": "list_modify", + "operations": [ + { "type": "addItem", "after": "item_3", "content": "New list item" }, + { "type": "updateItem", "itemId": "item_1", "content": "Updated first item" }, + { "type": "toggleCheck", "itemId": "item_2", "checked": true } + ] +} +``` + +--- + +## Tables + +### table_insert + +**Call:** +```json +{ + "tool": "table_insert", + "rows": 4, + "cols": 3 +} +``` + +### table_modify + +**Call:** +```json +{ + "tool": "table_modify", + "operations": [ + { "type": "updateCell", "row": 0, "col": 0, "content": "Name" }, + { "type": "updateCell", "row": 0, "col": 1, "content": "Value" }, + { "type": "updateCell", "row": 0, "col": 2, "content": "Status" }, + { "type": "addRow", "position": "after", "rowIndex": 3 }, + { "type": "updateCell", "row": 4, "col": 0, "content": "Total" } + ] +} +``` + +--- + +## Suggestions + +### suggestion_list + +**Call:** +```json +{ + "tool": "suggestion_list" +} +``` + +**Response:** +```json +{ + "count": 3, + "suggestions": [ + { + "id": "sug_a1b2c3", + "type": "replace", + "position": { "from": 234, "to": 289 }, + "original": "This is an important finding...", + "replacement": "This is a critically important finding...", + "createdAt": "2024-01-15T10:30:00Z" + }, + { + "id": "sug_d4e5f6", + "type": "insert", + "position": { "from": 450, "to": 450 }, + "content": "Furthermore, this aligns with...", + "createdAt": "2024-01-15T10:30:05Z" + } + ] +} +``` + +### suggestion_accept + +**Call:** +```json +{ + "tool": "suggestion_accept", + "suggestionId": "sug_a1b2c3" +} +``` + +**Response:** +```json +{ + "success": true, + "message": "Suggestion sug_a1b2c3 accepted and applied" +} +``` + +### suggestion_accept_all + +**Call:** +```json +{ + "tool": "suggestion_accept_all" +} +``` + +**Response:** +```json +{ + "success": true, + "count": 3, + "message": "Accepted 3 suggestion(s)" +} +``` + +--- + +## Workspace & Tabs + +### tabs_list + +**Call:** +```json +{ + "tool": "tabs_list" +} +``` + +**Response:** +```json +{ + "tabs": [ + { "id": "tab_1", "title": "Research Paper.md", "path": "/docs/paper.md", "active": true, "dirty": false }, + { "id": "tab_2", "title": "Notes.md", "path": "/docs/notes.md", "active": false, "dirty": true }, + { "id": "tab_3", "title": "Untitled", "path": null, "active": false, "dirty": false } + ] +} +``` + +### tabs_switch + +**Call:** +```json +{ + "tool": "tabs_switch", + "tabId": "tab_2" +} +``` + +### workspace_open_document + +**Call:** +```json +{ + "tool": "workspace_open_document", + "path": "/Users/writer/Documents/reference.md" +} +``` + +### workspace_save_document + +**Call:** +```json +{ + "tool": "workspace_save_document" +} +``` + +--- + +## Special Content + +### insert_math_inline + +**Call:** +```json +{ + "tool": "insert_math_inline", + "latex": "E = mc^2" +} +``` + +### insert_math_block + +**Call:** +```json +{ + "tool": "insert_math_block", + "latex": "\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}" +} +``` + +### insert_mermaid + +**Call:** +```json +{ + "tool": "insert_mermaid", + "code": "graph TD\n A[Start] --> B{Decision}\n B -->|Yes| C[Action 1]\n B -->|No| D[Action 2]" +} +``` + +### insert_wiki_link + +**Call:** +```json +{ + "tool": "insert_wiki_link", + "target": "Related Concepts", + "alias": "see also" +} +``` + +--- + +## Error Responses + +### Conflict Error + +```json +{ + "error": "CONFLICT", + "message": "Document revision changed from rev_a7b3c9 to rev_f1g2h3", + "currentRevision": "rev_f1g2h3" +} +``` + +**Action:** Re-read document, get new revision, retry. + +### Node Not Found + +```json +{ + "error": "NODE_NOT_FOUND", + "message": "Node node_999 does not exist", + "nodeId": "node_999" +} +``` + +**Action:** Re-query with `list_blocks` to find current node IDs. + +### Invalid Operation + +```json +{ + "error": "INVALID_OPERATION", + "message": "Cannot apply 'bold' mark to codeBlock node" +} +``` + +**Action:** Check node type before applying formatting. + +### Max Operations Exceeded + +```json +{ + "error": "LIMIT_EXCEEDED", + "message": "Maximum 100 operations per batch", + "limit": 100, + "requested": 150 +} +``` + +**Action:** Split into multiple batch_edit calls. diff --git a/plugins/vmark-mcp/skills/vmark-mcp/references/tools-by-intent.md b/plugins/vmark-mcp/skills/vmark-mcp/references/tools-by-intent.md new file mode 100644 index 0000000..6ef0bb1 --- /dev/null +++ b/plugins/vmark-mcp/skills/vmark-mcp/references/tools-by-intent.md @@ -0,0 +1,264 @@ +# VMark MCP Tools by Intent + +This reference organizes tools by **what you want to accomplish**, not by category. + +## Understanding the Document + +### "What's in this document?" + +| Tool | Returns | Use When | +|------|---------|----------| +| `get_document_digest` | Title, word count, outline, block counts, flags | First call to understand structure | +| `get_document_ast` | Full AST with projections | Need detailed structure | +| `document_get_content` | Raw markdown | Need exact source text | + +**Best practice:** Start with `get_document_digest`. Only use AST/content if you need more detail. + +### "Find specific content" + +| Tool | Capability | Parameters | +|------|------------|------------| +| `list_blocks` | Query by type, level, text content | `query: {type: "paragraph", contains: "keyword"}` | +| `document_search` | Find text with positions | `query: "search term"` | +| `resolve_targets` | Pre-flight check with confidence scores | `query: {...}` | + +**Best practice:** Use `list_blocks` to find nodeIds before editing. + +### "Read a specific section" + +| Tool | Capability | +|------|------------| +| `get_section` | Get heading + content until next equal/higher heading | + +``` +get_section(heading: "Introduction") +get_section(heading: {level: 2, index: 0}) // First H2 +``` + +--- + +## Making Content Changes + +### "Insert new content" + +| Tool | Where | Best For | +|------|-------|----------| +| `document_insert_at_cursor` | At cursor position | Continuing where writer left off | +| `batch_edit` with insert op | After specific node | Precise placement | +| `insert_section` | New section with heading | Adding new document section | + +**Always use `mode: "suggest"` for content insertion.** + +### "Update existing content" + +| Tool | Capability | Best For | +|------|------------|----------| +| `batch_edit` with update op | Change node text/attrs | Targeted node updates | +| `update_section` | Replace entire section content | Section rewrites | +| `apply_diff` | Find and replace | Pattern-based changes | +| `replace_text_anchored` | Context-aware replacement | Drift-tolerant edits | + +### "Delete content" + +| Tool | Capability | +|------|------------| +| `batch_edit` with delete op | Remove specific nodes | +| `selection_delete` | Delete current selection | + +### "Move content" + +| Tool | Capability | +|------|------------| +| `move_section` | Reorder sections by heading | +| `batch_edit` with move op | Move specific nodes | + +--- + +## Formatting + +### "Apply text formatting" + +| Tool | Marks Available | +|------|-----------------| +| `format_toggle` | bold, italic, code, strike, underline, highlight | +| `format_set_link` | Create hyperlink | +| `format_remove_link` | Remove hyperlink | +| `format_clear` | Remove all marks | + +``` +format_toggle(mark: "bold") // Toggle on selection +format_set_link(url: "https://...") +``` + +### "Change block type" + +| Tool | Block Types | +|------|-------------| +| `block_set_type` | paragraph, heading (with level), codeBlock, blockquote | +| `block_toggle` | Toggle between types | + +``` +block_set_type(type: "heading", attrs: {level: 2}) +block_set_type(type: "codeBlock", attrs: {language: "python"}) +``` + +--- + +## Lists + +| Intent | Tool | +|--------|------| +| Convert to list | `list_toggle(type: "bulletList")` | +| Change list type | `list_toggle(type: "orderedList")` | +| Create task list | `list_toggle(type: "taskList")` | +| Indent item | `list_indent` | +| Outdent item | `list_outdent` | +| Batch list operations | `list_modify` | + +--- + +## Tables + +| Intent | Tool | +|--------|------| +| Insert new table | `table_insert(rows: 3, cols: 3)` | +| Delete table | `table_delete` | +| Add row | `table_add_row(position: "after")` | +| Delete row | `table_delete_row` | +| Add column | `table_add_column(position: "after")` | +| Delete column | `table_delete_column` | +| Toggle header | `table_toggle_header_row` | +| Batch operations | `table_modify(operations: [...])` | + +**Best practice:** Use `table_modify` for multiple operations (atomic). + +--- + +## Special Content + +| Intent | Tool | +|--------|------| +| Inline math | `insert_math_inline(latex: "E = mc^2")` | +| Block math | `insert_math_block(latex: "\\int_0^\\infty...")` | +| Mermaid diagram | `insert_mermaid(code: "graph TD...")` | +| Wiki link | `insert_wiki_link(target: "Other Page")` | +| Horizontal rule | `block_insert_horizontal_rule` | + +--- + +## CJK (Chinese/Japanese/Korean) + +| Intent | Tool | +|--------|------| +| Convert punctuation | `cjk_punctuation_convert(direction: "toFullWidth")` | +| Fix CJK-Latin spacing | `cjk_spacing_fix` | + +--- + +## Cursor and Selection + +### "Where is the cursor?" + +| Tool | Returns | +|------|---------| +| `cursor_get_context` | Surrounding text, position, current block info | +| `selection_get` | Selection range, selected text, isEmpty | + +### "Move cursor/selection" + +| Tool | Capability | +|------|------------| +| `cursor_set_position(offset)` | Move cursor to character offset | +| `selection_set(from, to)` | Set selection range | + +### "Work with selection" + +| Tool | Capability | +|------|------------| +| `selection_replace(text)` | Replace selection with new text | +| `selection_delete` | Delete selection | + +--- + +## Suggestions (Pending Edits) + +| Intent | Tool | +|--------|------| +| List pending suggestions | `suggestion_list` | +| Accept one | `suggestion_accept(suggestionId)` | +| Reject one | `suggestion_reject(suggestionId)` | +| Accept all | `suggestion_accept_all` | +| Reject all | `suggestion_reject_all` | + +**Note:** When using `mode: "suggest"`, the mutation tool returns a `suggestionId`. + +--- + +## Editor State + +| Intent | Tool | +|--------|------| +| Undo | `editor_undo` | +| Redo | `editor_redo` | +| Focus editor | `editor_focus` | + +--- + +## Multi-Window / Multi-Tab + +### Window Operations + +| Intent | Tool | +|--------|------| +| List all windows | `workspace_list_windows` | +| Get focused window | `workspace_get_focused` | +| Focus a window | `workspace_focus_window(label)` | +| Close a window | `workspace_close_window(label)` | + +### Document Operations + +| Intent | Tool | +|--------|------| +| New document | `workspace_new_document` | +| Open document | `workspace_open_document(path)` | +| Save document | `workspace_save_document` | +| Save as | `workspace_save_document_as(path)` | +| Get document info | `workspace_get_document_info` | +| Recent files | `workspace_list_recent_files` | + +### Tab Operations + +| Intent | Tool | +|--------|------| +| List tabs | `tabs_list` | +| Get active tab | `tabs_get_active` | +| Switch tab | `tabs_switch(tabId)` | +| Close tab | `tabs_close(tabId)` | +| Create tab | `tabs_create` | +| Reopen closed | `tabs_reopen_closed` | + +--- + +## Protocol / Meta + +| Intent | Tool | +|--------|------| +| Check capabilities | `get_capabilities` | +| Get current revision | `get_document_revision` | + +--- + +## Operation Modes + +Most mutation tools support three modes: + +| Mode | Behavior | +|------|----------| +| `apply` | Execute immediately (default for formatting) | +| `suggest` | Create suggestion for user approval (default for content) | +| `dryRun` | Preview without making changes | + +**Rule of thumb:** +- Content changes → `suggest` +- Formatting/structure → `apply` (instant feedback expected) +- Uncertain about targets → `dryRun` first diff --git a/plugins/vmark-mcp/skills/vmark-mcp/references/workflows.md b/plugins/vmark-mcp/skills/vmark-mcp/references/workflows.md new file mode 100644 index 0000000..468c9a6 --- /dev/null +++ b/plugins/vmark-mcp/skills/vmark-mcp/references/workflows.md @@ -0,0 +1,506 @@ +# VMark MCP Workflows + +Detailed step-by-step patterns for common writing tasks. + +--- + +## Workflow 1: AI Writing Partner + +**Scenario:** Writer has a partial thought, wants AI to continue. + +### Steps + +``` +1. READ CONTEXT + ┌─────────────────────────────────────────────────────┐ + │ cursor_get_context(charsBefore: 500, charsAfter: 100) + │ │ + │ Returns: { before: "...", after: "...", │ + │ currentBlock: {...}, position: 1234 } │ + └─────────────────────────────────────────────────────┘ + +2. UNDERSTAND DOCUMENT STRUCTURE (if needed) + ┌─────────────────────────────────────────────────────┐ + │ get_document_digest │ + │ │ + │ Returns: { title, wordCount, outline: [...], │ + │ blockCounts: {paragraph: 12, ...} } │ + └─────────────────────────────────────────────────────┘ + +3. GENERATE CONTINUATION + ┌─────────────────────────────────────────────────────┐ + │ (AI reasoning based on context) │ + │ - Match tone and style of existing text │ + │ - Consider document structure from digest │ + │ - Generate appropriate continuation │ + └─────────────────────────────────────────────────────┘ + +4. INSERT AS SUGGESTION + ┌─────────────────────────────────────────────────────┐ + │ document_insert_at_cursor( │ + │ text: "...generated content...", │ + │ mode: "suggest" │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +5. COMMUNICATE TO WRITER + ┌─────────────────────────────────────────────────────┐ + │ "I've suggested a continuation that [brief desc]. │ + │ Press Tab to accept or Escape to reject. │ + │ Want me to try a different approach?" │ + └─────────────────────────────────────────────────────┘ +``` + +### Variations + +**Continue with specific direction:** +- Writer says "continue, but make it more technical" +- AI adjusts tone in generated content + +**Continue at specific location:** +- Use `cursor_set_position` first if cursor isn't at right place +- Or use `batch_edit` with insert operation targeting specific nodeId + +--- + +## Workflow 2: Improve a Section + +**Scenario:** Writer wants a specific section refined. + +### Steps + +``` +1. GET DOCUMENT STRUCTURE + ┌─────────────────────────────────────────────────────┐ + │ get_document_digest │ + │ │ + │ Look at outline to confirm section exists │ + └─────────────────────────────────────────────────────┘ + +2. READ THE SECTION + ┌─────────────────────────────────────────────────────┐ + │ get_section(heading: "Introduction") │ + │ │ + │ Returns: { heading: {...}, content: [...], │ + │ markdown: "...", wordCount: 234 } │ + └─────────────────────────────────────────────────────┘ + +3. ANALYZE AND IMPROVE + ┌─────────────────────────────────────────────────────┐ + │ (AI reasoning) │ + │ - Identify issues: wordiness, unclear points, etc. │ + │ - Draft improved version │ + │ - Preserve writer's voice │ + └─────────────────────────────────────────────────────┘ + +4. PROPOSE REPLACEMENT + ┌─────────────────────────────────────────────────────┐ + │ update_section( │ + │ heading: "Introduction", │ + │ content: "...improved markdown...", │ + │ mode: "suggest" │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +5. EXPLAIN CHANGES + ┌─────────────────────────────────────────────────────┐ + │ "I've suggested improvements to the Introduction: │ + │ - Tightened the opening paragraph │ + │ - Clarified the thesis statement │ + │ - Removed redundant phrases │ + │ │ + │ Review the highlighted suggestion to accept." │ + └─────────────────────────────────────────────────────┘ +``` + +### Handling Large Sections + +For sections with many paragraphs, consider: + +1. **Preview first:** `update_section(..., mode: "dryRun")` +2. **Split if needed:** Multiple `batch_edit` calls targeting specific paragraphs +3. **Max 100 operations per batch** + +--- + +## Workflow 3: Reorganize Document + +**Scenario:** Writer wants to reorder sections. + +### Steps + +``` +1. GET CURRENT STRUCTURE + ┌─────────────────────────────────────────────────────┐ + │ get_document_digest │ + │ │ + │ outline: [ │ + │ { level: 1, text: "Title" }, │ + │ { level: 2, text: "Introduction" }, │ + │ { level: 2, text: "Methods" }, │ + │ { level: 2, text: "Results" }, │ + │ { level: 2, text: "Conclusion" } │ + │ ] │ + └─────────────────────────────────────────────────────┘ + +2. CONFIRM MOVE WITH WRITER + ┌─────────────────────────────────────────────────────┐ + │ "I see the current order is: │ + │ 1. Introduction │ + │ 2. Methods │ + │ 3. Results │ + │ 4. Conclusion │ + │ │ + │ You want to move 'Conclusion' before 'Methods'?" │ + └─────────────────────────────────────────────────────┘ + +3. EXECUTE MOVE + ┌─────────────────────────────────────────────────────┐ + │ move_section( │ + │ heading: "Conclusion", │ + │ before: "Methods" │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +4. CONFIRM NEW STRUCTURE + ┌─────────────────────────────────────────────────────┐ + │ get_document_digest │ + │ │ + │ "Done. New order: │ + │ 1. Introduction │ + │ 2. Conclusion │ + │ 3. Methods │ + │ 4. Results" │ + └─────────────────────────────────────────────────────┘ +``` + +--- + +## Workflow 4: Find and Replace + +**Scenario:** Writer wants to change a term throughout the document. + +### Steps + +``` +1. GET REVISION + ┌─────────────────────────────────────────────────────┐ + │ get_document_revision │ + │ │ + │ Returns: { revision: "rev_abc123" } │ + └─────────────────────────────────────────────────────┘ + +2. PREVIEW MATCHES + ┌─────────────────────────────────────────────────────┐ + │ apply_diff( │ + │ baseRevision: "rev_abc123", │ + │ original: "machine learning", │ + │ replacement: "ML", │ + │ matchPolicy: "error_if_multiple", │ + │ mode: "dryRun" │ + │ ) │ + │ │ + │ Returns: { matchCount: 7, matches: [...] } │ + └─────────────────────────────────────────────────────┘ + +3. CONFIRM WITH WRITER + ┌─────────────────────────────────────────────────────┐ + │ "Found 7 occurrences of 'machine learning'. │ + │ Replace all with 'ML'?" │ + └─────────────────────────────────────────────────────┘ + +4. EXECUTE REPLACEMENT + ┌─────────────────────────────────────────────────────┐ + │ apply_diff( │ + │ baseRevision: "rev_abc123", │ + │ original: "machine learning", │ + │ replacement: "ML", │ + │ matchPolicy: "all", │ + │ mode: "suggest" │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +5. REPORT + ┌─────────────────────────────────────────────────────┐ + │ "Created 7 suggestions. Review and accept each, │ + │ or use 'accept all' to apply them at once." │ + └─────────────────────────────────────────────────────┘ +``` + +### Match Policy Options + +| Policy | Use When | +|--------|----------| +| `first` | Only want the first occurrence | +| `all` | Replace every match | +| `nth` | Replace specific occurrence (0-indexed) | +| `error_if_multiple` | Need to disambiguate before replacing | + +--- + +## Workflow 5: Convert Notes to Prose + +**Scenario:** Writer has bullet points, wants them as paragraphs. + +### Steps + +``` +1. FIND THE BULLET LIST + ┌─────────────────────────────────────────────────────┐ + │ list_blocks(query: { type: "bulletList" }) │ + │ │ + │ Returns: [{ id: "node_456", text: "- Point one..." }] + └─────────────────────────────────────────────────────┘ + +2. GET FULL CONTENT + ┌─────────────────────────────────────────────────────┐ + │ get_document_ast( │ + │ filter: { type: "bulletList" }, │ + │ projection: ["id", "text", "children"] │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +3. TRANSFORM TO PROSE + ┌─────────────────────────────────────────────────────┐ + │ (AI reasoning) │ + │ - Understand relationships between points │ + │ - Create flowing paragraphs │ + │ - Add transitions │ + └─────────────────────────────────────────────────────┘ + +4. REPLACE LIST WITH PARAGRAPHS + ┌─────────────────────────────────────────────────────┐ + │ batch_edit( │ + │ baseRevision: "...", │ + │ mode: "suggest", │ + │ operations: [ │ + │ { type: "delete", nodeId: "node_456" }, │ + │ { type: "insert", after: "node_455", │ + │ content: "...prose paragraphs..." } │ + │ ] │ + │ ) │ + └─────────────────────────────────────────────────────┘ +``` + +--- + +## Workflow 6: Multi-Document Reference + +**Scenario:** Writer needs to reference content from another open document. + +### Steps + +``` +1. LIST AVAILABLE DOCUMENTS + ┌─────────────────────────────────────────────────────┐ + │ tabs_list │ + │ │ + │ Returns: [ │ + │ { id: "tab_1", title: "Draft.md", active: true }, │ + │ { id: "tab_2", title: "Notes.md", active: false } │ + │ ] │ + └─────────────────────────────────────────────────────┘ + +2. REMEMBER CURRENT POSITION + ┌─────────────────────────────────────────────────────┐ + │ activeTab = "tab_1" │ + └─────────────────────────────────────────────────────┘ + +3. SWITCH TO SOURCE DOCUMENT + ┌─────────────────────────────────────────────────────┐ + │ tabs_switch(tabId: "tab_2") │ + └─────────────────────────────────────────────────────┘ + +4. READ FROM SOURCE + ┌─────────────────────────────────────────────────────┐ + │ get_section(heading: "Key Points") │ + └─────────────────────────────────────────────────────┘ + +5. SWITCH BACK + ┌─────────────────────────────────────────────────────┐ + │ tabs_switch(tabId: "tab_1") │ + └─────────────────────────────────────────────────────┘ + +6. INSERT REFERENCE + ┌─────────────────────────────────────────────────────┐ + │ document_insert_at_cursor( │ + │ text: "...content from notes...", │ + │ mode: "suggest" │ + │ ) │ + └─────────────────────────────────────────────────────┘ +``` + +--- + +## Workflow 7: Format Cleanup + +**Scenario:** Writer wants consistent formatting applied. + +### Steps + +``` +1. FIND CONTENT TO FORMAT + ┌─────────────────────────────────────────────────────┐ + │ list_blocks(query: { contains: "important" }) │ + │ │ + │ Returns: [ │ + │ { id: "node_101", text: "This is important..." }, │ + │ { id: "node_205", text: "Another important..." } │ + │ ] │ + └─────────────────────────────────────────────────────┘ + +2. BATCH APPLY FORMATTING + ┌─────────────────────────────────────────────────────┐ + │ batch_edit( │ + │ baseRevision: "...", │ + │ mode: "apply", // Formatting is immediate │ + │ operations: [ │ + │ { type: "format", nodeId: "node_101", │ + │ marks: [{ type: "bold" }] }, │ + │ { type: "format", nodeId: "node_205", │ + │ marks: [{ type: "bold" }] } │ + │ ] │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +3. CONFIRM + ┌─────────────────────────────────────────────────────┐ + │ "Applied bold formatting to 2 paragraphs │ + │ containing 'important'." │ + └─────────────────────────────────────────────────────┘ +``` + +--- + +## Workflow 8: Handling Conflicts + +**Scenario:** Document changed while AI was processing. + +### Detection + +``` +batch_edit(...) returns: +{ + "error": "CONFLICT", + "message": "Document revision changed from rev_abc to rev_xyz" +} +``` + +### Recovery Steps + +``` +1. ACKNOWLEDGE + ┌─────────────────────────────────────────────────────┐ + │ "The document changed while I was working. │ + │ Let me re-read and update my suggestion." │ + └─────────────────────────────────────────────────────┘ + +2. RE-READ + ┌─────────────────────────────────────────────────────┐ + │ get_document_digest // or get_section if targeted │ + │ get_document_revision → "rev_xyz" │ + └─────────────────────────────────────────────────────┘ + +3. RE-ANALYZE + ┌─────────────────────────────────────────────────────┐ + │ (AI re-examines content with fresh state) │ + │ - Check if original target still exists │ + │ - Adjust suggestion if content changed │ + └─────────────────────────────────────────────────────┘ + +4. RE-PROPOSE + ┌─────────────────────────────────────────────────────┐ + │ batch_edit( │ + │ baseRevision: "rev_xyz", // New revision │ + │ ... │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +5. COMMUNICATE + ┌─────────────────────────────────────────────────────┐ + │ "Updated my suggestion based on your recent edits." │ + └─────────────────────────────────────────────────────┘ +``` + +--- + +## Workflow 9: Creating Tables + +**Scenario:** Writer wants to create or modify a table. + +### Creating a New Table + +``` +1. INSERT TABLE + ┌─────────────────────────────────────────────────────┐ + │ table_insert(rows: 3, cols: 4) │ + └─────────────────────────────────────────────────────┘ + +2. POPULATE WITH CONTENT + ┌─────────────────────────────────────────────────────┐ + │ table_modify( │ + │ operations: [ │ + │ { type: "updateCell", row: 0, col: 0, │ + │ content: "Header 1" }, │ + │ { type: "updateCell", row: 0, col: 1, │ + │ content: "Header 2" }, │ + │ // ... more cells │ + │ ] │ + │ ) │ + └─────────────────────────────────────────────────────┘ + +3. SET HEADER ROW + ┌─────────────────────────────────────────────────────┐ + │ table_toggle_header_row │ + └─────────────────────────────────────────────────────┘ +``` + +### Modifying Existing Table + +``` +table_modify( + operations: [ + { type: "addRow", position: "after", rowIndex: 2 }, + { type: "updateCell", row: 3, col: 0, content: "New data" }, + { type: "deleteColumn", colIndex: 4 } + ] +) +``` + +--- + +## Anti-Patterns to Avoid + +### Don't: Edit without reading first + +``` +❌ batch_edit(operations: [...]) // Where does this go? + +✓ get_document_digest // Understand structure +✓ list_blocks(...) // Find target +✓ batch_edit(operations: [...]) // Now edit +``` + +### Don't: Use apply mode for content changes + +``` +❌ batch_edit(mode: "apply", operations: [{type: "update", ...}]) + +✓ batch_edit(mode: "suggest", operations: [{type: "update", ...}]) +``` + +### Don't: Assume suggestions are accepted + +``` +❌ "I've made the changes to your document." + +✓ "I've suggested changes. Review the highlights to accept or reject." +``` + +### Don't: Ignore conflicts + +``` +❌ (Conflict error) → Retry immediately with same content + +✓ (Conflict error) → Re-read → Re-analyze → Re-propose +```