Skip to main content
Glama

The Workbook standard

A workbook is a zip file that answers a machine-learning question in a form another agent can execute. It is three things at once, and the combination is the point:

  • a notebook — cell-delimited source in whatever language the answer needs;

  • a skillSKILL.md, so an agent knows what this is and when to reach for it;

  • an MCP server — dependency-free, stdio, installs the environment and runs the cells.

The hand-off it exists for: someone asks a question, gets an answer with citations, downloads a workbook, drops the folder in front of a coding agent, and says "set this up and run it". The agent reads SKILL.md, registers mcp/server.py, then calls workbook_check, workbook_setup, workbook_run. Nothing in that sequence asks it to guess a dependency, a model id, or a command.

Read SPEC.md for the standard. It is the normative document; everything else here is an implementation of it.

Why not just a notebook

A notebook alone loses what made the answer correct. It does not say which file to take out of a repository that holds forty of them, what the download actually weighs, which packages the imports imply, what hardware the code assumes, or which paper the method came from. A workbook keeps that in workbook.json, and the runner reads it rather than inferring it.

The manifest is also what makes this framework-agnostic. Nothing in it is Python. A runtime is a declaration — interpreter, dependency manager, setup commands, argv prefix — so a Rust workbook and a browser/WebGL workbook are the same shape as a PyTorch one, and one server drives all of them.

Related MCP server: Jupyter MCP Server

What is in this repository

path

what it is

SPEC.md

the standard

manifest.ts

schema, types, cell-marker parsing, and the nine completeness rules

runtimes.ts

per-runtime defaults: setup, exec prefix, dependency file

templates.ts

SKILL.md, README.md, .mcp.json, links, notebook scaffolds

pack.ts

manifest plus notebook to zip

form.ts

the intake form: how a workbook gets scoped before it is built

templates/server.py

the MCP server that ships inside every workbook

conformance/

a language-neutral validator and a live MCP handshake test

Conformance

The validator works on an unpacked workbook directory, so it is not tied to this implementation.

python3 conformance/run.py                        # the whole suite
python3 conformance/validate.py path/to/workbook  # validate any workbook, from any implementation
python3 conformance/handshake.py path/to/workbook # drive its MCP server the way a client would
python3 path/to/workbook/mcp/server.py --selfcheck

run.py closes the loop twice. It assembles the hand-written example in conformance/example/, validates it, and drives its server through seventeen protocol checks; then it packs a workbook with the TypeScript implementation and puts that one through the same three stages. It also asserts that each of the nine completeness rules actually rejects a workbook that breaks it, because a validator nobody has seen fail is not evidence of anything.

The validator and the handshake need no packages installed, and the handshake speaks raw JSON-RPC rather than using a client library. That is deliberate: the tests have to run on the same bare machine the server is designed to start on.

Using the TypeScript implementation

import { normalize, pack, validate } from "workbook-standard";

const manifest = normalize(draftFromYourGenerator, notebookSource);
const { zip, issues, files } = pack({ manifest, notebook: notebookSource });

pack renders the environment file from the declared packages, the skill and readme from the manifest, and copies in the MCP server and the spec, then validates the result. A generator only has to supply what needs judgement: what to run, what it needs, and why.

There is no build step and no bundler requirement. templates/server.py and SPEC.md are inlined into generated/assets.ts by node tools/gen-assets.mjs, which --check verifies has not drifted, so the packer works in a Worker, in Node, and under any bundler. Relative imports carry explicit .ts extensions so the sources run unbuilt under Node's type stripping; a TypeScript consumer needs allowImportingTsExtensions.

Status

Version 1. workbook: "1" in a manifest refers to SPEC.md in this repository. A reader that does not recognise the version must refuse rather than guess.

Related MCP Connectors

Related MCP Servers