Skip to main content
Glama

Preview an edit plan

preview_plan
Read-onlyIdempotent

Dry-runs a DocumentPlan JSON against a Word, PowerPoint, or Excel document to validate edits before applying, returning drift, errors, and changes without committing.

Instructions

Dry-run a DocumentPlan JSON against (connectionId, documentId). Returns {isValid, committed, receipt, sourceDocumentId, outputConnectionId, outputDocumentId, outputVersion, outputName, outputContentType, changes, errors, calculation}; the output fields are null and committed is false. Plan shape: { "snapshot": { "eTag": "" }, "revision": { "author": "Review Bot", "timestampUtc": "2026-09-09T10:00:00Z" }, "operations": [ ... ] }. revision controls Word's displayed revision identity; omit timestampUtc to use one engine timestamp for the whole apply. The snapshot detects drift in Word text-host XML, PowerPoint slide/notes XML, and Excel workbook, worksheet, table and note XML; other parts rely on anchors and provider version checks. Omit it only intentionally. Omit contractVersion for legacy 0.2 behavior, or set it to exactly "0.2". Other values fail with contract-mismatch. Unknown properties and enum values fail with invalid-json. Each operation is one object. Concrete examples:

// Replace text: { "op": "changeText", "target": { "paraId": "w14:...", "expect": "Acme Corp", "occurrence": 0 }, "with": "Globex Inc.", "mode": "Tracked" }

// Unified formatting (paragraph/run/table/row/cell/image): { "op": "format", "target": { "paraId": "w14:...", "expect": "important", "occurrence": 0 }, "highlight": "yellow", "bold": true, "color": "FF0000" } { "op": "format", "target": { "kind": "table", "path": "table#0" }, "styleId": "TableGrid", "borderStyle": "single" } { "op": "format", "target": { "kind": "image", "path": "image#0" }, "widthPx": 320, "heightPx": 200 }

// Fill / comment / insert paragraph / setProperty: { "op": "fill", "target": { "tag": "ClientName" }, "value": "Globex" } { "op": "comment", "target": { "paraId": "w14:...", "expect": "..." }, "text": "Confirm this." } { "op": "insert", "target": { "paraId": "w14:...", "expect": "..." }, "position": "After", "text": "New paragraph." } { "op": "insertParagraphs", "target": { "paraId": "w14:...", "expect": "..." }, "position": "After", "paragraphs": [{ "text": "First" }, { "text": "Second" }] } { "op": "removeParagraph", "target": { "paraId": "w14:...", "expect": "Complete paragraph text" } } { "op": "setProperty", "target": { "kind": "docProperty", "path": "core/title" }, "value": "My Title" }

// Every verb above that changes Word content also takes "mode": "Tracked" (the default - the edit lands as a redline a reviewer accepts or rejects) or "Direct". A deck refuses "Tracked": PresentationML has no revision markup.

// Review an existing redline. Revision paths come from inspect_document.nodes (kind "revision"): 'ins#7', 'del#7', 'markIns#7', 'rowIns#7', 'cellDel#7', 'runFormat#7', 'paraFormat#7'. 'all' takes every one; 'author:' takes one person's. An edit that spans a pending revision is refused with revision-overlap; resolve it here first, then re-inspect: { "op": "revision", "target": { "kind": "revision", "path": "all" }, "action": "Accept" } { "op": "revision", "target": { "kind": "revision", "path": "author:Jane Doe" }, "action": "Reject" }

// Reply to, resolve, or delete an existing comment (comment paths from inspect_document.nodes, kind "comment"): { "op": "comment", "target": { "kind": "comment", "path": "comment#1" }, "action": "Reply", "text": "Forty-five, per the MSA." } { "op": "comment", "target": { "kind": "comment", "path": "comment#1" }, "action": "Resolve" } { "op": "comment", "target": { "kind": "comment", "path": "comment#1" }, "action": "Remove" }

// Link existing text (Word only, Direct; http, https or mailto): { "op": "link", "target": { "paraId": "w14:...", "expect": "the price list" }, "url": "https://example.com/prices" } // Continue a list the document already defines (numbering id from a "list#N" node in inspect_document.nodes): { "op": "format", "target": { "paraId": "w14:...", "expect": "" }, "numberingId": 42, "listLevel": 1 }

// Define a style once instead of repeating direct formatting on every paragraph. Word only. // Define it first, then apply it with format's styleId - both can sit in the same plan: { "op": "defineStyle", "styleId": "Quote", "name": "Pull Quote", "basedOn": "Normal", "next": "Normal", "fontFamily": "Georgia", "sizeHalfPoints": 24, "italic": true, "color": "444444", "alignment": "center", "indentLeftTwips": 720, "spacingBeforeTwips": 240 } { "op": "format", "target": { "paraId": "w14:...", "expect": "" }, "styleId": "Quote" } // type is paragraph (default), character or table. outlineLevel 1-9 puts a heading in the outline. // Defining a style that exists updates it; properties you leave out keep their values. Styles are // never deleted. A style cannot carry a highlight - w:highlight belongs to a run, so use color here.

// Word page geometry, breaks, and notes. All measurements are twips (1440 to the inch). Word only: { "op": "pageSetup", "paperSize": "A4", "orientation": "Landscape", "marginTopTwips": 720, "marginLeftTwips": 1080 } { "op": "insertBreak", "target": { "paraId": "w14:...", "expect": "..." }, "kind": "Page", "position": "After" } { "op": "insertBreak", "target": { "paraId": "w14:...", "expect": "..." }, "kind": "SectionNextPage" } // then pageSetup with a target inside the new section { "op": "note", "target": { "paraId": "w14:...", "expect": "thirty days" }, "kind": "Footnote", "text": "Subject to clause 8.2." } { "op": "note", "target": { "kind": "note", "path": "footnote#1" }, "action": "Update", "text": "Revised wording." } { "op": "note", "target": { "kind": "note", "path": "footnote#1" }, "action": "Remove" }

// Insert a whole new table after a paragraph, or remove an entire table (table path from inspect_document.nodes): { "op": "insertTable", "target": { "paraId": "w14:...", "expect": "..." }, "position": "After", "table": { "headers": ["Region", "Q1"], "rows": [["NL", "41850"]] } } { "op": "removeTable", "target": { "kind": "table", "path": "table#0" } }

// Add or remove table rows / columns; insert or remove image; copy or clear styles. Paths come from inspect_document.nodes: { "op": "insertTableRows", "target": { "kind": "table", "path": "table#0" }, "rows": [["NL","17","41850"]], "position": "End" } { "op": "repeatTableRow", "target": { "kind": "table", "path": "table#0" }, "templateRowIndex": 1, "records": [{ "Description": "Consulting", "Amount": "1200.00" }] } { "op": "removeTableRows", "target": { "kind": "table", "path": "table#0" }, "onlyIfEmpty": true } { "op": "mergeTableCells", "target": { "kind": "tableCell", "path": "table#0/cell#0/1" }, "columnSpan": 2 } // Word only, Direct: merges with the cells to its right { "op": "insertImage", "target": { "paraId": "w14:...", "expect": "..." }, "base64Bytes": "iVBORw0KGgo...", "imageType": "png", "widthPx": 200, "heightPx": 80 } { "op": "insertImage", "target": { "paraId": "w14:...", "expect": "..." }, "imageConnectionId": "images", "imageDocumentId": "", "imageType": "png", "widthPx": 200, "heightPx": 80 } { "op": "removeImage", "target": { "kind": "image", "path": "image#0" } } { "op": "backgroundImage", "base64Bytes": "iVBORw0KGgo...", "imageType": "png", "opacity": 0.2 } { "op": "backgroundImage", "target": { "kind": "slide", "path": "slide#256" }, "base64Bytes": "iVBORw0KGgo...", "opacity": 0.15 } { "op": "headerFooter", "header": "Northwind Traders", "footer": "Confidential", "showPageNumber": true, "alignment": "edges", "differentFirstPage": true }

// Native PowerPoint chart with an editable embedded workbook: { "op": "insertChart", "target": { "kind": "slide", "path": "slide#256" }, "kind": "ClusteredColumn", "categories": ["Q1","Q2"], "series": [{ "name": "Revenue", "values": [10,12] }], "title": "Revenue", "description": "Quarterly revenue" }

// Excel cells and table rows; sheet ids and table paths come from inspection: { "op": "setCell", "target": { "sheetId": 7, "address": "B2" }, "formula": "SUM(B3:B8)" } { "op": "appendTableRows", "target": { "kind": "spreadsheetTable", "path": "table#7/Sales" }, "rows": [["APAC","15"]] }

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
planJsonYes
documentIdYes
connectionIdYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/idempotent/non-destructive, and the description goes well beyond them: it enumerates the failure modes (contract-mismatch, invalid-json, revision-overlap), explains what drifts the snapshot detects across Word/PowerPoint/Excel XML and what falls back to anchors, and states that outputs are null. That is substantive behavioral context beyond the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and return contract are front-loaded, which is good, but the body then sprawls into a very long reference of examples and op variants. Most of it earns its place given the 0% schema coverage, yet the density and length make it hard to scan for the single decision the agent is making.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool whose real complexity is an undocumented JSON DSL, the description supplies the plan grammar, per-provider constraints (deck refuses Tracked, style cannot carry highlight), error semantics, and the shape of the dry-run result even though no output schema exists. Nothing essential for a correct call appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden. It documents planJson exhaustively (snapshot, revision, contractVersion, every op verb and target shape), which is the hard parameter, but connectionId and documentId are only named parenthetically with no explanation of what they identify.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a precise verb and resource: 'Dry-run a DocumentPlan JSON against (connectionId, documentId),' and the return contract (output fields null, committed false) makes clear this is a non-mutating preview. It doesn't explicitly name the sibling apply_plan as the operation that actually commits, so the distinction from that sibling is inferred rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Dry-run' implies the validate-before-apply workflow, and there is scattered procedural guidance ('resolve it here first, then re-inspect', 'Omit it only intentionally'). But there is no explicit when-to-use/when-not statement and no direct routing to apply_plan or inspect_document as the source of paths, leaving the agent to infer the workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.