Skip to main content
Compose can run as an MCP server instead of opening a window, which lets an AI agent author a course the same way a person does.
Register that command with any MCP client as a stdio server. No arguments, no configuration.
This is the real application, not a separate script. The agent’s course and yours are the same format, produced by the same code — which is why an agent can hand you a .course file you then open and keep editing.

Setting it up

1

Find the binary

Wherever Compose is installed. On Linux that is inside the AppImage; on Windows, next to the installed MauvelyCompose.exe.
2

Add it to your client's config

3

Check the tools loaded

Your client should report 25 tools. If it reports none, run the command by hand — anything it prints to stderr is the reason.

What an agent can do

Every block type is reachable, including quizzes, flashcards, branching scenarios and custom code.

Writing a good prompt

Two things trip agents up, both worth saying explicitly in your instructions.
new_course gives you one lesson that already contains a Welcome block — the same thing you get opening the app, so a person has something to edit rather than a blank page.If you want exact control over what the course contains, tell the agent to pass empty: true, or ask it to remove the Welcome block. Otherwise “make a course with one block” produces two.
Text fields take actual line breaks. An agent that sends the two characters \ and n gets them rendered literally in the finished course, which looks like \n\n sitting in the middle of a paragraph.Smaller models get this wrong fairly often. If you see it, the fix is in the prompt rather than the course.
Blocks carry every type’s fields at once, so setting the wrong ones is not an error — it just produces an empty block. list_block_kinds returns each type’s field list, and an agent that reads it first makes far fewer silent mistakes.

Checking the result

preview_course renders the real exported course and returns a PNG. This matters: it is the same runtime a learner gets, not a sketch of it, so an agent looking at the picture is looking at what you would actually ship.
Ask the agent to call it after building something and describe what it sees. It catches empty blocks, broken media and theme choices that read badly far faster than reading the JSON does.

On a server

Rendering needs a graphics backend. On a headless machine, run the whole thing under a virtual framebuffer:
Without one, every other tool still works — only preview_course returns an error, and it says why.
The screenshot is rendered in a separate process. A browser engine that cannot find a graphics backend does not fail politely, it exits — and doing that inside the tool server would take your agent’s unsaved work with it.

A worked prompt

Using Mauvely Compose, make a course called “Onboarding” with exactly two lessons. Call new_course with empty: true so there is no starter content. Read list_block_kinds before adding anything. Lesson one gets a rich text introduction and a multiple-choice question with three answers; lesson two gets a flashcard set. Use real newlines in any text. Then call preview_course and tell me whether it looks right before saving to ~/onboarding.course.

Limits

Worth knowing

  • The server holds one course at a time. new_course and open_course discard what is in memory.
  • There is no undo across tool calls — an agent that removes the wrong block has to add it back.
  • Media has to exist on disk for add_asset; the agent cannot generate an image.
  • Nothing here talks to Mauvely Cloud. Courses are saved and exported locally.