@tiwater/office-mcp 0.18.2 → 0.18.4

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.
@@ -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,
@@ -99,6 +99,7 @@
99
99
  "output": {
100
100
  "type": "string",
101
101
  "minLength": 1,
102
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
102
103
  "x-tiwater-file-role": "write"
103
104
  },
104
105
  "receiptOutput": {
@@ -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": {
@@ -45,6 +45,7 @@
45
45
  "output": {
46
46
  "type": "string",
47
47
  "minLength": 1,
48
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
48
49
  "x-tiwater-file-role": "write"
49
50
  },
50
51
  "receiptOutput": {
@@ -45,6 +45,7 @@
45
45
  "output": {
46
46
  "type": "string",
47
47
  "minLength": 1,
48
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
48
49
  "x-tiwater-file-role": "write"
49
50
  },
50
51
  "receiptOutput": {
@@ -11,7 +11,7 @@
11
11
  "output": {
12
12
  "type": "string",
13
13
  "minLength": 1,
14
- "description": "New DOCX output path. Existing files are never overwritten.",
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": {
@@ -10,6 +10,7 @@
10
10
  "output": {
11
11
  "type": "string",
12
12
  "minLength": 1,
13
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
13
14
  "x-tiwater-file-role": "write"
14
15
  },
15
16
  "styleMap": {
@@ -292,6 +292,7 @@
292
292
  "output": {
293
293
  "type": "string",
294
294
  "minLength": 1,
295
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
295
296
  "x-tiwater-file-role": "write"
296
297
  },
297
298
  "receiptOutput": {
@@ -45,6 +45,7 @@
45
45
  "output": {
46
46
  "type": "string",
47
47
  "minLength": 1,
48
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
48
49
  "x-tiwater-file-role": "write"
49
50
  },
50
51
  "receiptOutput": {
@@ -45,6 +45,7 @@
45
45
  "output": {
46
46
  "type": "string",
47
47
  "minLength": 1,
48
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
48
49
  "x-tiwater-file-role": "write"
49
50
  },
50
51
  "receiptOutput": {
@@ -10,6 +10,7 @@
10
10
  "output": {
11
11
  "type": "string",
12
12
  "minLength": 1,
13
+ "description": "Output DOCX path; may equal input for an atomic in-place update.",
13
14
  "x-tiwater-file-role": "write"
14
15
  }
15
16
  },
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "tiwater.office-mcp-input/docx_table_index/v1",
4
+ "type": "object",
5
+ "properties": {
6
+ "input": {
7
+ "type": "string",
8
+ "minLength": 1,
9
+ "description": "Current DOCX path.",
10
+ "x-tiwater-file-role": "read"
11
+ },
12
+ "output": {
13
+ "type": "string",
14
+ "minLength": 1,
15
+ "description": "New JSON artifact path for the complete table index.",
16
+ "x-tiwater-file-role": "write"
17
+ }
18
+ },
19
+ "required": ["input", "output"],
20
+ "additionalProperties": false
21
+ }
@@ -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.2"
5
+ "version": "0.18.4"
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": "d7c0006cc1ee6a001f8a82f26a9ed260c4ff48babcc7a93b785c019cfa91a3a0"
12
+ "sha256": "0df423bca745d196923086d3ff9e5b20be59303460dbb54d5a367cfd701e03d3"
13
13
  },
14
14
  "inputContract": {
15
15
  "path": "office/contracts/docx_apply_font_policy.schema.json",
16
- "sha256": "d7c0006cc1ee6a001f8a82f26a9ed260c4ff48babcc7a93b785c019cfa91a3a0"
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": "20e97023efe9a06354f22c93fff1576e0102a5d8b16058e9684af9478cb36286"
23
+ "sha256": "bd912b9c2442ad2528ae5411a4399bb02ea5a44d5d64ed4a87e212d6d7b57dc2"
24
24
  },
25
25
  "inputContract": {
26
26
  "path": "office/contracts/docx_apply_toc_style_policy.schema.json",
27
- "sha256": "20e97023efe9a06354f22c93fff1576e0102a5d8b16058e9684af9478cb36286"
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": "50e1633e97d0aaab32c58935b92aa73128b566ae3ed742bc3ae1a62d0b1ba617"
45
+ "sha256": "a7b4998f8c9f6423c6d6ca5953d4b8ca5572f38dfdc23bcc06c20c7c488af727"
46
46
  },
47
47
  "inputContract": {
48
48
  "path": "office/contracts/docx_copy_content.schema.json",
49
- "sha256": "50e1633e97d0aaab32c58935b92aa73128b566ae3ed742bc3ae1a62d0b1ba617"
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": "5c76b96e7a56f10a2e2c14e5d40dfe40e44dc6b21c2265bbf54c06953703ac12"
56
+ "sha256": "f5ebb6c59a2bcb82e0504ab517505fe7525e905ff71bd9dea817967e79cee7a3"
57
57
  },
58
58
  "inputContract": {
59
59
  "path": "office/contracts/docx_copy_object.schema.json",
60
- "sha256": "5c76b96e7a56f10a2e2c14e5d40dfe40e44dc6b21c2265bbf54c06953703ac12"
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": "efbb9017fe4b5dd0a66ee7d1229560d006fbca09beffbc6a600bda225b4f2d05"
67
+ "sha256": "4497eb24df0e5631601232a8b35a9eddf914d02146992dd22f1cfba93ef7780f"
68
68
  },
69
69
  "inputContract": {
70
70
  "path": "office/contracts/docx_delete_object.schema.json",
71
- "sha256": "efbb9017fe4b5dd0a66ee7d1229560d006fbca09beffbc6a600bda225b4f2d05"
71
+ "sha256": "4497eb24df0e5631601232a8b35a9eddf914d02146992dd22f1cfba93ef7780f"
72
72
  }
73
73
  },
74
74
  {
@@ -108,11 +108,11 @@
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": "417def05619b271471c76883eea52a2f5772ac399111215df5a7259b8a41c3d1"
111
+ "sha256": "2106f2b2a39f47fb766e43bcb9a6e586827b3f31a079d875b6cc5c647d253dd4"
112
112
  },
113
113
  "inputContract": {
114
114
  "path": "office/contracts/docx_merge_cells.schema.json",
115
- "sha256": "417def05619b271471c76883eea52a2f5772ac399111215df5a7259b8a41c3d1"
115
+ "sha256": "2106f2b2a39f47fb766e43bcb9a6e586827b3f31a079d875b6cc5c647d253dd4"
116
116
  }
117
117
  },
118
118
  {
@@ -130,66 +130,77 @@
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": "5f2a4f928796752adf7a44098919bca94c6faba8dbc9e5ad36b43e7f33035c7c"
133
+ "sha256": "8f2f8694b6d533d7f48b6e1e0c82be3a9c5aac55c50dba00daadd0ea0a76a8a7"
134
134
  },
135
135
  "inputContract": {
136
136
  "path": "office/contracts/docx_refresh_fields.schema.json",
137
- "sha256": "5f2a4f928796752adf7a44098919bca94c6faba8dbc9e5ad36b43e7f33035c7c"
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": "aa8fc12a350a391fadf32546847f29a816319efcab01866a1f406dc8313ea1ed"
144
+ "sha256": "25f4d4e7c69fa5a2c4a82621aa58ea8eda21245636f84f2243ca4e9092616b68"
145
145
  },
146
146
  "inputContract": {
147
147
  "path": "office/contracts/docx_replace_style_ids.schema.json",
148
- "sha256": "aa8fc12a350a391fadf32546847f29a816319efcab01866a1f406dc8313ea1ed"
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": "8dfc2cb6f366610281eb6f14118d3855e1e27a34f27b5e2a425690b581ada5a6"
155
+ "sha256": "02ce941414496ddffa7d531ca6fa982598f607b516d990d598ace521d725cdf6"
156
156
  },
157
157
  "inputContract": {
158
158
  "path": "office/contracts/docx_replace_table_rows.schema.json",
159
- "sha256": "8dfc2cb6f366610281eb6f14118d3855e1e27a34f27b5e2a425690b581ada5a6"
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": "0e0ccfb2ac910660c6aea6b4dca0e023bd30931c691913647576999b096f43e9"
166
+ "sha256": "9feca848acff5ff7c0f2e08f618e183494959b5a74e9e37e06086d7a627810ca"
167
167
  },
168
168
  "inputContract": {
169
169
  "path": "office/contracts/docx_set_text.schema.json",
170
- "sha256": "0e0ccfb2ac910660c6aea6b4dca0e023bd30931c691913647576999b096f43e9"
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": "9d53d0234d98c6cc5cb5b523e1457b777d015c5aaf49cbd745e6598c1793d6bb"
177
+ "sha256": "085a5b8e924c68958752eeb2de9644a3084c249408e9f135ee936f14e9ce5f9b"
178
178
  },
179
179
  "inputContract": {
180
180
  "path": "office/contracts/docx_split_cells.schema.json",
181
- "sha256": "9d53d0234d98c6cc5cb5b523e1457b777d015c5aaf49cbd745e6598c1793d6bb"
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": "49a6682f7c8aecce6e30e5a4bfc08111151d9c755d38e759de6b7efb66979cac"
188
+ "sha256": "4931d4432c574154eb7a344ee4dc485d99d8840c07d2e46f647e14490cbeedae"
189
189
  },
190
190
  "inputContract": {
191
191
  "path": "office/contracts/docx_strip_direct_formatting.schema.json",
192
- "sha256": "49a6682f7c8aecce6e30e5a4bfc08111151d9c755d38e759de6b7efb66979cac"
192
+ "sha256": "4931d4432c574154eb7a344ee4dc485d99d8840c07d2e46f647e14490cbeedae"
193
+ }
194
+ },
195
+ {
196
+ "name": "docx_table_index",
197
+ "providerContract": {
198
+ "source": "packages/docx-cli/contracts/mcp-input/docx_table_index.schema.json",
199
+ "sha256": "7549ce28e3cc51ae17cd86c77c97698b6e90f0125afd34ae8831fde7f87ddf67"
200
+ },
201
+ "inputContract": {
202
+ "path": "office/contracts/docx_table_index.schema.json",
203
+ "sha256": "7549ce28e3cc51ae17cd86c77c97698b6e90f0125afd34ae8831fde7f87ddf67"
193
204
  }
194
205
  },
195
206
  {
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';
@@ -216,6 +216,18 @@ const docxListObjectsOutput = artifactOutput('docx_list_objects').extend({
216
216
  runtime: runtimeIdentity,
217
217
  }).strict();
218
218
 
219
+ const docxTableIndexOutput = artifactOutput('docx_table_index').extend({
220
+ schema: z.literal('tiwater.docx-table-index/v1'),
221
+ tables: z.array(z.object({
222
+ address: docxAddress,
223
+ parentAddress: docxAddress.nullable(),
224
+ rowCount: z.number().int().nonnegative(),
225
+ columnCount: z.number().int().nonnegative(),
226
+ textPreview: z.string(),
227
+ textLength: z.number().int().nonnegative(),
228
+ }).strict()),
229
+ }).strict();
230
+
219
231
  const docxReadObjectOutput = artifactOutput('docx_read_object').extend({
220
232
  observations: z.array(docxObservationNode).min(1),
221
233
  }).strict();
@@ -237,6 +249,14 @@ const tools = [
237
249
  annotations: { readOnlyHint: true, idempotentHint: true },
238
250
  handler: args => docxObservation('docx_list_objects', args),
239
251
  },
252
+ {
253
+ name: 'docx_table_index',
254
+ description: 'List every table in one current DOCX as a compact native index with its OpenXML address, row count, column count, and short text preview. Use it to choose a table and confirm its shape before listing rows or reading selected content. It does not return full cell content or decide table semantics.',
255
+ inputSchema: inputContract('docx_table_index'),
256
+ outputSchema: docxTableIndexOutput,
257
+ annotations: { readOnlyHint: true, idempotentHint: true },
258
+ handler: args => docxObservation('docx_table_index', args),
259
+ },
240
260
  {
241
261
  name: 'docx_read_object',
242
262
  description: 'Read selected tables, rows, cells, or paragraphs from one native DOCX in one call and return them in address order. Pass the document path once and only the OpenXML addresses needed for the current target. For exact inline content, use an observed cell or paragraph address and request run or text.',
@@ -559,6 +579,7 @@ async function docxObservation(tool, args) {
559
579
  if (tool === 'docx_list_objects') {
560
580
  return { ...retained, ...payload, objects: payload.objects.map(compactDocxObjectIdentity) };
561
581
  }
582
+ if (tool === 'docx_table_index') return { ...retained, ...payload };
562
583
  throw new Error(`unsupported-docx-observation-tool:${tool}`);
563
584
  });
564
585
  }
@@ -610,34 +631,39 @@ async function docxRefreshFields(args) {
610
631
  const input = path.resolve(requireString(args.input, 'input'));
611
632
  const output = path.resolve(requireString(args.output, 'output'));
612
633
  const receiptOutput = path.resolve(requireString(args.receiptOutput, 'receiptOutput'));
634
+ const inPlace = input === output;
635
+ const invocationOutput = inPlace ? temporarySibling(output) : output;
613
636
  if (path.extname(input).toLowerCase() !== '.docx' || path.extname(output).toLowerCase() !== '.docx') {
614
637
  throw Object.assign(new Error('DOCX field refresh requires .docx input and output'), { code: -32602 });
615
638
  }
616
- await requireNewFile(output, 'output');
639
+ if (!inPlace) await requireNewFile(output, 'output');
617
640
  await requireNewFile(receiptOutput, 'receiptOutput');
618
641
  const inputArtifact = await fileArtifact(input);
619
642
  try {
620
- const result = await runJsonCandidateChain(convertCandidates, ['refresh-docx-fields', input, output]);
643
+ const result = await runJsonCandidateChain(convertCandidates, ['refresh-docx-fields', input, invocationOutput]);
621
644
  const providerReceipt = docxFieldRefreshReceipt.parse(result.json);
622
- const outputArtifact = await fileArtifact(output);
645
+ const invocationArtifact = await fileArtifact(invocationOutput);
623
646
  if (path.resolve(providerReceipt.input) !== input
624
- || path.resolve(providerReceipt.output) !== output
647
+ || path.resolve(providerReceipt.output) !== invocationOutput
625
648
  || providerReceipt.input_sha256 !== inputArtifact.sha256
626
- || providerReceipt.output_sha256 !== outputArtifact.sha256) {
649
+ || providerReceipt.output_sha256 !== invocationArtifact.sha256) {
627
650
  throw new Error('DOCX field refresh receipt is not bound to the current input and output');
628
651
  }
652
+ if (inPlace) await rename(invocationOutput, output);
653
+ const outputArtifact = await fileArtifact(output);
654
+ const acceptedReceipt = { ...providerReceipt, output, output_sha256: outputArtifact.sha256 };
629
655
  return {
630
656
  tool: 'docx_refresh_fields',
631
657
  runtime: commandRuntime(result),
632
658
  output: outputArtifact,
633
- receipt: await writeJsonArtifact(receiptOutput, providerReceipt),
659
+ receipt: await writeJsonArtifact(receiptOutput, acceptedReceipt),
634
660
  summary: {
635
661
  backend: providerReceipt.backend,
636
662
  refreshScope: providerReceipt.refresh_scope,
637
663
  },
638
664
  };
639
665
  } catch (error) {
640
- await rm(output, { force: true });
666
+ await rm(invocationOutput, { force: true });
641
667
  throw error;
642
668
  }
643
669
  }
@@ -645,15 +671,24 @@ async function docxRefreshFields(args) {
645
671
  async function copyTransform(tool, candidates, command, args, suffix = []) {
646
672
  const input = path.resolve(requireString(args.input, 'input'));
647
673
  const output = path.resolve(requireString(args.output, 'output'));
648
- await requireNewFile(output, 'output');
649
- const result = await runCandidateChain(candidates, [...command, input, output, ...suffix]);
650
- return { tool, runtime: commandRuntime(result), output: await fileArtifact(output) };
674
+ const inPlace = input === output;
675
+ const invocationOutput = inPlace ? temporarySibling(output) : output;
676
+ if (!inPlace) await requireNewFile(output, 'output');
677
+ try {
678
+ const result = await runCandidateChain(candidates, [...command, input, invocationOutput, ...suffix]);
679
+ if (inPlace) await rename(invocationOutput, output);
680
+ return { tool, runtime: commandRuntime(result), output: await fileArtifact(output) };
681
+ } catch (error) {
682
+ await rm(invocationOutput, { force: true });
683
+ throw error;
684
+ }
651
685
  }
652
686
 
653
687
  async function fixedEdit(tool, args) {
688
+ const input = path.resolve(requireString(args.input, 'input'));
654
689
  const output = path.resolve(requireString(args.output, 'output'));
655
690
  const receiptOutput = path.resolve(requireString(args.receiptOutput, 'receiptOutput'));
656
- await requireNewFile(output, 'output');
691
+ if (!(tool.startsWith('docx_') && input === output)) await requireNewFile(output, 'output');
657
692
  await requireNewFile(receiptOutput, 'receiptOutput');
658
693
  const candidates = tool.startsWith('docx_') ? docxCandidates
659
694
  : tool.startsWith('xlsx_') ? xlsxCandidates
@@ -880,6 +915,12 @@ async function requireNewFile(filePath, label) {
880
915
  throw Object.assign(new Error(`${label} already exists: ${filePath}`), { code: -32602 });
881
916
  }
882
917
 
918
+ function temporarySibling(filePath) {
919
+ const extension = path.extname(filePath);
920
+ const stem = path.basename(filePath, extension);
921
+ return path.join(path.dirname(filePath), `.${stem}.${randomUUID()}.tmp${extension}`);
922
+ }
923
+
883
924
  function commandRuntime(result) {
884
925
  return {
885
926
  command: result.command,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiwater/office-mcp",
3
- "version": "0.18.2",
3
+ "version": "0.18.4",
4
4
  "description": "Published MCP server for Tiwater Office document capabilities",
5
5
  "type": "module",
6
6
  "license": "MIT",