MP-301f · Module 1

Unified Schemas

3 min read

Every enterprise system has its own data model. Salesforce calls them "Accounts," ServiceNow calls them "Companies," SAP calls them "Business Partners." The fields differ too — Salesforce has "AnnualRevenue," ServiceNow has "revenue," SAP has "ANNUAL_TURNOVER." Without a unified schema, the AI model must understand each system's terminology independently, and cross-system queries become error-prone. A unified schema provides a canonical vocabulary that maps system-specific terms to standardized field names.

The schema unification layer sits between the MCP server and the raw data source. It transforms system-specific responses into a canonical format before returning them as resource content. A customer resource from any system returns the same field structure: { id, name, industry, revenue, status, source }. The source field indicates which system the data came from, preserving provenance. The transformation is configured per system — a mapping file that says "Salesforce.AnnualRevenue → revenue, ServiceNow.revenue → revenue, SAP.ANNUAL_TURNOVER → revenue."

// Canonical entity schema
interface UnifiedCompany {
  id: string;
  name: string;
  industry: string | null;
  revenue: number | null;
  employeeCount: number | null;
  status: "active" | "inactive" | "prospect";
  source: "salesforce" | "servicenow" | "sap";
  sourceId: string; // Native ID in the source system
  lastUpdated: string;
}

// Per-system field mappings
const FIELD_MAPS: Record<string, Record<string, string>> = {
  salesforce: {
    Id: "sourceId",
    Name: "name",
    Industry: "industry",
    AnnualRevenue: "revenue",
    NumberOfEmployees: "employeeCount",
    Status__c: "status",
  },
  servicenow: {
    sys_id: "sourceId",
    name: "name",
    industry: "industry",
    revenue: "revenue",
    employee_count: "employeeCount",
    operational_status: "status",
  },
  sap: {
    PARTNER: "sourceId",
    NAME_ORG1: "name",
    INDUSTRY: "industry",
    ANNUAL_TURNOVER: "revenue",
    EMPLOYEE_COUNT: "employeeCount",
    STATUS: "status",
  },
};

function unifyCompany(
  raw: Record<string, unknown>,
  source: "salesforce" | "servicenow" | "sap"
): UnifiedCompany {
  const map = FIELD_MAPS[source];
  const unified: Record<string, unknown> = { source };
  for (const [sourceField, canonicalField] of Object.entries(map)) {
    unified[canonicalField] = raw[sourceField] ?? null;
  }
  unified.id = `${source}:${unified.sourceId}`;
  return unified as UnifiedCompany;
}
  1. Define canonical entities Identify the 5-10 core entity types that span multiple systems (Company, Contact, Ticket, Order, Product). For each, define a canonical field set with standardized names and types.
  2. Build per-system mappings For each system, create a field mapping that translates native field names to canonical names. Handle type conversions (string revenue to number), null coercion, and enum normalization (status values differ across systems).
  3. Preserve provenance Always include source and sourceId in unified responses. The model needs to know where data came from, and users need to trace back to the authoritative system for corrections.