Skip to main content
Glama

diff-mcp

by benjamine
server.ts4.42 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import * as consoleFormatter from "jsondiffpatch/formatters/console"; import * as jsonpatchFormatter from "jsondiffpatch/formatters/jsonpatch"; import { create } from "jsondiffpatch/with-text-diffs"; import { XMLParser } from "fast-xml-parser"; import yaml from "js-yaml"; import json5 from "json5"; import { parse as tomlParse } from "smol-toml"; import { z } from "zod"; export const createMcpServer = () => { // Create server instance const server = new McpServer({ name: "diff-mcp", version: "0.0.1", capabilities: { resources: {}, tools: {}, }, }); server.tool( "diff", "compare text or data and get a readable diff", { state: z.object({ left: inputDataSchema.describe("The left side of the diff."), leftFormat: formatSchema .optional() .describe("format of left side of the diff"), right: inputDataSchema.describe( "The right side of the diff (to compare with the left side).", ), rightFormat: formatSchema .optional() .describe("format of right side of the diff"), outputFormat: z .enum(["text", "json", "jsonpatch"]) .default("text") .describe( "The output format. " + "text: (default) human readable text diff, " + "json: a compact json diff (jsondiffpatch delta format), " + "jsonpatch: json patch diff (RFC 6902)", ) .optional(), }), }, ({ state }) => { try { const jsondiffpatch = create({ textDiff: { ...(state.outputFormat === "jsonpatch" ? { // jsonpatch doesn't support text diffs minLength: Number.MAX_VALUE, } : {}), }, }); const left = parseData(state.left, state.leftFormat); const right = parseData(state.right, state.rightFormat); const delta = jsondiffpatch.diff(left, right); const output = state.outputFormat === "json" ? delta : state.outputFormat === "jsonpatch" ? jsonpatchFormatter.format(delta) : consoleFormatter.format(delta, left); const legend = state.outputFormat === "text" ? `\n\nlegend: - lines starting with "+" indicate new property or item array - lines starting with "-" indicate removed property or item array - "value => newvalue" indicate property value changed - "x: ~> y indicate array item moved from index x to y - text diffs are lines that start "line,char" numbers, and have a line below with "+" under added chars, and "-" under removed chars. - you can use this exact representations when showing differences to the user \n` : ""; return { content: [ { type: "text", text: (typeof output === "string" ? output : JSON.stringify(output, null, 2)) + legend, }, ], }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { isError: true, content: [ { type: "text", text: `error creating diff: ${message}`, }, ], }; } }, ); return server; }; const inputDataSchema = z .string() .or(z.record(z.string(), z.unknown())) .or(z.array(z.unknown())); const formatSchema = z .enum(["text", "json", "json5", "yaml", "toml", "xml", "html"]) .default("json5"); const parseData = ( data: z.infer<typeof inputDataSchema>, format: z.infer<typeof formatSchema> | undefined, ) => { if (typeof data !== "string") { // already parsed return data; } if (!format || format === "text") { return data; } if (format === "json") { try { return JSON.parse(data); } catch { // if json is invalid, try json5 return json5.parse(data); } } if (format === "json5") { return json5.parse(data); } if (format === "yaml") { return yaml.load(data); } if (format === "xml") { const parser = new XMLParser({ ignoreAttributes: false, preserveOrder: true, }); return parser.parse(data); } if (format === "html") { const parser = new XMLParser({ ignoreAttributes: false, preserveOrder: true, unpairedTags: ["hr", "br", "link", "meta"], stopNodes: ["*.pre", "*.script"], processEntities: true, htmlEntities: true, }); return parser.parse(data); } if (format === "toml") { return tomlParse(data); } format satisfies never; throw new Error(`unsupported format: ${format}`); };

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/benjamine/jsondiffpatch'

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