mcp-word-bridge 3.5.0 → 3.5.1

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/README.md CHANGED
@@ -80,7 +80,7 @@ mcp-word-bridge/
80
80
  └── README.md
81
81
  ```
82
82
 
83
- ## Tools (90)
83
+ ## Tools (91)
84
84
 
85
85
  ### Document
86
86
  | Tool | Description |
@@ -222,6 +222,7 @@ mcp-word-bridge/
222
222
  | `word_get_sections` | List all sections with page setup |
223
223
  | `word_insert_page_break` | Insert a page break after a paragraph |
224
224
  | `word_insert_section_break` | Insert a section break after a paragraph |
225
+ | `word_get_page_info` | Get page count and per-page paragraphs with document indices (Desktop only) |
225
226
 
226
227
  ### Custom Properties
227
228
  | Tool | Description |
package/index.js CHANGED
@@ -134,7 +134,7 @@ function sendToTaskpane(action, params) {
134
134
  }
135
135
 
136
136
  const mcpServer = new Server(
137
- { name: 'mcp-word-bridge', version: '3.5.0' },
137
+ { name: 'mcp-word-bridge', version: '3.5.1' },
138
138
  { capabilities: { tools: {}, resources: {} } }
139
139
  );
140
140
 
package/lib/tools.js CHANGED
@@ -100,6 +100,7 @@ const tools = [
100
100
  { name: 'word_get_sections', description: '[Layout] List all sections with their page setup (margins, orientation, paper size).', inputSchema: { type: 'object', properties: {} } },
101
101
  { name: 'word_insert_page_break', description: '[Layout] Insert a page break after a paragraph. Omit paragraphIndex to insert at end of document.', inputSchema: { type: 'object', properties: { paragraphIndex: { type: 'number', description: 'Paragraph index (0-based). Omit for end of document.' } } } },
102
102
  { name: 'word_insert_section_break', description: '[Layout] Insert a section break after a paragraph. Cannot be used inside table cells.', inputSchema: { type: 'object', properties: { paragraphIndex: { type: 'number', description: 'Paragraph index (0-based). Omit for end of document.' }, breakType: { type: 'string', enum: ['SectionNext', 'SectionContinuous', 'SectionEven', 'SectionOdd'], description: 'Default: SectionNext' } } } },
103
+ { name: 'word_get_page_info', description: '[Layout] Get page count and per-page paragraph ranges. Returns page dimensions and the first/last document paragraph index for each page. Use with word_get_paragraphs to read specific page content.', inputSchema: { type: 'object', properties: {} } },
103
104
  // 16. CUSTOM PROPERTIES
104
105
  { name: 'word_get_custom_properties', description: '[Properties] Get all custom document properties (key-value pairs with types).', inputSchema: { type: 'object', properties: {} } },
105
106
  { name: 'word_set_custom_property', description: '[Properties] Set a custom document property. Creates or updates the key-value pair.', inputSchema: { type: 'object', properties: { key: { type: 'string' }, value: { type: 'string' } }, required: ['key', 'value'] } },
@@ -161,6 +162,7 @@ const toolActionMap = {
161
162
  word_delete_custom_property: 'deleteCustomProperty',
162
163
  word_insert_html: 'insertHtml', word_insert_ooxml: 'insertOoxml',
163
164
  word_insert_table_of_contents: 'insertTableOfContents', word_get_fields: 'getFields',
165
+ word_get_page_info: 'getPageInfo',
164
166
  // word_insert_equation, word_batch, word_get_document_outline, word_move_paragraph
165
167
  // are handled directly in index.js (not via taskpane action map)
166
168
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-word-bridge",
3
- "version": "3.5.0",
3
+ "version": "3.5.1",
4
4
  "description": "MCP server for live Word document editing via Office Add-in",
5
5
  "main": "index.js",
6
6
  "bin": {
package/taskpane-app.js CHANGED
@@ -1431,6 +1431,55 @@ commands.clearFormatting = (p) => Word.run(async (ctx) => {
1431
1431
  return { success: true };
1432
1432
  });
1433
1433
 
1434
+ // == PAGE INFO (WordApiDesktop 1.2+) ==
1435
+ commands.getPageInfo = async () => {
1436
+ if (!Office.context.requirements.isSetSupported('WordApiDesktop', '1.2')) {
1437
+ throw new Error('Page API not available on this platform (requires desktop Word).');
1438
+ }
1439
+ return Word.run(async (ctx) => {
1440
+ const bodyRange = ctx.document.body.getRange();
1441
+ const pages = bodyRange.pages;
1442
+ pages.load('items');
1443
+ await ctx.sync();
1444
+ const pageCount = pages.items.length;
1445
+ // Load all body paragraphs to map page boundaries to document indices
1446
+ const allParas = ctx.document.body.paragraphs;
1447
+ allParas.load('text,style');
1448
+ await ctx.sync();
1449
+ const pageDetails = [];
1450
+ const usedIndices = new Set();
1451
+ for (let i = 0; i < pages.items.length; i++) {
1452
+ const page = pages.items[i];
1453
+ page.load('index,height,width');
1454
+ const paras = page.getRange().paragraphs;
1455
+ paras.load('text,style');
1456
+ await ctx.sync();
1457
+ let firstIdx = -1;
1458
+ let lastIdx = -1;
1459
+ for (let j = 0; j < paras.items.length; j++) {
1460
+ const p = paras.items[j];
1461
+ for (let k = 0; k < allParas.items.length; k++) {
1462
+ if (!usedIndices.has(k) && allParas.items[k].text === p.text && allParas.items[k].style === p.style) {
1463
+ usedIndices.add(k);
1464
+ if (firstIdx === -1) firstIdx = k;
1465
+ lastIdx = k;
1466
+ break;
1467
+ }
1468
+ }
1469
+ }
1470
+ pageDetails.push({
1471
+ pageIndex: page.index,
1472
+ height: page.height,
1473
+ width: page.width,
1474
+ paragraphCount: paras.items.length,
1475
+ firstParagraphIndex: firstIdx,
1476
+ lastParagraphIndex: lastIdx
1477
+ });
1478
+ }
1479
+ return { pageCount, pages: pageDetails };
1480
+ });
1481
+ };
1482
+
1434
1483
  // == INSERT TOC ==
1435
1484
  commands.insertTableOfContents = (p) => Word.run(async (ctx) => {
1436
1485
  const body = ctx.document.body;