Skip to main content
Glama

flowzap_diff

Compare two versions of FlowZap Code to generate a structured diff showing nodes, edges, and updates for explaining changes to users.

Instructions

Compare two versions of FlowZap Code and get a structured diff showing what changed (nodes/edges added, removed, updated). Use this to explain changes to users.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
oldCodeYesOriginal FlowZap Code
newCodeYesUpdated FlowZap Code

Implementation Reference

  • The handleDiff function is the main entry point for the flowzap_diff tool. It validates input (ensuring both oldCode and newCode are strings), calls diffCode to compute the diff, and returns a JSON response with structured changes (added/removed/updated nodes and edges) and a human-readable summary.
    export function handleDiff(oldCode: unknown, newCode: unknown): string { if (typeof oldCode !== "string" || typeof newCode !== "string") { return JSON.stringify({ success: false, error: "Both oldCode and newCode must be strings", }); } try { const diff = diffCode(oldCode, newCode); return JSON.stringify({ success: true, changes: { nodesAdded: diff.nodesAdded.map((n) => ({ id: n.id, label: n.label, lane: n.laneId })), nodesRemoved: diff.nodesRemoved.map((n) => ({ id: n.id, label: n.label, lane: n.laneId })), nodesUpdated: diff.nodesUpdated, edgesAdded: diff.edgesAdded.map((e) => ({ from: e.from, to: e.to, label: e.label })), edgesRemoved: diff.edgesRemoved.map((e) => ({ from: e.from, to: e.to, label: e.label })), lanesAdded: diff.lanesAdded, lanesRemoved: diff.lanesRemoved, }, summary: diff.summary, }, null, 2); } catch (error) { return JSON.stringify({ success: false, error: `Failed to diff code: ${error instanceof Error ? error.message : String(error)}`, }); } }
  • The diffCode function implements the core diff logic for FlowZap Code. It parses both code versions into graph structures, compares nodes (detecting additions, removals, and label/shape/lane updates), compares edges, compares lanes, and generates a structured DiffResult with a summary of all changes.
    export function diffCode(oldCode: string, newCode: string): DiffResult { const oldGraph = parseToGraph(oldCode); const newGraph = parseToGraph(newCode); // Build maps for comparison const oldNodes = new Map(oldGraph.nodes.map((n) => [n.id, n])); const newNodes = new Map(newGraph.nodes.map((n) => [n.id, n])); const oldEdges = new Map(oldGraph.edges.map((e) => [`${e.from}->${e.to}`, e])); const newEdges = new Map(newGraph.edges.map((e) => [`${e.from}->${e.to}`, e])); const oldLanes = new Set(oldGraph.lanes.map((l) => l.id)); const newLanes = new Set(newGraph.lanes.map((l) => l.id)); // Find added/removed nodes const nodesAdded: GraphNode[] = []; const nodesRemoved: GraphNode[] = []; const nodesUpdated: Array<{ id: string; changes: Record<string, { old: string; new: string }> }> = []; for (const [id, node] of newNodes) { if (!oldNodes.has(id)) { nodesAdded.push(node); } else { // Check for updates const oldNode = oldNodes.get(id)!; const changes: Record<string, { old: string; new: string }> = {}; if (oldNode.label !== node.label) { changes.label = { old: oldNode.label, new: node.label }; } if (oldNode.shape !== node.shape) { changes.shape = { old: oldNode.shape, new: node.shape }; } if (oldNode.laneId !== node.laneId) { changes.laneId = { old: oldNode.laneId, new: node.laneId }; } if (Object.keys(changes).length > 0) { nodesUpdated.push({ id, changes }); } } } for (const [id, node] of oldNodes) { if (!newNodes.has(id)) { nodesRemoved.push(node); } } // Find added/removed edges const edgesAdded: GraphEdge[] = []; const edgesRemoved: GraphEdge[] = []; for (const [key, edge] of newEdges) { if (!oldEdges.has(key)) { edgesAdded.push(edge); } } for (const [key, edge] of oldEdges) { if (!newEdges.has(key)) { edgesRemoved.push(edge); } } // Find added/removed lanes const lanesAdded = Array.from(newLanes).filter((l) => !oldLanes.has(l)); const lanesRemoved = Array.from(oldLanes).filter((l) => !newLanes.has(l)); // Generate summary const parts: string[] = []; if (nodesAdded.length > 0) { parts.push(`Added ${nodesAdded.length} node(s): ${nodesAdded.map((n) => `"${n.label}"`).join(", ")}`); } if (nodesRemoved.length > 0) { parts.push(`Removed ${nodesRemoved.length} node(s): ${nodesRemoved.map((n) => `"${n.label}"`).join(", ")}`); } if (nodesUpdated.length > 0) { parts.push(`Updated ${nodesUpdated.length} node(s)`); } if (edgesAdded.length > 0) { parts.push(`Added ${edgesAdded.length} connection(s)`); } if (edgesRemoved.length > 0) { parts.push(`Removed ${edgesRemoved.length} connection(s)`); } if (lanesAdded.length > 0) { parts.push(`Added lane(s): ${lanesAdded.join(", ")}`); } if (lanesRemoved.length > 0) { parts.push(`Removed lane(s): ${lanesRemoved.join(", ")}`); } const summary = parts.length > 0 ? parts.join(". ") : "No changes detected"; return { nodesAdded, nodesRemoved, nodesUpdated, edgesAdded, edgesRemoved, lanesAdded, lanesRemoved, summary, }; }
  • The diffTool schema definition defines the tool's name, description, and input validation schema. It requires two string parameters: oldCode (original FlowZap Code) and newCode (updated FlowZap Code).
    export const diffTool: Tool = { name: "flowzap_diff", description: "Compare two versions of FlowZap Code and get a structured diff showing what changed (nodes/edges added, removed, updated). Use this to explain changes to users.", inputSchema: { type: "object" as const, properties: { oldCode: { type: "string", description: "Original FlowZap Code", }, newCode: { type: "string", description: "Updated FlowZap Code", }, }, required: ["oldCode", "newCode"], }, };
  • The DiffResult interface defines the TypeScript type for the diff output structure, including arrays for added/removed/updated nodes and edges, added/removed lanes, and a summary string.
    export interface DiffResult { nodesAdded: GraphNode[]; nodesRemoved: GraphNode[]; nodesUpdated: Array<{ id: string; changes: Record<string, { old: string; new: string }> }>; edgesAdded: GraphEdge[]; edgesRemoved: GraphEdge[]; lanesAdded: string[]; lanesRemoved: string[]; summary: string; }
  • src/index.ts:502-506 (registration)
    The switch case statement in the CallToolRequestSchema handler that routes 'flowzap_diff' tool calls to the handleDiff function, extracting oldCode and newCode from the arguments.
    case "flowzap_diff": { const { oldCode, newCode } = args as { oldCode?: unknown; newCode?: unknown }; const result = handleDiff(oldCode, newCode); return { content: [{ type: "text", text: result }] }; }

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/flowzap-xyz/flowzap-mcp'

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