Skip to main content
Glama

accept_changes

Destructive

Accept all tracked changes in a DOCX document to remove revision markup and produce a clean final version with acceptance statistics.

Instructions

Accept all tracked changes in the document body, producing a clean document with no revision markup. Returns acceptance stats.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_pathYesPath to the DOCX file.

Implementation Reference

  • MCP tool handler that calls doc.acceptChanges() and marks the session as edited.
    export async function acceptChanges(
      manager: SessionManager,
      params: { file_path?: string },
    ): Promise<ToolResponse> {
      const resolved = await resolveSessionForTool(manager, params, { toolName: 'accept_changes' });
      if (!resolved.ok) return resolved.response;
      const { session, metadata } = resolved;
    
      try {
        const stats = session.doc.acceptChanges();
        manager.markEdited(session);
        return ok(mergeSessionResolutionMetadata({
          ...stats,
          file_path: manager.normalizePath(session.originalPath),
        }, metadata));
      } catch (e: unknown) {
        return err('ACCEPT_CHANGES_ERROR', errorMessage(e));
      }
    }
  • Core implementation of acceptChanges, which traverses the XML DOM to remove/unwrap revision-related elements.
    export function acceptChanges(doc: Document): AcceptChangesResult {
      const body = doc.getElementsByTagNameNS(W_NS, 'body').item(0);
      if (!body) {
        return { insertionsAccepted: 0, deletionsAccepted: 0, movesResolved: 0, propertyChangesResolved: 0 };
      }
    
      // Phase A — Identify paragraphs to remove
      const paragraphsToRemove = new Set<Element>();
      const allParagraphs = collectByLocalName(body, 'p');
    
      for (const p of allParagraphs) {
        // Paragraph-level deletion marker: w:p > w:pPr > w:rPr > w:del
        if (paragraphHasParaMarker(p, 'del')) {
          paragraphsToRemove.add(p);
          continue;
        }
        // Paragraphs whose only content is inside w:del or w:moveFrom
        if (paragraphHasOnlyRemovedContent(p)) {
          paragraphsToRemove.add(p);
        }
      }
    
      // Phase B — Remove deletions and move sources
      const deletionsAccepted = removeAllByLocalName(body, 'del');
      const moveFromRemoved = removeAllByLocalName(body, 'moveFrom');
      removeAllByLocalName(body, 'moveFromRangeStart');
      removeAllByLocalName(body, 'moveFromRangeEnd');
      removeAllByLocalName(body, 'moveToRangeStart');
      removeAllByLocalName(body, 'moveToRangeEnd');
    
      // Phase C — Unwrap insertions and move destinations (depth-sorted)
      const insertionsAccepted = unwrapAllByLocalName(body, 'ins');
      const moveToUnwrapped = unwrapAllByLocalName(body, 'moveTo');
    
      // Phase D — Remove property change records
      let propertyChangesResolved = 0;
      for (const localName of PR_CHANGE_LOCALS) {
        propertyChangesResolved += removeAllByLocalName(body, localName);
      }
    
      // Phase E — Cleanup
      // Strip paragraph-level revision markers from w:pPr/w:rPr
      for (const p of collectByLocalName(body, 'p')) {
        for (let i = 0; i < p.childNodes.length; i++) {
          const child = p.childNodes[i]!;
          if (!isW(child, 'pPr')) continue;
          for (let j = 0; j < child.childNodes.length; j++) {
            const pPrChild = child.childNodes[j]!;
            if (!isW(pPrChild, 'rPr')) continue;
            // Remove w:ins and w:del marker elements inside pPr > rPr
            const toRemove: Element[] = [];
            for (let k = 0; k < pPrChild.childNodes.length; k++) {
              const rPrChild = pPrChild.childNodes[k]!;
              if (isW(rPrChild, 'ins') || isW(rPrChild, 'del')) {
                toRemove.push(rPrChild as Element);
              }
            }
            for (const el of toRemove) {
              pPrChild.removeChild(el);
            }
          }
        }
      }
    
      // Remove paragraphs collected in Phase A (check parentNode still exists)
      for (const p of paragraphsToRemove) {
        if (p.parentNode) {
          p.parentNode.removeChild(p);
        }
      }
    
      // Strip w:rsidDel attributes on remaining elements
      const allElements = body.getElementsByTagNameNS(W_NS, '*');
      for (let i = 0; i < allElements.length; i++) {
        const el = allElements[i]!;
        if (el.hasAttributeNS(W_NS, 'rsidDel')) {
          el.removeAttributeNS(W_NS, 'rsidDel');
        }
        // Also check prefixed form
        if (el.hasAttribute('w:rsidDel')) {
          el.removeAttribute('w:rsidDel');
        }
      }
    
      return {
        insertionsAccepted,
        deletionsAccepted,
        movesResolved: moveFromRemoved + moveToUnwrapped,
        propertyChangesResolved,
      };
    }
  • Registration of the 'accept_changes' tool in the tool catalog.
    name: 'accept_changes',
Behavior4/5

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

Annotations already indicate this is a destructive operation (destructiveHint: true), which the description confirms by explaining the result is a 'clean document with no revision markup.' It adds valuable behavioral context by disclosing that the tool 'Returns acceptance stats,' information not available in annotations or schema.

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

Conciseness5/5

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

The description consists of two efficient sentences with zero waste. It is front-loaded with the action and effect, followed by the return value, making it immediately scannable and actionable.

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

Completeness4/5

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

Given the destructive nature and lack of output schema, the description appropriately compensates by mentioning the return of 'acceptance stats' and explaining the document transformation. It covers the essential behavioral contract despite being a single-parameter tool.

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

Parameters3/5

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

With 100% schema description coverage for the single 'file_path' parameter, the schema fully documents the input requirements. The description provides no additional parameter semantics, but this is acceptable given the comprehensive schema coverage.

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

Purpose5/5

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

The description uses a specific verb ('Accept') with a clear resource ('tracked changes in the document body') and outcome ('producing a clean document with no revision markup'). It effectively distinguishes from siblings like extract_revisions (which extracts) and has_tracked_changes (which checks).

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?

While the description implies this tool is for finalizing documents by removing revision markup, it provides no explicit guidance on when to choose this over alternatives like extract_revisions or has_tracked_changes, nor does it mention prerequisites or irreversibility.

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

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/UseJunior/safe-docx'

If you have feedback or need assistance with the MCP directory API, please join our Discord server