Skip to main content
Glama

Document Comparator

compare_documents

Analyze document changes by comparing original and revised versions to identify semantic differences including additions, deletions, and modifications.

Instructions

Compare two versions of a document and produce a semantic diff with additions, deletions, and modifications. Works with contracts, READMEs, policies, essays, or any text. Powered by Claude.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
originalYesThe original version of the document
revisedYesThe revised version of the document
modeNoOutput formatstructured
contextNoDocument type for more relevant analysis

Implementation Reference

  • The core handler function for the document-comparator tool that processes the input and calls Anthropic's API for semantic diffing.
    async function handler(input: Input) {
      const { original, revised, mode, context } = input;
    
      if (!config.anthropicApiKey) {
        throw new Error("ANTHROPIC_API_KEY is not configured");
      }
    
      const client = new Anthropic({ apiKey: config.anthropicApiKey });
    
      const contextHint = context ? `\nDocument type: ${context}` : "";
    
      const systemPrompt =
        "You are an expert document analyst specializing in comparing and diffing text documents. " +
        "You identify meaningful semantic changes, not just whitespace or formatting differences. " +
        "Always respond with valid JSON exactly matching the requested schema. " +
        "Be precise and specific — quote relevant text when describing changes.";
    
      const schemas: Record<string, string> = {
        summary: `{
      "summary": "2-4 sentence overview of what changed between the two versions",
      "overallAssessment": "minor | moderate | major",
      "changeCount": <estimated number of distinct changes>,
      "stats": {
        "additions": <count of added sections/paragraphs/items>,
        "deletions": <count of removed sections/paragraphs/items>,
        "modifications": <count of changed sections/paragraphs/items>
      }
    }`,
        detailed: `{
      "summary": "2-4 sentence overview of what changed",
      "overallAssessment": "minor | moderate | major",
      "analysis": "Full detailed prose explanation of every meaningful change, organized logically",
      "stats": {
        "additions": <count>,
        "deletions": <count>,
        "modifications": <count>
      }
    }`,
        structured: `{
      "summary": "2-4 sentence overview of what changed",
      "overallAssessment": "minor | moderate | major",
      "additions": [
        { "description": "what was added", "content": "the added text or a short excerpt", "significance": "high | medium | low" }
      ],
      "deletions": [
        { "description": "what was removed", "content": "the removed text or a short excerpt", "significance": "high | medium | low" }
      ],
      "modifications": [
        { "description": "what changed", "before": "original text excerpt", "after": "revised text excerpt", "significance": "high | medium | low" }
      ],
      "stats": {
        "additions": <count>,
        "deletions": <count>,
        "modifications": <count>
      }
    }`,
      };
    
      const userPrompt = `Compare the following two document versions and produce a ${mode} diff analysis.${contextHint}
    
    Return a JSON object with this exact structure:
    ${schemas[mode]}
    
    --- ORIGINAL DOCUMENT ---
    ${original}
    
    --- REVISED DOCUMENT ---
    ${revised}`;
    
      const message = await client.messages.create({
        model: "claude-haiku-4-5-20251001",
        max_tokens: 4096,
        messages: [{ role: "user", content: userPrompt }],
        system: systemPrompt,
      });
    
      const rawText = message.content[0].type === "text" ? message.content[0].text : "";
      const jsonText = rawText.replace(/^```(?:json)?\n?/m, "").replace(/\n?```$/m, "").trim();
    
      let parsed: Record<string, unknown>;
      try {
        parsed = JSON.parse(jsonText);
      } catch {
        throw new Error("Failed to parse structured response from LLM");
      }
    
      return {
        mode,
        ...parsed,
      };
    }
  • Zod input schema defining the parameters for the document-comparator tool.
    const inputSchema = z.object({
      original: z
        .string()
        .min(1)
        .max(50_000)
        .describe("The original version of the document"),
      revised: z
        .string()
        .min(1)
        .max(50_000)
        .describe("The revised version of the document"),
      mode: z
        .enum(["summary", "detailed", "structured"])
        .default("structured")
        .describe(
          "'summary' — brief overview of what changed. " +
          "'detailed' — full prose explanation of every change. " +
          "'structured' — categorized lists of additions, deletions, and modifications with context."
        ),
      context: z
        .string()
        .optional()
        .describe("Optional: what type of document this is (e.g. 'software contract', 'README', 'terms of service'). Helps generate more relevant analysis."),
    });
  • Tool definition and registration of the document-comparator tool.
    const documentComparatorTool: ToolDefinition<Input> = {
      name: "document-comparator",
      description:
        "Compare two versions of a document and produce a semantic diff. Identifies additions, deletions, and modifications with significance ratings. " +
        "Works with contracts, READMEs, terms of service, technical docs, essays, or any text. Powered by Claude.",
      version: "1.0.0",
      inputSchema,
      handler,
      metadata: {
        tags: ["document", "diff", "comparison", "legal", "writing", "llm"],
        pricing: "$0.05 per call",
        exampleInput: {
          original: "Payment is due within 30 days. Late fees apply after 45 days.",
          revised: "Payment is due within 14 days. A 2% late fee applies after 30 days. Accounts unpaid after 60 days will be sent to collections.",
          mode: "structured",
          context: "payment terms in a service contract",
        },
      },
    };
    
    registerTool(documentComparatorTool);
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively explains the output format (semantic diff) and implies read-only behavior through the verb 'compare,' but fails to confirm idempotency, side effects, rate limits, or whether the comparison is performed locally or via external API (despite 'Powered by Claude' hinting at the latter).

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?

The three-sentence structure is well-organized: functionality first, applicable domains second, implementation detail third. 'Powered by Claude' earns its place by signaling AI-powered semantic analysis rather than simple text diffing. Only minor efficiency could be gained by merging the document types into the first sentence.

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

Completeness3/5

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

Given the absence of annotations and output schema, the description adequately explains the return concept (semantic diff with specific change types) for this 4-parameter tool. However, it omits error handling behaviors, size limitations, or specific return structure details that would be necessary for a complete operational picture.

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?

Schema coverage is 100%, so the baseline is 3. The description adds semantic value by mapping 'two versions' to original/revised parameters and listing document types (contracts, READMEs) that contextualize the 'context' parameter. It does not add format details or syntax beyond what the schema already provides.

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 clearly states the specific action (compare), resource (document versions), and output type (semantic diff with additions, deletions, modifications). It effectively distinguishes from siblings like extract_contract_clauses or convert_markdown by emphasizing differential analysis rather than extraction or format conversion.

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?

The description provides implied usage guidance by listing applicable document types (contracts, READMEs, policies, essays), helping the agent understand appropriate contexts. However, it lacks explicit when-to-use/when-not-to-use rules or named alternatives for scenarios requiring different comparison approaches.

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/marras0914/agent-toolbelt'

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