mcp-word-bridge 4.1.0 → 4.1.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/dist/server.js CHANGED
@@ -18722,7 +18722,15 @@ var Bridge = class {
18722
18722
 
18723
18723
  // src/server/mcp.ts
18724
18724
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
18725
- var import_types7 = require("@modelcontextprotocol/sdk/types.js");
18725
+ var import_types8 = require("@modelcontextprotocol/sdk/types.js");
18726
+
18727
+ // src/server/types.ts
18728
+ var ToolError = class extends Error {
18729
+ constructor(message) {
18730
+ super(message);
18731
+ this.name = "ToolError";
18732
+ }
18733
+ };
18726
18734
 
18727
18735
  // src/server/tools/helpers.ts
18728
18736
  function jsonResult(data) {
@@ -18823,6 +18831,9 @@ var getDocumentOutline = {
18823
18831
  },
18824
18832
  async handler(args, bridge2) {
18825
18833
  const maxLevel = args.maxLevel ?? 3;
18834
+ if (typeof args.maxLevel === "number" && (args.maxLevel < 1 || args.maxLevel > 9 || !Number.isInteger(args.maxLevel))) {
18835
+ throw new ToolError("maxLevel must be an integer between 1 and 9.");
18836
+ }
18826
18837
  const result = await bridge2.send("getParagraphs", {});
18827
18838
  const headings = [];
18828
18839
  for (const para of result.paragraphs) {
@@ -18854,14 +18865,6 @@ var documentTools = [
18854
18865
  getDocumentOutline
18855
18866
  ];
18856
18867
 
18857
- // src/server/types.ts
18858
- var ToolError = class extends Error {
18859
- constructor(message) {
18860
- super(message);
18861
- this.name = "ToolError";
18862
- }
18863
- };
18864
-
18865
18868
  // src/server/validation.ts
18866
18869
  function checkNonEmpty(value, name) {
18867
18870
  if (!value || typeof value !== "string" || value.trim() === "") {
@@ -19180,12 +19183,17 @@ var paragraphTools = [
19180
19183
  // src/server/tools/search.ts
19181
19184
  var search = forwardTool(
19182
19185
  "word_search",
19183
- '[Search] Find text in the document. Returns match count and up to 30 matches. Query must be \u2264255 chars. Note: Word search codes (^p = paragraph mark, ^t = tab) are interpreted. To search for literal "^", use "^^".',
19186
+ '[Search] Find text in the document. Returns match count and up to 30 matches. Query must be \u2264255 chars. Supports Word search codes (^p = paragraph mark, ^t = tab, etc.) and wildcard mode (?, *, [], {n,m}). To search for literal "^", use "^^".',
19184
19187
  {
19185
19188
  properties: {
19186
19189
  query: { type: "string" },
19187
19190
  matchCase: { type: "boolean", description: "Case-sensitive search. Default: false" },
19188
- matchWholeWord: { type: "boolean" }
19191
+ matchWholeWord: { type: "boolean", description: "Match whole words only. Default: false" },
19192
+ matchWildcards: { type: "boolean", description: "Enable wildcard/regex search (?, *, [], {n,m}, @). Default: false" },
19193
+ matchPrefix: { type: "boolean", description: "Match words that begin with the search string. Default: false" },
19194
+ matchSuffix: { type: "boolean", description: "Match words that end with the search string. Default: false" },
19195
+ ignorePunct: { type: "boolean", description: "Ignore punctuation between words when matching. Default: false" },
19196
+ ignoreSpace: { type: "boolean", description: "Ignore whitespace between words when matching. Default: false" }
19189
19197
  },
19190
19198
  required: ["query"]
19191
19199
  },
@@ -19193,13 +19201,18 @@ var search = forwardTool(
19193
19201
  );
19194
19202
  var searchAndReplace = {
19195
19203
  name: "word_search_and_replace",
19196
- description: "[Search] Find and replace ALL occurrences. Supports Word search codes (^p = paragraph mark, ^t = tab). For single-paragraph edits, prefer word_replace_paragraph_text.",
19204
+ description: "[Search] Find and replace ALL occurrences. Supports Word search codes in both find and replace: ^p (paragraph mark), ^l (line break), ^m (page break), ^n (column break), ^t (tab), ^s (non-breaking space), ^~ (non-breaking hyphen), ^- (optional hyphen), ^+ (em dash), ^= (en dash), ^^ (literal caret). Supports wildcard search in find string. For single-paragraph edits, prefer word_replace_paragraph_text.",
19197
19205
  schema: {
19198
19206
  properties: {
19199
19207
  find: { type: "string" },
19200
19208
  replace: { type: "string" },
19201
19209
  matchCase: { type: "boolean", description: "Default: false" },
19202
- matchWholeWord: { type: "boolean" },
19210
+ matchWholeWord: { type: "boolean", description: "Match whole words only. Default: false" },
19211
+ matchWildcards: { type: "boolean", description: "Enable wildcard/regex search in find string (?, *, [], {n,m}, @). Default: false" },
19212
+ matchPrefix: { type: "boolean", description: "Match words that begin with the find string. Default: false" },
19213
+ matchSuffix: { type: "boolean", description: "Match words that end with the find string. Default: false" },
19214
+ ignorePunct: { type: "boolean", description: "Ignore punctuation between words when matching. Default: false" },
19215
+ ignoreSpace: { type: "boolean", description: "Ignore whitespace between words when matching. Default: false" },
19203
19216
  preserveBookmarks: { type: "boolean", description: "Re-create bookmarks on replacement text after replace. Default: false" }
19204
19217
  },
19205
19218
  required: ["find", "replace"]
@@ -19215,14 +19228,19 @@ var searchAndReplace = {
19215
19228
  };
19216
19229
  var insertTextAtMatch = forwardTool(
19217
19230
  "word_insert_text_at_match",
19218
- '[Search] Insert text before or after a search match. Provide "after" OR "before" as the anchor text. Use occurrence for Nth match.',
19231
+ '[Search] Insert text before or after a search match. Supports Word search codes in inserted text: ^p (paragraph mark), ^l (line break), ^t (tab), ^s (non-breaking space), ^m (page break), ^n (column break), ^~ (non-breaking hyphen), ^- (optional hyphen), ^+ (em dash), ^= (en dash), ^^ (literal caret). Provide "after" OR "before" as the anchor text. Use occurrence for Nth match.',
19219
19232
  {
19220
19233
  properties: {
19221
19234
  text: { type: "string", description: "Text to insert" },
19222
19235
  after: { type: "string", description: "Search for this text and insert AFTER it" },
19223
19236
  before: { type: "string", description: "Search for this text and insert BEFORE it" },
19224
19237
  occurrence: { type: "number", description: "0=first, 1=second, etc. Default: 0" },
19225
- matchCase: { type: "boolean", description: "Default: false" }
19238
+ matchCase: { type: "boolean", description: "Default: false" },
19239
+ matchWildcards: { type: "boolean", description: "Enable wildcard/regex search for anchor text. Default: false" },
19240
+ matchPrefix: { type: "boolean", description: "Match words that begin with the anchor text. Default: false" },
19241
+ matchSuffix: { type: "boolean", description: "Match words that end with the anchor text. Default: false" },
19242
+ ignorePunct: { type: "boolean", description: "Ignore punctuation between words when matching. Default: false" },
19243
+ ignoreSpace: { type: "boolean", description: "Ignore whitespace between words when matching. Default: false" }
19226
19244
  },
19227
19245
  required: ["text"]
19228
19246
  },
@@ -19813,6 +19831,9 @@ var setContentControlText = {
19813
19831
  if (tag) {
19814
19832
  const ccResult = await bridge2.send("getContentControls", {});
19815
19833
  const matches = ccResult.controls.filter((c) => c.tag === tag);
19834
+ if (matches.length === 0) {
19835
+ throw new ToolError(`Content control with tag "${tag}" not found. Use word_get_content_controls to list available controls.`);
19836
+ }
19816
19837
  if (matches.length > 1) {
19817
19838
  throw new ToolError(
19818
19839
  `Multiple content controls (${matches.length}) share tag "${tag}". Use "id" instead to target a specific control. Matching IDs: ${matches.map((m) => m.id).join(", ")}.`
@@ -20442,7 +20463,7 @@ After inserting a Table of Contents, heading text appears twice (in TOC and body
20442
20463
  // package.json
20443
20464
  var package_default = {
20444
20465
  name: "mcp-word-bridge",
20445
- version: "4.1.0",
20466
+ version: "4.1.1",
20446
20467
  description: "MCP server for live Word document editing via Office Add-in",
20447
20468
  main: "dist/server.js",
20448
20469
  bin: {
@@ -20507,7 +20528,7 @@ function createMcpServer(bridge2) {
20507
20528
  );
20508
20529
  const { tools, handlers } = buildToolRegistry();
20509
20530
  const toolMutex = createMutex();
20510
- server.setRequestHandler(import_types7.ListToolsRequestSchema, async () => ({
20531
+ server.setRequestHandler(import_types8.ListToolsRequestSchema, async () => ({
20511
20532
  tools: tools.map((t) => ({
20512
20533
  name: t.name,
20513
20534
  description: t.description,
@@ -20518,7 +20539,7 @@ function createMcpServer(bridge2) {
20518
20539
  }
20519
20540
  }))
20520
20541
  }));
20521
- server.setRequestHandler(import_types7.CallToolRequestSchema, async (request) => {
20542
+ server.setRequestHandler(import_types8.CallToolRequestSchema, async (request) => {
20522
20543
  return toolMutex.run(async () => {
20523
20544
  const { name, arguments: args } = request.params;
20524
20545
  const handler = handlers.get(name);
@@ -20534,7 +20555,7 @@ function createMcpServer(bridge2) {
20534
20555
  }
20535
20556
  });
20536
20557
  });
20537
- server.setRequestHandler(import_types7.ListResourcesRequestSchema, async () => ({
20558
+ server.setRequestHandler(import_types8.ListResourcesRequestSchema, async () => ({
20538
20559
  resources: [{
20539
20560
  uri: "word-bridge://usage-guide",
20540
20561
  name: "Word Bridge Usage Guide",
@@ -20542,7 +20563,7 @@ function createMcpServer(bridge2) {
20542
20563
  mimeType: "text/markdown"
20543
20564
  }]
20544
20565
  }));
20545
- server.setRequestHandler(import_types7.ReadResourceRequestSchema, async (request) => {
20566
+ server.setRequestHandler(import_types8.ReadResourceRequestSchema, async (request) => {
20546
20567
  if (request.params.uri === "word-bridge://usage-guide") {
20547
20568
  return { contents: [{ uri: request.params.uri, mimeType: "text/markdown", text: usageGuide }] };
20548
20569
  }