@tiwater/office-mcp 0.18.10 → 0.18.12

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.
@@ -17,6 +17,18 @@
17
17
  "required": ["part", "path"],
18
18
  "additionalProperties": false
19
19
  },
20
+ "limit": {
21
+ "type": "integer",
22
+ "minimum": 1,
23
+ "maximum": 9007199254740991,
24
+ "description": "Maximum number of table rows requested in this response page. The provider may return fewer to keep the machine response bounded."
25
+ },
26
+ "offset": {
27
+ "type": "integer",
28
+ "minimum": 0,
29
+ "maximum": 9007199254740991,
30
+ "description": "Zero-based row offset. Continue from receipt.nextOffset until it is null."
31
+ },
20
32
  "output": {
21
33
  "type": "string",
22
34
  "minLength": 1,
@@ -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.18.10"
5
+ "version": "0.18.12"
6
6
  },
7
7
  "tools": [
8
8
  {
@@ -130,11 +130,11 @@
130
130
  "name": "docx_read_table",
131
131
  "providerContract": {
132
132
  "source": "packages/docx-cli/contracts/mcp-input/docx_read_table.schema.json",
133
- "sha256": "3b85fb6bc390053abdcdbcf4d5a2a4f958a06154286a0327676144324706af83"
133
+ "sha256": "c9c2bbab97bd58cb1426418f022f9c78be802eefb509e951fc4efa35e0096b63"
134
134
  },
135
135
  "inputContract": {
136
136
  "path": "office/contracts/docx_read_table.schema.json",
137
- "sha256": "3b85fb6bc390053abdcdbcf4d5a2a4f958a06154286a0327676144324706af83"
137
+ "sha256": "c9c2bbab97bd58cb1426418f022f9c78be802eefb509e951fc4efa35e0096b63"
138
138
  }
139
139
  },
140
140
  {
package/office/index.mjs CHANGED
@@ -247,6 +247,15 @@ const docxTableIndexOutput = artifactOutput('docx_table_index').extend({
247
247
 
248
248
  const docxTableReadOutput = artifactOutput('docx_read_table').extend({
249
249
  schema: z.literal('tiwater.docx-table-read/v1'),
250
+ receipt: z.object({
251
+ schema: z.literal('tiwater.docx-table-read-receipt/v1'),
252
+ totalRowCount: z.number().int().nonnegative(),
253
+ returnedRowCount: z.number().int().nonnegative(),
254
+ remaining: z.number().int().nonnegative(),
255
+ nextOffset: z.number().int().nonnegative().nullable(),
256
+ inlineTextNodesOmitted: z.literal(true),
257
+ narrowingRequired: z.boolean(),
258
+ }).strict(),
250
259
  address: docxAddress,
251
260
  rowCount: z.number().int().nonnegative(),
252
261
  columnCount: z.number().int().nonnegative(),
@@ -281,7 +290,14 @@ const docxTableReadOutput = artifactOutput('docx_read_table').extend({
281
290
  }).strict();
282
291
 
283
292
  const docxReadObjectOutput = artifactOutput('docx_read_object').extend({
284
- observations: z.array(docxObservationNode).min(1),
293
+ receipt: z.object({
294
+ schema: z.literal('tiwater.docx-read-object-receipt/v1'),
295
+ observationCount: z.number().int().positive(),
296
+ returnedCount: z.number().int().nonnegative(),
297
+ responseComplete: z.boolean(),
298
+ narrowingRequired: z.boolean(),
299
+ }).strict(),
300
+ observations: z.array(docxObservationNode),
285
301
  }).strict();
286
302
 
287
303
  const tools = [
@@ -295,7 +311,7 @@ const tools = [
295
311
  },
296
312
  {
297
313
  name: 'docx_list_objects',
298
- description: 'Page through mixed nearest-child OpenXML objects when document order or paragraph relationships are required. Continue with nextOffset and descend through a returned parent address. Do not use this tool to locate tables or read a whole document: use docx_table_index to locate tables, then docx_read_table for one selected table.',
314
+ description: 'Page through mixed nearest-child OpenXML objects when document order or paragraph relationships are required. The complete requested provider page is retained at output; the response returns a byte-bounded prefix. Continue with receipt.nextOffset and descend through a returned parent address. Do not use this tool to locate tables or read a whole document: use docx_table_index to locate tables, then docx_read_table for one selected table.',
299
315
  inputSchema: inputContract('docx_list_objects'),
300
316
  outputSchema: docxListObjectsOutput,
301
317
  annotations: { readOnlyHint: true, idempotentHint: true },
@@ -311,7 +327,7 @@ const tools = [
311
327
  },
312
328
  {
313
329
  name: 'docx_read_object',
314
- description: 'Read selected rows, cells, or paragraphs from one native DOCX in one call and return their requested descendants in address order. Use docx_read_table when the current task needs one complete table. For exact inline content, use an observed cell or paragraph address and request run or text.',
330
+ description: 'Read selected rows, cells, or paragraphs from one native DOCX and retain the complete result at output. The response returns compact requested descendants when bounded; if receipt.narrowingRequired is true, request fewer observed addresses or descendants. Use docx_read_table for a table.',
315
331
  inputSchema: inputContract('docx_read_object'),
316
332
  outputSchema: docxReadObjectOutput,
317
333
  annotations: { readOnlyHint: true, idempotentHint: true },
@@ -319,7 +335,7 @@ const tools = [
319
335
  },
320
336
  {
321
337
  name: 'docx_read_table',
322
- description: 'Read exactly one table selected from docx_table_index by native OpenXML address. Returns its nearest non-empty paragraph before and after the table, rows, cells, spans, vertical merges, paragraphs, text nodes, and reusable addresses in document order. It does not locate a table or decide business meaning.',
338
+ description: 'Read exactly one table selected from docx_table_index by native OpenXML address. Writes the complete table, including text nodes, to output and returns a bounded row page with cells, spans, vertical merges, paragraph text, and reusable addresses. Continue with receipt.nextOffset. If receipt.narrowingRequired is true, list rows under the same table and read smaller objects. It does not locate a table or decide business meaning.',
323
339
  inputSchema: inputContract('docx_read_table'),
324
340
  outputSchema: docxTableReadOutput,
325
341
  annotations: { readOnlyHint: true, idempotentHint: true },
@@ -637,7 +653,28 @@ async function docxObservation(tool, args) {
637
653
  artifact: await writeJsonArtifact(output, result.json),
638
654
  };
639
655
  if (tool === 'docx_list_objects') {
640
- return { ...retained, ...payload, objects: payload.objects.map(compactDocxObjectIdentity) };
656
+ const totalCount = payload.receipt.totalCount;
657
+ const offset = Math.min(args.offset ?? 0, totalCount);
658
+ const objects = [];
659
+ for (const sourceObject of payload.objects.map(compactDocxObjectIdentity)) {
660
+ const candidate = [...objects, sourceObject];
661
+ if (objects.length > 0 && Buffer.byteLength(JSON.stringify(candidate)) > 6_500) break;
662
+ objects.push(sourceObject);
663
+ }
664
+ const nextOffset = offset + objects.length < totalCount ? offset + objects.length : null;
665
+ return {
666
+ ...retained,
667
+ schema: payload.schema,
668
+ receipt: {
669
+ schema: 'tiwater.docx-observation-receipt/v1',
670
+ operation: 'list',
671
+ totalCount,
672
+ returnedCount: objects.length,
673
+ remaining: totalCount - offset - objects.length,
674
+ nextOffset,
675
+ },
676
+ objects,
677
+ };
641
678
  }
642
679
  if (tool === 'docx_table_index') {
643
680
  const totalCount = payload.tables.length;
@@ -663,7 +700,50 @@ async function docxObservation(tool, args) {
663
700
  tables,
664
701
  };
665
702
  }
666
- if (tool === 'docx_read_table') return { ...retained, ...payload };
703
+ if (tool === 'docx_read_table') {
704
+ const totalRowCount = payload.rows.length;
705
+ const offset = Math.min(args.offset ?? 0, totalRowCount);
706
+ const requestedLimit = args.limit ?? totalRowCount;
707
+ const rows = [];
708
+ let narrowingRequired = false;
709
+ for (const sourceRow of payload.rows.slice(offset, offset + requestedLimit)) {
710
+ const row = {
711
+ ...sourceRow,
712
+ cells: sourceRow.cells.map(cell => ({
713
+ ...cell,
714
+ paragraphs: cell.paragraphs.map(paragraph => ({ ...paragraph, textNodes: [] })),
715
+ })),
716
+ };
717
+ const candidate = [...rows, row];
718
+ if (Buffer.byteLength(JSON.stringify(candidate)) > 6_500) {
719
+ narrowingRequired = rows.length === 0;
720
+ break;
721
+ }
722
+ rows.push(row);
723
+ }
724
+ const nextOffset = !narrowingRequired && offset + rows.length < totalRowCount
725
+ ? offset + rows.length
726
+ : null;
727
+ return {
728
+ ...retained,
729
+ schema: payload.schema,
730
+ address: payload.address,
731
+ rowCount: payload.rowCount,
732
+ columnCount: payload.columnCount,
733
+ precedingParagraph: payload.precedingParagraph,
734
+ followingParagraph: payload.followingParagraph,
735
+ receipt: {
736
+ schema: 'tiwater.docx-table-read-receipt/v1',
737
+ totalRowCount,
738
+ returnedRowCount: rows.length,
739
+ remaining: totalRowCount - offset - rows.length,
740
+ nextOffset,
741
+ inlineTextNodesOmitted: true,
742
+ narrowingRequired,
743
+ },
744
+ rows,
745
+ };
746
+ }
667
747
  throw new Error(`unsupported-docx-observation-tool:${tool}`);
668
748
  });
669
749
  }
@@ -674,12 +754,21 @@ async function docxReadObject(args) {
674
754
  const { output: _output, ...request } = args;
675
755
  return withTempJsonFile(request, async requestPath => {
676
756
  const result = await runJsonCandidateChain(docxCandidates, ['docx_read_object', requestPath]);
757
+ const observations = result.json.observations.map(compactDocxObservation);
758
+ const responseComplete = Buffer.byteLength(JSON.stringify(observations)) <= 6_500;
677
759
  return {
678
760
  tool: 'docx_read_object',
679
761
  runtime: commandRuntime(result),
680
762
  source: await fileArtifact(input),
681
763
  artifact: await writeJsonArtifact(output, result.json),
682
- observations: result.json.observations.map(compactDocxObservation),
764
+ receipt: {
765
+ schema: 'tiwater.docx-read-object-receipt/v1',
766
+ observationCount: observations.length,
767
+ returnedCount: responseComplete ? observations.length : 0,
768
+ responseComplete,
769
+ narrowingRequired: !responseComplete,
770
+ },
771
+ observations: responseComplete ? observations : [],
683
772
  };
684
773
  });
685
774
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiwater/office-mcp",
3
- "version": "0.18.10",
3
+ "version": "0.18.12",
4
4
  "description": "Published MCP server for Tiwater Office document capabilities",
5
5
  "type": "module",
6
6
  "license": "MIT",