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