← All writing
Data Architecture Aug 2026 6 min read

AI OSHA Recordkeeping: Deterministic Compliance via MCP

Why safety compliance cannot run on probabilistic prompts, how MCP separates fuzzy narrative parsing from deterministic law, and why verified data is the actual product.

AI OSHA Recordkeeping: Deterministic Compliance via MCP

A worker slices their hand on Line 3. The clinic closes the cut with two stitches. That injury is now recordable — it goes on your OSHA 300 Log. Close the same cut with a butterfly bandage instead, and it does not. The line between a recordable injury and a first-aid case is exactly that narrow, and most safety managers walk it from memory, under time pressure, while the injured worker waits in the next room.

Get it wrong in one direction and you over-record. Your Total Recordable Incident Rate (TRIR) climbs for injuries that never belonged on the log. That number is not cosmetic — hiring clients use TRIR thresholds to disqualify contractor bids, and insurers use it to price your risk. Get it wrong in the other direction and you under-record. When OSHA audits your 300 Log, unrecorded cases trigger mandatory citations. Two opposite mistakes, both expensive, and both flowing from a ten-second decision at the clinic door.

That decision was never a matter of opinion. Federal regulation — 29 CFR 1904.7 — defines the boundary with a fixed list. The rule is not ambiguous; it is simply buried in regulatory text, leaving safety managers to decide from memory.

The False Promise of Probabilistic AI

When generative AI arrived, safety teams immediately attempted the obvious shortcut: pasting incident narratives into a chat assistant and asking, "Is this OSHA recordable?"

Enterprise EHS platforms attempt to digitize OSHA's multi-step decision flowchart (29 CFR § 1904.4) into rigid intake questionnaires. In practice, forcing practitioners through sequential forms to evaluate work-relatedness exceptions, lost-time thresholds, and treatment categories exceeds their friction budget. Under shift pressure, safety managers bypass those multi-step workflows and seek the path of least resistance: they paste the raw incident narrative into a chat assistant. The assistant responds instantly with polished, confident prose.

Sometimes it gets the answer right. That is the dangerous part.

Even when connected to web search or document retrieval, a Large Language Model (LLM) does not execute rules. It summarizes text probabilistically. For statutory compliance, text summarization is the wrong mechanism. An LLM fills information gaps with plausible phrasing. When it misinterprets a boundary condition, it delivers the wrong answer with the same authoritative tone as a correct one.

Worse, it leaves no verifiable audit trail. You cannot defend an uncited conversational guess to an OSHA compliance officer during a site inspection. Asking a probabilistic text generator to make a statutory legal determination is using the wrong tool for the job.

Data Is the Product, Not the Model

In applied safety technology, the underlying AI model is a disposable commodity. Foundation models change every few months, and attempting to hardcode federal regulations into a system prompt is fragile. Prompts suffer from subtle reasoning drift, and you cannot defend an ungrounded prompt instruction during an audit. The verified, versioned data architecture — the structured rules, controlled vocabularies, and timestamped datasets — is the actual product.

Section 1904.7(b)(5)(ii) does something rare in federal rulemaking: it provides a closed list of exactly fourteen treatments that constitute first aid:

  1. Using non-prescription medication at nonprescription strength
  2. Administering tetanus immunizations
  3. Cleaning, flushing, or soaking wounds on the surface of the skin
  4. Using wound coverings such as bandages, Band-Aids, or butterfly closures (Steri-Strips)
  5. Using hot or cold therapy
  6. Using any non-rigid means of support (elastic bandages, wraps, non-rigid back belts)
  7. Using temporary immobilization devices while transporting an accident victim
  8. Drilling a fingernail or toenail to relieve pressure, or draining fluid from a blister
  9. Using eye patches
  10. Removing foreign bodies from the eye using only irrigation or a cotton swab
  11. Removing splinters or foreign material from areas other than the eye by irrigation, tweezers, cotton swabs or other simple means
  12. Using finger guards
  13. Using massages
  14. Drinking fluids for relief of heat stress

The statutory list is closed: any treatment on the list is first aid; anything outside it is medical treatment that makes the case recordable.

Logic Gate: 29 CFR § 1904.7(b)(5)
INPUT: Administered Treatment (e.g., butterfly closure, suture, prescription ibuprofen)
↓ Evaluated against 14-item closed statutory list
✓ IN 14-ITEM LIST
FIRST AID
Not Recordable on OSHA 300 Log
✕ OUTSIDE 14-ITEM LIST
MEDICAL TREATMENT
Mandatory Recordable Case

Regulatory Data Expiration

Compliance software rarely fails because of broken code. It fails when regulatory datasets fall behind amendments and standard interpretations.

In our reference implementation, every dataset carries a last_verified date and an automated expiration check. If a build runs against a dataset verified more than 365 days ago, automated test pipelines break immediately. The product being shipped is not code that runs; it is regulatory data with verifiable audit dates.

How an MCP Server Enforces the Boundary

The Model Context Protocol (MCP) solves this problem by separating conversational language models from statutory compliance rules. It splits the workflow along the exact boundary of what each system does best:

Architecture: The 3-Tier Execution Boundary

1. Probabilistic Layer (Large Language Model)

  • Reads messy incident narrative from practitioner
  • Translates free-text notes into standardized category codes
↓ MCP Tool Request (Strict Parameter Validation)

2. Protocol Boundary (Model Context Protocol)

  • Rejects unmapped free text; enforces pre-approved category codes
  • Pauses to ask for missing details (e.g., medication strength)
↓ Validated Arguments

3. Deterministic Layer (OSHA Recordkeeping Engine)

  • Evaluates inputs against 29 CFR 1904.7 statutory rules
  • Halts with requires_judgment on legal gray areas
  • Returns verified determination + exact CFR citation + timestamp

1. Standardized Codes Over Free Text

When an incident is described, the assistant reads the tool definitions registered by the MCP server and converts the narrative into structured parameters rather than answering from memory. The server accepts no raw text descriptions. The LLM cannot pass "gave him some strong pain cream." It must map the narrative to explicit category codes (e.g., non_prescription_medication, prescription_strength_otc, sutures_or_staples). If the narrative does not clearly match an approved code, the system rejects the entry.

2. Elicitation: Asking Instead of Guessing

The most common point of failure in recordkeeping is ambiguous data — specifically medication strength. Over-the-counter ibuprofen at 200mg is first aid; physician-prescribed ibuprofen at 800mg is medical treatment.

When a narrative says "employee given ibuprofen" without dosage, a raw LLM completes the sentence with an ungrounded assumption. The MCP server rejects ambiguity. It detects medication_unspecified_strength, halts execution, and returns a structured request for missing data (elicitation). The client assistant is forced to pause and prompt the user for the dosage before evaluating the rule.

3. Preserving the Human Boundary (requires_judgment)

Automated systems must have explicit boundaries where algorithmic rules stop and human legal review begins. Under 29 CFR 1904.5 (Work-Relatedness), determining whether an injury during business travel or telework arose out of employment requires case-by-case legal analysis.

Rather than forcing a false yes-or-no determination, the engine halts and returns requires_judgment whenever an incident falls into these statutory exceptions.

The Full Triage Suite

The open-source osha-recordkeeping-mcp implementation packages this architecture into eleven distinct tools covering the complete 29 CFR Part 1904 lifecycle:

  • osha_check_recordkeeping_obligation: Evaluates employer size (1904.1) and matches industry classification (NAICS) codes against the Appendix A partially exempt industry list.
  • osha_assess_covered_employee: Tests day-to-day supervision criteria for contractors and temporary workers (1904.31).
  • osha_assess_work_relatedness: Evaluates work premises presumptions and the ten statutory exceptions under 1904.5.
  • osha_assess_new_case: Applies 1904.6 rules to differentiate new injury events from recurring symptoms.
  • osha_assess_recordability: Executes the 1904.7 general criteria and 14-item first-aid decision gates.
  • Special Case Analyzers: Dedicated tools for needlestick events (1904.8), medical removal under toxic substance standards (1904.9), and occupational hearing loss Standard Threshold Shifts (1904.10).
  • osha_classify_case: Maps recordable cases to 300 Log Columns (G, H, I, J) and enforces the statutory 180-day cap on lost time (1904.29).
  • osha_assess_privacy_case: Screens sensitive injuries (privacy concern cases) under 1904.29(b)(7) to redact employee names from public logs.
  • osha_check_severe_injury_reporting: Calculates exact 8-hour (fatality) and 24-hour (inpatient hospitalization, amputation, eye loss) statutory reporting clocks under 1904.39.

The complete reference server is published on GitHub, hosted on Cloudflare Workers, and includes an interactive Skill specification.

Connecting to Your AI Assistant

You can connect this deterministic engine to your AI assistant in seconds:

  • UI Connectors (Claude, ChatGPT, Web Assistants): Add a new connector with the hosted URL: https://osha-recordkeeping-mcp.srhtdmrkl.workers.dev/mcp
  • Desktop & IDE Configs (Claude Desktop, Cursor): Add the server endpoint to your JSON configuration:
{
  "mcpServers": {
    "osha-recordkeeping": {
      "url": "https://osha-recordkeeping-mcp.srhtdmrkl.workers.dev/mcp"
    }
  }
}

For autonomous agent workflows, the repository includes a standardized SKILL.md definition that embeds these 11 decision gates into your agent's tool catalog.

The Code: Reference Implementation

Below is the standalone TypeScript reference implementation showing the structured data definitions, sequential decision gates, and automated clarification prompts.

/**
 * 29 CFR 1904.7 Deterministic Recordability Engine
 * Reference Implementation — osha-recordkeeping-mcp
 */

// 1. DATA AS THE PRODUCT: The closed first-aid list (1904.7(b)(5)(ii))
export const FIRST_AID_DATASET = {
  last_verified: "2026-07-26",
  source: "29 CFR § 1904.7(b)(5)(ii)",
  items: new Set([
    "non_prescription_medication",              // (A) at nonprescription strength ONLY
    "tetanus_immunization",                     // (B)
    "wound_cleaning",                           // (C) cleaning, flushing, soaking skin wounds
    "wound_covering",                           // (D) bandages, gauze, butterfly closures / Steri-Strips
    "hot_or_cold_therapy",                      // (E)
    "non_rigid_support",                        // (F) elastic bandages, wraps, non-rigid belts
    "temporary_immobilization_for_transport",   // (G) splints/slings while moving victim
    "fingernail_drilling_or_blister_draining",  // (H)
    "eye_patch",                                // (I)
    "eye_foreign_body_irrigation_or_swab",      // (J)
    "splinter_removal_simple",                  // (K) tweezers, irrigation, simple means
    "finger_guard",                             // (L)
    "massage",                                  // (M)
    "drinking_fluids_heat_stress",              // (N)
  ]),
};

export type Determination = {
  recordable: boolean | "requires_judgment";
  basis: string;
  cfr_cite: string;
  last_verified: string;
  requires_elicitation?: boolean;
  elicitation_prompt?: string;
};

export type IncidentAssessmentInput = {
  workRelated: boolean | "unclear";
  newCase: boolean;
  generalOutcomes: Array<"death" | "days_away" | "restricted_work" | "loss_of_consciousness">;
  significantDiagnoses: Array<"fracture_or_crack" | "perforated_eardrum" | "cancer" | "chronic_irreversible_disease">;
  treatments: string[]; // Standardized category codes
};

/**
 * Evaluates recordability through sequential decision gates.
 */
export function assessRecordability(input: IncidentAssessmentInput): Determination {
  const meta = { last_verified: FIRST_AID_DATASET.last_verified };

  // Gate 0: Clarification Check (Never guess on ambiguous medication strength)
  if (input.treatments.includes("medication_unspecified_strength")) {
    return {
      recordable: "requires_judgment",
      basis: "Medication was administered but dosage strength is unspecified.",
      cfr_cite: "29 CFR § 1904.7(b)(5)(ii)(A)",
      requires_elicitation: true,
      elicitation_prompt:
        "The report states medication was administered without dosage strength. " +
        "Nonprescription strength is first aid; prescription strength is recordable. Confirm the strength.",
      ...meta,
    };
  }

  // Gate 1: Work-Relatedness Boundary (1904.5)
  if (input.workRelated === "unclear") {
    return {
      recordable: "requires_judgment",
      basis: "Work-relatedness requires case-by-case review under 1904.5(b).",
      cfr_cite: "29 CFR § 1904.5",
      ...meta,
    };
  }
  if (!input.workRelated) {
    return {
      recordable: false,
      basis: "Injury or illness is not work-related.",
      cfr_cite: "29 CFR § 1904.5",
      ...meta,
    };
  }

  // Gate 2: New Event vs Continuation (1904.6)
  if (!input.newCase) {
    return {
      recordable: false,
      basis: "Continuation of a previously recorded case. Update existing 300 Log entry if outcomes changed.",
      cfr_cite: "29 CFR § 1904.6",
      ...meta,
    };
  }

  // Gate 3: General Recording Criteria (1904.7(b)(1))
  if (input.generalOutcomes.length > 0) {
    return {
      recordable: true,
      basis: `Meets general recording criteria: ${input.generalOutcomes.join(", ")}.`,
      cfr_cite: "29 CFR § 1904.7(b)(1)",
      ...meta,
    };
  }

  // Gate 4: Significant Diagnoses (1904.7(b)(7))
  // A fractured bone is recordable even if only first aid treatment was provided.
  if (input.significantDiagnoses.length > 0) {
    return {
      recordable: true,
      basis: `Diagnosed condition is recordable regardless of treatment provided: ${input.significantDiagnoses.join(", ")}.`,
      cfr_cite: "29 CFR § 1904.7(b)(7)",
      ...meta,
    };
  }

  // Gate 5: The Closed-Set First Aid Test (1904.7(b)(5))
  const medicalTreatments = input.treatments.filter(
    (treatment) => !FIRST_AID_DATASET.items.has(treatment)
  );

  if (medicalTreatments.length > 0) {
    return {
      recordable: true,
      basis: `Treatment provided exceeds the closed first-aid list: ${medicalTreatments.join(", ")}.`,
      cfr_cite: "29 CFR § 1904.7(b)(5)(i)",
      ...meta,
    };
  }

  // Default: All treatments match the closed first aid list
  return {
    recordable: false,
    basis: "All administered treatments are contained within the closed 14-item first-aid list.",
    cfr_cite: "29 CFR § 1904.7(b)(5)(ii)",
    ...meta,
  };
}

Conclusion

The value of an AI assistant in safety management is not its ability to recite regulations from memory. It is its capacity to parse messy human narratives and pass standardized parameters into auditable rule engines.

When an OSHA compliance officer examines your 300 Log, saying "the AI thought it was first aid" guarantees a citation. Providing the exact CFR sub-clause, the validated input code, the execution timestamp, and the verification date of the underlying statutory dataset demonstrates compliance control.

Compliance is not a prompt. It is a verifiable protocol.

Serhat Demirkol
Serhat Demirkol

A decade running management systems on-site, then seven years leading product for enterprise EHS software. Builds the tools, then writes about why most of them fail.

Reach out →
Keep reading