Skip to main content
Glama
ethanolivertroy

FedRAMP Docs MCP Server

diff_frmr

Compare two FRMR documents to identify differences in compliance requirements and security controls for FedRAMP analysis.

Instructions

Compute a structured diff between two FRMR documents by identifier.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
left_pathYes
right_pathYes
id_keyNo

Implementation Reference

  • The execute function implementing the core logic of the 'diff_frmr' tool, which calls diffFrmrDocuments with the input parameters.
    execute: async (input) => {
      return diffFrmrDocuments(input.left_path, input.right_path, {
        idKey: input.id_key,
      });
    },
  • Zod input schema for the 'diff_frmr' tool defining left_path, right_path, and optional id_key.
    const schema = z.object({
      left_path: z.string(),
      right_path: z.string(),
      id_key: z.string().optional(),
    });
  • The registerTools function registers the 'diff_frmr' tool (imported as diffFrmrTool) by including it in the array passed to registerToolDefs.
    export function registerTools(server: McpServer): void {
      registerToolDefs(server, [
        // Document discovery
        listFrmrDocumentsTool,
        getFrmrDocumentTool,
        listVersionsTool,
        // KSI tools
        listKsiTool,
        getKsiTool,
        filterByImpactTool,
        getThemeSummaryTool,
        getEvidenceExamplesTool,
        // Control mapping tools
        listControlsTool,
        getControlRequirementsTool,
        analyzeControlCoverageTool,
        // Search & lookup tools
        searchMarkdownTool,
        readMarkdownTool,
        searchDefinitionsTool,
        getRequirementByIdTool,
        // Analysis tools
        diffFrmrTool,
        grepControlsTool,
        significantChangeTool,
        // System tools
        healthCheckTool,
        updateRepositoryTool,
      ]);
    }
  • The diffFrmrDocuments helper function that computes the structured diff between two FRMR documents, handling additions, removals, and modifications.
    export function diffFrmrDocuments(
      leftPath: string,
      rightPath: string,
      options: DiffOptions = {},
    ): DiffResult {
      const leftDoc = resolveFrmrDocument(leftPath);
      const rightDoc = resolveFrmrDocument(rightPath);
      if (!leftDoc || !rightDoc) {
        throw createError({
          code: "NOT_FOUND",
          message: "One or both FRMR documents could not be found in the index.",
        });
      }
    
      const idKey = getIdKey(options, leftDoc, rightDoc);
    
      const leftItems = extractItems(leftDoc);
      const rightItems = extractItems(rightDoc);
    
      const leftMap = toMap(leftItems, idKey);
      const rightMap = toMap(rightItems, idKey);
    
      const changes: DiffChange[] = [];
    
      for (const [id, rightValue] of rightMap.entries()) {
        if (!leftMap.has(id)) {
          changes.push({
            type: "added",
            id,
            title:
              typeof rightValue.title === "string" ? rightValue.title : undefined,
          });
        }
      }
    
      for (const [id, leftValue] of leftMap.entries()) {
        if (!rightMap.has(id)) {
          changes.push({
            type: "removed",
            id,
            title:
              typeof leftValue.title === "string" ? leftValue.title : undefined,
          });
          continue;
        }
        const rightValue = rightMap.get(id)!;
        const fields = detectChangedFields(leftValue, rightValue, idKey);
        if (fields.length) {
          changes.push({
            type: "modified",
            id,
            title:
              typeof rightValue.title === "string"
                ? rightValue.title
                : typeof leftValue.title === "string"
                  ? leftValue.title
                  : undefined,
            fields,
          });
        }
      }
    
      const summary = {
        added: changes.filter((change) => change.type === "added").length,
        removed: changes.filter((change) => change.type === "removed").length,
        modified: changes.filter((change) => change.type === "modified").length,
      };
    
      return {
        summary,
        changes,
      };
    }

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/ethanolivertroy/fedramp-docs-mcp'

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