@tiwater/office-mcp 0.21.21 → 0.21.27
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.
- package/office/contracts/docx_fill_table_from_tables.schema.json +2 -1
- package/office/contracts/docx_replace_content_from_source.schema.json +3 -3
- package/office/contracts/docx_set_paragraph_pagination.schema.json +36 -0
- package/office/contracts/docx_set_table_body.schema.json +8 -1
- package/office/contracts/docx_table_index.schema.json +0 -6
- package/office/contracts/tiwater-office-provider-contract-manifest-v1.json +20 -9
- package/office/docx-object-identity.mjs +11 -0
- package/office/index.mjs +31 -46
- package/package.json +2 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "tiwater.office-mcp-input/docx_fill_table_from_tables",
|
|
4
|
+
"description": "Project source-table rows into one target template table atomically. Use this instead of manually rebuilding rows when target cells derive from source tables. Target formatting is reused, and native vertical-merge owners are preserved within each source range.",
|
|
4
5
|
"type": "object",
|
|
5
6
|
"properties": {
|
|
6
7
|
"input": { "type": "string", "minLength": 1, "description": "Current target DOCX.", "x-tiwater-file-role": "read" },
|
|
@@ -96,7 +97,7 @@
|
|
|
96
97
|
},
|
|
97
98
|
"recordColumn": {
|
|
98
99
|
"type": "object",
|
|
99
|
-
"description": "Source grid-column address
|
|
100
|
+
"description": "Source grid-column address that defines output-row records. Choose an unmerged column when every physical source row must remain an output row; vertical merges in other mapped columns are still preserved. Choose a merged column only when every mapping into one target cell has one equal scalar value throughout that merge group.",
|
|
100
101
|
"properties": {
|
|
101
102
|
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
102
103
|
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
"sourceSelections": {
|
|
45
45
|
"minItems": 1,
|
|
46
46
|
"type": "array",
|
|
47
|
-
"description": "Ordered native source paragraphs, runs, or text nodes.
|
|
47
|
+
"description": "Ordered native source cells, paragraphs, runs, or text nodes. Consecutive run or text selections from one source paragraph form one target paragraph; a range retains the native runs it crosses. A source paragraph boundary remains a target paragraph boundary. Selected content becomes the target content without Agent transcription.",
|
|
48
48
|
"items": {
|
|
49
49
|
"type": "object",
|
|
50
50
|
"properties": {
|
|
51
51
|
"address": {
|
|
52
52
|
"type": "object",
|
|
53
|
-
"description": "Native source object address returned by docx_read_object or docx_read_table. Selecting a paragraph copies that paragraph's inline content; selecting a cell copies its direct paragraphs.",
|
|
53
|
+
"description": "Native source object address returned by docx_read_object or docx_read_table. Selecting a paragraph copies that paragraph's inline content; selecting a cell copies its direct paragraphs; selecting a run or text copies native inline content and formatting.",
|
|
54
54
|
"properties": {
|
|
55
55
|
"part": {
|
|
56
56
|
"type": "string",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
},
|
|
71
71
|
"range": {
|
|
72
72
|
"type": "object",
|
|
73
|
-
"description": "Optional Unicode-scalar substring of
|
|
73
|
+
"description": "Optional Unicode-scalar substring of the selected object's observed text. For a cell, offsets use its docx_read_table text with one newline between direct paragraphs. The selected native runs and paragraph boundaries are retained. Omit it to copy the complete selected object.",
|
|
74
74
|
"properties": {
|
|
75
75
|
"start": {
|
|
76
76
|
"type": "integer",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "tiwater.office-mcp-input/docx_set_paragraph_pagination",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"input": { "type": "string", "minLength": 1, "x-tiwater-file-role": "read" },
|
|
7
|
+
"changes": {
|
|
8
|
+
"type": "array",
|
|
9
|
+
"minItems": 1,
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"paragraph": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
17
|
+
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
18
|
+
},
|
|
19
|
+
"required": ["part", "path"],
|
|
20
|
+
"additionalProperties": false
|
|
21
|
+
},
|
|
22
|
+
"keepWithNext": { "type": "boolean", "description": "Keep this paragraph on the same page as the immediately following paragraph or table. This does not guarantee that a table header remains with its first body row." },
|
|
23
|
+
"keepLinesTogether": { "type": "boolean", "description": "Keep all lines of this paragraph on one page." },
|
|
24
|
+
"pageBreakBefore": { "type": "boolean", "description": "Start this paragraph on a new page." },
|
|
25
|
+
"preventWidowOrphanLines": { "type": "boolean", "description": "Prevent a single first or last line from being isolated across pages." }
|
|
26
|
+
},
|
|
27
|
+
"required": ["paragraph"],
|
|
28
|
+
"additionalProperties": false
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"output": { "type": "string", "minLength": 1, "description": "Output DOCX path; may equal input for one atomic in-place update.", "x-tiwater-file-role": "write" },
|
|
32
|
+
"receiptOutput": { "type": "string", "minLength": 1, "x-tiwater-file-role": "write", "x-tiwater-file-effect": false }
|
|
33
|
+
},
|
|
34
|
+
"required": ["input", "changes", "output", "receiptOutput"],
|
|
35
|
+
"additionalProperties": false
|
|
36
|
+
}
|
|
@@ -94,7 +94,10 @@
|
|
|
94
94
|
"description": "One or more contiguous request-local column IDs occupied by this cell.",
|
|
95
95
|
"items": { "type": "string", "minLength": 1, "maxLength": 80 }
|
|
96
96
|
},
|
|
97
|
-
"text": {
|
|
97
|
+
"text": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"description": "Final plain text for this cell. If the current cell at the same row and grid span already has exactly this text, its native paragraphs and run formatting are retained while row and merge properties are updated."
|
|
100
|
+
},
|
|
98
101
|
"rowSpan": {
|
|
99
102
|
"type": "integer",
|
|
100
103
|
"minimum": 1,
|
|
@@ -105,6 +108,10 @@
|
|
|
105
108
|
"required": ["columns", "text"],
|
|
106
109
|
"additionalProperties": false
|
|
107
110
|
}
|
|
111
|
+
},
|
|
112
|
+
"cantSplit": {
|
|
113
|
+
"type": "boolean",
|
|
114
|
+
"description": "Whether Word may split this physical row across pages. Omit to preserve the prototype row property."
|
|
108
115
|
}
|
|
109
116
|
},
|
|
110
117
|
"required": ["prototypeRow", "cells"],
|
|
@@ -19,12 +19,6 @@
|
|
|
19
19
|
"description": "Optional new JSON artifact path for retaining the complete table index. May be combined with returnContent.",
|
|
20
20
|
"x-tiwater-file-role": "write"
|
|
21
21
|
},
|
|
22
|
-
"limit": {
|
|
23
|
-
"type": "integer",
|
|
24
|
-
"minimum": 1,
|
|
25
|
-
"maximum": 1000,
|
|
26
|
-
"description": "Maximum number of table summaries requested in this response page. The provider may return fewer to keep the machine response bounded."
|
|
27
|
-
},
|
|
28
22
|
"offset": {
|
|
29
23
|
"type": "integer",
|
|
30
24
|
"minimum": 0,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema": "tiwater.office-provider-contract-manifest/v1",
|
|
3
3
|
"provider": {
|
|
4
4
|
"id": "@tiwater/office-mcp",
|
|
5
|
-
"version": "0.21.
|
|
5
|
+
"version": "0.21.27"
|
|
6
6
|
},
|
|
7
7
|
"tools": [
|
|
8
8
|
{
|
|
@@ -75,11 +75,11 @@
|
|
|
75
75
|
"name": "docx_fill_table_from_tables",
|
|
76
76
|
"providerContract": {
|
|
77
77
|
"source": "packages/docx-cli/contracts/mcp-input/docx_fill_table_from_tables.schema.json",
|
|
78
|
-
"sha256": "
|
|
78
|
+
"sha256": "4e80fff1c08fd16f8a5b4c638cf6469aa51e3a499743b44f3bf900ae7194ea9b"
|
|
79
79
|
},
|
|
80
80
|
"inputContract": {
|
|
81
81
|
"path": "office/contracts/docx_fill_table_from_tables.schema.json",
|
|
82
|
-
"sha256": "
|
|
82
|
+
"sha256": "4e80fff1c08fd16f8a5b4c638cf6469aa51e3a499743b44f3bf900ae7194ea9b"
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
{
|
|
@@ -174,11 +174,11 @@
|
|
|
174
174
|
"name": "docx_replace_content_from_source",
|
|
175
175
|
"providerContract": {
|
|
176
176
|
"source": "packages/docx-cli/contracts/mcp-input/docx_replace_content_from_source.schema.json",
|
|
177
|
-
"sha256": "
|
|
177
|
+
"sha256": "3ce7730317f1b9429f5da38b0eaecb53664a056545904a7f3904cdf148b94ad1"
|
|
178
178
|
},
|
|
179
179
|
"inputContract": {
|
|
180
180
|
"path": "office/contracts/docx_replace_content_from_source.schema.json",
|
|
181
|
-
"sha256": "
|
|
181
|
+
"sha256": "3ce7730317f1b9429f5da38b0eaecb53664a056545904a7f3904cdf148b94ad1"
|
|
182
182
|
}
|
|
183
183
|
},
|
|
184
184
|
{
|
|
@@ -192,15 +192,26 @@
|
|
|
192
192
|
"sha256": "25f4d4e7c69fa5a2c4a82621aa58ea8eda21245636f84f2243ca4e9092616b68"
|
|
193
193
|
}
|
|
194
194
|
},
|
|
195
|
+
{
|
|
196
|
+
"name": "docx_set_paragraph_pagination",
|
|
197
|
+
"providerContract": {
|
|
198
|
+
"source": "packages/docx-cli/contracts/mcp-input/docx_set_paragraph_pagination.schema.json",
|
|
199
|
+
"sha256": "ccb90bb5b811cfc82985050094637b1afe4c9daf51d7243c0d81b2d63d875825"
|
|
200
|
+
},
|
|
201
|
+
"inputContract": {
|
|
202
|
+
"path": "office/contracts/docx_set_paragraph_pagination.schema.json",
|
|
203
|
+
"sha256": "ccb90bb5b811cfc82985050094637b1afe4c9daf51d7243c0d81b2d63d875825"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
195
206
|
{
|
|
196
207
|
"name": "docx_set_table_body",
|
|
197
208
|
"providerContract": {
|
|
198
209
|
"source": "packages/docx-cli/contracts/mcp-input/docx_set_table_body.schema.json",
|
|
199
|
-
"sha256": "
|
|
210
|
+
"sha256": "adb0898a253a60fc80e3e811fdd6d19ac01ae76abe16b077e8af1f0960b640af"
|
|
200
211
|
},
|
|
201
212
|
"inputContract": {
|
|
202
213
|
"path": "office/contracts/docx_set_table_body.schema.json",
|
|
203
|
-
"sha256": "
|
|
214
|
+
"sha256": "adb0898a253a60fc80e3e811fdd6d19ac01ae76abe16b077e8af1f0960b640af"
|
|
204
215
|
}
|
|
205
216
|
},
|
|
206
217
|
{
|
|
@@ -240,11 +251,11 @@
|
|
|
240
251
|
"name": "docx_table_index",
|
|
241
252
|
"providerContract": {
|
|
242
253
|
"source": "packages/docx-cli/contracts/mcp-input/docx_table_index.schema.json",
|
|
243
|
-
"sha256": "
|
|
254
|
+
"sha256": "737052f653fe0d222bfc2b808e0fbc298376ab88cf052352888ff02e5b71ed52"
|
|
244
255
|
},
|
|
245
256
|
"inputContract": {
|
|
246
257
|
"path": "office/contracts/docx_table_index.schema.json",
|
|
247
|
-
"sha256": "
|
|
258
|
+
"sha256": "737052f653fe0d222bfc2b808e0fbc298376ab88cf052352888ff02e5b71ed52"
|
|
248
259
|
}
|
|
249
260
|
},
|
|
250
261
|
{
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function compactDocxObjectIdentity(object) {
|
|
2
|
+
return {
|
|
3
|
+
address: object.address,
|
|
4
|
+
parentAddress: object.parentAddress ?? null,
|
|
5
|
+
kind: object.kind,
|
|
6
|
+
textPreview: object.textPreview ?? null,
|
|
7
|
+
gridSpan: object.gridSpan ?? null,
|
|
8
|
+
verticalMerge: object.verticalMerge ?? null,
|
|
9
|
+
verticalTextAlignment: object.verticalTextAlignment ?? null,
|
|
10
|
+
};
|
|
11
|
+
}
|
package/office/index.mjs
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
writeJsonArtifact,
|
|
24
24
|
} from '../_shared/large-json-result.mjs';
|
|
25
25
|
import { withOutputWriteLock } from '../_shared/output-write-lock.mjs';
|
|
26
|
+
import { compactDocxObjectIdentity } from './docx-object-identity.mjs';
|
|
26
27
|
|
|
27
28
|
const packageMetadata = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
28
29
|
const inputContractManifest = JSON.parse(await readFile(
|
|
@@ -237,7 +238,7 @@ function docxInspectionOutput(tool) {
|
|
|
237
238
|
address: docxAddress,
|
|
238
239
|
textPreview: z.string().min(1).max(240),
|
|
239
240
|
}).strict()).max(6),
|
|
240
|
-
}).strict()
|
|
241
|
+
}).strict(),
|
|
241
242
|
}).strict();
|
|
242
243
|
}
|
|
243
244
|
|
|
@@ -248,6 +249,7 @@ const docxObjectIdentity = z.object({
|
|
|
248
249
|
textPreview: z.string().nullable(),
|
|
249
250
|
gridSpan: z.number().int().positive().nullable(),
|
|
250
251
|
verticalMerge: z.string().nullable(),
|
|
252
|
+
verticalTextAlignment: z.enum(['baseline', 'superscript', 'subscript']).nullable(),
|
|
251
253
|
}).strict();
|
|
252
254
|
|
|
253
255
|
const docxNestedObjectIdentity = docxObjectIdentity.pick({
|
|
@@ -259,6 +261,7 @@ const docxNestedObjectIdentity = docxObjectIdentity.pick({
|
|
|
259
261
|
verticalMerge: z.string().optional(),
|
|
260
262
|
verticalMergeOwner: docxAddress.optional(),
|
|
261
263
|
logicalText: z.string().optional(),
|
|
264
|
+
verticalTextAlignment: z.enum(['baseline', 'superscript', 'subscript']).optional(),
|
|
262
265
|
}).strict();
|
|
263
266
|
const docxObservationNode = z.lazy(() => z.object({
|
|
264
267
|
object: docxNestedObjectIdentity,
|
|
@@ -292,21 +295,11 @@ const docxTableIndexOutput = docxObservationOutput('docx_table_index').extend({
|
|
|
292
295
|
}).strict(),
|
|
293
296
|
tables: z.array(z.object({
|
|
294
297
|
address: docxAddress,
|
|
295
|
-
parentAddress: docxAddress.nullable(),
|
|
296
298
|
rowCount: z.number().int().nonnegative(),
|
|
297
299
|
columnCount: z.number().int().nonnegative(),
|
|
298
300
|
textPreview: z.string(),
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
address: docxAddress,
|
|
302
|
-
textPreview: z.string(),
|
|
303
|
-
textLength: z.number().int().nonnegative(),
|
|
304
|
-
}).strict().nullable(),
|
|
305
|
-
followingParagraph: z.object({
|
|
306
|
-
address: docxAddress,
|
|
307
|
-
textPreview: z.string(),
|
|
308
|
-
textLength: z.number().int().nonnegative(),
|
|
309
|
-
}).strict().nullable(),
|
|
301
|
+
precedingText: z.string().nullable(),
|
|
302
|
+
followingText: z.string().nullable(),
|
|
310
303
|
}).strict()).optional(),
|
|
311
304
|
}).strict();
|
|
312
305
|
|
|
@@ -370,7 +363,7 @@ const docxReadObjectOutput = docxObservationOutput('docx_read_object').extend({
|
|
|
370
363
|
const tools = [
|
|
371
364
|
{
|
|
372
365
|
name: 'docx_inspect',
|
|
373
|
-
description: 'Inspect one current DOCX. Set returnContent true
|
|
366
|
+
description: 'Inspect one current DOCX for identity and package overview. The response always includes a bounded identity summary. Set returnContent true when that summary is the requested direct result. Provide output to retain the complete machine observation and return its artifact receipt. These channels are independent and may be used together. At least one channel is required. Use list and read operations to traverse selected document objects in native structure order. This overview is not a complete final-document readback; use docx_export_json when a downstream consumer requires the complete body projection.',
|
|
374
367
|
inputSchema: inputContract('docx_inspect'),
|
|
375
368
|
outputSchema: docxInspectionOutput('docx_inspect'),
|
|
376
369
|
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
@@ -386,7 +379,7 @@ const tools = [
|
|
|
386
379
|
},
|
|
387
380
|
{
|
|
388
381
|
name: 'docx_table_index',
|
|
389
|
-
description: 'Locate tables in one current DOCX without returning full cell content or deciding table semantics. Set returnContent true to return
|
|
382
|
+
description: 'Locate tables in one current DOCX without returning full cell content or deciding table semantics. Set returnContent true to return as many compact native addresses, shapes, and short text clues as fit the bounded response; the provider chooses page size. Provide output to store the complete index and return its artifact receipt. These channels are independent and may be used together; at least one is required. Continue from receipt.nextOffset only when an unreturned table is needed for the current decision, then pass one returned address unchanged to a narrow table or object read.',
|
|
390
383
|
inputSchema: inputContract('docx_table_index'),
|
|
391
384
|
outputSchema: docxTableIndexOutput,
|
|
392
385
|
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
@@ -394,7 +387,7 @@ const tools = [
|
|
|
394
387
|
},
|
|
395
388
|
{
|
|
396
389
|
name: 'docx_read_object',
|
|
397
|
-
description: 'Read explicitly selected rows, cells, or paragraphs from one native DOCX. Set returnContent true to return compact requested descendants; if receipt.narrowingRequired is true, request fewer addresses or descendant kinds. Provide output to store the complete selected observation and return its artifact receipt. These channels are independent and may be used together; at least one is required. A selected cell exposes its vertical-merge owner and logical text, so a continue cell keeps its physical identity while resolving the restart cell value. Use docx_read_table for a table range.',
|
|
390
|
+
description: 'Read explicitly selected rows, cells, or paragraphs from one native DOCX. Set returnContent true to return compact requested descendants; if receipt.narrowingRequired is true, request fewer addresses or descendant kinds. Provide output to store the complete selected observation and return its artifact receipt. These channels are independent and may be used together; at least one is required. A selected cell exposes its vertical-merge owner and logical text, so a continue cell keeps its physical identity while resolving the restart cell value. Run and text descendants expose their native verticalTextAlignment when it is baseline, superscript, or subscript. Use docx_read_table for a table range.',
|
|
398
391
|
inputSchema: inputContract('docx_read_object'),
|
|
399
392
|
outputSchema: docxReadObjectOutput,
|
|
400
393
|
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
@@ -402,7 +395,7 @@ const tools = [
|
|
|
402
395
|
},
|
|
403
396
|
{
|
|
404
397
|
name: 'docx_read_table',
|
|
405
|
-
description: 'Read an explicit row range from exactly one table selected by native OpenXML address; it never builds another whole-table data object. Set returnContent true to return a byte-bounded compact row page. Provide output to store full paragraph and text-node detail for the selected row page and return its artifact receipt. These channels are independent and may be used together; at least one is required. Request only rows needed for the current decision; receipt.remaining is navigation information, not an obligation to read unused rows, and blank template rows need not be paged through. receipt.nextOffset is present only when another row page exists. Each returned row and cell keeps its reusable native address, zero-based logical gridColumnStart, gridSpan, vertical-merge owner, physical text, and logical text. Match columns across rows by gridColumnStart; a tc[n] path or array position is only that row\'s physical cell ordinal and is not a column identity when gridSpan or gridBefore is present. In a vertical merge, restart begins one logical cell and a continue cell is not an independent row value: logicalText resolves the restart cell value while text remains the physical cell value. Use docx_read_object when one exact object needs a narrower descendant view. The provider reports physical structure only; the Agent decides template and business meaning.',
|
|
398
|
+
description: 'Read an explicit row range from exactly one table selected by native OpenXML address; it never builds another whole-table data object. Set returnContent true to return a byte-bounded compact row page. Provide output to store full paragraph and text-node detail, including native verticalTextAlignment, for the selected row page and return its artifact receipt. These channels are independent and may be used together; at least one is required. Request only rows needed for the current decision; receipt.remaining is navigation information, not an obligation to read unused rows, and blank template rows need not be paged through. receipt.nextOffset is present only when another row page exists. Each returned row and cell keeps its reusable native address, zero-based logical gridColumnStart, gridSpan, vertical-merge owner, physical text, and logical text. Match columns across rows by gridColumnStart; a tc[n] path or array position is only that row\'s physical cell ordinal and is not a column identity when gridSpan or gridBefore is present. In a vertical merge, restart begins one logical cell and a continue cell is not an independent row value: logicalText resolves the restart cell value while text remains the physical cell value. Use docx_read_object when one exact object needs a narrower descendant view. The provider reports physical structure only; the Agent decides template and business meaning.',
|
|
406
399
|
inputSchema: inputContract('docx_read_table'),
|
|
407
400
|
outputSchema: docxTableReadOutput,
|
|
408
401
|
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
@@ -410,28 +403,35 @@ const tools = [
|
|
|
410
403
|
},
|
|
411
404
|
{
|
|
412
405
|
name: 'docx_replace_content_from_source',
|
|
413
|
-
description: 'Replace existing target paragraph or table-cell content from explicitly selected native source paragraphs, runs, text nodes, or exact text ranges while retaining target container formatting and table structure. Use it after docx_fill_table_from_tables when the target needs selected source
|
|
406
|
+
description: 'Replace existing target paragraph or table-cell content from explicitly selected native source cells, paragraphs, runs, text nodes, or exact text ranges while retaining target container formatting and table structure. For a source cell already returned by docx_read_table, select a Unicode-scalar range directly against its returned text; the provider retains every crossed native run, including superscript and subscript, without another descendant read. Consecutive run or text selections from one source paragraph form one target paragraph, and source paragraph boundaries remain paragraph boundaries. Use it after docx_fill_table_from_tables when the target needs selected source content instead of the whole source cell; pass returned addresses unchanged and never retype source-owned text. It does not copy source rows, cells, spans, or merges.',
|
|
414
407
|
inputSchema: inputContract('docx_replace_content_from_source'),
|
|
415
408
|
outputSchema: fixedEditOutput('docx_replace_content_from_source'),
|
|
416
409
|
handler: args => fixedEdit('docx_replace_content_from_source', args),
|
|
417
410
|
},
|
|
418
411
|
{
|
|
419
412
|
name: 'docx_set_text',
|
|
420
|
-
description: 'Replace the whole text content of paragraph or cell objects observed from this exact input DOCX while retaining target formatting, bookmarks, spans, and vertical merges. For a vertically merged logical cell, write its visible text to the restart cell rather than a continue cell. Tabs and line breaks remain native document text controls; targets containing non-text objects are rejected.
|
|
413
|
+
description: 'Replace the whole text content of paragraph or cell objects observed from this exact input DOCX while retaining target formatting, bookmarks, spans, and vertical merges. For a vertically merged logical cell, write its visible text to the restart cell rather than a continue cell. Tabs and line breaks remain native document text controls; targets containing non-text objects are rejected. Use this only for newly derived text. Content copied or selected from a source DOCX uses docx_replace_content_from_source so native runs such as superscript and subscript are retained. This does not insert objects, change table structure, copy source formatting, or decide business wording.',
|
|
421
414
|
inputSchema: inputContract('docx_set_text'),
|
|
422
415
|
outputSchema: fixedEditOutput('docx_set_text'),
|
|
423
416
|
handler: args => fixedEdit('docx_set_text', args),
|
|
424
417
|
},
|
|
418
|
+
{
|
|
419
|
+
name: 'docx_set_paragraph_pagination',
|
|
420
|
+
description: 'Set native pagination properties on explicitly selected current DOCX paragraphs. Each change sets at least one pagination property. keepWithNext keeps a paragraph with the immediately following paragraph or table but does not guarantee that a table header remains with its first body row. keepLinesTogether keeps one paragraph on one page; pageBreakBefore starts it on a new page; preventWidowOrphanLines controls isolated first or last lines. Omitted properties remain unchanged. The caller chooses paragraphs from current native addresses; the provider does not decide document layout or business meaning.',
|
|
421
|
+
inputSchema: inputContract('docx_set_paragraph_pagination'),
|
|
422
|
+
outputSchema: fixedEditOutput('docx_set_paragraph_pagination'),
|
|
423
|
+
handler: args => fixedEdit('docx_set_paragraph_pagination', args),
|
|
424
|
+
},
|
|
425
425
|
{
|
|
426
426
|
name: 'docx_set_table_body',
|
|
427
|
-
description: 'Atomically replace one exact current target-table row range while retaining the table, target styles, grid widths, and all rows and surrounding content outside the range. When retaining leading rows reported with repeatHeader=true, existingRows starts after all of them and never at a verticalMerge=continue row. Name every target grid column in native order and choose one current row inside existingRows as the style prototype for each final row. Horizontal spans use contiguous column IDs. Set rowSpan on one logical cell to occupy multiple rows and omit those columns from the covered rows; the provider writes native vertical merge cells. Every other grid column remains explicit. Every explicit cell includes an already-derived value; source-owned content is not retyped here. An empty final row array removes the range when another table row remains. The provider commits once and returns structural readback. It does not read source tables, map source to target, derive text, choose business columns, identify headers, or accept non-text cell content; use docx_fill_table_from_tables and docx_replace_content_from_source for source-owned table content.',
|
|
427
|
+
description: 'Atomically replace one exact current target-table row range while retaining the table, target styles, grid widths, and all rows and surrounding content outside the range. When retaining leading rows reported with repeatHeader=true, existingRows starts after all of them and never at a verticalMerge=continue row. Name every target grid column in native order and choose one current row inside existingRows as the style prototype for each final row. Horizontal spans use contiguous column IDs. Set rowSpan on one logical cell to occupy multiple rows and omit those columns from the covered rows; the provider writes native vertical merge cells. Set cantSplit on a final physical row when it must remain whole across page boundaries; omit it to preserve the prototype row property. Every other grid column remains explicit. Every explicit cell includes an already-derived value; source-owned content is not retyped here. An empty final row array removes the range when another table row remains. The provider commits once and returns structural readback. It does not read source tables, map source to target, derive text, choose business columns, identify headers, or accept non-text cell content; use docx_fill_table_from_tables and docx_replace_content_from_source for source-owned table content.',
|
|
428
428
|
inputSchema: inputContract('docx_set_table_body'),
|
|
429
429
|
outputSchema: fixedEditOutput('docx_set_table_body'),
|
|
430
430
|
handler: args => fixedEdit('docx_set_table_body', args),
|
|
431
431
|
},
|
|
432
432
|
{
|
|
433
433
|
name: 'docx_fill_table_from_tables',
|
|
434
|
-
description: 'Fill one current target-table body from one or more explicitly ordered current source-table row ranges. For each source, select
|
|
434
|
+
description: 'Fill one current target-table body from one or more explicitly ordered current source-table row ranges. For each source, select an unmerged record column when every physical source row must remain an output row; mapped columns still retain their native vertical merges. Select a merged record column only when every mapping into one target cell has one equal scalar value throughout that merge group. Map source grid columns onto every target prototype cell. The provider concatenates source records in declared order, copies each mapped source cell in full, preserves horizontal spans, rebuilds vertical merges only within each source range, validates the complete target grid, commits once, and returns structural readback. It does not discover source tables, choose source or target business meaning, filter records, translate or rewrite text, or apply business-specific rules. A single source uses the same sources array with one item. If a target needs only selected source descendants, such as one language from a bilingual cell, immediately use the returned target-cell addresses with docx_replace_content_from_source before releasing that source or reading back the completed target.',
|
|
435
435
|
inputSchema: inputContract('docx_fill_table_from_tables'),
|
|
436
436
|
outputSchema: fixedEditOutput('docx_fill_table_from_tables'),
|
|
437
437
|
handler: args => fixedEdit('docx_fill_table_from_tables', args),
|
|
@@ -488,7 +488,7 @@ const tools = [
|
|
|
488
488
|
},
|
|
489
489
|
{
|
|
490
490
|
name: 'docx_export_json',
|
|
491
|
-
description: 'Produce
|
|
491
|
+
description: 'Produce the complete body-only DOCX JSON projection required for final-document readback or another downstream consumer of that format. Set returnContent true to return the complete result when it fits the response limit. Provide output to write the complete result to a new JSON file. The two choices are independent and may be used together; at least one is required. This does not replace bounded list and read operations during document processing.',
|
|
492
492
|
inputSchema: inputContract('docx_export_json'),
|
|
493
493
|
outputSchema: largeResultOutput('docx_export_json'),
|
|
494
494
|
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
@@ -692,32 +692,17 @@ function compactDocxInspection(report) {
|
|
|
692
692
|
};
|
|
693
693
|
}
|
|
694
694
|
|
|
695
|
-
function compactDocxObjectIdentity(object) {
|
|
696
|
-
return {
|
|
697
|
-
address: object.address,
|
|
698
|
-
parentAddress: object.parentAddress,
|
|
699
|
-
kind: object.kind,
|
|
700
|
-
textPreview: object.textPreview,
|
|
701
|
-
gridSpan: object.gridSpan,
|
|
702
|
-
verticalMerge: object.verticalMerge,
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
|
|
706
695
|
function compactTableIndexEntry(table) {
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
textLength: value.textLength,
|
|
711
|
-
};
|
|
696
|
+
const paragraphText = value => value === null
|
|
697
|
+
? null
|
|
698
|
+
: value.textPreview.trim().replace(/\s+/gu, ' ').slice(0, 32);
|
|
712
699
|
return {
|
|
713
700
|
address: table.address,
|
|
714
|
-
parentAddress: table.parentAddress,
|
|
715
701
|
rowCount: table.rowCount,
|
|
716
702
|
columnCount: table.columnCount,
|
|
717
|
-
textPreview: table.textPreview.trim().replace(/\s+/gu, ' ').slice(0,
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
followingParagraph: paragraph(table.followingParagraph),
|
|
703
|
+
textPreview: table.textPreview.trim().replace(/\s+/gu, ' ').slice(0, 64),
|
|
704
|
+
precedingText: paragraphText(table.precedingParagraph),
|
|
705
|
+
followingText: paragraphText(table.followingParagraph),
|
|
721
706
|
};
|
|
722
707
|
}
|
|
723
708
|
|
|
@@ -734,6 +719,7 @@ function compactDocxObservation(observation) {
|
|
|
734
719
|
...(identity.verticalMerge === null ? {} : { verticalMerge: identity.verticalMerge }),
|
|
735
720
|
...(node.object.verticalMergeOwner === null ? {} : { verticalMergeOwner: node.object.verticalMergeOwner }),
|
|
736
721
|
...(node.object.logicalText === null ? {} : { logicalText: node.object.logicalText }),
|
|
722
|
+
...(identity.verticalTextAlignment === null ? {} : { verticalTextAlignment: identity.verticalTextAlignment }),
|
|
737
723
|
};
|
|
738
724
|
return {
|
|
739
725
|
object,
|
|
@@ -755,7 +741,7 @@ async function docxInspect(args) {
|
|
|
755
741
|
artifact: delivery.output === null
|
|
756
742
|
? null
|
|
757
743
|
: await writeIdempotentJsonArtifact(delivery.output, result.json),
|
|
758
|
-
...
|
|
744
|
+
...compactDocxInspection(result.json),
|
|
759
745
|
};
|
|
760
746
|
}
|
|
761
747
|
|
|
@@ -829,9 +815,8 @@ async function docxObservation(tool, args) {
|
|
|
829
815
|
};
|
|
830
816
|
}
|
|
831
817
|
const offset = Math.min(args.offset ?? 0, totalCount);
|
|
832
|
-
const requestedLimit = args.limit ?? totalCount;
|
|
833
818
|
const tables = [];
|
|
834
|
-
for (const sourceTable of payload.tables.slice(offset
|
|
819
|
+
for (const sourceTable of payload.tables.slice(offset)) {
|
|
835
820
|
const table = compactTableIndexEntry(sourceTable);
|
|
836
821
|
const candidate = [...tables, table];
|
|
837
822
|
if (tables.length > 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiwater/office-mcp",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.27",
|
|
4
4
|
"description": "Published MCP server for Tiwater Office document capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"_shared/large-json-result.mjs",
|
|
21
21
|
"_shared/output-write-lock.mjs",
|
|
22
22
|
"office/index.mjs",
|
|
23
|
+
"office/docx-object-identity.mjs",
|
|
23
24
|
"office/README.md",
|
|
24
25
|
"office/contracts/tiwater-office-provider-contract-manifest-v1.json",
|
|
25
26
|
"office/contracts/*.schema.json"
|