@tiwater/office-mcp 0.21.1 → 0.21.3
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.
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
const pendingWrites = new Map();
|
|
4
|
+
|
|
5
|
+
export async function withOutputWriteLock(output, write) {
|
|
6
|
+
const target = path.resolve(output);
|
|
7
|
+
const previous = pendingWrites.get(target) ?? Promise.resolve();
|
|
8
|
+
const current = previous.catch(() => undefined).then(write);
|
|
9
|
+
pendingWrites.set(target, current);
|
|
10
|
+
try {
|
|
11
|
+
return await current;
|
|
12
|
+
} finally {
|
|
13
|
+
if (pendingWrites.get(target) === current) pendingWrites.delete(target);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "tiwater.office-mcp-input/docx_set_table_body",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"minLength": 1,
|
|
9
|
+
"x-tiwater-file-role": "read"
|
|
10
|
+
},
|
|
11
|
+
"table": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"part": { "type": "string", "minLength": 1 },
|
|
15
|
+
"path": { "type": "string", "pattern": "^\\/" }
|
|
16
|
+
},
|
|
17
|
+
"required": ["part", "path"],
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"description": "Current target table address returned by docx_read_table or docx_table_index."
|
|
20
|
+
},
|
|
21
|
+
"existingRows": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"description": "Exact contiguous current row range to replace. Rows outside this range stay unchanged, and the range must enclose every vertical merge it intersects.",
|
|
24
|
+
"properties": {
|
|
25
|
+
"first": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"properties": {
|
|
28
|
+
"part": { "type": "string", "minLength": 1 },
|
|
29
|
+
"path": { "type": "string", "pattern": "^\\/" }
|
|
30
|
+
},
|
|
31
|
+
"required": ["part", "path"],
|
|
32
|
+
"additionalProperties": false
|
|
33
|
+
},
|
|
34
|
+
"last": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"properties": {
|
|
37
|
+
"part": { "type": "string", "minLength": 1 },
|
|
38
|
+
"path": { "type": "string", "pattern": "^\\/" }
|
|
39
|
+
},
|
|
40
|
+
"required": ["part", "path"],
|
|
41
|
+
"additionalProperties": false
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"required": ["first", "last"],
|
|
45
|
+
"additionalProperties": false
|
|
46
|
+
},
|
|
47
|
+
"columns": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"minItems": 1,
|
|
50
|
+
"description": "Complete target table grid in the native order returned by docx_read_table. IDs are request-local names used only by rows below.",
|
|
51
|
+
"items": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"id": { "type": "string", "minLength": 1, "maxLength": 80 },
|
|
55
|
+
"gridColumn": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"properties": {
|
|
58
|
+
"part": { "type": "string", "minLength": 1 },
|
|
59
|
+
"path": { "type": "string", "pattern": "^\\/" }
|
|
60
|
+
},
|
|
61
|
+
"required": ["part", "path"],
|
|
62
|
+
"additionalProperties": false
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"required": ["id", "gridColumn"],
|
|
66
|
+
"additionalProperties": false
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"rows": {
|
|
70
|
+
"type": "array",
|
|
71
|
+
"minItems": 0,
|
|
72
|
+
"description": "Exact final rows; an empty array removes the declared range when at least one table row remains. Each final row names one current row in existingRows as its style prototype. Cells plus active row spans must cover the complete target grid exactly once.",
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {
|
|
76
|
+
"prototypeRow": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"properties": {
|
|
79
|
+
"part": { "type": "string", "minLength": 1 },
|
|
80
|
+
"path": { "type": "string", "pattern": "^\\/" }
|
|
81
|
+
},
|
|
82
|
+
"required": ["part", "path"],
|
|
83
|
+
"additionalProperties": false
|
|
84
|
+
},
|
|
85
|
+
"cells": {
|
|
86
|
+
"type": "array",
|
|
87
|
+
"minItems": 1,
|
|
88
|
+
"items": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"properties": {
|
|
91
|
+
"columns": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"minItems": 1,
|
|
94
|
+
"description": "One or more contiguous request-local column IDs occupied by this cell.",
|
|
95
|
+
"items": { "type": "string", "minLength": 1, "maxLength": 80 }
|
|
96
|
+
},
|
|
97
|
+
"text": { "type": "string" },
|
|
98
|
+
"rowSpan": {
|
|
99
|
+
"type": "integer",
|
|
100
|
+
"minimum": 1,
|
|
101
|
+
"maximum": 2147483647,
|
|
102
|
+
"description": "Number of final rows occupied by this cell; omitted means one row."
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"required": ["columns", "text"],
|
|
106
|
+
"additionalProperties": false
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"required": ["prototypeRow", "cells"],
|
|
111
|
+
"additionalProperties": false
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"output": {
|
|
115
|
+
"type": "string",
|
|
116
|
+
"minLength": 1,
|
|
117
|
+
"description": "Output DOCX path; may equal input for one atomic in-place update.",
|
|
118
|
+
"x-tiwater-file-role": "write"
|
|
119
|
+
},
|
|
120
|
+
"receiptOutput": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"minLength": 1,
|
|
123
|
+
"x-tiwater-file-role": "write",
|
|
124
|
+
"x-tiwater-file-effect": false
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"required": ["input", "table", "existingRows", "columns", "rows", "output", "receiptOutput"],
|
|
128
|
+
"additionalProperties": false
|
|
129
|
+
}
|
|
@@ -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.3"
|
|
6
6
|
},
|
|
7
7
|
"tools": [
|
|
8
8
|
{
|
|
@@ -181,6 +181,17 @@
|
|
|
181
181
|
"sha256": "25f4d4e7c69fa5a2c4a82621aa58ea8eda21245636f84f2243ca4e9092616b68"
|
|
182
182
|
}
|
|
183
183
|
},
|
|
184
|
+
{
|
|
185
|
+
"name": "docx_set_table_body",
|
|
186
|
+
"providerContract": {
|
|
187
|
+
"source": "packages/docx-cli/contracts/mcp-input/docx_set_table_body.schema.json",
|
|
188
|
+
"sha256": "2270274f25154dc0573c972c8c71240636e29e7e23a1eacae616952cc600b1e0"
|
|
189
|
+
},
|
|
190
|
+
"inputContract": {
|
|
191
|
+
"path": "office/contracts/docx_set_table_body.schema.json",
|
|
192
|
+
"sha256": "2270274f25154dc0573c972c8c71240636e29e7e23a1eacae616952cc600b1e0"
|
|
193
|
+
}
|
|
194
|
+
},
|
|
184
195
|
{
|
|
185
196
|
"name": "docx_set_text",
|
|
186
197
|
"providerContract": {
|
package/office/index.mjs
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
returnedContentBudgetBytes,
|
|
22
22
|
writeJsonArtifact,
|
|
23
23
|
} from '../_shared/large-json-result.mjs';
|
|
24
|
+
import { withOutputWriteLock } from '../_shared/output-write-lock.mjs';
|
|
24
25
|
|
|
25
26
|
const packageMetadata = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
26
27
|
const inputContractManifest = JSON.parse(await readFile(
|
|
@@ -420,6 +421,13 @@ const tools = [
|
|
|
420
421
|
outputSchema: fixedEditOutput('docx_set_text'),
|
|
421
422
|
handler: args => fixedEdit('docx_set_text', args),
|
|
422
423
|
},
|
|
424
|
+
{
|
|
425
|
+
name: 'docx_set_table_body',
|
|
426
|
+
description: 'Atomically replace one exact current target-table row range with final text rows while retaining the table, target styles, grid widths, and all rows and surrounding content outside the range. Name every target grid column in native order, choose one current row as the style prototype for each final row, and express horizontal spans with contiguous column IDs and vertical spans with rowSpan. 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 a source table, map source to target, derive text, choose business columns, identify headers, or accept non-text cell content.',
|
|
427
|
+
inputSchema: inputContract('docx_set_table_body'),
|
|
428
|
+
outputSchema: fixedEditOutput('docx_set_table_body'),
|
|
429
|
+
handler: args => fixedEdit('docx_set_table_body', args),
|
|
430
|
+
},
|
|
423
431
|
{
|
|
424
432
|
name: 'docx_insert_objects',
|
|
425
433
|
description: 'Insert selected current DOCX objects under an existing parent. Table rows are objects: expand a target table by copying one contiguous observed row range and use repeat for count; sourceInput may equal input. A row range beginning with vertical-merge continuations may be inserted only inside a target boundary with the same active grid spans, which extends those merges. Individual table cells are not raw insertion targets because that would bypass the table grid.',
|
|
@@ -644,7 +652,9 @@ function buildServer() {
|
|
|
644
652
|
...(tool.annotations ? { annotations: tool.annotations } : {}),
|
|
645
653
|
},
|
|
646
654
|
async args => {
|
|
647
|
-
const payload =
|
|
655
|
+
const payload = typeof args.output === 'string'
|
|
656
|
+
? await withOutputWriteLock(args.output, () => tool.handler(args))
|
|
657
|
+
: await tool.handler(args);
|
|
648
658
|
return createToolResult(payload, { isError: payload?.summary?.pass === false });
|
|
649
659
|
},
|
|
650
660
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiwater/office-mcp",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.3",
|
|
4
4
|
"description": "Published MCP server for Tiwater Office document capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"files": [
|
|
19
19
|
"_shared/tool-runtime.mjs",
|
|
20
20
|
"_shared/large-json-result.mjs",
|
|
21
|
+
"_shared/output-write-lock.mjs",
|
|
21
22
|
"office/index.mjs",
|
|
22
23
|
"office/README.md",
|
|
23
24
|
"office/contracts/tiwater-office-provider-contract-manifest-v1.json",
|