npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@workingdevshero/olympia-ait-adapter

v1.0.0

Published

MCP adapter that converts between Olympia Fitness & Performance XLSX workbooks (programs and companion warm-ups) and strict JSON schemas.

Readme

olympia-ait-adapter

MCP adapter that converts Olympia Fitness & Performance XLSX workbooks — training programs and their companion warm-up documents — to and from strict JSON schemas. Built for the Automate It framework so AI agents can author new strength-and-conditioning paperwork from prior client data without ever touching XLSX directly.

Why this exists

Olympia's coaches build client programs in XLSX workbooks — one client per file, one sheet per training day, with merged cells, custom borders, an embedded logo, and a domain-specific notation (12E, :20E, 12EL, x3 Rest :60, etc.). Asking an LLM to edit XLSX directly is fragile: it corrupts merges, loses the logo, and can't reason about the implicit 6-week / 1A-1B / set-by-set structure encoded in the visual layout.

Each program also ships with a companion warm-up workbook — same client, same date, paired day-for-day (the "Day 4" warm-up column is performed before the "Day 4" program sheet). It's a completely different layout: one sheet where each day is a column of titled sections of freeform exercise lines.

This package gives the agent a clean structured view of both document types and guarantees well-formed output: the LLM reads JSON, reasons about it, writes JSON, and the adapter handles all the visual fidelity on the way back to XLSX.

What it does

Four MCP tools, exposed over stdio:

| Tool | Direction | Purpose | | ------------------------------ | ----------- | ---------------------------------------------------------------- | | olympia_program_xlsx_to_json | XLSX → JSON | Parse an Olympia program workbook into a typed Program. | | olympia_program_json_to_xlsx | JSON → XLSX | Render a Program back to a styled .xlsx on disk. | | olympia_warmup_xlsx_to_json | XLSX → JSON | Parse a companion warm-up workbook into a typed WarmUpDocument. | | olympia_warmup_json_to_xlsx | JSON → XLSX | Render a WarmUpDocument back to a styled .xlsx on disk. |

The JSON schemas are defined once in src/schema/program.ts and src/schema/warmup.ts using Zod and surface as:

  1. The TypeScript type used internally
  2. The runtime validator at each tool boundary
  3. The JSON Schema published as each tool's inputSchema so the LLM sees the full typed contract at discovery time

All object schemas are strict: unknown fields are rejected with an error rather than silently stripped, so callers authoring against a stale contract fail loudly.

JSON shape — programs

type Program = {
  client: string;                  // "Bobby Galli"
  programDate: string;             // "4.26"
  days: Day[];
};

type Day = {
  name: string;                    // "Day 1"
  sections: Section[];
  supplementalNotes?: SupplementalNote[];
};

type Section = {
  kind: "warmup" | "main" | "sportSpecific" | "supplemental" | "conditioning";
  exercises: Exercise[];
};

type Exercise = {
  name: string;                    // "2DB Alternating Bench Press"
  groupLabel?: string;             // "1A", "1B", "2A"…  matches /^\d+[A-Z]$/
  notes?: string;
  sets: (string | null)[][];       // [setIdx][weekIdx]; inner length 6
};

type SupplementalNote = {
  row: number;                     // offset from "Sport Specific/" label row
  col: string;                     // "C" | "D" | … | "P"
  value: string;
};

Prescription cell grammar

Olympia does not prescribe weights. Each sets[setIdx][weekIdx] is a single opaque string encoding reps, time, or breaths:

| Format | Meaning | | --------------------- | ------------------------------------ | | "12" / "10E" | reps (E = each side) | | ":20" / ":20E" | seconds (E = each side) | | "5 breaths" | breath count | | "12EL" / "10ER" | reps each side, left or right lead | | free-form strings | circuit-style instructions, OK too | | null | empty cell |

The schema enforces shape (6 weeks per set, group label regex, allowed section kinds) but does not validate the grammar of each prescription string — Olympia's own files include free-form entries in some spots.

The Date: cells in each sheet's header row are intentionally left blank — clients hand-write the week dates on the printed sheet, so the schema has no field for them and the writer never fills them.

Supplemental area

The bottom of every day sheet is a trainer-managed "Sport Specific / Supplemental" area where coaches write athlete-specific instructions that don't fit the structured exercise table (conditioning circuits, sport drills, recovery work). The adapter:

  • Reads that area as a sparse list of { row, col, value } entries (master cells only) so the signal is preserved for downstream agents.
  • Writes the fixed 10-row template (with "Sport Specific/" and "Supplemental" labels) at the bottom of every day, then layers any supplied supplementalNotes on top.

JSON shape — warm-ups

type WarmUpDocument = {
  client: string;                  // "Bobby Galli" — same as companion program
  warmUpDate: string;              // "4.26" — matches the companion programDate
  days: WarmUpDay[];
};

type WarmUpDay = {
  name: string;                    // "Day 4" — matches a program day sheet name
  sections: WarmUpSection[];
};

type WarmUpSection = {
  title: string;                   // "Foam Roll", "Prep \ Activation X2 Rounds"
  items: WarmUpItem[];
};

type WarmUpItem = {
  text: string;                    // "Pecs :45E" — prescription inline, never parsed
  note?: string;                   // "(^R.F.E on SB, F-Roller for Balance^)"
};

The warm-up layout is days-as-columns on a single sheet (A, C, E, … with empty gutter columns between), sections row-aligned across days. Section headers are bold; exercise lines are plain with the prescription shorthand embedded in the text (:45E, X8br, X4ES — trainer conventions, kept opaque); note lines render in italics under their exercise. When decoding, italic or fully-parenthesized lines are treated as notes attached to the item above — so never author an item whose entire text is parenthesized.

Skill

skills/olympia-authoring/SKILL.md (shipped in the npm package) is an agent-facing technical reference covering both formats: the schemas, the prescription notation, the program/warm-up pairing rules, and the decode → author → encode workflow.

Installation

npm install
npm run build

The built CLI lives at dist/server.js; the bin entry registers it as olympia-ait-adapter.

Running the MCP server

# Dev (TypeScript via tsx)
npm run dev

# Built (after `npm run build`)
npm start
# or
npx olympia-ait-adapter

The server speaks the Model Context Protocol over stdio. To wire it into Claude or another MCP client, add an entry like:

{
  "mcpServers": {
    "olympia-ait-adapter": {
      "command": "npx",
      "args": ["olympia-ait-adapter"]
    }
  }
}

All tools take absolute paths to .xlsx files on the local filesystem.

Repo layout

src/
  schema/
    program.ts               # Zod schema for programs — single source of truth
    warmup.ts                # Zod schema for warm-up documents
  reader/
    cell-utils.ts            # Shared ExcelJS cell-value helpers
    parse-workbook.ts        # Workbook → Program JSON
    parse-day-sheet.ts       # One sheet, section detection, supplemental capture
    parse-warmup-workbook.ts # Warm-up workbook → WarmUpDocument JSON
  writer/
    build-workbook.ts        # Program → ExcelJS workbook
    build-warmup-workbook.ts # WarmUpDocument → ExcelJS workbook
    layout.ts                # Column widths, row positions, logo anchor
    styles.ts                # All borders/fonts/fills as constants
    stamp-exercise.ts        # One exercise block (variable sets, group borders)
    supplemental-template.ts # Fixed bottom template + supplementalNotes overlay
  tools/
    program-xlsx-to-json.ts  # MCP handler
    program-json-to-xlsx.ts  # MCP handler
    warmup-xlsx-to-json.ts   # MCP handler
    warmup-json-to-xlsx.ts   # MCP handler
  server.ts                  # Bootstrap, registers all four tools
  assets/
    olympia-logo.png         # Extracted from sample workbooks; embedded in output

skills/
  olympia-authoring/SKILL.md # Agent-facing technical reference for both formats
samples/                     # Real Olympia .xlsx files used as round-trip fixtures
scripts/                     # Inspection helpers used during development
tests/                       # vitest — schema, reader, round-trip, MCP smoke

Tests

npm test                     # one-shot
npm run test:watch           # vitest watch mode
npm run typecheck            # tsc --noEmit

Coverage:

  • schema.test.ts — Zod rejects malformed program input (week count, group label regex, section kinds, missing fields).
  • reader.test.ts — All three program samples parse into schema-valid Program documents; spot checks on Bobby's first exercise, Giulianna's variable set counts, exercise notes, supplemental notes.
  • round-trip.test.ts — The primary determinism guarantee: for each program sample, parse → write → parse produces JSON equal to the original.
  • warmup-doc-schema.test.ts — Zod accept/reject tables for the warm-up document schema.
  • warmup-doc-reader.test.ts — The warm-up sample parses into a schema-valid WarmUpDocument with verbatim spot checks (including the note-attachment rule); warning paths for irregular layouts.
  • warmup-doc-writer.test.ts — Day/section/item/note styling and cross-day section alignment, verified by re-reading the written file.
  • warmup-doc-round-trip.test.ts — Warm-up determinism: the sample and an authored document both survive parse → write → parse / write → parse unchanged.
  • mcp-smoke.test.ts — End-to-end MCP server check via the in-memory transport: tool discovery (all four tools), round-trips via client.callTool for both document types, schema rejection of malformed input at the SDK boundary.

Determinism

The writer is fully programmatic — no template .xlsx file. Every byte of the output is determined by code plus the input JSON, so the same JSON produces the same workbook. The Olympia logo is the only binary asset (src/assets/olympia-logo.png).

This trade-off is intentional: templates introduce hidden state that ExcelJS occasionally drops (drawings, theme colors), whereas pure code → output gives byte-stable, snapshot-testable results.

License

Internal — Automate It / Olympia Fitness & Performance RI.