@tiwater/office-mcp 0.18.1 → 0.18.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.
- package/office/contracts/docx_apply_font_policy.schema.json +1 -1
- package/office/contracts/docx_apply_toc_style_policy.schema.json +1 -1
- package/office/contracts/docx_copy_content.schema.json +1 -0
- package/office/contracts/docx_copy_object.schema.json +2 -1
- package/office/contracts/docx_delete_object.schema.json +1 -0
- package/office/contracts/docx_list_objects.schema.json +1 -1
- package/office/contracts/docx_merge_cells.schema.json +1 -0
- package/office/contracts/docx_refresh_fields.schema.json +1 -1
- package/office/contracts/docx_replace_style_ids.schema.json +1 -0
- package/office/contracts/docx_replace_table_rows.schema.json +1 -0
- package/office/contracts/docx_set_text.schema.json +1 -0
- package/office/contracts/docx_split_cells.schema.json +1 -0
- package/office/contracts/docx_strip_direct_formatting.schema.json +1 -0
- package/office/contracts/tiwater-office-provider-contract-manifest-v1.json +27 -27
- package/office/index.mjs +33 -13
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"x-tiwater-file-role": "read",
|
|
11
11
|
"description": "Path to the current caller-authorized tiwater.docx-font-policy/v1 JSON asset."
|
|
12
12
|
},
|
|
13
|
-
"output": { "type": "string", "minLength": 1, "x-tiwater-file-role": "write" },
|
|
13
|
+
"output": { "type": "string", "minLength": 1, "description": "Output DOCX path; may equal input for an atomic in-place update.", "x-tiwater-file-role": "write" },
|
|
14
14
|
"receiptOutput": {
|
|
15
15
|
"type": "string",
|
|
16
16
|
"minLength": 1,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"input": { "type": "string", "minLength": 1, "x-tiwater-file-role": "read" },
|
|
7
7
|
"italic": { "type": "boolean" },
|
|
8
8
|
"indentCharactersPerLevel": { "type": "integer", "minimum": 0, "maximum": 21474836 },
|
|
9
|
-
"output": { "type": "string", "minLength": 1, "x-tiwater-file-role": "write" },
|
|
9
|
+
"output": { "type": "string", "minLength": 1, "description": "Output DOCX path; may equal input for an atomic in-place update.", "x-tiwater-file-role": "write" },
|
|
10
10
|
"receiptOutput": {
|
|
11
11
|
"type": "string",
|
|
12
12
|
"minLength": 1,
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"repeat": {
|
|
80
80
|
"type": "integer",
|
|
81
81
|
"minimum": 1,
|
|
82
|
-
"maximum":
|
|
82
|
+
"maximum": 2147483647
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
"required": [
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"output": {
|
|
94
94
|
"type": "string",
|
|
95
95
|
"minLength": 1,
|
|
96
|
+
"description": "Output DOCX path; may equal input for an atomic in-place update.",
|
|
96
97
|
"x-tiwater-file-role": "write"
|
|
97
98
|
},
|
|
98
99
|
"receiptOutput": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"output": {
|
|
12
12
|
"type": "string",
|
|
13
13
|
"minLength": 1,
|
|
14
|
-
"description": "
|
|
14
|
+
"description": "Output DOCX path; may equal input for an atomic in-place update.",
|
|
15
15
|
"x-tiwater-file-role": "write"
|
|
16
16
|
},
|
|
17
17
|
"receiptOutput": {
|
|
@@ -2,29 +2,29 @@
|
|
|
2
2
|
"schema": "tiwater.office-provider-contract-manifest/v1",
|
|
3
3
|
"provider": {
|
|
4
4
|
"id": "@tiwater/office-mcp",
|
|
5
|
-
"version": "0.18.
|
|
5
|
+
"version": "0.18.3"
|
|
6
6
|
},
|
|
7
7
|
"tools": [
|
|
8
8
|
{
|
|
9
9
|
"name": "docx_apply_font_policy",
|
|
10
10
|
"providerContract": {
|
|
11
11
|
"source": "packages/docx-cli/contracts/mcp-input/docx_apply_font_policy.schema.json",
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "0df423bca745d196923086d3ff9e5b20be59303460dbb54d5a367cfd701e03d3"
|
|
13
13
|
},
|
|
14
14
|
"inputContract": {
|
|
15
15
|
"path": "office/contracts/docx_apply_font_policy.schema.json",
|
|
16
|
-
"sha256": "
|
|
16
|
+
"sha256": "0df423bca745d196923086d3ff9e5b20be59303460dbb54d5a367cfd701e03d3"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"name": "docx_apply_toc_style_policy",
|
|
21
21
|
"providerContract": {
|
|
22
22
|
"source": "packages/docx-cli/contracts/mcp-input/docx_apply_toc_style_policy.schema.json",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "bd912b9c2442ad2528ae5411a4399bb02ea5a44d5d64ed4a87e212d6d7b57dc2"
|
|
24
24
|
},
|
|
25
25
|
"inputContract": {
|
|
26
26
|
"path": "office/contracts/docx_apply_toc_style_policy.schema.json",
|
|
27
|
-
"sha256": "
|
|
27
|
+
"sha256": "bd912b9c2442ad2528ae5411a4399bb02ea5a44d5d64ed4a87e212d6d7b57dc2"
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
{
|
|
@@ -42,33 +42,33 @@
|
|
|
42
42
|
"name": "docx_copy_content",
|
|
43
43
|
"providerContract": {
|
|
44
44
|
"source": "packages/docx-cli/contracts/mcp-input/docx_copy_content.schema.json",
|
|
45
|
-
"sha256": "
|
|
45
|
+
"sha256": "a7b4998f8c9f6423c6d6ca5953d4b8ca5572f38dfdc23bcc06c20c7c488af727"
|
|
46
46
|
},
|
|
47
47
|
"inputContract": {
|
|
48
48
|
"path": "office/contracts/docx_copy_content.schema.json",
|
|
49
|
-
"sha256": "
|
|
49
|
+
"sha256": "a7b4998f8c9f6423c6d6ca5953d4b8ca5572f38dfdc23bcc06c20c7c488af727"
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"name": "docx_copy_object",
|
|
54
54
|
"providerContract": {
|
|
55
55
|
"source": "packages/docx-cli/contracts/mcp-input/docx_copy_object.schema.json",
|
|
56
|
-
"sha256": "
|
|
56
|
+
"sha256": "f5ebb6c59a2bcb82e0504ab517505fe7525e905ff71bd9dea817967e79cee7a3"
|
|
57
57
|
},
|
|
58
58
|
"inputContract": {
|
|
59
59
|
"path": "office/contracts/docx_copy_object.schema.json",
|
|
60
|
-
"sha256": "
|
|
60
|
+
"sha256": "f5ebb6c59a2bcb82e0504ab517505fe7525e905ff71bd9dea817967e79cee7a3"
|
|
61
61
|
}
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"name": "docx_delete_object",
|
|
65
65
|
"providerContract": {
|
|
66
66
|
"source": "packages/docx-cli/contracts/mcp-input/docx_delete_object.schema.json",
|
|
67
|
-
"sha256": "
|
|
67
|
+
"sha256": "4497eb24df0e5631601232a8b35a9eddf914d02146992dd22f1cfba93ef7780f"
|
|
68
68
|
},
|
|
69
69
|
"inputContract": {
|
|
70
70
|
"path": "office/contracts/docx_delete_object.schema.json",
|
|
71
|
-
"sha256": "
|
|
71
|
+
"sha256": "4497eb24df0e5631601232a8b35a9eddf914d02146992dd22f1cfba93ef7780f"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
74
|
{
|
|
@@ -97,22 +97,22 @@
|
|
|
97
97
|
"name": "docx_list_objects",
|
|
98
98
|
"providerContract": {
|
|
99
99
|
"source": "packages/docx-cli/contracts/mcp-input/docx_list_objects.schema.json",
|
|
100
|
-
"sha256": "
|
|
100
|
+
"sha256": "37b32320e04584f837d36a5c90c726434ab875cdbf0840d2cd62dd98e93ae882"
|
|
101
101
|
},
|
|
102
102
|
"inputContract": {
|
|
103
103
|
"path": "office/contracts/docx_list_objects.schema.json",
|
|
104
|
-
"sha256": "
|
|
104
|
+
"sha256": "37b32320e04584f837d36a5c90c726434ab875cdbf0840d2cd62dd98e93ae882"
|
|
105
105
|
}
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
"name": "docx_merge_cells",
|
|
109
109
|
"providerContract": {
|
|
110
110
|
"source": "packages/docx-cli/contracts/mcp-input/docx_merge_cells.schema.json",
|
|
111
|
-
"sha256": "
|
|
111
|
+
"sha256": "2106f2b2a39f47fb766e43bcb9a6e586827b3f31a079d875b6cc5c647d253dd4"
|
|
112
112
|
},
|
|
113
113
|
"inputContract": {
|
|
114
114
|
"path": "office/contracts/docx_merge_cells.schema.json",
|
|
115
|
-
"sha256": "
|
|
115
|
+
"sha256": "2106f2b2a39f47fb766e43bcb9a6e586827b3f31a079d875b6cc5c647d253dd4"
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
118
|
{
|
|
@@ -130,66 +130,66 @@
|
|
|
130
130
|
"name": "docx_refresh_fields",
|
|
131
131
|
"providerContract": {
|
|
132
132
|
"source": "packages/convert-cli/schemas/mcp-input/docx_refresh_fields.schema.json",
|
|
133
|
-
"sha256": "
|
|
133
|
+
"sha256": "8f2f8694b6d533d7f48b6e1e0c82be3a9c5aac55c50dba00daadd0ea0a76a8a7"
|
|
134
134
|
},
|
|
135
135
|
"inputContract": {
|
|
136
136
|
"path": "office/contracts/docx_refresh_fields.schema.json",
|
|
137
|
-
"sha256": "
|
|
137
|
+
"sha256": "8f2f8694b6d533d7f48b6e1e0c82be3a9c5aac55c50dba00daadd0ea0a76a8a7"
|
|
138
138
|
}
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
"name": "docx_replace_style_ids",
|
|
142
142
|
"providerContract": {
|
|
143
143
|
"source": "packages/docx-cli/contracts/mcp-input/docx_replace_style_ids.schema.json",
|
|
144
|
-
"sha256": "
|
|
144
|
+
"sha256": "25f4d4e7c69fa5a2c4a82621aa58ea8eda21245636f84f2243ca4e9092616b68"
|
|
145
145
|
},
|
|
146
146
|
"inputContract": {
|
|
147
147
|
"path": "office/contracts/docx_replace_style_ids.schema.json",
|
|
148
|
-
"sha256": "
|
|
148
|
+
"sha256": "25f4d4e7c69fa5a2c4a82621aa58ea8eda21245636f84f2243ca4e9092616b68"
|
|
149
149
|
}
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
152
|
"name": "docx_replace_table_rows",
|
|
153
153
|
"providerContract": {
|
|
154
154
|
"source": "packages/docx-cli/contracts/mcp-input/docx_replace_table_rows.schema.json",
|
|
155
|
-
"sha256": "
|
|
155
|
+
"sha256": "02ce941414496ddffa7d531ca6fa982598f607b516d990d598ace521d725cdf6"
|
|
156
156
|
},
|
|
157
157
|
"inputContract": {
|
|
158
158
|
"path": "office/contracts/docx_replace_table_rows.schema.json",
|
|
159
|
-
"sha256": "
|
|
159
|
+
"sha256": "02ce941414496ddffa7d531ca6fa982598f607b516d990d598ace521d725cdf6"
|
|
160
160
|
}
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
"name": "docx_set_text",
|
|
164
164
|
"providerContract": {
|
|
165
165
|
"source": "packages/docx-cli/contracts/mcp-input/docx_set_text.schema.json",
|
|
166
|
-
"sha256": "
|
|
166
|
+
"sha256": "9feca848acff5ff7c0f2e08f618e183494959b5a74e9e37e06086d7a627810ca"
|
|
167
167
|
},
|
|
168
168
|
"inputContract": {
|
|
169
169
|
"path": "office/contracts/docx_set_text.schema.json",
|
|
170
|
-
"sha256": "
|
|
170
|
+
"sha256": "9feca848acff5ff7c0f2e08f618e183494959b5a74e9e37e06086d7a627810ca"
|
|
171
171
|
}
|
|
172
172
|
},
|
|
173
173
|
{
|
|
174
174
|
"name": "docx_split_cells",
|
|
175
175
|
"providerContract": {
|
|
176
176
|
"source": "packages/docx-cli/contracts/mcp-input/docx_split_cells.schema.json",
|
|
177
|
-
"sha256": "
|
|
177
|
+
"sha256": "085a5b8e924c68958752eeb2de9644a3084c249408e9f135ee936f14e9ce5f9b"
|
|
178
178
|
},
|
|
179
179
|
"inputContract": {
|
|
180
180
|
"path": "office/contracts/docx_split_cells.schema.json",
|
|
181
|
-
"sha256": "
|
|
181
|
+
"sha256": "085a5b8e924c68958752eeb2de9644a3084c249408e9f135ee936f14e9ce5f9b"
|
|
182
182
|
}
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
"name": "docx_strip_direct_formatting",
|
|
186
186
|
"providerContract": {
|
|
187
187
|
"source": "packages/docx-cli/contracts/mcp-input/docx_strip_direct_formatting.schema.json",
|
|
188
|
-
"sha256": "
|
|
188
|
+
"sha256": "4931d4432c574154eb7a344ee4dc485d99d8840c07d2e46f647e14490cbeedae"
|
|
189
189
|
},
|
|
190
190
|
"inputContract": {
|
|
191
191
|
"path": "office/contracts/docx_strip_direct_formatting.schema.json",
|
|
192
|
-
"sha256": "
|
|
192
|
+
"sha256": "4931d4432c574154eb7a344ee4dc485d99d8840c07d2e46f647e14490cbeedae"
|
|
193
193
|
}
|
|
194
194
|
},
|
|
195
195
|
{
|
package/office/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { createReadStream } from 'node:fs';
|
|
4
|
-
import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { mkdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { isDeepStrictEqual } from 'node:util';
|
|
7
7
|
import { McpServer } from '@modelcontextprotocol/server';
|
|
@@ -610,34 +610,39 @@ async function docxRefreshFields(args) {
|
|
|
610
610
|
const input = path.resolve(requireString(args.input, 'input'));
|
|
611
611
|
const output = path.resolve(requireString(args.output, 'output'));
|
|
612
612
|
const receiptOutput = path.resolve(requireString(args.receiptOutput, 'receiptOutput'));
|
|
613
|
+
const inPlace = input === output;
|
|
614
|
+
const invocationOutput = inPlace ? temporarySibling(output) : output;
|
|
613
615
|
if (path.extname(input).toLowerCase() !== '.docx' || path.extname(output).toLowerCase() !== '.docx') {
|
|
614
616
|
throw Object.assign(new Error('DOCX field refresh requires .docx input and output'), { code: -32602 });
|
|
615
617
|
}
|
|
616
|
-
await requireNewFile(output, 'output');
|
|
618
|
+
if (!inPlace) await requireNewFile(output, 'output');
|
|
617
619
|
await requireNewFile(receiptOutput, 'receiptOutput');
|
|
618
620
|
const inputArtifact = await fileArtifact(input);
|
|
619
621
|
try {
|
|
620
|
-
const result = await runJsonCandidateChain(convertCandidates, ['refresh-docx-fields', input,
|
|
622
|
+
const result = await runJsonCandidateChain(convertCandidates, ['refresh-docx-fields', input, invocationOutput]);
|
|
621
623
|
const providerReceipt = docxFieldRefreshReceipt.parse(result.json);
|
|
622
|
-
const
|
|
624
|
+
const invocationArtifact = await fileArtifact(invocationOutput);
|
|
623
625
|
if (path.resolve(providerReceipt.input) !== input
|
|
624
|
-
|| path.resolve(providerReceipt.output) !==
|
|
626
|
+
|| path.resolve(providerReceipt.output) !== invocationOutput
|
|
625
627
|
|| providerReceipt.input_sha256 !== inputArtifact.sha256
|
|
626
|
-
|| providerReceipt.output_sha256 !==
|
|
628
|
+
|| providerReceipt.output_sha256 !== invocationArtifact.sha256) {
|
|
627
629
|
throw new Error('DOCX field refresh receipt is not bound to the current input and output');
|
|
628
630
|
}
|
|
631
|
+
if (inPlace) await rename(invocationOutput, output);
|
|
632
|
+
const outputArtifact = await fileArtifact(output);
|
|
633
|
+
const acceptedReceipt = { ...providerReceipt, output, output_sha256: outputArtifact.sha256 };
|
|
629
634
|
return {
|
|
630
635
|
tool: 'docx_refresh_fields',
|
|
631
636
|
runtime: commandRuntime(result),
|
|
632
637
|
output: outputArtifact,
|
|
633
|
-
receipt: await writeJsonArtifact(receiptOutput,
|
|
638
|
+
receipt: await writeJsonArtifact(receiptOutput, acceptedReceipt),
|
|
634
639
|
summary: {
|
|
635
640
|
backend: providerReceipt.backend,
|
|
636
641
|
refreshScope: providerReceipt.refresh_scope,
|
|
637
642
|
},
|
|
638
643
|
};
|
|
639
644
|
} catch (error) {
|
|
640
|
-
await rm(
|
|
645
|
+
await rm(invocationOutput, { force: true });
|
|
641
646
|
throw error;
|
|
642
647
|
}
|
|
643
648
|
}
|
|
@@ -645,15 +650,24 @@ async function docxRefreshFields(args) {
|
|
|
645
650
|
async function copyTransform(tool, candidates, command, args, suffix = []) {
|
|
646
651
|
const input = path.resolve(requireString(args.input, 'input'));
|
|
647
652
|
const output = path.resolve(requireString(args.output, 'output'));
|
|
648
|
-
|
|
649
|
-
const
|
|
650
|
-
|
|
653
|
+
const inPlace = input === output;
|
|
654
|
+
const invocationOutput = inPlace ? temporarySibling(output) : output;
|
|
655
|
+
if (!inPlace) await requireNewFile(output, 'output');
|
|
656
|
+
try {
|
|
657
|
+
const result = await runCandidateChain(candidates, [...command, input, invocationOutput, ...suffix]);
|
|
658
|
+
if (inPlace) await rename(invocationOutput, output);
|
|
659
|
+
return { tool, runtime: commandRuntime(result), output: await fileArtifact(output) };
|
|
660
|
+
} catch (error) {
|
|
661
|
+
await rm(invocationOutput, { force: true });
|
|
662
|
+
throw error;
|
|
663
|
+
}
|
|
651
664
|
}
|
|
652
665
|
|
|
653
666
|
async function fixedEdit(tool, args) {
|
|
667
|
+
const input = path.resolve(requireString(args.input, 'input'));
|
|
654
668
|
const output = path.resolve(requireString(args.output, 'output'));
|
|
655
669
|
const receiptOutput = path.resolve(requireString(args.receiptOutput, 'receiptOutput'));
|
|
656
|
-
await requireNewFile(output, 'output');
|
|
670
|
+
if (!(tool.startsWith('docx_') && input === output)) await requireNewFile(output, 'output');
|
|
657
671
|
await requireNewFile(receiptOutput, 'receiptOutput');
|
|
658
672
|
const candidates = tool.startsWith('docx_') ? docxCandidates
|
|
659
673
|
: tool.startsWith('xlsx_') ? xlsxCandidates
|
|
@@ -880,6 +894,12 @@ async function requireNewFile(filePath, label) {
|
|
|
880
894
|
throw Object.assign(new Error(`${label} already exists: ${filePath}`), { code: -32602 });
|
|
881
895
|
}
|
|
882
896
|
|
|
897
|
+
function temporarySibling(filePath) {
|
|
898
|
+
const extension = path.extname(filePath);
|
|
899
|
+
const stem = path.basename(filePath, extension);
|
|
900
|
+
return path.join(path.dirname(filePath), `.${stem}.${randomUUID()}.tmp${extension}`);
|
|
901
|
+
}
|
|
902
|
+
|
|
883
903
|
function commandRuntime(result) {
|
|
884
904
|
return {
|
|
885
905
|
command: result.command,
|