Skip to main content
Glama

doc_diff

Read-onlyIdempotent

Align paragraphs of two document versions to map old addresses to new and reveal unchanged, modified, moved, split, merged, inserted, or deleted content.

Instructions

Align the paragraphs of two versions (old, new; .docx, or .txt/.md/.odt): which are unchanged, modified, moved, split, merged, inserted or deleted, with a map from old addresses to new ones (null for deleted). Use it to carry addresses read from an older version over to the current one, or to see what changed; doc.compare writes the same differences as a redline .docx instead. collapse_runs folds runs of shifted unchanged paragraphs into one record. Read-only; paged at about 8,000 bytes with limit and cursor (the next of the previous reply).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
newYesPath of the later version (.docx).
oldYesPath of the earlier version (.docx).
limitNoMost items to return; a response is also capped at about 8,000 bytes.
cursorNoThe `next` value of the previous response, to continue the list.
collapse_runsNoList runs of shifted unchanged paragraphs as one record each.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv0.7.2
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "api": {
      +      "description": "API version (1.0).",
      +      "type": "string"
      +    },
      +    "doc": {
      +      "description": "The document read or written: path, sha256 and paragraph count.",
      +      "properties": {
      +        "characters": {
      +          "description": "text.normalize of a text string: its length.",
      +          "type": "integer"
      +        },
      +        "paragraphs": {
      +          "description": "Body paragraphs.",
      +          "type": "integer"
      +        },
      +        "path": {
      +          "description": "Path of the document.",
      +          "type": "string"
      +        },
      +        "sha256": {
      +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
      +          "type": "string"
      +        },
      +        "source": {
      +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
      +          "type": [
      +            "object",
      +            "string"
      +          ]
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "next": {
      +      "description": "Cursor for the next page (pass as cursor), or null.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "ok": {
      +      "description": "Always true on success.",
      +      "type": "boolean"
      +    },
      +    "op": {
      +      "description": "The operation that ran.",
      +      "type": "string"
      +    },
      +    "result": {
      +      "description": "What the operation returns.",
      +      "properties": {
      +        "address_map": {
      +          "description": "Old address -> new address (null if deleted) for this page.",
      +          "type": "object"
      +        },
      +        "changes": {
      +          "description": "This page of change records (unchanged paragraphs that kept their address are left out).",
      +          "items": {
      +            "description": "One aligned change.",
      +            "properties": {
      +              "count": {
      +                "description": "With collapse_runs: unchanged paragraphs this record stands for.",
      +                "type": "integer"
      +              },
      +              "kind": {
      +                "description": "unchanged, modified, inserted, deleted, moved, split or merged.",
      +                "type": "string"
      +              },
      +              "moved": {
      +                "description": "True when it also moved.",
      +                "type": "boolean"
      +              },
      +              "new": {
      +                "description": "New addresses involved.",
      +                "items": {
      +                  "type": "string"
      +                },
      +                "type": "array"
      +              },
      +              "old": {
      +                "description": "Old addresses involved.",
      +                "items": {
      +                  "type": "string"
      +                },
      +                "type": "array"
      +              },
      +              "similarity": {
      +                "description": "Text similarity, 0-1, for a modified paragraph.",
      +                "type": "number"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "type": "array"
      +        },
      +        "new": {
      +          "description": "The later version.",
      +          "properties": {
      +            "characters": {
      +              "description": "text.normalize of a text string: its length.",
      +              "type": "integer"
      +            },
      +            "paragraphs": {
      +              "description": "Body paragraphs.",
      +              "type": "integer"
      +            },
      +            "path": {
      +              "description": "Path of the document.",
      +              "type": "string"
      +            },
      +            "sha256": {
      +              "description": "sha256 of the file (pass as expect.sha256 to a write).",
      +              "type": "string"
      +            },
      +            "source": {
      +              "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
      +              "type": [
      +                "object",
      +                "string"
      +              ]
      +            }
      +          },
      +          "type": "object"
      +        },
      +        "old": {
      +          "description": "The earlier version.",
      +          "properties": {
      +            "characters": {
      +              "description": "text.normalize of a text string: its length.",
      +              "type": "integer"
      +            },
      +            "paragraphs": {
      +              "description": "Body paragraphs.",
      +              "type": "integer"
      +            },
      +            "path": {
      +              "description": "Path of the document.",
      +              "type": "string"
      +            },
      +            "sha256": {
      +              "description": "sha256 of the file (pass as expect.sha256 to a write).",
      +              "type": "string"
      +            },
      +            "source": {
      +              "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
      +              "type": [
      +                "object",
      +                "string"
      +              ]
      +            }
      +          },
      +          "type": "object"
      +        },
      +        "summary": {
      +          "description": "Paragraphs per alignment kind.",
      +          "properties": {
      +            "deleted": {
      +              "description": "Deleted.",
      +              "type": "integer"
      +            },
      +            "inserted": {
      +              "description": "Inserted.",
      +              "type": "integer"
      +            },
      +            "merged": {
      +              "description": "Joined.",
      +              "type": "integer"
      +            },
      +            "modified": {
      +              "description": "Edited in place.",
      +              "type": "integer"
      +            },
      +            "moved": {
      +              "description": "Moved.",
      +              "type": "integer"
      +            },
      +            "split": {
      +              "description": "Split in two or more.",
      +              "type": "integer"
      +            },
      +            "unchanged": {
      +              "description": "Unchanged.",
      +              "type": "integer"
      +            }
      +          },
      +          "type": "object"
      +        },
      +        "total": {
      +          "description": "Change records in all pages.",
      +          "type": "integer"
      +        }
      +      },
      +      "required": [
      +        "old",
      +        "new",
      +        "summary",
      +        "total",
      +        "changes",
      +        "address_map"
      +      ],
      +      "type": "object"
      +    },
      +    "warnings": {
      +      "description": "Things to know about the result.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    }
      +  },
      +  "required": [
      +    "api",
      +    "ok",
      +    "op",
      +    "result",
      +    "warnings",
      +    "next"
      +  ],
      +  "type": "object"
      +}
  2. Addedv0.1.3

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotentHint/openWorldHint=false, so the safety profile is covered, but the description adds genuinely new behavior: paging at ~8,000 bytes with limit and cursor carried forward from the previous reply's `next`, and that deleted paragraphs map to null. A minor gap is that it doesn't describe error behavior on missing/mismatched files.

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

Conciseness4/5

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

Front-loaded with the core verb+resource, then alternatives, then pagination mechanics. No filler sentences, though the single dense paragraph packs several distinct ideas (output, alternatives, siblings, pagination) that could be split for faster scanning.

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?

With an output schema present, return shape need not be spelled out, yet the description still explains the address map and null-for-deleted semantics. Combined with read-only disclosure, sibling routing, and pagination rules, an agent has everything needed to call this correctly.

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 coverage is 100% and the schema documents each parameter, so the baseline is 3. The description still adds value by tying limit+cursor together as a pagination mechanism ('the `next` of the previous reply') and explaining collapse_runs as folding shifted-unchanged runs into one record, which the schema only states in one line.

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?

States a specific verb and resource ('Align the paragraphs of two versions') and enumerates the exact change categories (unchanged, modified, moved, split, merged, inserted, deleted) plus the old-to-new address map. It also names the sibling doc.compare and how it differs, so an agent can select correctly without opening schemas.

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

Usage Guidelines5/5

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

Explicitly gives the two intended uses ('carry addresses read from an older version over to the current one, or to see what changed') and routes the alternative case to doc.compare ('writes the same differences as a redline .docx instead'). It also notes when to reach for collapse_runs.

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