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.
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:
- Using non-prescription medication at nonprescription strength
- Administering tetanus immunizations
- Cleaning, flushing, or soaking wounds on the surface of the skin
- Using wound coverings such as bandages, Band-Aids, or butterfly closures (Steri-Strips)
- Using hot or cold therapy
- Using any non-rigid means of support (elastic bandages, wraps, non-rigid back belts)
- Using temporary immobilization devices while transporting an accident victim
- Drilling a fingernail or toenail to relieve pressure, or draining fluid from a blister
- Using eye patches
- Removing foreign bodies from the eye using only irrigation or a cotton swab
- Removing splinters or foreign material from areas other than the eye by irrigation, tweezers, cotton swabs or other simple means
- Using finger guards
- Using massages
- 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.
Not Recordable on OSHA 300 Log
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:
1. Probabilistic Layer (Large Language Model)
- Reads messy incident narrative from practitioner
- Translates free-text notes into standardized category codes
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)
3. Deterministic Layer (OSHA Recordkeeping Engine)
- Evaluates inputs against 29 CFR 1904.7 statutory rules
- Halts with
requires_judgmenton 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.
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.