osha-recordkeeping-mcp
OSHA Recordkeeping MCP — 29 CFR Part 1904
Детерминированный сервер Model Context Protocol, который помогает менеджеру по охране труда ответить на вопрос, возникающий каждый раз, когда кто-то пострадал: подлежит ли это регистрации по стандарту OSHA?
Одиннадцать инструментов проводят инцидент от кто-то пострадал до корректной записи в журнале, каждый возвращает обоснованное решение со ссылкой на нормативный акт, а не пересказ правила моделью. Лицензия MIT, бесплатно для использования.
Только для справки и триажа — не юридическая консультация и не медицинское заключение. Каждое решение содержит ссылку на CFR и дату последней проверки исходных данных по eCFR, так что логика рассуждения поддаётся аудиту, а не просто декларируется.
Использование
git clone https://github.com/srhtdmrkl/osha-recordkeeping-mcp.git
cd osha-recordkeeping-mcp && npm install && npm run buildЗатем добавьте его в claude_desktop_config.json в Claude Desktop:
{
"mcpServers": {
"osha": { "command": "node", "args": ["/absolute/path/to/dist/index.js"] }
}
}Используйте абсолютный путь к вашему бинарному файлу node, если вы пользуетесь nvm — Claude Desktop не читает ваш shell-профиль, поэтому голый node не будет найден.
Сопутствующий Skill содержит процедуру: когда цепочка применима, что нужно установить до вызова и какие вопросы инструменты не могут решить.
Related MCP server: stcc-mcp
Зачем существует этот инструмент
Оценка регистрируемости производственной травмы по 29 CFR Part 1904 выполняется при каждом инциденте. Неверные решения несут прямые риски комплаенса: завышенная регистрация искусственно завышает общий коэффициент регистрируемых инцидентов (TRIR), а заниженная влечёт предписания OSHA по 29 CFR 1904.4.
Регистрируемость по Part 1904 оценивает несколько независимых триггеров: общие критерии (смерть, дни отсутствия, ограничение работы, потеря сознания, диагнозы PLHCP по 1904.7), специальные правила для конкретных случаев (уколы иглой, медицинское отстранение, потеря слуха, туберкулёз по 1904.8–1904.12) и классификацию лечения. Для лечения 1904.7(b)(5)(ii) определяет закрытый, перечисленный список из 14 пунктов мер первой помощи. Реализация этих закрытых нормативных правил внутри типизированных инструментов заменяет интерполяцию LLM по тексту нормативных актов воспроизводимой логикой поиска.
Разделение труда: LLM описывает, инструмент решает
Вызывающая модель делает то, в чём она сильна — читает запутанное описание инцидента и сопоставляет его с каноническими кодами (типы лечения, исходы). Инструмент делает то, что модель не должна делать для юридического решения — применяет закрытый список детерминированно и возвращает ответ со ссылкой на нормативный акт. Инструмент никогда не принимает свободный текст описания лечения; он принимает контролируемый словарь, чтобы решение было воспроизводимым.
Основной инструмент: osha_assess_recordability
Входные данные. Модель сопоставляет описание с этими полями; она никогда не передаёт свободный текст.
Поле | Значение |
| 1904.5 — берите из |
| 1904.6 — берите из |
|
|
|
|
| триггеры 1904.8-1904.12 — укол иглой, медицинское отстранение, потеря слуха, туберкулёз, контакт с кровью с диагнозом |
| Три места, где рекомендация обязывает, даже если работник её проигнорировал (1904.7(b)(3)(ii), (b)(4)(viii), (b)(5)(v)) |
| Защита для 1904.9(b)(3) — досрочное отстранение не регистрируется |
| Защита для 1904.11(b)(1) — положительный результат при приёме на работу не является профессиональным |
| Контролируемые коды. Коды первой помощи берутся из закрытого списка; два кода — ни первая помощь, ни медицинское лечение (1904.7(b)(5)(i)) |
Первые три массива обязательны, намеренно. Значение по умолчанию [] нельзя отличить от «я проверил, и их не было», поэтому значение по умолчанию позволяет недостаточно специфицированному описанию вернуть уверенный, цитируемый ложный отрицательный результат — направление занижения, которое влечёт предписание.
Выходные данные. RuleRecord, значение которого содержит recordable, basis, triggering_factors (каждый со своей ссылкой на подпункт), severe_injury_reporting_note, когда может применяться 1904.39, log_entry_notes для последствий, которые критерий накладывает на сам журнал, и under_specified, когда вообще ничего не было указано. Слой регистрации добавляет determination_final и clarification_required — см. Элицитация ниже.
Логика определения (детерминированная) — дерево решений 1904.4(b)(2) по порядку:
Если
work_relatedравно false → не регистрируется (1904.5).Если
new_caseравно false → новая запись не создаётся, но обновите существующую, если изменились количество дней или исход (1904.6). Дерево направляет сюда; оно не просто останавливается.Иначе, если присутствует любой
specific_case_criteria→ регистрируется по 1904.8-1904.12, вообще не обращаясь к списку первой помощи.Иначе, если присутствует любой
outcome→ регистрируется (общие критерии регистрации, 1904.7(b)(1)).Иначе, если присутствует любой
significant_diagnosis→ регистрируется, даже если была оказана только первая помощь (1904.7(b)(7)).Иначе, если любой
treatmentне входит в закрытый список первой помощи → регистрируется (медицинское лечение сверх первой помощи, 1904.7(b)(5)(i)).Иначе → не регистрируется (только первая помощь, и нет критерия конкретного случая).
Шаг 3 существует потому, что 1904.4(a)(3) — это дизъюнкция: 1904.7 или конкретные случаи 1904.8-1904.12. Без него загрязнённый укол иглой, обработанный очисткой и пластырем, возвращал «не регистрируется» — со ссылкой на нормативный акт — в то время как инструмент конфиденциальности того же сервера правильно называл его случаем конфиденциальности. Критерии регистрации, которые вообще не обращаются к списку первой помощи, должны проверяться до него, а не после.
Поверхность протокола (все три примитива MCP)
Этот сервер использует полный протокол, а не только Tools:
Tools — одиннадцать определений, перечисленных в разделе Цепочка триажа инцидента ниже. Каждый объявляет
outputSchemaи возвращает типизированныйstructuredContent, а не JSON-строку, и каждый аннотированreadOnlyHint: true,destructiveHint: false,idempotentHint: true,openWorldHint: false— безопасные, повторяемые, чистые поиски.Resources — все пятнадцать наборов данных доступны напрямую, так что клиент может загрузить справочные данные как контекст, а не только через вызов инструмента. Модель данных — это продукт; Resources делают её видимой. URI —
osha://data/<id>, где<id>— ключ вsrc/datasets.ts— например,osha://data/first-aid-treatments,osha://data/partially-exempt-industries,osha://data/privacy-cases.Prompt —
triage_incidentпроводит один инцидент через всю цепочку как единый пользовательский рабочий процесс: область применения → регистрирующий работодатель → связь с работой → новый случай → ограниченная работа → потеря слуха → регистрируемость → срок отчётности → колонка журнала 300 → случай конфиденциальности → предприятие.Элицитация —
osha_assess_recordabilityразрешает один пограничный случай, который не должен угадывать: безрецептурная vs. рецептурная сила лекарства. Не рецептурная сила — первая помощь; рецептурная — медицинское лечение и регистрируется. Когда описание молчит, модель передаётmedication_unspecified_strength, и сила разрешается путём вопроса человеку — никогда не выбором инструмента.Двухуровневое разрешение. Элицитация — необязательная возможность MCP, поэтому сервер проверяет
getClientCapabilities()и выбирает свой канал:Клиент объявляет
elicitationКанал
Результат
Да
Сервер запрашивает пользователя напрямую
Разрешено за один вызов инструмента
Нет
Возвращает
determination_final: false+clarification_requiredМодель спрашивает в чате, затем повторно вызывает с разрешённым кодом
В любом случае вопрос доходит до человека, и инструмент никогда не угадывает. Предварительный результат остаётся консервативным —
recordable: true, основание помечено ожидает подтверждения — иclarification_requiredнесёт вопрос, причину по CFR и точный код лечения для отправки обратно для каждого ответа.В какой уровень попадает конкретный клиент, стоит проверить, а не предполагать. Проверено здесь: чат-клиент Claude Desktop не объявляет возможность
elicitation, и MCP Inspector 0.15.0 или 1.0.0 тоже. Агентные клиенты могут отличаться, и клиент, который спрашивает пользователя через собственный механизм, выглядит извне одинаково. Сервер записываетelicitation=supported|NOT supportedв stderr при подключении — запустите его под любым клиентом и прочитайте эту строку.
Происхождение и принудительное устаревание
RuleRecord<T> (см. src/types.ts) несёт нормативные правила: cfr_cite, source_url, last_verified, и где eCFR предоставляет их, amendment_history и editorial_note. Поля effective_date нет; наборы данных несут текущий текст eCFR, а last_verified указывает дату нормативной проверки.
Устаревание принудительно через scripts/check-decay.ts, который завершает сборку, если last_verified любой записи превышает порог устаревания. Он запускается при push и по еженедельному расписанию CI, проверяет цели source_url подразделов и проверяет записи editorial_note в eCFR.
Цепочка триажа инцидента (поставляется)
Одиннадцать детерминированных инструментов, которые проводят один инцидент от «кто-то пострадал» до корректной записи в журнале:
osha_check_recordkeeping_obligation(1904.1, 1904.2) — вопрос, который предполагает каждое другое определение: обязано ли это предприятие вообще вести учёт? Освобождение по размеру измеряется по всей компании на пиковой численности за последний календарный год — не по среднему значению, не по одному объекту. Освобождение по отрасли привязано к предприятию, и инструмент разрешает его по закрытому списку из 82 кодов Приложения A, когда ему дан код NAICS. Оба освобождения частичны: обязанность сообщать о тяжёлых травмах по 1904.39 сохраняется при любом из них — именно этот вывод освобождённый работодатель ошибочно упускает.osha_determine_recording_employer(1904.31) — пороговый вопрос, а не шаг: когда пострадавший не числится в платёжной ведомости, является ли этот случай вообще делом данного работодателя? Решает повседневный надзор, а не платёжная ведомость. Временный работник, числящийся в ведомости агентства, но чью работу вы направляете ежедневно, подлежит учёту у вас; тот же временный работник под надзором агентства — нет. Самозанятые полностью вне сферы действия OSH Act, а владельцы или партнёры единоличного предприятия не считаются работниками для целей ведения учёта. Пункт(b)(4)требует, чтобы случай был зарегистрирован ровно один раз — никогда в обоих журналах.osha_assess_work_relatedness(1904.5) — ворота, на которых держится всё остальное, и до сих пор единственное юридическое суждение, которое этот проект передавал модели. Пункт 1904.5(a) предполагает связь с работой для всего, что возникает в рабочей среде; пункт 1904.5(b)(2) — закрытый список из девяти исключений, которые могут её опровергнуть. Вердикт намеренно трёхзначный —work_related,not_work_relatedилиrequires_judgment— потому что 1904.5 содержит пути, которые само регулирование возлагает на работодателя: неясное происхождение (1904.5(b)(3)), командировочный статус (b)(6), работа на дому (b)(7) и вывод о «исключительности», от которого зависит каждое исключение. Принудительное сведение их к булеву значению означало бы, что инструмент угадывает самый спорный вывод в части 1904. Он также разрешает случаи, которые память переворачивает. ДТП с автомобилем при поездке на работу на территории компании подпадает под исключение (b)(2)(vii); падение при скольжении на той же территории не покрыто ни одним исключением и остаётся связанным с работой. А психическое заболевание инвертирует обычное направление — не связано с работой, если только работник сам не предоставит заключение PLHCP (b)(2)(ix).osha_assess_new_case(1904.6) — новая запись в журнале 300 или обновление уже существующей? Второе условие конъюнкции 1904.4(a). Оно разделяет два случая рецидива, которые регулирование намеренно разводит: эпизод, вызванный воздействием на рабочем месте, — это новый случай (b)(2) — профессиональная астма, спровоцированная на линии, — тогда как хроническое заболевание, симптомы которого повторяются без воздействия, регистрируется только один раз (b)(1). Обратите внимание: (b)(1) — не закрытый список: регулирование говорит, что «примеры могут включать» рак, асбестоз, биссиноз и силикоз, поэтому инструмент спрашивает о характере состояния, а не сопоставляет названия болезней. Это также единственный инструмент в сервере, который делегирует полномочия внешнему авторитету. Согласно (b)(3) работодатель не обязан консультироваться с PLHCP, но если он уже проконсультировался, то обязан следовать рекомендации — поэтому заключение PLHCP полностью переопределяет логику правил, а противоречащие заключения возвращаютrequires_judgment, поскольку их взвешивание — прямо обязанность работодателя.osha_evaluate_restricted_work(1904.7(b)(4)) — действительно ли ограничение учитывается? Не каждое, и обе ошибки перемещают случаи в журнал или из него. Ограничение, ограниченное днём травмы, не учитывается (b)(4)(iii); сниженная выработка при сохранении всех обычных функций — не учитывается (b)(4)(vi); «обычные функции» означают действия, выполняемые не реже одного раза в неделю (b)(4)(ii). Частичная смена учитывается (b)(4)(v), а переводы разделяют колонку ограничений (b)(4)(x). Интересный случай — (b)(4)(vii): когда расплывчатая рекомендация, например «лёгкий труд», не может быть уточнена у PLHCP, случай должен быть зарегистрирован как ограниченная работа. Это регулирование разрешает собственную неопределённость в сторону учёта — и единственное правило по умолчанию в пользу записи во всей части 1904.osha_evaluate_hearing_loss(1904.10) — единственный критерий учёта в части 1904, который является чистой арифметикой, и единственный инструмент здесь, который вычисляет, а не ищет. Два теста должны быть выполнены в одном и том же ухе: стандартный сдвиг порога на 10 дБ относительно базового уровня и общий уровень слуха 25 дБ или более выше аудиометрического нуля, каждый усреднённый на частотах 2000, 3000 и 4000 Гц. STS в одном ухе и уровень 25 дБ в другом не регистрируются. Возрастная корректировка применяется только к тесту сдвига, никогда к тесту 25 дБ.osha_assess_recordability(1904.4) — подлежит ли учёту? (якорь, выше)osha_check_severe_injury_reporting(1904.39) — должно ли это быть сообщено в OSHA, и к какому сроку? Возвращает фактическую временную метку дедлайна (8 часов для смертельного случая, 24 для госпитализации / ампутации / потери глаза), вычисленную с момента, когда работодатель узнал о происшествии, проверяет окно допустимости с момента инцидента и указывает, не истёк ли уже срок.osha_classify_300_log_entry(1904.29) — какая колонка результата в журнале 300 (G/H/I/J) по правилу наиболее серьёзного исхода, колонка типа травмы/заболевания и количество дней, ограниченное 180.osha_check_privacy_case(1904.29(b)(6)-(9)) — может ли имя работника вообще попасть в журнал? Второй закрытый список, и закрытый в обоих направлениях:(b)(7)перечисляет шесть случаев, вызывающих озабоченность по конфиденциальности, а(b)(8)запрещает считать таковым что-либо ещё — поэтому работодатель не может расширить его из сочувствия, как и не может его игнорировать. Возвращает буквальную запись в журнале ("privacy case") плюс следующие обязательства: отдельный конфиденциальный список ((b)(6)), усмотрение при описании случая, когда само описание может идентифицировать работника ((b)(9)), и редактирование, когда записи передаются кому-либо, кроме представителя правительства ((b)(10)).osha_route_to_establishment_log(1904.30) — в журнал какого предприятия, последний вопрос об отдельном инциденте. Правило противоречит интуиции: случай следует за местом, а не за человеком. Тот, кто пострадал, прикрывая смену на другом заводе работодателя, регистрируется в журнале этого завода, что меняет число, определяющее его сайтовый TRIR. Травма вне всех предприятий — на объекте клиента, в пути, удалённо — попадает в журнал того объекта, где работник обычно работает.
Область применения: Часть 1904, и ничего больше
Всё здесь отвечает на один вопрос — кто-то пострадал; что OSHA требует от меня записать и сообщить? Это 29 CFR Part 1904 от начала до конца, и одиннадцать инструментов выше — это определения, которые она навязывает.
Распространение: сервер и Skill
Два артефакта, потому что они отвечают на разные вопросы. Сервер решает; Skill знает, когда его спросить.
Сервер — три точки входа, один движок
Точка входа | Транспорт | Для |
| stdio | Claude Desktop, локальная разработка |
| Streamable HTTP | контейнер или node-хостинг |
| Streamable HTTP | Cloudflare Workers |
Все три вызывают один и тот же createServer() с одними и теми же одиннадцатью инструментами и пятнадцатью наборами данных — ничего в src/tools/ не знает, какой из них работает. Эта переносимость возникла из двух более ранних решений, а не из усилий по переносу: определения — чистые функции, а datasets.ts — единственная точка контакта с JSON.
Каждый вариант без состояния — новый сервер на каждый запрос, без идентификаторов сессий, ничего не хранится между вызовами, потому что каждый инструмент — это чистый поиск по встроенным данным. /health сообщает возраст каждого набора данных относительно порога устаревания и возвращает 503, когда один из них устаревает, поэтому размещённое развёртывание контролируется по тому же правилу, что и сборка.
npm run start:http # node host — PORT=3000 MCP_PATH=/mcp by default
npm run smoke:http # boots it, drives it with a real client, checks /health
npm run dev:worker # wrangler dev — runs under workerd, not Node
npm run smoke:worker # boots workerd and drives it with a real client
npm run deploy:worker # wrangler deploysmoke:worker — единственная проверка, которая запускает инструменты под workerd. Два других smoke-теста работают на Node и структурно не могут увидеть, как встроенный узел проникает в путь кода — а именно это проявилось бы при развёртывании первым. nodejs_compat намеренно выключен в wrangler.toml, чтобы этот сбой был громким в разработке, а не тихим.
Воркер принимает только POST. Сервер без состояния не инициирует сообщений, поэтому поток GET SSE не несёт ничего и оставался бы открытым вечно; workerd отменяет запрос, ответ которого никогда не завершается. 405 с Allow: POST — это способ протокола сказать, что потока «сервер-клиент» нет.
Без аутентификации, намеренно. Сервер предоставляет опубликованный нормативный текст, ничего не хранит и не имеет побочных эффектов, поэтому контроль доступа должен быть перед ним — Cloudflare Access или слой OAuth — а не полуреализован внутри.
Ограничение скорости
Ограничение скорости — исключение, и оно живёт в воркере, а не перед ним. Развёртывание находится на workers.dev, который не является зоной в аккаунте, поэтому правилу ограничения скорости WAF не к чему прикрепиться. Объявлено как привязка [[ratelimits]] в wrangler.toml, что также означает, что оно проверяется, версионируется и путешествует вместе с развёртыванием, а не живёт в панели управления, которую никто не диффузит.
300 запросов в минуту на IP-адрес клиента. Намеренно щедро: ограничитель ключует по IP, и команда безопасности за одним корпоративным NAT делит один ключ. Одна цепочка триажа — примерно 15 запросов, поэтому несколько человек, работающих одновременно, легитимно превышают 150/мин. Это рассчитано на отсечение модели, зацикливающейся на ошибке — именно тот сбой, который реально угрожает размещённому развёртыванию, — а не на ограничение нормального использования. Превышение лимита возвращает 429 с Retry-After.
/health находится выше проверки, поэтому монитор аптайма, опрашивающий по расписанию, никогда не сможет исчерпать бюджет. Ограничение применяется по каждому центру обработки данных, а не глобально скоординировано, поэтому это скорее отсечка, чем точная квота.
Что получают инструменты
Сервер ничего не извлекает и ничего не хранит. Но аргументы всё же поступают внутрь, и они описывают реальный инцидент, поэтому «нет пользовательских данных» — это утверждение о хранении, которое ничего не говорит о передаче. Это различие стоит сформулировать прямо, потому что именно его должна оценить команда EHS.
Ни один вход не является идентификатором. Нигде в схемах нет поля для имени, номера сотрудника, даты рождения, адреса или свободного текстового описания — каждый вход — это атрибут случая (work_related, days_away_from_work, treatments), и для определения больше ничего не нужно. Это свойство схем, а не политика: нет поля, куда можно вписать имя. Skill также инструктирует модель не переносить идентичность в вызов, поэтому ограничение действует на обоих концах — см. Передавайте факты, никогда не идентичности.
Некоторые атрибуты всё же чувствительны. osha_check_privacy_case принимает ровно те категории, которые перечисляет 1904.29(b)(7) — sexual_assault, mental_illness, hiv_hepatitis_or_tuberculosis, contaminated_needlestick_or_sharps. Регулирование выделяет их именно потому, что они не должны появляться в журнале, который может прочитать коллега. Только атрибуты — это также не то же самое, что анонимность: код характера плюс дата инцидента на предприятии из девяти человек может идентифицировать кого-то для любого, кто там работает.
Куда это попадает, зависит от транспорта, и только от транспорта:
Точка входа | Куда идут аргументы |
stdio | остаётся на машине, где работает сервер; AI-хост всё равно его видит |
node HTTP / worker | пересекает сеть к тому, кто управляет этим развёртыванием |
Ничего не логируется ни в ту, ни в другую сторону — ни логирования запросов, ни логирования вызовов инструментов, успешных или неуспешных. Это сделано намеренно. Журнал таких аргументов был бы сам по себе регулируемым хранилищем на сервере, которому в остальном нечего регулировать, а сами определения и так воспроизводимы из входных данных и отметки last_verified в составе каждого ответа. Провенанс в ответе делает ту же работу, что и журнал аудита, но без хранения записей.
Итак: если вы работаете с реальными случаями в условиях GDPR или HIPAA, используйте транспорт stdio либо разворачивайте worker на инфраструктуре, которой управляете сами. Направлять регулируемые данные об инцидентах в чью-то чужую хостируемую копию этого сервера — значит передавать атрибуты травмы третьей стороне, с которой у вас нет соглашения. Определения — это чистые функции над входящими в комплект JSON-данными: самостоятельный хостинг стоит одного wrangler deploy и ничуть не меняет ответы.
Проверка Host и Origin
Аутентификация решает, кому можно спрашивать. Проверка Host защищает от того, чтобы браузер заставляли спрашивать от чужого имени, и никакой вышестоящий шлюз не может это наверстать задним числом — поэтому эта часть реализована в src/httpGuard.ts и применяется в обеих точках входа HTTP.
Закрывается здесь DNS rebinding: вредоносный домен пере-resolвляется на 127.0.0.1, браузер считает запрос same-origin и отправляет его без preflight, а локально запущенный MCP-сервер отвечает. Выдаёт атаку заголовок Host: он содержит домен атакующего, поэтому работает точная сверка с разрешённым списком хостов.
Переменная | Node ( | Worker |
| адрес привязки, по умолчанию | — |
| по умолчанию | не задан = без ограничений |
| не задан = без ограничений | не задан = без ограничений |
Обе переменные принимают список через запятую; * отключает проверку, когда решение принимает внешний шлюз. Origin проверяется только в случае присутствия заголовка, потому что небrowерные MCP-клиенты его не отправляют. /health находится вне разрешённого списка — мониторинг доступности не является угрозой.
Точка входа Node по умолчанию работает только через loopback. Развёртывание в контейнере или за reverse-proxy доступно по другому имени и обязано задать MCP_ALLOWED_HOSTS; при ошибке возвращается 403 с указанием увиденного заголовка — это чинится за пять секунд. Противоположное значение по умолчанию — это дыра, которую никто не замечает. Обратите внимание: адрес привязки не является защитой — по умолчанию остаётся 0.0.0.0, чтобы работали контейнеры, а безопасность обеспечивается именно разрешённым списком.
Отклонённые запросы получают 403 с ошибкой JSON-RPC -32000. Слишком большие тела (>1 MB) получают 413, невалидный JSON — 400 — ошибки клиента не регистрируются в журнале как инциденты.
The Skill
skills/osha-incident-triage/ содержит процедуру: когда применима цепочка шагов, что установить до вызова, как представить определение и что инструменты не могут решить. Это руководство по процессу разбора инцидентов, у него нет непосредственной регуляторной логики.
Структура
Логика составления определений чистая и тестируемая; сервер — лишь вязкаора вокруг неё.
src/
index.ts stdio entry point — Claude Desktop, local development
http.ts Streamable HTTP entry point — container / node host
worker.ts Cloudflare Workers entry point — same server, fetch handler
server.ts createServer() factory + registerRuleTool/toolResult helpers
httpGuard.ts Host/Origin allowlisting shared by both HTTP entry points —
one implementation, since Node and workerd share no middleware
datasets.ts the one place JSON assets are loaded and named — static imports,
so the same module resolves with or without a filesystem
types.ts RuleRecord, Provenance, and the ruleRecord() constructor
md.d.ts ambient declaration letting SKILL.md be imported as a string,
so the worker can serve it without a filesystem
tools/ one pure function per determination — no MCP imports except
medicationStrength.ts, which owns the elicitation exchange
registrations/
tools/ one registerX.ts per tool + a barrel; metadata and summaries
resources.ts generated from the DATASETS table
prompts.ts triage_incidentДобавление инструмента — это один файл в src/tools/ (раacket правило), один в src/registrations/tools/ (как он описан и резюмируется) и одна строка в картеле. Префикс register держит эти имена файлов отличными от их собратьев в src/tools/ в панели вкладок редактора.
Полезно сохранять два инварианта: данные о происхождении собираются только функцией ruleRecord(), а Resources генерируются из той же таблицы DATASETS, откуда загружают инструменты, поэтому набор данных не может быть опубликован по пути, до которого ни один инструмент не читает.
Непрерывная интеграция
.github/workflows/ci.yml запускает проверку типов, сборку, модульные тесты и smoke-тесты на Node 20 и 22.
Проверка decay и npm audit запускаются по тем же триггерам, что и остальной CI — push, pull request, недельное расписание — в виде отдельных задач, чтобы любой из возможных отказов был хорошо виден сам по себе, а не одним красным крестом среди остальных. npm audit блокирует сборку, если появляются рекомендаций о уязвимостях в production-зависимостях; предупреждения о dev-зависимостях только сообщаются, но не блокируют. Еженедельное расписание ловит тот случай, когда рекомендация выходит для версии зависимости, уже находящейся на main, и никакой push-события не будет, чтобы запустить перепроверку.
tsconfig.json исключает test/, поэтому tsc --noEmit проверяет только src/, а ts-jest во время npm test дополнительно типобезопасность тестовых файлов.
Контроль изменений и версионирование
CHANGELOG.md описывает все изменения по двум независимым осям выпусков:
Код: логика определений, схемы инструментов и транспорты сервера следуют SemVersion.
Регуляторные данные: упакованные JSON-dataset в
src/data/. Повторная сверка набора с текущим текстом eCFR обновляет датуlast_verifiedи публикуется как patch-релиз, даже если регуляторный текст не изменился, — так сохраняется аудируемое происхождение для комплаенс-команд.Принудительное устаревание: CI еженедельно запускает
scripts/check-decay.ts, чтобы сборка падала, если любой набор превышает порог устаревания 365 дней без ручной повторной верификации.Релизы: Тег версии (
vX.Y.Z) required на GitHub запускает.github/workflows/release.yml, где выполняется полный набор проверок (typecheck, тесты, smoke тесты, decay, audit) и создаётся верифицированный GitHub Release.
Разработка
npm install
npm run build # tsc + copy src/data → dist/data
npm test # jest — deterministic logic
npm run check-decay # build-breaking staleness trap
npm run smoke # end-to-end: spawn the server, list tools/resources/prompts, call a toolПодключение локально — через npx @modelcontextprotocol/inspector или добавить в claude_desktop_config.json указание на dist/index.js.
npm run smoke:worker и npm run dev:worker требуют Node 22 или новее, потому что этого требует wrangler. Всё остальное работает на Node 20, а engines осознанно остаётся >=20 چهه это поле — заявление о том, кто может установить и запускать сервер, которому достаточно только SDK и zod. Wrangler — это утилита разработма, и до потребителя она вообще не доходит, поэтому её требование не является требованием пакета. Именно поэтому CI содержит Node 20 в матрице и пропускает там только worker-smoke.
Оценки
evals/recordkeeping-evals.xml — сорок семь вопросов, которые проверяют, достигает ли LLM правильного ответа через инструменты, и это нельзя проверитьюнит-тестами. Каждый ответ был сгенерирован обращением к собранному серверу реальным MCP-клиентом; трасса находится в evals/README.md. У большинства из, что стара этой — и ста сорока семи есть интуитивный неверный ответ, к которому без оружия потянется модель, рассуждающая по памяти.
Отказ от ответственности
Только справка и разбор инцидента. Не является юридической консультацией и не является медицинским заключением. Спорные случаи фиксации часто требуют участия PLHCP или юриста. Связь с работой (1904.5) устанавливается только по детерминированной ветке; неясное происхождение, командировка, работа из дома и неподтверждённый вывод «только по этой» — всё это возвращает requires_judgment, а не verdict.
Available Tools
11 toolsosha_assess_new_caseAssess New Case vs. Continuation (29 CFR 1904.6)ARead-onlyIdempotent
Determine whether an injury or illness is a NEW case or a continuation of one already on the 300 Log — the second condition of the 1904.4(a) conjunction. Run this after osha_assess_work_relatedness and before osha_assess_recordability, and pass its new_case result through. Key distinctions it settles: a recurrence CAUSED by a workplace exposure is a new case (1904.6(b)(2), e.g. an occupational asthma episode), while a chronic illness whose symptoms recur WITHOUT exposure is recorded only once (1904.6(b)(1)). A PLHCP recommendation, once sought, is binding and overrides the rule logic (1904.6(b)(3)). Returns work_case verdicts of new_case, not_new_case, or requires_judgment — the last when PLHCP opinions conflict or causation is unestablished. Treat requires_judgment as a question for the user, never as a licence to pick. Reference and triage only — not legal advice or a medical determination.
| Name | Required | Description | Default |
|---|---|---|---|
| plhcp_opinion | No | Any physician or licensed health care professional recommendation on whether this is a new case or a recurrence. Under 1904.6(b)(3) an employer need not seek one, but MUST follow it once sought — so this OVERRIDES the rule logic. Use 'conflicting' when two or more PLHCPs disagree; the employer must then decide which is most authoritative. | none |
| causation_is_clear | No | Is it clear whether a workplace event caused the current signs or symptoms, as opposed to the condition simply continuing? Pass false when the narrative does not establish this; the tool will return requires_judgment rather than pick. | |
| recovered_completely_from_prior | No | Had the employee recovered completely from the prior recorded case — ALL signs and symptoms had disappeared — before the current signs or symptoms appeared? (1904.6(a)(2)) | |
| prior_recorded_same_type_same_body_part | Yes | Has the employee previously experienced a RECORDED injury or illness of the same type affecting the same part of the body? (1904.6(a)(1)) If false, the case is new and nothing else needs deciding. | |
| workplace_event_caused_current_symptoms | No | Did an event or exposure in the workplace cause the current signs or symptoms? (1904.6(b)(2)) An episode of occupational asthma triggered by a workplace exposure is a new case even though the asthma itself is not new. | |
| chronic_recurs_without_workplace_exposure | No | Is this an occupational illness whose signs or symptoms may recur or continue in the ABSENCE of a workplace exposure? Examples may include occupational cancer, asbestosis, byssinosis and silicosis (1904.6(b)(1)). This is a description of character, NOT a closed list of illnesses — judge the condition, do not match the name. Such cases are recorded once only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the basic safety and side-effect profile. The description adds meaningful context beyond that by explaining the binding PLHCP override (1904.6(b)(3)) and clarifying that requires_judgment is a non-decision state to be escalated, not acted upon. It does not detail return-format specifics, but with an output schema present and the annotations already carrying the safety burden, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured: purpose first, then workflow ordering, then the key legal distinctions, then the output verdicts and a caution about misuse. Each sentence carries distinct regulatory or procedural information. It loses one point for density — the 1904.6(b)(3) PLHCP rule is described in a long single sentence, and the overlap between the description's example ('occupational asthma episode') and the schema's parameter description is some slight redundancy, but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 100% parameter coverage, an output schema, and read-only/idempotent annotations, the description fills every remaining gap: imputed workflow position among 10 sibling tools, special-case handling (PLHCP binding), and the output's semantics (requires_judgment means ask the user). No side-effect or resource-lifetime concerns exist for this read-only classifier, so nothing is arguably missing to invoke/triage correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (all 6 parameters have rich schema descriptions), so the baseline is already 3. The description adds substantial value beyond the schema by interpreting the regulatory context: why PLHCP opinion overrides the logic, what 'conflicting' means in practice, and what makes requires_judgment occur. The parameter 'causation_is_clear' gets practical meaning — 'Pass false when the narrative does not establish this' — which the schema itself does not fully convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Determine whether an injury or illness is a NEW case or a continuation of one already on the 300 Log.' It precisely names the second condition of the 1904.4(a) conjunction and distinguishes itself from sibling tools by placing itself explicitly between osha_assess_work_relatedness and osha_assess_recordability. This gives an agent an unambiguous understanding of what the tool does and how it differs from the rest of the osha_* family.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit sequencing: 'Run this after osha_assess_work_relatedness and before osha_assess_recordability, and pass its new_case result through.' It also lists key distinctions the tool settles and provides a clear behavioral rule for ambiguous results: 'Treat requires_judgment as a question for the user, never as a licence to pick.' This is strong when-to-use guidance with a direct exclusion of misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_assess_recordabilityAssess OSHA Recordability (29 CFR 1904.4)ARead-onlyIdempotent
Determine whether a work-related injury or illness is OSHA recordable under the 1904.4 decision tree: work-related AND a new case AND meeting either the general recording criteria of 1904.7 OR a specific-case criterion of 1904.8-1904.12 (needlestick, medical removal, hearing loss, tuberculosis). Map the incident narrative to the controlled inputs. The tool applies the closed first-aid list in 1904.7(b)(5)(ii) deterministically and returns a cited determination. Reference and triage only — not legal advice or a medical determination. If the result has determination_final=false, it is provisional: follow the clarification_required instruction, ask the user, and call this tool again with their answer.
| Name | Required | Description | Default |
|---|---|---|---|
| new_case | Yes | Is this a new case, not a continuation of a previously recorded one? (1904.6) | |
| outcomes | Yes | General recording criteria outcomes present in this case. REQUIRED — pass [] only when the narrative affirmatively establishes there were none. If the narrative is silent on time off or work restrictions, ask the user before calling; do not pass [] to mean 'unknown'. | |
| treatments | Yes | Controlled treatment codes. Map the incident narrative to these codes. First-aid codes come from the closed 1904.7(b)(5)(ii) list; anything else is medical treatment. Use 'other_medical_treatment' if unsure. If the report mentions medication but not its strength, use 'medication_unspecified_strength' — the strength will be resolved by asking the user, either by the server or by you. Never guess it. REQUIRED — pass [] only when the narrative affirmatively establishes no treatment was given. Note two codes are NEITHER first aid nor medical treatment: 'observation_or_counseling_only' and 'diagnostic_procedure_only' (1904.7(b)(5)(i)) — an x-ray or a clinic visit to be checked out does not make a case recordable. And the professional status of whoever provided the treatment is irrelevant (1904.7(b)(5)(iv)): a bandage is first aid even when a physician applies it. | |
| work_related | Yes | Did the work environment cause or contribute to the injury/illness? (1904.5) | |
| significant_diagnoses | Yes | Significant injuries/illnesses that are recordable even if only first aid was given (1904.7(b)(7)). REQUIRED — pass [] only when affirmatively established, not when the narrative is silent. | |
| specific_case_criteria | Yes | Specific-case recording criteria under 1904.8-1904.12, which are INDEPENDENT of the first-aid list: a case meeting one of these is recordable even when only first aid was given. One of: contaminated_needlestick_or_sharps, medical_removal, occupational_hearing_loss_sts, tuberculosis_infection, bloodborne_exposure_with_diagnosis. REQUIRED — pass [] only when affirmatively established. Note 'occupational_hearing_loss_sts' asks whether the 1904.10 audiometric test is already MET; the tool does not compute the shift. | |
| plhcp_recommendations_not_followed | No | Situations where a PLHCP recommended something and the employee did not follow it. The case is recordable anyway — what was recommended controls, not what the employee did. One of: days_away_recommended_but_employee_worked, restriction_recommended_but_employee_worked_normally, medical_treatment_recommended_but_declined. (1904.7(b)(3)(ii), (b)(4)(viii), (b)(5)(v)) | |
| tuberculosis_test_was_pre_employment | No | For a tuberculosis case only: was the positive skin test obtained at a PRE-EMPLOYMENT physical? If so the case is NOT recordable (1904.11(b)(1)) — the employee was not occupationally exposed to a known active case in your workplace. | |
| medical_removal_was_voluntary_and_early | No | For a medical removal only: was the employee removed VOLUNTARILY, before the medical removal levels required by the OSHA standard were reached? If so the case is NOT recordable (1904.9(b)(3)) — an employer who acts early is not penalised. Leave false when the removal met the standard's criteria. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the already helpful annotations of readOnlyHint, idempotentHint, and destructiveHint, the description adds meaningful behavioral detail: the tool applies the closed first-aid list deterministically, returns a cited determination, marks results provisional when needed, and requires a follow-up interaction when clarification is pending. It also discloses the limitation that this is not legal advice or a medical determination.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is thorough and front-loaded with the main decision. Every sentence contributes something valuable: the decision rule, the deterministic behavior, the input-mapping requirement, the disclaimer, and the follow-up workflow. It is long because it needs to be, but it still feels tight and structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a regulatory decision tool with nine parameters, rich annotated safety metadata, and a complex sibling set, the description is complete. It covers the decision tree, the output provisional state, user clarification flow, mapping of narrative input to controlled fields, and the non-legal/non-medical disclaimer. An agent has enough information to invoke the tool and respond to the results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter already carries detailed regulatory guidance, so the description does not need to re-explain individual inputs. It adds a high-level instruction to map the incident narrative to controlled inputs, but most of the substantive usage semantics are already embedded in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action and resource: 'Determine whether a work-related injury or illness is OSHA recordable under the 1904.4 decision tree.' It then spells out the exact conditions of the decision tree, and the resource and scope are clearly distinct from sibling tools that assess only one component such as work-relatedness or new-case status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear operational context by stating 'Reference and triage only' and by specifying what to do when the result is provisional: follow the clarification_required instruction, ask the user, and call again. However, it does not explicitly name sibling tools or give exclusion conditions for when a caller should use one of them instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_check_privacy_caseCheck Privacy Concern Case (29 CFR 1904.29(b)(6)-(9))ARead-onlyIdempotent
Determine whether a recordable case is a privacy concern case, meaning the employee's name must NOT be entered on the OSHA 300 Log. 1904.29(b)(7) is a closed list — injury to an intimate body part or the reproductive system, sexual assault, mental illness, HIV/hepatitis/tuberculosis, a contaminated needlestick or sharps cut, and other illnesses where the employee voluntarily asks to be left off. 1904.29(b)(8) forbids treating anything else as a privacy case. Returns the required log entry and the confidential-list and redaction obligations that follow, plus the only three recipients who may receive the forms with identifying information intact (1904.29(b)(10)). Run this after a case is determined recordable.
| Name | Required | Description | Default |
|---|---|---|---|
| nature | Yes | The nature of the case, mapped from the incident narrative. Use 'none_of_these' if the case does not match any enumerated category. One of: intimate_body_part_or_reproductive_system, sexual_assault, mental_illness, hiv_hepatitis_or_tuberculosis, contaminated_needlestick_or_sharps, other_illness_employee_requested, none_of_these. | |
| is_illness | No | Is this an illness (not an injury)? Only relevant to 1904.29(b)(7)(vi), which covers other ILLNESSES and never injuries. | |
| employee_requested_name_omitted | No | Did the employee voluntarily request that their name not be entered on the log? Only relevant to 1904.29(b)(7)(vi), which covers other ILLNESSES. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the agent knows it's a safe, read-only operation. The description adds valuable behavioral context beyond annotations: it specifies what the tool returns (required log entry, confidential-list and redaction obligations, and the only three recipients) and warns about the closed-list prohibition (1904.29(b)(8)), which prevents misapplication. This enriches the agent's understanding of side effects and output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately long but each sentence carries substantive information. The core purpose is front-loaded in the first sentence, followed by the closed-list explanation, output summary, and usage timing. For a complex regulatory topic requiring precision, this structure is efficient and not padded. It is slightly denser than necessary but appropriate given the need to convey legal nuances.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential elements: what the tool determines, what it returns, when to invoke it, and the closed-list constraint. Since an output schema exists (has output schema: true), the return structure is presumably detailed there, but the description mentions the key outputs (log entry, confidential-list, redaction obligations, three recipients) to orient the agent. It does not explicitly address edge cases like 'none_of_these' returning false, but the schema and closed-list description imply that. Overall, it is complete enough for a read-only classification tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are fully documented in the input schema. The tool description adds meaning by explaining the regulatory basis for the enum values (e.g., '1904.29(b)(7) is a closed list — injury to an intimate body part or the reproductive system, sexual assault...') and clarifies that 'other_illness_employee_requested' is the only category that requires both is_illness and employee_requested_name_omitted. This helps the agent map incident narratives to the correct enum value and understand the conditional logic.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Determine'), a precise resource ('whether a recordable case is a privacy concern case'), and the core consequence (name must NOT be entered on the OSHA 300 Log). It explicitly distinguishes from siblings by indicating this runs after recordability is established, which is not obvious from any other tool. The mention of the closed list and prohibition adds specificity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly indicates when to run the tool ('Run this after a case is determined recordable') and provides context for the input nature by enumerating the closed list. It does not explicitly name alternative tools for different steps, but the instruction 'after a case is determined recordable' implicitly separates it from recordability assessment tools like osha_assess_recordability. The guidance is sufficient for correct usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_check_recordkeeping_obligationCheck Whether Recordkeeping Applies (29 CFR 1904.1)ARead-onlyIdempotent
The threshold question every other Part 1904 determination assumes: is this employer required to keep OSHA injury and illness records at all? Run this FIRST for any small employer or any establishment that may be in a partially exempt industry — otherwise the chain will confidently instruct them to make 300-Log entries for a log they need not keep. Two things are commonly got backwards: the size exemption is measured across the ENTIRE COMPANY, not one establishment (1904.1(b)(1)), and it uses PEAK employment during the last calendar year, not an average or year-end figure (1904.1(b)(2)). A written request from OSHA or BLS under 1904.41/1904.42 defeats the exemption. CRITICALLY, the exemption is PARTIAL: 1904.39 severe-injury reporting binds every employer covered by the OSH Act regardless — an exempt employer still owes OSHA the 8-hour fatality call. Supply establishment_naics_code and the tool resolves the 1904.2 industry question itself against the closed Appendix A list, matching on the first four digits. Reference and triage only.
| Name | Required | Description | Default |
|---|---|---|---|
| establishment_naics_code | No | The establishment's NAICS code, 4 to 6 digits. Supply this and the tool looks it up against the closed Appendix A list itself — the match is on the first FOUR digits, since Appendix A lists industry groups. If you do not know the code, omit it and use establishment_in_partially_exempt_industry instead. | |
| notified_in_writing_to_keep_records | No | Has OSHA or the Bureau of Labor Statistics informed the employer IN WRITING that it must keep records under 1904.41 or 1904.42? Appendix A extends this to a STATE AGENCY operating under the authority of OSHA or the BLS. Such a request defeats BOTH exemptions — 1904.1(a)(1) for size, 1904.2(a)(1) for industry. | |
| company_peak_employees_last_calendar_year | Yes | The PEAK number of employees across the ENTIRE COMPANY at any time during the last calendar year (1904.1(b)(1)-(b)(2)). Not an average, not a year-end headcount, and not a single establishment's count — if the company touched 11 employees for one week, it is over the threshold. | |
| establishment_in_partially_exempt_industry | No | Fallback for when the NAICS code is unknown: is this ESTABLISHMENT classified in a partially exempt industry under 1904.2? Ignored when establishment_naics_code is supplied, because the tool then determines it. Note this exemption attaches to the establishment, whereas the size exemption applies to the whole company. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, openWorldHint=false, idempotentHint=true, destructiveHint=false. The description adds meaningful behavioral context beyond those: it explains the size exemption measurement (entire company, peak employment), the industry exemption resolution against Appendix A, the partial nature of the exemption (1904.39 still binds), and that written notice defeats the exemption. It also notes the tool resolves the 1904.2 industry question itself. No contradictions. The only minor gap is not detailing what the return value looks like, but output schema exists and the description says 'Reference and triage only', which hints at the read-only consultative nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the critical 'Run this FIRST' instruction, then covers key behavioral traps. It is structured in logical flow: purpose, when to use, common mistakes, exceptions, and parameter hints. It is somewhat dense — the sentences are long and packed with regulatory citations. But every sentence earns its place: each clause adds a distinct fact (coverage scope, peak employment, written request exception, partial exemption). Slight deduction for density that may slow parsing, but not for waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex regulatory tool with 4 parameters (including a fallback boolean), the description and parameter-level detail together cover the key nuanced behaviors: the across-company scope, peak employment, industry exemption resolution, the written-notice defeat, and the partial exemption caveat. With output schema present, return format is not a gap. The sibling set includes many downstream chain tools, and this description establishes itself as the entry point. The completeness is high for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%. The description adds significant meaning beyond each property description. For company_peak_employees_last_calendar_year it emphasizes 'PEAK', 'ENTIRE COMPANY', 'not an average, not a year-end headcount', with an illustrative example ('if the company touched 11 employees for one week, it is over the threshold'). For establishment_naics_code it explains the 4-digit matching logic against Appendix A and the fallback to boolean. For notified_in_writing it adds context about state agencies and that it defeats both exemptions. This goes well beyond the schema's basic descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'check whether recordkeeping applies' under 29 CFR 1904.1, and frames it as the threshold question before all other Part 1904 determinations. It clearly distinguishes from siblings by naming the first step in a chain and explicitly instructing to 'Run this FIRST'. The title reinforces the regulatory citation, and the description exceeds mere tautology by explaining the consequence of skipping this check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent when to use: 'Run this FIRST for any small employer or any establishment that may be in a partially exempt industry'. It gives a clear when-not condition: 'otherwise the chain will confidently instruct them to make 300-Log entries for a log they need not keep.' It also reveals two common mistakes to guard against, which adds practical usage context. No direct alternative named, but the sibling set context implies the chain, and the description frames this as the gate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_check_severe_injury_reportingCheck Severe-Injury Reporting Deadline (29 CFR 1904.39)ARead-onlyIdempotent
Determine whether a fatality, in-patient hospitalization, amputation, or loss of an eye must be reported to OSHA, and compute the actual reporting deadline (8 hours for a fatality, 24 hours for the others) from when the employer learned of it. Also checks the eligibility window from the incident. Datetimes must be full ISO 8601. Applies the 1904.39(b)(11) amputation definition (a severed ear, avulsion, degloving or chipped tooth is NOT an amputation), the (b)(10) rule that a hospitalization for observation or diagnostics alone is not reportable, and the (b)(3)-(b)(4) exclusions for public-road motor vehicle accidents outside construction work zones and events on commercial or public transport. Every one of those still leaves the case RECORDABLE. Reference and triage only — not legal advice.
| Name | Required | Description | Default |
|---|---|---|---|
| outcome | Yes | The severe outcome, if any. 'none' means no 1904.39 reporting is triggered. | |
| amputation_kind | No | For an amputation only: what kind. 1904.39(b)(11) defines amputation as the traumatic loss of a limb or external body part, and expressly EXCLUDES avulsions, enucleations, deglovings, scalpings, severed ears, and broken or chipped teeth. Fingertip amputations count with or without bone loss, as do medical amputations and parts since reattached. One of: severed_or_cut_off, fingertip_amputation, medical_amputation, reattached_part, avulsion, enucleation, degloving, scalping, severed_ear, broken_or_chipped_tooth, not_applicable. | not_applicable |
| learned_datetime | Yes | ISO 8601 datetime the employer LEARNED of the outcome. Reporting deadlines run from this moment. | |
| outcome_datetime | No | ISO 8601 datetime the outcome occurred (e.g. date of death). Used to check the eligibility window (fatality within 30 days of incident; hospitalization/amputation/eye loss within 24 hours). If omitted, the window cannot be verified. | |
| incident_datetime | Yes | ISO 8601 datetime of the work-related incident, e.g. 2026-07-25T09:40:00-05:00. | |
| reporting_exclusion | No | Whether a 1904.39(b)(3)-(b)(4) reporting exclusion applies. A motor vehicle accident on a public street or highway is excluded UNLESS it happened in a construction work zone; events on commercial or public transport (airplane, train, subway, bus) are excluded. Either way the event is still RECORDABLE. One of: public_road_motor_vehicle_not_in_work_zone, commercial_or_public_transportation, none. | none |
| hospitalization_for_observation_or_diagnostics_only | No | For an in-patient hospitalization only: was the admission for OBSERVATION or DIAGNOSTIC TESTING alone? If so it is not reportable (1904.39(b)(10)) — only admissions for care or treatment are. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description transparently explains key behavioral rules: exclusions still leave the case recordable, observation-only hospitalizations are not reportable, and specific amputation definitions. It also clarifies that deadlines run from the learned datetime. Annotations already cover safety (read-only, idempotent), so the description adds regulatory context without redundancy.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but necessary given the regulatory complexity. It is structured logically: purpose, key rules, exclusions, and a disclaimer. While slightly long, every sentence adds relevant information, and it is not redundant with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides sufficient regulatory context for the tool's operation, including definitions, exclusions, and deadline logic. Since an output schema is present, the lack of explicit return-value explanation is acceptable. The tool appears complete for its intended triage role.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers 100% of parameters with descriptions, and the tool description reinforces the meaning of each parameter by explaining regulatory context (e.g., amputation_kind definitions, exclusion categories). It adds value beyond the schema by linking parameters to the regulation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: determine if reporting is required and compute deadlines for severe outcomes. It uses specific verbs like 'determine' and 'compute' and references the specific regulation (29 CFR 1904.39). It distinguishes itself from general recordability tools by focusing on reporting obligations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when the tool is applicable (severe outcomes) and includes exclusions (e.g., public road accidents, transport). It also notes it is for reference and triage only, not legal advice. However, it does not explicitly contrast with sibling tools, which slightly reduces clarity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_classify_300_log_entryClassify OSHA 300 Log Entry (29 CFR 1904.29)ARead-onlyIdempotent
For a recordable case, determine the correct OSHA 300 Log outcome column (G death, H days away, I job transfer/restriction, J other recordable) using the most-serious-outcome rule, the injury/illness type column, and the day counts capped at 180. Check on_log first — it is false when the case is not recordable. Medical removal cases must be days-away or restricted, never column J, and a removal following a chemical exposure goes in the poisoning column (1904.9(b)(1)); a tuberculosis case goes in the respiratory condition column (1904.11(a)), and may be lined out on the three kinds of evidence 1904.11(b)(2) enumerates. Run osha_assess_recordability first. Reference and triage only.
| Name | Required | Description | Default |
|---|---|---|---|
| death | No | Did the injury/illness result in death? | |
| illness_type | No | The injury/illness type column (M). | injury |
| is_recordable | Yes | Is the case recordable? Run osha_assess_recordability first. If false, it does not go on the 300 Log. | |
| tuberculosis_case | No | Is this a tuberculosis case? 1904.11(a) requires the RESPIRATORY CONDITION column. | |
| days_away_from_work | No | CALENDAR days away from work. Do NOT count the day the injury occurred (1904.7(b)(3)(i)). Count calendar days the employee was unable to work regardless of schedule — weekends, holidays and vacation days are included if they could not have worked (1904.7(b)(3)(iv)). If a PLHCP recommended a return date but the employee stayed home, end the count there (1904.7(b)(3)(iii)). | |
| medical_removal_case | No | Is this a medical removal case? 1904.9(b)(1) requires it be entered as EITHER days away OR restricted work depending on how the removal requirement was met — 'other recordable' (column J) is not available. | |
| date_information_received | No | ISO 8601 date the employer RECEIVED information that a recordable case occurred. 1904.29(b)(3) gives 7 calendar days from that moment — not from the incident — to complete both the 300 Log entry and the 301 Incident Report. | |
| days_restricted_or_transfer | No | CALENDAR days of job transfer or restricted work, counted the same way as days away (1904.7(b)(4)(xi)). Run osha_evaluate_restricted_work first — not every restriction counts. If the employee was permanently reassigned to a job that eliminates the restricted functions, the count may stop when that becomes permanent, but at least ONE day must be counted. | |
| tb_non_occupational_evidence | No | For a TB case already on the log: evidence that the infection was NOT caused by occupational exposure. 1904.11(b)(2) enumerates three circumstances and permits — does not require — lining out or erasing the entry. One of: household_contact, public_health_department_contact, medical_investigation, none. | none |
| bloodborne_diagnosis_after_recording | No | Has a case already recorded as a needlestick or sharps INJURY since produced a diagnosis of an infectious bloodborne disease? 1904.8(b)(3) then requires the existing entry to be amended rather than a new case recorded — including changing its classification from injury to illness. | |
| medical_removal_from_chemical_exposure | No | Did the medical removal follow a CHEMICAL exposure? If so the POISONING column must be checked (1904.9(b)(1)) — set illness_type to 'poisoning'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is clear. The description adds specific behavioral rules: the most-serious-outcome rule, 180-day cap, on_log false for non-recordable, medical removal never column J, chemical exposure → poisoning column, TB → respiratory condition column, and lining out on three kinds of evidence. This is substantial context beyond annotations. It doesn't restate the annotations and adds value on the regulatory logic. Not a 5 because it doesn't address what happens on edge cases like the 7-day completion deadline (though that's in the schema) or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a dense but well-structured paragraph: opens with the decision target, then the key rule, then the on_log gate, then the two special-column rules, and closes with the prerequisite and a triage note. No wasted words. It front-loads the most critical info (the classification rule) before regulatory details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 11 parameters, a rich output schema, and a complex regulatory domain. The description ties into the prerequisite tools and gives enough context to invoke correctly: what to check first, when not to use (on_log false, medical removal not J), and special cases. It could go deeper on the interaction with e.g. osha_evaluate_restricted_work for the restricted-days counting, or clarify the refusal of the 180-day cap on the day counts, but it covers the major decisions. Given the output schema exists, not explaining return format is acceptable. 4 is fair.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema thoroughly documents every parameter. The tool description itself doesn't expand on individual parameters, but it does compound the regulatory logic: e.g., it mentions the medical-removal rule and the chemical-exposure/poisoning link that ties to the medical_removal_from_chemical_exposure and medical_removal_case parameters, and notes the TB/gas evidence that maps to tb_non_occupational_evidence. That gives the parameters regulatory meaning beyond the schema's own text, which is already rich. I'd give 3—the schema carries most of the weight, but the description adds some regulatory interrelations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('determine the correct OSHA 300 Log outcome column'), names the exact resource (OSHA 300 Log column G/H/I/J), and explains the selection rule (most-serious-outcome, injury/illness type, day counts capped at 180). It clearly distinguishes this tool from siblings like osha_assess_recordability and osha_evaluate_restricted_work, which are mentioned as prerequisites.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs 'Run osha_assess_recordability first' and mentions 'Check on_log first' for non-recordable cases. It also references osha_evaluate_restricted_work for days restrictions in the parameter description, and 'Reference and triage only' clarifies this is a classification tool, not one that creates or modifies records. It clearly scopes when to use this tool versus when to use the assess/evaluate siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_determine_recording_employerDetermine Which Employer Records the Case (29 CFR 1904.31)ARead-onlyIdempotent
Decide WHOSE OSHA 300 Log a case belongs on when the injured person is not a straightforward payroll employee — a temp, a leased or supplied worker, a contractor's employee, someone self-employed, or an owner. Run this FIRST whenever the injured person is not on the employer's payroll: if the answer is 'the other employer' or 'no one', the rest of the chain is not this employer's obligation. The controlling test is DAY-TO-DAY SUPERVISION, not who issues the paycheck (1904.31(b)(2)-(b)(3)): a temp on an agency's payroll whose work you direct daily is your case to record. Self-employed people are not covered by the OSH Act at all (b)(1)), and owners or partners of a sole proprietorship or partnership are not employees for recordkeeping (a)). Every payroll category counts — part-time, seasonal and migrant workers included. 1904.31(b)(4) requires the case be recorded exactly once, never on both employers' logs. Reference and triage only — not legal advice.
| Name | Required | Description | Default |
|---|---|---|---|
| worker_relationship | Yes | The injured person's relationship to the employer asking. One of: on_your_payroll, temporary_leased_or_supplied, contractor_employee, self_employed, owner_or_partner. Note 'on_your_payroll' covers every category — labor, executive, hourly, salary, part-time, seasonal and migrant workers all count (1904.31(a)). | |
| you_supervise_day_to_day | No | Do YOU supervise this worker's work on a day-to-day basis? This is the controlling test for temporary, leased, supplied and contractor workers — not who issues the paycheck. Irrelevant for payroll employees, the self-employed, and owners or partners. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description fully discloses the decision logic, including the day-to-day supervision test and the irrelevance of paycheck issuer for temporary workers. It also references specific OSHA regulations (1904.31(a), (b)(1)-(b)(4)) and notes that it is not legal advice, which sets appropriate expectations. No contradictions with the readOnlyHint and idempotentHint annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a bit lengthy but well-structured with clear sentences addressing different aspects (purpose, when to use, controlling test, exclusions, and legal reference). It avoids unnecessary fluff, though some points are repeated across the description and parameter descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides comprehensive context for the decision process, including the rule for temporary workers and the exclusion of self-employed and owners. It also mentions that the case must be recorded only once (1904.31(b)(4)), making it complete for the tool's intended use within the OSHA recording workflow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides descriptions for both parameters, but the overall description adds meaningful context, such as clarifying that 'on_your_payroll' covers all employee types and that supervision is irrelevant for payroll employees. This enriches understanding beyond the schema's individual descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: determining which employer records a case on their OSHA 300 Log for non-payroll workers. It lists specific categories (temp, contractor, self-employed, owner) and the controlling test (day-to-day supervision), distinguishing it from sibling tools like assess_work_relatedness or evaluate_restricted_work.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs to run this tool first whenever the injured person is not on the employer's payroll, and explains that if the outcome is 'the other employer' or 'no one', the rest of the chain is not this employer's obligation. This provides clear when-to-use guidance and differentiates from later steps in the recordability assessment chain.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_evaluate_hearing_lossEvaluate Occupational Hearing Loss (29 CFR 1904.10)ARead-onlyIdempotent
Compute whether an audiogram produces a recordable hearing loss. Two tests must BOTH be met and, critically, in the SAME ear: a Standard Threshold Shift of 10 dB or more averaged at 2000, 3000 and 4000 Hz against the employee's baseline (1904.10(b)(1)), and a total hearing level of 25 dB or more above audiometric zero on the current audiogram (1904.10(a)). An STS in one ear and a 25 dB level in the other does not record. Pass raw audiogram values and the tool does the arithmetic — do not compute averages yourself. If the employee has had a prior recordable hearing loss, pass the REVISED baseline (b)(2)(i)). Age adjustment from Tables F-1/F-2 of 1910.95 appendix F applies to the STS test only, never to the 25 dB test (b)(3)). A retest within 30 days that does not confirm the STS defeats the case; one that confirms it starts a 7-day recording clock (b)(4)). A PLHCP determination of no work-relatedness ends it entirely (b)(6)). Reference and triage only — not legal advice.
| Name | Required | Description | Default |
|---|---|---|---|
| retest_date | No | ISO 8601 date of a confirming retest. Used to compute the 7-calendar-day recording deadline (1904.10(b)(4)). | |
| current_left | Yes | LEFT ear current audiogram. | |
| baseline_left | Yes | LEFT ear baseline audiogram. If the employee has previously had a recordable hearing loss, use the REVISED baseline reflecting that case, not the original (1904.10(b)(2)(i)). | |
| current_right | Yes | RIGHT ear current audiogram. | |
| baseline_right | Yes | RIGHT ear baseline audiogram, or the revised baseline if a prior hearing loss was recorded. | |
| retest_confirmed_sts | No | If retested, did the retest CONFIRM the recordable STS? A retest within 30 days that does not confirm it means the case need not be recorded. | |
| age_adjustment_db_left | No | Optional dB age correction for the LEFT ear, derived from Tables F-1/F-2 of 29 CFR 1910.95 appendix F. Applies ONLY to the STS test — it may NOT be applied to the 25 dB total-hearing-level test (1904.10(b)(3)). The tool does not compute this; supply it from the tables or leave 0. | |
| age_adjustment_db_right | No | Optional dB age correction for the RIGHT ear. Same rules as the left. | |
| retested_within_30_days | No | Was the employee's hearing retested within 30 days of the first test? (1904.10(b)(4)) | |
| plhcp_determined_not_work_related | No | Has a PLHCP determined, applying 1904.5, that the hearing loss is not work-related or that occupational noise did not significantly aggravate it? If so the case need not be recorded (1904.10(b)(6)). |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds substantial behavioral context: the two tests must be met in the same ear, age adjustment applies only to the STS test, retest rules (30-day window, confirmation vs. non-confirmation), and the PLHCP determination ending the case. It also warns that the tool does arithmetic and the user must supply age adjustments. This rich disclosure goes well beyond the annotations and precisely explains the decision logic.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though long, every sentence carries unique regulatory detail. The main purpose is front-loaded, and the subsequent sentences each clarify a distinct condition or exception. The structure uses parentheses for references and enumerations, making it scannable. There is no redundancy or filler; the length is justified for the regulatory complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 10 parameters, nested objects, and an output schema present, the description covers all essential behavioral aspects: the two decision tests, same-ear requirement, age adjustment scope, retest logic, PLHCP override, and usage constraints. It also includes a disclaimer about legal advice. The output schema handles return values, so that gap is not an issue. For a complex OSHA evaluation tool, this description is thoroughly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so a baseline of 3 applies. The description adds meaning beyond the schema by clarifying relationships: it explains the same-ear condition, that baseline values should be the revised baseline when applicable, and that age adjustments are for STS only. It instructs the agent to pass raw values and not precompute averages, and clarifies the interplay between retest flags and the PLHCP flag. This adds semantic depth that the schema alone does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb and resource: 'Compute whether an audiogram produces a recordable hearing loss.' It also specifies the regulatory basis (29 CFR 1904.10) and the two tests, making it unmistakable from sibling tools that handle other OSHA recordkeeping aspects. The purpose is specific, actionable, and distinguishes this tool from the broader osha_assess_recordability and similar siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context and instructions: 'Pass raw audiogram values and the tool does the arithmetic — do not compute averages yourself,' and explains when to pass a revised baseline. It also disclaims 'Reference and triage only — not legal advice.' However, it does not explicitly name sibling tools or state when NOT to use this tool (e.g., for work-relatedness determination, use osha_assess_work_relatedness). Since the domain is specific, the exclusion is implicit but not explicit, so a 4 is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_evaluate_restricted_workEvaluate Restricted Work or Job Transfer (29 CFR 1904.7(b)(4))ARead-onlyIdempotent
Decide whether a work restriction or job transfer actually counts as restricted work — not every restriction does. Run this BEFORE passing 'restricted_work_or_transfer' as an outcome to osha_assess_recordability, because getting it wrong moves cases onto or off the 300 Log. The rules it applies: a restriction confined to the day of injury does not count (b)(4)(iii); reduced output while still doing all routine functions does not count (b)(4)(vi); a restriction that misses every routine function does not count (b)(4)(iv), where routine functions are activities performed at least once per week (b)(4)(ii); a partial shift does count (b)(4)(v); and a job transfer is recorded in the same column (b)(4)(ix)-(x)). Critically, when a vague recommendation such as 'light duty' cannot be clarified with the PLHCP, the case MUST be recorded as restricted work (b)(4)(vii)) — the regulation resolves that doubt toward recording. Reference and triage only — not legal advice.
| Name | Required | Description | Default |
|---|---|---|---|
| reduced_output_only | No | Is the ONLY effect that the employee produces less while still performing all routine functions and working the full shift? That is not restricted work (1904.7(b)(4)(vi)). | |
| restriction_is_vague | No | Is the recommendation vague — 'light duty', 'take it easy for a week' — rather than specific? (1904.7(b)(4)(vii)) | |
| worked_partial_shift | No | Did the employee work only part of a shift because of the injury or illness? A partial day counts as a day of restriction or transfer, except on the day of the injury (1904.7(b)(4)(v)). | |
| transferred_to_another_job | No | Was the employee assigned to a job other than their regular job for part of the day? Transfers are recorded in the same 300-Log box as restricted work (1904.7(b)(4)(ix)-(x)). | |
| vague_restriction_clarified | No | If the restriction was vague, was the PLHCP successfully asked whether the employee can do ALL routine functions AND work the FULL shift? If clarification could NOT be obtained, pass false — 1904.7(b)(4)(vii) then requires the case to be recorded as restricted work. | |
| restriction_applies_beyond_day_of_injury | Yes | Does the restriction or transfer extend beyond the day the injury occurred or the illness began? A restriction imposed ONLY for that day is not recordable as restricted work (1904.7(b)(4)(iii)). | |
| keeps_from_routine_function_or_full_shift | Yes | Does the restriction keep the employee from one or more ROUTINE functions, or from working the full workday they would otherwise have been scheduled? Routine functions are activities the employee regularly performs AT LEAST ONCE PER WEEK (1904.7(b)(4)(ii)). A restriction on something done less often than weekly is not a restriction on a routine function. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description does not need to repeat those. It does add valuable behavioral context beyond the annotations: the tool applies a decision tree based on regulation, and it emphasizes the doubt-resolution rule that vague recommendations default to recording. It also notes the tool is not legal advice, which is a helpful behavioral caveat. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it packs a dense set of regulatory rules that are essential for correct usage. It front-loads the purpose and usage instruction ('Run this BEFORE...'), then lists the key rules in a structured sequence. While it could be slightly trimmed, the length is justified by the complexity of the regulatory domain. It is not tautological or redundant with the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of the tool (7 parameters, complex decision rules, and an output schema), the description provides sufficient context: it explains the decision criteria, the critical vague-restriction rule, and the tool's place in the workflow. Since an output schema exists, the description need not describe return values. The only minor gap is that it does not explicitly state the ternary nature of the output (true/false/unknown), but the output schema presumably covers that. It is complete enough for an agent to understand when and how to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% — every parameter has a detailed description including regulatory references (e.g., '1904.7(b)(4)(iii)' for restriction confined to day of injury). The description itself does not elaborate on individual parameters, but that is unnecessary given the schema's thoroughness. The description does add context about the overall decision logic, but it does not go beyond what the schema already explains for each parameter. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action: 'Decide whether a work restriction or job transfer actually counts as restricted work'. It immediately differentiates itself from siblings by mandating that it runs BEFORE passing 'restricted_work_or_transfer' to osha_assess_recordability, and it lists the exact regulatory references (29 CFR 1904.7(b)(4) subsections). This is a specific verb+resource with explicit sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is precisely defined: 'Run this BEFORE passing restricted_work_or_transfer as an outcome to osha_assess_recordability'. It also enumerates what does and does not count as restricted work, including the critical caveat about vague restrictions that must be recorded unless clarified. It further warns that it is 'Reference and triage only — not legal advice,' setting clear boundaries for its use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
osha_route_to_establishment_logRoute a Case to the Right Establishment Log (29 CFR 1904.30)ARead-onlyIdempotent
Decide WHICH establishment's OSHA 300 Log a recordable case belongs on — the last question about an individual incident, and one multi-site employers routinely get backwards. Under 1904.30(b)(4) the case follows the PLACE, not the person: an injury occurring at one of the employer's establishments is recorded on THAT establishment's log even when the employee normally works elsewhere, while an injury away from all of them (a customer site, in transit, remote work) goes on the log of the establishment where the employee normally works. Also reports whether the destination needs its own log — required for establishments expected to operate a year or longer (1904.30(a)), optional for short-term sites which may share a combined log (b)(1) — and, when records are kept centrally, the 7-calendar-day transmission deadline and the two conditions central recordkeeping depends on (b)(2)). Reference and triage only — not legal advice.
| Name | Required | Description | Default |
|---|---|---|---|
| records_kept_centrally | No | Are the establishment's records kept at headquarters or another central location? Permitted only on the two conditions in 1904.30(b)(2). | |
| date_information_received | No | ISO 8601 date the employer received information that a recordable case occurred. Used with central recordkeeping to compute the 7-calendar-day transmission deadline (1904.30(b)(2)(i)). | |
| employee_was_telecommuting_from_home | No | Was the employee working from home at the time? A home is NEVER a business establishment and needs no separate 300 Log (1904.46(3)) — the case goes on the log of the establishment the telecommuter is linked to under 1904.30(b)(3). Pass false for occurred_at_one_of_your_establishments in this case. | |
| occurred_at_one_of_your_establishments | Yes | Did the injury or illness occur AT one of the employer's own establishments? True even if it is not the employee's usual site. False for a customer site, in transit, or working from home. An establishment is a single physical location where business is conducted (1904.46); for mobile work — construction, transportation, utilities — it is the office, terminal or station that supervises the activity or is the base for it. | |
| destination_expected_to_operate_a_year_or_longer | No | Is the establishment whose log will carry the case expected to be in operation for a year or longer? If not, no separate log is required — its cases may go on a combined short-term log, optionally per division or geographic region (1904.30(a), (b)(1)). |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| value | Yes | |
| cfr_cite | Yes | |
| source_url | Yes | |
| last_verified | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=true, idempotentHint=true, destructiveHint=false, and the description fully aligns with these. It goes beyond annotations by elaborating the regulatory framework and edge cases (e.g., telecommuting, mobile work, short-term establishments), providing transparency about the tool's decision-making behavior without contradiction. No side effects are implied, consistent with read-only nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
While lengthy, the description is well-structured and information-dense. It front-loads the core purpose and then systematically explains the decision logic, referencing specific regulations and edge cases. Every sentence adds value, and the regulatory citations (1904.30(a), (b)(1)-(4), 1904.46) are precise. No redundancy or filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of OSHA regulations, the description is remarkably complete. It covers the main rule (place of injury), exceptions (telecommuting, mobile work), and ancillary considerations (short-term establishments, central recordkeeping deadlines). Since an output schema exists, the lack of explicit return-value description is acceptable. The description equips an agent to make the correct routing decision without ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with all 5 parameters described in detail. The description adds semantic depth by explaining the significance of each parameter (e.g., 'occurred_at_one_of_your_establishments' definition includes mobile work nuances, and 'employee_was_telecommuting_from_home' clarifies that a home is never an establishment). This exceeds the schema's basic descriptions and provides the rationale for parameter values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to decide which establishment's OSHA 300 Log a recordable case belongs on. It uses a specific verb ('Decide') and a specific resource ('establishment's OSHA 300 Log'), and it distinguishes itself from sibling tools like check_recordkeeping_obligation and determine_recording_employer by focusing on the final routing decision.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly positions this as 'the last question about an individual incident,' making clear it is used after other recordability steps. It also provides detailed regulatory context (1904.30(b)(4)) and explains the decision logic, effectively guiding when to use this tool versus alternatives. The 'last question' phrasing implies it's the final step in a sequence, which is sufficient for routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
11 tool updates
v0.1.0- First observed
osha_assess_new_case - First observed
osha_assess_recordability - First observed
osha_assess_work_relatedness - First observed
osha_check_privacy_case - First observed
osha_check_recordkeeping_obligation - First observed
osha_check_severe_injury_reporting - First observed
osha_classify_300_log_entry - First observed
osha_determine_recording_employer - First observed
osha_evaluate_hearing_loss - First observed
osha_evaluate_restricted_work - First observed
osha_route_to_establishment_log
TDQS
Scored across 11 tools
Each tool maps to a distinct, named regulatory decision point in the Part 1904 pipeline, and the cross-references ('Run this BEFORE...') make the flow clear. However, there is residual ambiguity risk: 'assess' tools (work_relatedness, new_case) are near-synonyms for 'evaluate' tools (restricted_work, hearing_loss), and an agent could initially hesitate between osha_assess_recordability and its sub-tools despite the explicit guidance. The two 'check' obligation gates are also conceptually parallel, though the domain separation is real.
All tool names follow a uniform snake_case `osha_<verb>_<object>` pattern, and the object nouns are clear and meaningful. However, the verb choices — assess, evaluate, check, determine, classify, route — are largely interchangeable near-synonyms that follow a subtle internal logic (check=obligation gates, assess=decision nodes, evaluate=sub-computations) that is not self-evident from the names alone. The pattern is consistent but the verb selection is slightly muddier than a strict verb_noun taxonomy.
With 11 tools, the server is well within the ideal 3-15 range for a domain as broad as Part 1904 recordkeeping. Each tool earns its place by covering a genuine regulatory gate, and the count feels appropriately granular — not so few that decisions are conflated, not so many that the surface becomes unmanageable. The split of the 1904.4 decision tree into discrete tools is justified by the complexity of each step.
The end-to-end recordkeeping lifecycle is thoroughly covered: threshold obligation → employer attribution → work-relatedness → new case → recordability → classification → privacy → establishment routing, plus severe-injury reporting. Notable gaps include the 300A annual summary and posting requirement, employee/authorized-representative access to records, and corrections to already-filed logs, but these are administrative follow-ons rather than core decision dead-ends. The coverage of 1904.8-1904.12 specific-case criteria is also mostly folded into the broader tools.
Maintenance
Related MCP Connectors
Typed AI decisions for agents: classify, route, screen evidence, score and batch-label text.
51Read-only, deterministic AI triage and readiness tools implementing Sophon's published rubrics.
Workplace safety citation counts, penalties and 29 CFR standards data for AI assistants
Deterministic CMS NCCI/MUE claim scrubbing and CARC/RARC denial explanations, cited to source.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to perform security alert triage by ingesting raw logs, extracting IOCs, querying threat intelligence sources, and generating structured NIST/MITRE assessments with reasoning traces.MIT
- AlicenseNot gradedqualityBmaintenanceDeterministic rule-based medical triage with citations, using a 0.6B LLM only to check criteria (yes/no/unknown).Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables users to trace regulatory rule changes to affected parties and required actions through deterministic safety gates, returning dated action plans and hash-linked evidence records. Supports 12 MCP tools over stdio or streamable HTTP for source comparison, obligation decomposition, scope assessment, planning, and evidence validation across multiple domain packs.MIT
- AlicenseAqualityAmaintenanceEnables local, deterministic clinical calculations for nursing and emergency care, including Parkland formula, body surface area, and IV drip rate tools with validated typed inputs.323 PyPIMIT