Workflows
Driving the API from an agent
How the Doclift MCP server drives the workflow API in the right order, surfaces the failures that answer 200, and where its self-check can never replace reading the document.
What it is
The MCP server is a small process that speaks the Model Context Protocol over stdio. It gives an agent, or a script standing in for one, the same workflow authoring surface described across Templates, Sections & theme and Variables & data, as callable tools, so that building or inspecting a workflow does not require a browser.
It is not additional API surface. Every tool is a thin wrapper over the REST endpoints documented across these pages: nothing it answers with comes from anywhere else, and nothing it refuses is refused for a reason those pages do not already give.
Workflows are a private beta, available on request at [email protected]; see Workflows.
What it encodes that the REST API cannot
Two things a plain HTTP client has no way to know from the shape of the endpoints alone.
The order operations should happen in. Nothing stops a caller from writing section content before the variable it cites exists, or before the theme is set: both save cleanly and fail later, quietly. See Building a workflow end to end for that order, alongside which steps the API actually enforces and which it only advises against.
The failures that answer 200. A stripped tag, a misspelled placement key, an inert token, an image the renderer cannot reach, a theme value that silently freezes: none of these refuse the write that caused them. See Failures that answer 200 for the complete list and how to catch each one.
It holds no catalogue of its own. Anything a caller needs to know about
what it may write, kinds, operators, placement keys, organization limits,
comes from calling workflow_capabilities live, exactly as
Capabilities are authoritative, not a copy
describes for the REST endpoint underneath it. A hardcoded copy in a
guide, or in a client's own memory, would eventually be wrong.
One more thing worth knowing before a first write: while a human holds
the workflow's edit lock in the builder, every write through the server
is refused with 409, exactly as it is over plain REST. See
Shared behaviour.
Running it
npm install
npm run build
DOCLIFT_API_KEY="<the key you send in X-Api-Key>" DOCLIFT_API_URL="https://app.doclift.io" node dist/index.js
| Variable | Required | Default |
|---|---|---|
| DOCLIFT_API_KEY | yes | none |
| DOCLIFT_API_URL | no | https://app.doclift.io |
The key must belong to an organization workflows are enabled for, and it carries exactly the rights it carries on the REST API: no more.
A client declares the server like any other MCP server, over stdio:
{
"mcpServers": {
"doclift-workflows": {
"command": "node",
"args": ["/path/to/mcp/dist/index.js"],
"env": {
"DOCLIFT_API_KEY": "...",
"DOCLIFT_API_URL": "..."
}
}
}
}
The five guides
Alongside its tools, the server exposes five read-only resources: prose the API's shape cannot carry on its own.
| Resource | What it answers |
|---|---|
| doclift://guides/how-to-build | The order to create things in, and the mistakes that produce no error. |
| doclift://guides/conditions | Which key each condition operator takes, and what a collection variable tolerates. |
| doclift://guides/repetitions | Section repetition against row repetition, and why nesting either is refused. |
| doclift://guides/before-you-finish | What a self-check can verify, and the one thing it cannot. |
| doclift://guides/anomalies | Which anomaly types block publication, and which only warn. |
Everything factual in them is already covered by
Workflows, Publishing a workflow
and Failures that answer 200. Reading a guide
before a write only saves a round trip against workflow_capabilities.
Generation is not a separate mechanism
workflow_render wraps a single existing endpoint: POST /api/v1/document_requests, with one entry in document_generations. It
adds no logic of its own: it accepts nothing the endpoint itself would
refuse, so the workflow still has to be published first. See
Create a document request
for the request and response shapes, and
Workflow templates
for what variables has to satisfy before you call it.
The self-check is a composition, not new logic
workflow_selfcheck calls three read endpoints already documented
elsewhere and reduces their bodies into a checklist:
POST .../validate, GET .../templates/:id, and
GET .../payload_contract. It adds no server-side logic and no data that
was not already there for a caller to read directly.
| Line on the checklist | Comes from |
|---|---|
| Nothing blocks publication | validate's blocking anomalies |
| No token is inert | validate's stored.inert_tokens |
| No picture is unreachable | validate's stored.unreachable_images |
| No running-title band is clipped | validate's stored.clipped_bands |
| No variable is declared and never used | validate's stored.unused_variables |
| A PDF exists and is newer than the last edit | validate's stored.last_render |
| No font weight prints by substitution | validate's stored.typography against capabilities.authoring.fonts |
| Page breaks were actually decided | validate's stored.page_breaks |
Each line reads pass, todo, or unknown, never a bare pass when the
evidence for it was absent from a response: a self-check that read
silence as success would defeat its own purpose.
The one line a self-check can never pass
This line stays unknown by design
The self-check names, but never checks off, whether the document is the one that was asked for. No tool can compare a rendered PDF to an intention it never saw.
Everything above it is a reading of the workflow's own state: anomalies,
tokens, images, fonts, timestamps. This last line is not, because that
information does not exist anywhere the tool can reach. Whether the
wording, the order of the sections and the values in place of the tokens
match what was actually requested is a judgment only the caller holding
the original request can make: fetch the URL workflow_render answers
with, and read the file.
Treat a self-check with everything else passing as a workflow that is mechanically sound, not as one confirmed correct.
Next
Workflows
The object model and the build order this server drives.
Failures that answer 200
The complete list of silent failures the self-check reads back.
Publishing a workflow
What validate and publication check, and what blocks a release.