The MCP server

Run Compose as an MCP tool server so an AI agent can build a course start to finish — and take a real screenshot to check what it made.

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.

MauvelyCompose --mcp

Register that command with any MCP client as a stdio server. No arguments, no configuration.

Setting it up

  1. 1
    Find the binary

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

  2. 2
    Add it to your client's config
    {
      "mcpServers": {
        "mauvely-compose": {
          "command": "/path/to/MauvelyCompose",
          "args": ["--mcp"]
        }
      }
    }
  3. 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

Group Tools
Project new_course · open_course · save_course · get_course · set_course
Design set_theme · list_fonts
Lessons list_lessons · add_lesson · rename_lesson · remove_lesson · move_lesson
Blocks list_block_kinds · list_blocks · add_block · get_block · update_block · remove_block · move_block · duplicate_block
Landing page set_overview · set_resources
Media add_asset
Output export_course · preview_course

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.

A new course is not empty

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.

Newlines must be real newlines

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.

Point it at list_block_kinds first

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.

preview_course { "width": 1200, "height": 900, "path": "/tmp/check.png" }

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:

xvfb-run -a --server-args="-screen 0 1400x1000x24" MauvelyCompose --mcp

Without one, every other tool still works — only preview_course returns an error, and it says why.

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

Ask AI

Ask anything about Mauvely

Answers come from this documentation.