Papera is still under development. Things may change or break as we build.
MCPBuild a workflow over MCP

Build a workflow over MCP

Read a workflow's graph, add nodes, connect them, attach renderers and transformers, and compose social posts from your AI client.

A project holds one or more workflows, and a workflow is a graph of nodes: content nodes, outputs from a renderer (a presentation, a document, a blog post, a social post), transformers, connected accounts, themes and triggers. It is the same graph you see on the flow canvas in the app.

The tools on this page are that canvas, addressable from your client. Each one names the workflow it acts on by project id and workflow id, both of which you get from save_project, create_workflow, or the project's URL.

Reading the graph

  • get_workflow returns the shape of the graph: every node and every connection. Node content is left out, which keeps it cheap to call between steps. Start here when you did not build the workflow in this conversation.
  • get_node_output returns one node's content: what a renderer produced, or a content node's resolved text. For a social post, pass platform to see that platform's version instead of the shared default. Anything too large to return in full comes back flagged, never quietly cut short.

Adding and connecting nodes

  • create_workflow adds a new, empty workflow to a project and returns its id, which is where you start when you build one from scratch.

  • add_node places one node and returns its id. The kinds are:

    KindNotes
    contentA content node. Pass title, and markdown to seed it with text.
    outputA renderer output. Pass renderer_id: slides, document, blog or social-post.
    transformerPicks and reorders sections from what feeds it.
    accountRefers to an account you connected in the app. Pass its connection_id.
    triggerFires publishing for the posts it reaches.
    cacheHolds a value between the step that produces it and the step that uses it.
    themeThe shared look outputs render with. Pass theme.

    You can also pass a position so the node lands somewhere sensible when you open the canvas.

  • connect_nodes draws a connection between two nodes. Papera works out what the connection means from the two ends: content to output attaches a source, post to account sends the post there, trigger to node makes the trigger fire it. A connection that is not allowed is refused with the reason, for example "that output already has a content source".

Shortcuts

These save round trips. They do nothing you could not do with add_node and connect_nodes, and they return what the new node produced so you can check it straight away.

  • attach_renderer creates an output over a content node or transformer and connects it in one call. This is how content becomes a presentation, a document, a blog post or a social post.
  • attach_transformer creates a transformer over a source and wires it up. A transformer picks and reorders the sections it takes from upstream; with no section_ids it passes everything through. Use one when an output should show part of a content node rather than all of it.
  • target_accounts sends one post to several accounts at once. Each account is handled on its own, so any that cannot take the post are reported with the reason while the rest still connect.
  • edit_post sets a post's content.

Composing a social post

A social post has a shared default plus optional per-platform versions. A version overrides only the fields it sets and inherits the rest, so you write the post once and tailor only what needs tailoring.

edit_post takes:

  • default_blocks: the shared content, as an ordered list of content blocks.
  • variants: overrides keyed by platform id (instagram, bluesky, telegram, linkedin), each setting any of caption, hashtags or media.
{
  "default_blocks": [
    {
      "id": "b1",
      "type": "paragraph",
      "content": [{ "type": "text", "text": "Our Q3 numbers are in." }]
    }
  ],
  "variants": {
    "bluesky": { "caption": "Q3 is in. Three charts, one takeaway.", "hashtags": ["q3"] },
    "instagram": { "media": [{ "blockId": "b2", "src": "https://example.com/chart.png" }] }
  }
}

Hashtags are written without the leading #. Media must be http(s) URLs, as there is no upload path over MCP: upload images in the app, or point at a URL that is already public.

Connected accounts

Connecting a social account always happens in the app, never over MCP. An account node refers to a connection you already made there, so connect the account first (see Connect a Bluesky account or Connect a Telegram channel), then add a node for it with its connection_id.

What comes next

A workflow with a post and accounts is ready to go out. See Publish and schedule, or follow Example: one post, every account for the whole sequence.