Skip to content

F09 — Poster built by an agent through MCP

An AI agent, connected to Madoo through the MCP server and never opening the editor, designs the poster template of a cultural festival, publishes it, builds the workflow that fills it from the programme — an invitation written by the AI, an AI illustration, one line per evening — runs it, looks at the result and corrects it. The outcome is the same kind of document as the examples made in the editor.

The poster produced by the agent’s workflow: a forest-green band with the kicker CORTILE APERTO PRESENTA, the title Libri in cortile, the edition line and a square illustration of readers under wisteria in an arcaded courtyard; below, on cream, a three-line invitation, the heading IL PROGRAMMA, five evenings one per line, the venue, the entry note and the contacts

A reference run of the second version of the workflow: 36 seconds, 5.04 credits. The build took 90 MCP calls in about 10 minutes. PDF · the approved words.

Cortile Aperto (a fictional association in Bologna) organises Libri in cortile every summer: five evenings with authors in a courtyard of via del Pratello. Every year it needs the same A4 poster with the new programme. The person in charge does not want to learn an editor: they ask their AI assistant to “make the festival poster, and a way to redo it next year from the programme”.

Input Who provides it Example
Festival programme the association, as JSON it already keeps title, edition, theme, venue, entry note, contacts and the list of evenings (date, time, author, book)
  • Surface parity. What can be done in the editor must be possible from REST, MCP and the agent with the same result. Here no step goes through the interface: the template is built with the design-template tools, the workflow with create_workflow_draft; validation, estimate, publishing, execution and reading the result are MCP calls too.
  • The agent works like a careful person: discover, try, look. It does not guess names: it searches the nodes (search_node_types), reads their exact contract (get_node_type) and reads each tool’s schema before using it. Before publishing the template it looks at the exact preview of a sample set (JPEG images of the page) and checks publish readiness; after the first run it looks at the poster and corrects the workflow.
  • The same rules as the other examples. The facts — dates, authors, venue, entry, contacts — come from the programme without passing through a model; the AI writes only the invitation and the illustration idea, inside a JSON Schema that limits their length; the workflow uses a published revision of the template.
  • Only the access it needs. The agent uses a workspace API key with only the scopes required (catalogue, workflows, executions, assets, templates) on the MCP server’s API-key endpoint, /mcp/automation.

What the agent did, in order (tool names as recorded during the build):

Step MCP tools What happens
Get oriented initialize (server instructions), list_fonts Reads the usage rules and the available fonts
The template create_design_template_draft, update_design_template_page, add_design_template_rectangle / _text / _image_placeholder / _repeating_text_list / _line A cream A4 page, a green band with kicker, title, edition and illustration; below, invitation, programme, venue, entry and contacts
The fields configure_design_template_text_placeholder Title, edition, invitation, venue, entry and contacts become required fields; the illustration is an image field; the programme is a repeated list (evenings, row key line)
The style update_design_template_element Playfair Display for the title, Lora for the texts, Montserrat for labels and notes; the title takes at most two lines and shrinks beyond
The flow arrange_design_template_elements Invitation, label, programme, venue and entry in a flowing Layout: a longer invitation pushes the rest down
The test add_design_template_sample_set, preview_design_template_sample_set, get_design_template_publish_readiness Sample Edizione 2026, preview inspected, spacing corrected, no blockers
Publish publish_design_template_draft Revision 1
The workflow search_node_types, get_node_type, validate_workflow, create_workflow_draft, publish_workflow Valid at the first attempt: 14 nodes, 19 connections
Run get_workflow (execution contract), estimate_execution, execute_workflow, get_execution, get_execution_result Estimate 6 credits, run, PDF and image
Correct update_workflow, execute_workflow A second version of the prompt after looking at the first poster

Since then the MCP server groups related commands into families: the same work today uses edit_design_template_page (operation update), configure_design_template_element_placeholder (type text), edit_design_template_sample_set (operation add) and get_design_template (view readiness). An agent can also create a template from one complete document instead of element by element — see Templates and the document model.

The correction after the first poster. The first run was correct but had two defects the agent saw in the image: the invitation repeated the free entry and the rain plan, already printed below, and the illustration had a white frame inside its box. The agent changed only the system prompt (“the poster already prints evenings, venue, entry and rain plan separately: do not repeat them”; “full bleed to the edges, no frame”) with update_workflow; the published workflow moved to version 2, and its run is the one shown above.

Gaps found during the build, in order of weight. Several have since been closed — rows with several elements (the add commands take a parent_id, see Repeated lists), letter spacing (char_spacing), and workspace fonts in list_fonts — and a template is best written as one complete document:

  • A Repeat row could hold only one text with the element tools: add_design_template_repeating_text_list created a list with one field per row, with no way to add other elements inside the row or a Layout. In the editor the programme row would have had the date in bold and author and book in italic, aligned; here it is a sentence composed by the workflow.
  • An opaque error on missing required arguments: update_design_template_page without format and orientation answered only “An error occurred invoking ‘update_design_template_page’”.
  • Searching nodes by capability sometimes misses: “iterate json array items” did not return enumerate/json; a search by family (“enumerate”) did.
  • Missing text properties in update_design_template_element at the time: letter spacing, and undocumented values of fill_paint.type.
  • list_fonts listed only built-in fonts, not the workspace’s private ones.
  • The 64 KiB limit of sample sets also applies to sample images: the agent had to shrink its test illustration; the error did not say which value exceeded it.
  • No tool for folders: the agent’s workflow was created at the root.
  • The execution contract’s example for a JSON input was a string ("\"Replace with your value\""); for an object, {} would be clearer.

What works well, and matters most for an agent: draft ETags prevent overwriting someone else’s changes, idempotency keys make every step repeatable, the exact preview lets the agent look before publishing, workflow validation is precise, and the execution contract gives the exact input keys and where to read the outputs.

One A4 page, three families: Playfair Display, Lora, Montserrat.

Area Content How it is built
Band forest green, kicker CORTILE APERTO PRESENTA, title, edition, square illustration fields title, edition; image field illustration, fills its box
Body the invitation (up to 6 lines), the label IL PROGRAMMA, the evenings, the venue, the entry note a flowing Layout; evenings is a Repeat of text rows, at most 6, an error beyond
Footer a rule and the contacts field contacts
Field Type Required Comes from
intro text yes the AI’s JSON, validated (data_0)
title, edition, venue, entry_note, contacts text yes the programme, printed as it is (data_1)
illustration image yes the generated illustration (its own port)
evenings list of { line } yes the rows composed by the workflow (its own port)

Design choice worth copying: the programme row is one sentence composed by the workflow ([date] · ore [time] — [author], «[book]»), not a row of four laid-out fields — a consequence of the first gap above.

Festival programme ──► Programme as text ──► Brief ──► Write the invitation and the illustration idea (AI, JSON)
│ │
│ Words fit the poster (JSON Schema) ──data_0──┐
│ └─► Illustration idea ──► Paint the illustration ──illustration──┤
├──► One evening at a time (enumerate) ──► Programme row ──► Evenings list (aggregate) ──evenings──────────────────────────┤
└──────────────────────────────────────────────data_1────────────────────────────────────────────────────► Compose the poster ──► PDF, image
+ approved words
Node Type Why
Programma della rassegna (festival programme) input/json_value The only input
Programma come testo, Programma per la redazione utility/extract, text/template The programme becomes the text of the prompt
Scrivi l’invito e l’idea di illustrazione (write the invitation and the illustration idea) ai/text_generation, response_format: json_object, temperature 0.6 intro in Italian and image_prompt in English; only facts from the programme, nothing already printed elsewhere
Le parole stanno nella locandina (the words fit the poster) utility/json_schema_validate, inline schema, mode fail Exactly two keys; intro between 120 and 340 characters
Idea di illustrazione, Disegna l’illustrazione utility/extract, ai/text_to_image, 1_1 A square, full-bleed editorial illustration, no text
Una serata alla volta (one evening at a time) enumerate/json over evenings One item per evening: date, time, author, book
Riga del programma, Elenco serate text/template, aggregate/json (column line) One sentence per evening, collected back into the list the template expects — see Iteration
Componi la locandina (compose the poster) design/template_render, fixed revision, output both, missing_policy: fail_required, max_repeat: 6 Approved words and programme on the data port (data_0, data_1), evenings and illustration on their named ports
Outputs output/pdf, output/image, output/json The PDF, the page image, the approved words

The node names are in Italian, like the poster. Reading a run: Parole approvate (approved words) holds the invitation and the image prompt; everything else on the poster comes from the programme.

Cost: 5.04 credits per run, almost all of it the illustration; the invitation is a small part. The estimate before running was 6 credits. Building the template, previews, validations and estimates are free.

The example installs into your workspace with an API key, through the public API only — see Installing an example:

Terminal window
node madoo-install-example.mjs f09 --api <your Madoo API URL> --key <key.json>

It publishes the template the agent built and version 2 of its workflow; there are no files to upload. To run it, use the programme in run-inputs.json, or add --run (about 5 credits). To repeat the experiment itself, give an agent connected to the MCP server the case above and let it build its own.

  • Next year’s festival: change the programme; the evenings follow the list, up to six.
  • Another kind of event: a concert season, a lecture series, a market calendar — change the programme, the row sentence in Riga del programma and the style rules in the system prompt.
  • A richer programme row: open the template in the editor and lay out date, author and book as separate elements of the Repeat row.

manifest · template · workflow · run inputs