# CourseCode Framework (npm · coursecode)

Preview, screenshot, lint, and test SCORM, cmi5, and LTI courses built with CourseCode Framework.

- Trust score: 71/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-04

## Components

- npm · `coursecode`: 71/100 (this document), [markdown](https://verifymcp.io/servers/course-code-framework-coursecode/coursecode.md), [page](https://verifymcp.io/servers/course-code-framework-coursecode/coursecode)

## Channel facts

- Registry: `npm`
- Package: `coursecode`
- Version: `0.4.4`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-04.

- **Supply Chain Security**: 93/100
  - No malware found by supply-chain analysis.
  - CVE check failed: a known medium-severity CVE affects minimatch 10.2.6, reached via archiver > readdir-glob > minimatch. A fixed version is available.
  - No install/post-install scripts declared.
  - 78 of 236 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 48/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 4 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 68/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 3310 tokens (~206/item across 16 items; 16 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 20/100
  - Stability observed for 6 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 16 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 17 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the CourseCode Framework MCP server?

CourseCode Framework runs locally as an npm package, launched with npx -y coursecode. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add course-code-framework-coursecode -- npx -y coursecode
```

### Cursor

```json
{
  "mcpServers": {
    "course-code-framework-coursecode": {
      "command": "npx",
      "args": [
        "-y",
        "coursecode"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "course-code-framework-coursecode": {
      "command": "npx",
      "args": [
        "-y",
        "coursecode"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add course-code-framework-coursecode -- npx -y coursecode
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "course-code-framework-coursecode": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "coursecode"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add course-code-framework-coursecode --command npx --arg -y --arg coursecode
```

### Hermes

```yaml
mcp_servers:
  course-code-framework-coursecode:
    command: "npx"
    args: ["-y", "coursecode"]
```

### Netclaw

```json
{
  "McpServers": {
    "course-code-framework-coursecode": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "coursecode"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add course-code-framework-coursecode -t stdio -c npx -a -y coursecode
```

### Other

```json
{
  "mcpServers": {
    "course-code-framework-coursecode": {
      "command": "npx",
      "args": [
        "-y",
        "coursecode"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-04 (score 71, +1)

No change was recorded against any check on this day. Stability & Change Management went from 17 to 20. That category is still filling its 30-day observation window: 5 days of observed history at the previous scan, 6 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-11-02 (score 70, +1)

No change was recorded against any check on this day. Stability & Change Management went from 10 to 13. That category is still filling its 30-day observation window: 3 days of observed history at the previous scan, 4 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-31 (score 69, +14)

- [security regression] CVE-2026-118764 affects this package: medium
- [security regression] Known CVEs: pass → fail
- [security improvement] Malware scan: unverified → pass

### 2026-10-30 (score 55, +1)

- [security improvement] Malware scan: unverified → pass
- [functional improvement] Stability: unverified → 0.03
- [functional] Package version: 0.4.3 → 0.4.4

### 2026-10-29 (score 54)

First indexed and scored.

## MCP tools (16)

### `coursecode_state` (~264 tokens)

Get course state and live preview diagnostics in one call.

Returns:
\- slide: current slide ID (string)
\- toc: course structure [{id, type, title, file?}]
\- interactions: interactions on current slide [{id, type, hasResponse, isChecked}]
\- engagement: slide engagement {complete, percentage, requirements}
\- lmsState: LMS data {score, completion, success, bookmark, format, objectives, state}
\- apiLog: last 20 LMS API calls [{timestamp, method, args, result}]
\- diagnostics: live issue rollup with build, runtime, framework, console, issues, count, clean
\- issues/errors: flat live issue list [{source, severity, isWarning, type, message, hint?}]
\- runtimeErrors: runtime/debug-panel errors and warnings only
\- buildErrors/buildWarnings: backward-compatible build-watch aliases
\- frameworkLogs: structured framework log events [{level, domain, operation, message, stack?, timestamp}]
\- consoleLogs: browser console warnings/errors [{type, text, time}]

Use this first to understand the course state before taking actions.
For checking what is broken after file edits, prefer coursecode_errors — same live diagnostic sources, smaller payload.
Requires preview server to be running.

### `coursecode_errors` (~185 tokens)

Get all current live preview diagnostics without the heavyweight course state payload.

This is the primary "what is broken right now?" tool after edits. It aggregates:
\- build: Vite/build-watch errors and warnings from the running preview server
\- runtime: stub LMS/debug-panel errors and warnings
\- framework: CourseCode logger warnings/errors
\- console: browser console warnings/errors

This is different from coursecode_lint, which is a static/build-time linter and does not inspect the running preview.

Returns:
\- build/runtime/framework/console: grouped diagnostics by source
\- issues/errors: flat list [{source, severity, isWarning, type, message, hint?}] for agents
\- count: total issue count
\- clean: true if no live issues were found
\- runtimeErrors/frameworkLogs/consoleLogs: source-specific aliases

Requires preview server to be running.

### `coursecode_navigate` (~166 tokens)

Navigate to a specific slide by ID. Returns:
\- slide: current slide ID
\- interactions: interactions on the new slide [{id, type, hasResponse, isChecked}]
\- engagement: slide engagement {complete, percentage, requirements}
\- accessibility: current accessibility state {theme, highContrast, largeFont, reducedMotion}

Optionally set theme or highContrast before navigating. Use this to toggle dark mode for visual inspection.

Use coursecode_state first to get the structure and find valid slide IDs.
Requires preview server to be running.

Input parameters:

- `highContrast` (boolean): Enable or disable high contrast mode before navigating
- `slideId` (string, required): The slide ID to navigate to
- `theme` (string): Set theme before navigating: "light" or "dark"

### `coursecode_interact` (~200 tokens)

Set a response for an interaction AND evaluate it in one call. Returns:
\- correct: boolean
\- score: 0-1
\- feedback: feedback message if any
\- state: updated course state

Response format depends on interaction type:
\- multiple-choice: 'a', 'b', 'c', etc.
\- true-false: true or false
\- fill-in-blank: {blankId: 'answer'}
\- drag-drop: {itemId: 'zoneId'}
\- numeric: number
\- sequencing: ['id1', 'id2', 'id3']

Assessment questions (see coursecode_assessment) are only saved here: the result is {answered, gradedOn: 'submit', assessment}, and the score comes from submitting the assessment.

Requires preview server to be running.

Input parameters:

- `interactionId` (string, required): The interaction ID to answer
- `response` (required): The response value (format depends on interaction type)

### `coursecode_assessment` (~305 tokens)

Read or drive the assessment (graded quiz) on the current slide by pressing the same buttons a learner would.

Without 'action': returns the assessment state. With 'action': presses that button, waits for the assessment to update, and returns the new state.

State: {id, view ('intro' | 'question' | 'review' | 'results'), questionIndex, question ({id, type, hasResponse} while a question shows), actions (buttons available now), modalOpen, attempts, lastResults}

Typical run:
1\. coursecode_navigate to the assessment slide
2\. action 'start'
3\. For each question: coursecode_interact with question.id from this state, then action 'next'
4\. On the review screen: action 'submit' (if an unanswered-questions dialog opens, use 'confirm-unanswered-submit' or 'dismiss-unanswered-modal')
5\. Read lastResults here and the LMS score/success in coursecode_state

Other actions: 'prev', 'jump-to-review', 'review-question' (with questionIndex), 'back-to-questions', 'retake', 'go-to-remedial', 'restart-course'. An unavailable action returns an error listing the available ones.

Requires preview server to be running.

Input parameters:

- `action` (string): Button to press. Omit to read the current assessment state.
- `questionIndex` (number): 0-based question to edit; required for 'review-question'

### `coursecode_reset` (~46 tokens)

Clear learner state and restart the course. Use this to test from a fresh state.

Clears localStorage and fully reloads the headless browser.

Requires preview server to be running.

### `coursecode_screenshot` (~206 tokens)

Take a screenshot of the course preview. Returns a JPEG image.

Two quality modes (neither changes viewport):
\- normal (default): JPEG@50 (~20-40KB) — layout checks
\- detailed: JPEG@90 (~100-200KB) — close text/element inspection

Captures at the current viewport size. Use coursecode_viewport to change viewport for responsive testing.

Use scrollY to scroll course content before capturing (useful for long slides).
fullPage captures the course iframe's full content area.

Use to visually inspect slide layout, design, and component rendering.
Requires preview server to be running.

Input parameters:

- `detailed` (boolean): Higher JPEG quality for close inspection (does not change viewport)
- `fullPage` (boolean): Capture full scrollable page instead of viewport
- `scrollY` (number): Scroll course content to this Y position (pixels) before capturing
- `slideId` (string): Navigate to this slide ID before taking screenshot

### `coursecode_viewport` (~238 tokens)

Set the headless browser viewport size for responsive design testing.

Two modes:
\- Breakpoint name: 'mobile-portrait', 'mobile-landscape', 'tablet-portrait', etc.
  Resolves width dynamically from the course's breakpoint manager (always in sync with CSS).
  Height follows the orientation: 16:9 for desktop and landscape, 9:16 for mobile-portrait, 3:4 for tablet-portrait.
\- Explicit dimensions: {width: 375, height: 812} for specific device sizes.

The viewport PERSISTS until changed again. Call with 'desktop' or {width: 1280, height: 720} to reset.

Returns the applied viewport dimensions and breakpoint name (if used).

Use before coursecode_screenshot to test responsive layouts.
Requires preview server to be running.

Input parameters:

- `breakpoint` (string): Named breakpoint from the course (e.g., "mobile-portrait", "tablet-landscape", "desktop")
- `height` (number): Explicit viewport height in pixels (use with width)
- `width` (number): Explicit viewport width in pixels (use with height)

### `coursecode_workflow_status` (~177 tokens)

Detect the current authoring stage and get stage-specific instructions.

Returns:
\- stage: human-readable stage name
\- stageNumber: 1-5
\- checklist: {hasRawRefs, hasConvertedRefs, hasOutline, hasSlides, hasCourseConfig, previewRunning}
\- nextAction: recommended next step
\- recommendedTool: MCP tool to use next
\- instructions: detailed guidance for the current stage

Stages:
1\. Source Ingestion - create project and convert reference docs
2\. Outline Creation - build COURSE_OUTLINE.md from references
3\. Course Building - create slides and course-config.js
4\. Preview & Polish - iterate on visual quality and correctness
5\. Export Ready - lint passes, ready for LMS deployment

Call this after completing a major milestone to get updated guidance for the next stage.

### `coursecode_build` (~112 tokens)

Build the course for deployment. Runs the Vite production build.

Returns:
\- success: boolean
\- format: LMS format used
\- outputDir: path to built output
\- errors: any build errors
\- warnings: any build warnings
\- duration: build time

Use in Stage 5 when the course is ready for export.

Input parameters:

- `format` (string): LMS format: cmi5, scorm2004, scorm1.2, or lti (default: cmi5)

### `coursecode_css_catalog` (~205 tokens)

Browse or search CSS classes available for slide authoring.

Three modes:
\- No args: compact table of contents (category names + class counts)
\- category: full class list with abbreviated declarations for one category
\- search: find classes by name across all categories

Author-facing categories (layout, utilities, common components) shown by default.
Framework-internal categories (interactions, accessibility, app shell) hidden — set includeInternal: true to include them.

Use to discover available CSS classes before authoring slides. Lint catches invalid classes with fix suggestions.

Input parameters:

- `category` (string): Get full class details for this category (e.g., "utilities/spacing", "layout", "components/cards")
- `includeInternal` (boolean): Include framework-internal categories (interactions, accessibility, app shell). Default: false.
- `search` (string): Search class names (e.g., "gap", "card", "text-"). Returns matching classes with declarations.

### `coursecode_component_catalog` (~111 tokens)

Get UI component information.

Without 'type': returns compact list of all components (name + description + engagement tracking type).
With 'type': returns full schema, metadata, and HTML usage template for that specific component.

Components are declarative HTML (data-component attributes). No imports needed—just use the HTML patterns in your slide template.
Use to discover available components before authoring slides.

Input parameters:

- `type` (string): Optional component type to get full details for (e.g., "tabs", "accordion")

### `coursecode_interaction_catalog` (~115 tokens)

Get interaction type information.

Without 'type': returns compact list of all interaction types (name + description).
With 'type': returns full schema, properties, and factory name for that specific interaction.

Interactions use factory functions from the global CourseCode object (e.g., const { createMultipleChoiceQuestion } = CourseCode). No import statements needed.
Use to discover available interactions before creating assessments.

Input parameters:

- `type` (string): Optional interaction type to get full details for (e.g., "multiple-choice", "drag-drop")

### `coursecode_lint` (~244 tokens)

Run the static course linter and get structured results.

This is a preflight/static validation tool for config, source structure, CSS class names, and schema rules. It does NOT inspect the running preview and does NOT include live runtime, browser console, or Vite build-watch diagnostics. Use coursecode_errors for the live "what is broken right now?" view when preview is running.

Returns:
\- errors: [{slideId?, rule, message, severity, hint?}]
\- warnings: [{slideId?, rule, message, severity, hint?}]
\- passed: boolean

Static rules (always checked):
\- undefined-css-class: hallucinated or stale class names (with fix suggestions)
\- unknown-component: unregistered data-component types
\- requirement-missing-component: engagement requirement without matching component
\- missing-slide-file: slide references non-existent file
\- slide-id-filename-mismatch: slide ID doesn't match component filename
\- assessment-id-mismatch: config ID doesn't match assessment ID
\- invalid-gating: bad gating condition configuration

Use after making source/config changes as a fast static check. Then use coursecode_errors against the running preview for live diagnostics.

### `coursecode_narration` (~429 tokens)

Generate (or dry-run) audio narration for slides via the configured TTS provider.

Reads `export const narration = ...` from each slide file, hashes text+voice settings, and only regenerates audio whose hash changed since the last run (cache: .narration-cache.json). MP3 files are written to course/assets/audio/.

Provider selection follows the same rules as the CLI:
  TTS_PROVIDER env var, or auto-detect from API keys, default deepgram.
The .env file at the project root supplies API keys.

USE WHEN:
\- The lint reports stale narration warnings ("narration audio is stale...").
\- You added or modified narration text in a slide.
\- You want to confirm what would be generated (use dryRun: true — no API calls, no audio written).

APPROVAL:
\- Real generation (dryRun omitted or false) calls a TTS provider and writes MP3 files, so it requires explicit user approval before running.
\- Use dryRun: true first when you only need to inspect what would be regenerated.

Returns:
\- success, summary (e.g. "3 generated, 5 unchanged")
\- generated, skipped, noNarration counts
\- errors[], warnings[]
\- output: tail of the generator's console output for debugging
\- dryRun: echoes the input flag

NOT idempotent: real runs call paid TTS APIs and write files. Prefer dryRun first.

Input parameters:

- `dryRun` (boolean): Show what would be generated without calling TTS or writing files (default: false).
- `force` (boolean): Regenerate every narration item, ignoring the cache (default: false). Use sparingly — costs API credits.
- `rebuildCache` (boolean): Rebuild .narration-cache.json from existing audio files without calling TTS (default: false). Use after a fresh clone or when the cache is missing but audio is committed. Free; no API calls.
- `slide` (string): Optional slide ID filter (e.g. "intro"). Only narration for this slide is processed.

### `coursecode_icon_catalog` (~94 tokens)

Get icon information.

Without 'name': returns all available icon names grouped by category, with counts and usage syntax.
With 'name': returns the icon's SVG content, category, and usage examples (JS, config, HTML).

Use to discover available icons before authoring slides or configuring menus.

Input parameters:

- `name` (string): Optional icon name to get full details for (e.g., "check", "book-open")

## Diagnostics

Captured diagnostic sections: Provenance, Vulnerabilities, Dependencies. The full working is on the page: https://verifymcp.io/servers/course-code-framework-coursecode/coursecode#diagnostics

## Score history

- 2026-11-04: 71
- 2026-11-03: 70
- 2026-11-02: 70
- 2026-11-01: 69
- 2026-10-31: 69
- 2026-10-30: 55
- 2026-10-29: 54

## Common questions

### What is the CourseCode Framework MCP server?

CourseCode Framework is an MCP server listed in the public MCP registry as io.github.course-code-framework/coursecode. Preview, screenshot, lint, and test SCORM, cmi5, and LTI courses built with CourseCode Framework. This page covers its npm package (coursecode).

### Is the CourseCode Framework MCP server safe to use?

CourseCode Framework scores 71 out of 100 on VerifyMCP. We recorded 1 known advisory against it as of 4 November 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the CourseCode Framework MCP server expose?

CourseCode Framework exposes 16 tools: coursecode_state, coursecode_errors, coursecode_navigate, coursecode_interact, coursecode_assessment, and 11 more. Their descriptions and schemas cost roughly 3,097 tokens of context every time the server is loaded.

### Is the CourseCode Framework MCP server still maintained?

CourseCode Framework is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the CourseCode Framework MCP server under?

CourseCode Framework declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/coursecode
- Socket report: https://socket.dev/npm/package/coursecode
- Repository: https://github.com/course-code-framework/coursecode
- Website: https://coursecodeframework.com/
- Changelog RSS feed: https://verifymcp.io/servers/course-code-framework-coursecode/coursecode.xml
- Changelog JSON feed: https://verifymcp.io/servers/course-code-framework-coursecode/coursecode.json
- HTML version of this page: https://verifymcp.io/servers/course-code-framework-coursecode/coursecode
