@usejunior/docx-mcp 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +46 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/cli/commands/edit.d.ts.map +1 -1
  4. package/dist/cli/commands/edit.js +2 -1
  5. package/dist/cli/commands/edit.js.map +1 -1
  6. package/dist/cli/commands/grep.d.ts.map +1 -1
  7. package/dist/cli/commands/grep.js +2 -1
  8. package/dist/cli/commands/grep.js.map +1 -1
  9. package/dist/cli/tool_runner.d.ts +6 -0
  10. package/dist/cli/tool_runner.d.ts.map +1 -1
  11. package/dist/cli/tool_runner.js +10 -1
  12. package/dist/cli/tool_runner.js.map +1 -1
  13. package/dist/odf_loader.d.ts +2 -0
  14. package/dist/odf_loader.d.ts.map +1 -0
  15. package/dist/odf_loader.js +19 -0
  16. package/dist/odf_loader.js.map +1 -0
  17. package/dist/server.d.ts +5 -2
  18. package/dist/server.d.ts.map +1 -1
  19. package/dist/server.js +110 -4
  20. package/dist/server.js.map +1 -1
  21. package/dist/session/manager.d.ts +44 -2
  22. package/dist/session/manager.d.ts.map +1 -1
  23. package/dist/session/manager.js +212 -2
  24. package/dist/session/manager.js.map +1 -1
  25. package/dist/tool_catalog.d.ts +40 -12
  26. package/dist/tool_catalog.d.ts.map +1 -1
  27. package/dist/tool_catalog.js +49 -17
  28. package/dist/tool_catalog.js.map +1 -1
  29. package/dist/tools/accept_changes.js +1 -1
  30. package/dist/tools/accept_changes.js.map +1 -1
  31. package/dist/tools/add_comment.d.ts.map +1 -1
  32. package/dist/tools/add_comment.js +4 -2
  33. package/dist/tools/add_comment.js.map +1 -1
  34. package/dist/tools/add_footnote.d.ts.map +1 -1
  35. package/dist/tools/add_footnote.js +3 -1
  36. package/dist/tools/add_footnote.js.map +1 -1
  37. package/dist/tools/apply_plan.d.ts.map +1 -1
  38. package/dist/tools/apply_plan.js +6 -4
  39. package/dist/tools/apply_plan.js.map +1 -1
  40. package/dist/tools/clear_formatting.d.ts +2 -1
  41. package/dist/tools/clear_formatting.d.ts.map +1 -1
  42. package/dist/tools/clear_formatting.js +62 -49
  43. package/dist/tools/clear_formatting.js.map +1 -1
  44. package/dist/tools/compare_documents.d.ts.map +1 -1
  45. package/dist/tools/compare_documents.js +11 -2
  46. package/dist/tools/compare_documents.js.map +1 -1
  47. package/dist/tools/delete_comment.d.ts.map +1 -1
  48. package/dist/tools/delete_comment.js +3 -1
  49. package/dist/tools/delete_comment.js.map +1 -1
  50. package/dist/tools/delete_footnote.d.ts.map +1 -1
  51. package/dist/tools/delete_footnote.js +3 -1
  52. package/dist/tools/delete_footnote.js.map +1 -1
  53. package/dist/tools/export.d.ts +20 -0
  54. package/dist/tools/export.d.ts.map +1 -0
  55. package/dist/tools/export.js +96 -0
  56. package/dist/tools/export.js.map +1 -0
  57. package/dist/tools/format_layout.d.ts.map +1 -1
  58. package/dist/tools/format_layout.js +5 -3
  59. package/dist/tools/format_layout.js.map +1 -1
  60. package/dist/tools/grep.d.ts.map +1 -1
  61. package/dist/tools/grep.js +4 -115
  62. package/dist/tools/grep.js.map +1 -1
  63. package/dist/tools/grep_core.d.ts +49 -0
  64. package/dist/tools/grep_core.d.ts.map +1 -0
  65. package/dist/tools/grep_core.js +126 -0
  66. package/dist/tools/grep_core.js.map +1 -0
  67. package/dist/tools/insert_paragraph.d.ts +2 -1
  68. package/dist/tools/insert_paragraph.d.ts.map +1 -1
  69. package/dist/tools/insert_paragraph.js +4 -2
  70. package/dist/tools/insert_paragraph.js.map +1 -1
  71. package/dist/tools/odf/add_comment.d.ts +21 -0
  72. package/dist/tools/odf/add_comment.d.ts.map +1 -0
  73. package/dist/tools/odf/add_comment.js +64 -0
  74. package/dist/tools/odf/add_comment.js.map +1 -0
  75. package/dist/tools/odf/close_file.d.ts +4 -0
  76. package/dist/tools/odf/close_file.d.ts.map +1 -0
  77. package/dist/tools/odf/close_file.js +16 -0
  78. package/dist/tools/odf/close_file.js.map +1 -0
  79. package/dist/tools/odf/compare_documents.d.ts +39 -0
  80. package/dist/tools/odf/compare_documents.d.ts.map +1 -0
  81. package/dist/tools/odf/compare_documents.js +156 -0
  82. package/dist/tools/odf/compare_documents.js.map +1 -0
  83. package/dist/tools/odf/get_comments.d.ts +11 -0
  84. package/dist/tools/odf/get_comments.d.ts.map +1 -0
  85. package/dist/tools/odf/get_comments.js +32 -0
  86. package/dist/tools/odf/get_comments.js.map +1 -0
  87. package/dist/tools/odf/get_file_status.d.ts +4 -0
  88. package/dist/tools/odf/get_file_status.d.ts.map +1 -0
  89. package/dist/tools/odf/get_file_status.js +28 -0
  90. package/dist/tools/odf/get_file_status.js.map +1 -0
  91. package/dist/tools/odf/grep.d.ts +19 -0
  92. package/dist/tools/odf/grep.d.ts.map +1 -0
  93. package/dist/tools/odf/grep.js +81 -0
  94. package/dist/tools/odf/grep.js.map +1 -0
  95. package/dist/tools/odf/insert_paragraph.d.ts +19 -0
  96. package/dist/tools/odf/insert_paragraph.d.ts.map +1 -0
  97. package/dist/tools/odf/insert_paragraph.js +50 -0
  98. package/dist/tools/odf/insert_paragraph.js.map +1 -0
  99. package/dist/tools/odf/read_file.d.ts +9 -0
  100. package/dist/tools/odf/read_file.d.ts.map +1 -0
  101. package/dist/tools/odf/read_file.js +124 -0
  102. package/dist/tools/odf/read_file.js.map +1 -0
  103. package/dist/tools/odf/replace_text.d.ts +9 -0
  104. package/dist/tools/odf/replace_text.d.ts.map +1 -0
  105. package/dist/tools/odf/replace_text.js +41 -0
  106. package/dist/tools/odf/replace_text.js.map +1 -0
  107. package/dist/tools/odf/save.d.ts +7 -0
  108. package/dist/tools/odf/save.d.ts.map +1 -0
  109. package/dist/tools/odf/save.js +48 -0
  110. package/dist/tools/odf/save.js.map +1 -0
  111. package/dist/tools/open_document.d.ts.map +1 -1
  112. package/dist/tools/open_document.js +36 -4
  113. package/dist/tools/open_document.js.map +1 -1
  114. package/dist/tools/path_policy.d.ts +9 -0
  115. package/dist/tools/path_policy.d.ts.map +1 -1
  116. package/dist/tools/path_policy.js +66 -5
  117. package/dist/tools/path_policy.js.map +1 -1
  118. package/dist/tools/provider_guard.d.ts +1 -0
  119. package/dist/tools/provider_guard.d.ts.map +1 -1
  120. package/dist/tools/provider_guard.js +10 -0
  121. package/dist/tools/provider_guard.js.map +1 -1
  122. package/dist/tools/read_file.d.ts +2 -0
  123. package/dist/tools/read_file.d.ts.map +1 -1
  124. package/dist/tools/read_file.js +370 -31
  125. package/dist/tools/read_file.js.map +1 -1
  126. package/dist/tools/replace_text.d.ts +2 -1
  127. package/dist/tools/replace_text.d.ts.map +1 -1
  128. package/dist/tools/replace_text.js +26 -5
  129. package/dist/tools/replace_text.js.map +1 -1
  130. package/dist/tools/save.d.ts.map +1 -1
  131. package/dist/tools/save.js +55 -8
  132. package/dist/tools/save.js.map +1 -1
  133. package/dist/tools/session_resolution.d.ts +25 -1
  134. package/dist/tools/session_resolution.d.ts.map +1 -1
  135. package/dist/tools/session_resolution.js +179 -2
  136. package/dist/tools/session_resolution.js.map +1 -1
  137. package/dist/tools/tag_parser.d.ts.map +1 -1
  138. package/dist/tools/tag_parser.js +69 -14
  139. package/dist/tools/tag_parser.js.map +1 -1
  140. package/dist/tools/update_footnote.d.ts.map +1 -1
  141. package/dist/tools/update_footnote.js +3 -1
  142. package/dist/tools/update_footnote.js.map +1 -1
  143. package/package.json +18 -14
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  **Install via the canonical package:** `npx -y @usejunior/safe-docx` — [see setup guide](../../README.md)
8
8
 
9
- Local MCP server for surgical editing of existing Microsoft Word `.docx` files with coding agents.
9
+ Local MCP server for surgical editing of existing Microsoft Word `.docx` files with coding agents. The same tool surface also services OpenDocument `.odt` files — including `compare_documents` redlines (two files, or a live session against its original) written as native ODF tracked changes with inline (run-level) granularity.
10
10
 
11
11
  Safe Docx is built for brownfield paperwork workflows: apply accepted AI edits to real Word documents while preserving formatting and review semantics.
12
12
 
@@ -49,6 +49,26 @@ Add to your MCP client:
49
49
  - Comments/Footnotes: `add_comment`, `get_comments`, `delete_comment`, `get_footnotes`, `add_footnote`, `update_footnote`, `delete_footnote`
50
50
  - Session/Safety: `clear_session`, path-policy + archive guardrails
51
51
 
52
+ ## Heading detection in `read_file(format="json")`
53
+
54
+ Each paragraph node in the JSON output may expose a top-level `heading` object:
55
+
56
+ ```ts
57
+ heading?: {
58
+ text: string;
59
+ source: 'word_style' | 'run_in_header' | 'title_with_period' | 'title_with_colon' | 'title_caps_centered' | 'title_bare';
60
+ level: number | null;
61
+ }
62
+ ```
63
+
64
+ Use `node.heading != null` as the canonical heading check.
65
+
66
+ - `source: 'word_style'` wins whenever `paragraph_style_id` matches `/^Heading([1-6])$/` exactly, and only then. Inherited styles like `HeadingPara1` do not count.
67
+ - Heuristic sources (`run_in_header`, `title_with_period`, `title_with_colon`, `title_caps_centered`, `title_bare`) always emit `level: null`.
68
+ - Body paragraphs omit the `heading` key entirely.
69
+
70
+ `list_metadata.header_style` remains the per-detector explanation layer, not the canonical "is heading" predicate. See [`skills/docx-editing/SKILL.md`](../../skills/docx-editing/SKILL.md) for the full precedence rule and the Google Docs asymmetry: the GDocs path only emits `heading` for built-in heading styles and does not run the Word heuristics.
71
+
52
72
  ## Document Families
53
73
 
54
74
  ### Automated fixture coverage in this repo
@@ -157,6 +177,31 @@ No native binaries and no .NET prerequisite for supported runtime usage. Safe Do
157
177
 
158
178
  If you need direct library imports in app code, use `@usejunior/docx-core`.
159
179
 
180
+ ## Paragraph Identity
181
+
182
+ `read_file` returns paragraphs with `id` fields like `_bk_a3f29c10b8e4`. These identifiers are **deterministic and stable**, not session-scoped.
183
+
184
+ | Field | Role | Editable anchor? | Stability |
185
+ |-------|------|------------------|-----------|
186
+ | `id` (`_bk_<12hex>`) | Canonical edit anchor — only thing edit tools accept | ✅ | Byte-identical across reopens, machines, and processes for **identical stored DOCX/OOXML bytes**. Intrinsic branch (Word 2010+ `w14:paraId`) is robust to text edits; fallback branch changes when paragraph or neighbor text changes. |
187
+ | `content_fingerprint` (opt-in) | Portable normalized-text hash for citation/reconciliation systems | ❌ — read-only metadata | Same normalized text → same hash on any machine. Changes when normalized text changes. **Not unique per paragraph** — two paragraphs with identical normalized text fingerprint identically. |
188
+
189
+ Consumers MAY persist `_bk_*` identifiers in indexes, citation databases, and other external stores keyed off the same source document.
190
+
191
+ For citation systems that want a portable hash whose canonicalization is documented and recomputable independent of safe-docx internals, pass `include_fingerprint: true` to `read_file` with `format: "json"`:
192
+
193
+ ```jsonc
194
+ {
195
+ "id": "_bk_a3f29c10b8e4",
196
+ "content_fingerprint": "sha256:nfkc:5d2e8f1a4c5b7d2e8f1a4c5b7d2e8f1a",
197
+ "clean_text": "The Company shall indemnify the Customer."
198
+ }
199
+ ```
200
+
201
+ The fingerprint is computed as `"sha256:nfkc:" + sha256( stripCfInvisibles(NFKC(visibleText)).replace(/\s+/g, " ").trim() )`, truncated to 32 hex chars. Case is preserved; curly quotes and dashes are NOT folded to ASCII. Cf-category invisibles (soft hyphen, ZWJ/ZWNJ, LRM/RLM, bidi controls, variation selectors, BOM) are stripped so byte-level round-trip noise does not change the hash. The flag has no effect on `format: "toon"` or `format: "simple"`, and is silently ignored for Google Docs sessions.
202
+
203
+ `content_fingerprint` is a content hash, not a paragraph key. Paragraphs with identical normalized visible text produce identical fingerprints by design; use `_bk_*` IDs whenever you need per-paragraph identity. Edit tools (`replace_text`, `insert_paragraph`, `apply_plan`, etc.) accept ONLY `_bk_*` IDs as anchors — `content_fingerprint` is never an edit anchor. The `sha256:nfkc:` prefix is intentional version reservation; future algorithm bumps will emit a different prefix (e.g. `sha256:nfkc-strip:`), so consumers should store and compare the full prefixed string.
204
+
160
205
  ## Reliability and Evidence
161
206
 
162
207
  - Tool catalog source: `packages/docx-mcp/src/tool_catalog.ts`