@doclift/workflows-mcp 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/guidance.js CHANGED
@@ -69,6 +69,18 @@ The name is the **inner text**; only an *image* token reads \`data-src\`. A
69
69
  integrity check, and prints the name of the variable instead of its value.
70
70
  \`workflow_validate\` reports those as \`inert_tokens\`.
71
71
 
72
+ Which of \`text\` and \`checkbox\` you pick is a **different** matter, and one
73
+ you cannot get wrong: for a name the workflow declares, the renderer reads the
74
+ genre off the variable's \`field_type\`, not off the class. Declare a box and
75
+ write it with either token and a box is drawn. Get the *type* right in
76
+ \`variable_create\` — that is the declaration everything follows — and stop
77
+ worrying about which of the two classes you wrote.
78
+
79
+ Two places the class still decides, because nothing declares a type there: a
80
+ row field (\`collection.field\`, which no \`fields\` entry types) and a name no
81
+ variable declares at all. A box inside a repeated table row is therefore
82
+ written with the checkbox class and only with it.
83
+
72
84
  **2 quinquies. A CSS property is dropped from inside a \`style\` that survives.**
73
85
  The attribute is on the allow list, its contents are filtered against a list of
74
86
  their own. \`text-transform\` goes, \`style\` stays, and nothing about the element
@@ -89,6 +101,17 @@ makes no network request at render time, so every picture has to go through
89
101
  \`image_upload\` and be cited by the URL it answers with. \`workflow_validate\`
90
102
  reports the others under \`unreachable_images\`.
91
103
 
104
+ **2 sexies. A running title band is clipped at the height of its margin.** The
105
+ band is framed at the margin reserved for its side — never less than
106
+ \`capabilities.authoring.band.reserved_mm_minimum\` — and what does not fit is
107
+ hidden. Measured at the default margins: it holds
108
+ \`capabilities.authoring.band.usable_lines_at_minimum\` lines and loses the rest,
109
+ **from the top for a footer**, so a paragraph of legal text comes back starting
110
+ mid-sentence. No write refuses it, \`workflow_validate\` sees nothing wrong with
111
+ the markup, and the render answers 200. \`workflow_selfcheck\` reports these as
112
+ \`clipped_bands\`. A band is a line, not a paragraph: legal text belongs in a
113
+ content section, which flows onto the next page instead of being cut.
114
+
92
115
  **3. Declaring inline what the theme already says freezes the document.** It
93
116
  looks identical today and stops following the theme forever. Set the theme, then
94
117
  write only what departs from it. This is the mistake that costs the most and
@@ -194,10 +217,13 @@ satisfied.
194
217
  the integrity check, and is invisible everywhere else.
195
218
  3. **No picture is unreachable.** The engine makes no network request, and a
196
219
  token that no longer names a stored image is removed at render time.
197
- 4. **No variable was declared and never used.** The mirror of a broken
220
+ 4. **No band is longer than the margin reserved for it.** A running head or
221
+ foot is clipped, without an error, and a footer loses its opening rather
222
+ than its end.
223
+ 5. **No variable was declared and never used.** The mirror of a broken
198
224
  reference: it usually means a token was written with a typo, and the typo
199
225
  became a second, dead name.
200
- 5. **A PDF exists, and it is newer than your last edit.** If you rendered before
226
+ 6. **A PDF exists, and it is newer than your last edit.** If you rendered before
201
227
  your last change, what you looked at is not what you have.
202
228
 
203
229
  ## What it cannot check, and you must
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
  // organization the key belongs to. The only knowledge that lives here is the
7
7
  // knowledge the API cannot express — the order to do things in, and the failures
8
8
  // that succeed.
9
+ import { createRequire } from 'node:module';
9
10
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
11
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
12
  import { z } from 'zod';
@@ -13,6 +14,10 @@ import { ApiClient } from './client.js';
13
14
  import { registerTools } from './tools/index.js';
14
15
  import { ANOMALIES, BEFORE_YOU_FINISH, CONDITIONS, HOW_TO_BUILD, REPETITIONS } from './guidance.js';
15
16
  const DEFAULT_BASE_URL = 'https://app.doclift.io';
17
+ // Read rather than written a second time: the first publish that changed the
18
+ // guides shipped as 0.1.1 and still announced 0.1.0 in the handshake, which is
19
+ // the version a client shows its user and a bug report quotes.
20
+ const { version } = createRequire(import.meta.url)('../package.json');
16
21
  const readConfig = () => {
17
22
  const apiKey = process.env['DOCLIFT_API_KEY'];
18
23
  if (!apiKey) {
@@ -55,7 +60,7 @@ const GUIDES = [
55
60
  ];
56
61
  const main = async () => {
57
62
  const { baseUrl, apiKey } = readConfig();
58
- const server = new McpServer({ name: 'doclift-workflows', version: '0.1.0' }, {
63
+ const server = new McpServer({ name: 'doclift-workflows', version }, {
59
64
  instructions: 'Authoring of Doclift workflows: conditional PDF documents assembled from a tree of sections. ' +
60
65
  'Call `workflow_capabilities` before writing anything — it carries the catalogues and the ' +
61
66
  'limits for this organization, and nothing in this server duplicates them. Read the ' +
@@ -99,6 +99,13 @@ const selfcheck = (validation, template, payload) => {
99
99
  };
100
100
  lines.push(listLine('inert_tokens', 'No variable token is inert', 'Rewrite each token with the class capabilities.content.tokens gives, then section_update.'));
101
101
  lines.push(listLine('unreachable_images', 'No picture is unreachable', 'Upload each picture with image_upload and cite the URL it answers with.'));
102
+ // A band is framed at the height of the margin reserved for it and clipped.
103
+ // Measured: at the default margins it holds two lines and loses the third,
104
+ // from the top for a footer — so a paragraph of legal text comes back
105
+ // starting mid-sentence, and nothing else in this API says a word about it.
106
+ lines.push(listLine('clipped_bands', 'No running title band is longer than the margin reserved for it', 'Shorten the band, or widen the margin on that side. A band is not a place ' +
107
+ 'for a paragraph: move legal text into a content section, which flows and ' +
108
+ 'is never cut.'));
102
109
  lines.push(listLine('layout_tables', 'No table is used for a column layout with its rules showing', 'Put capabilities.authoring.table.layout_row_class on the <tr>: it takes the rules away and ' +
103
110
  'leaves the columns. A ruled table around two blocks set side by side is a shape no ' +
104
111
  'hand-made document has.'));
@@ -31,7 +31,10 @@ export const registerSections = (server, api, base) => {
31
31
  'CLASS, not by its tag: <variable class="editor-text-variable non-editable-content editor-parsed">name</variable>, the name being ' +
32
32
  'the inner text. Take the exact string from capabilities.content.tokens — a token ' +
33
33
  'without the editor-parsed class prints the name instead of the value, and every ' +
34
- 'other check passes.'),
34
+ 'other check passes. Which of text and checkbox you write does NOT decide: for a ' +
35
+ "declared name the renderer reads the genre off the variable's field_type. The " +
36
+ 'class still decides for a row field and for a name nothing declares, since no type ' +
37
+ 'is attached to either.'),
35
38
  parent_id: z.number().int().nullable().optional().describe('Must name a group of the same workflow.'),
36
39
  position: z
37
40
  .number()
@@ -17,7 +17,11 @@ export const registerVariables = (server, api, base) => {
17
17
  inputSchema: {
18
18
  template_id: templateId,
19
19
  name: z.string().min(1),
20
- field_type: z.string().describe('See capabilities.variable.field_types.'),
20
+ field_type: z
21
+ .string()
22
+ .describe('See capabilities.variable.field_types. This is what decides how a token for this ' +
23
+ 'name renders: a `checkbox` prints a box whichever of the two token classes the ' +
24
+ 'content was written with, anything else prints the value.'),
21
25
  description: z.string().min(1).describe('Required. What the variable holds, for whoever fills it in.'),
22
26
  required: z.boolean().optional(),
23
27
  seed_value: z.string().optional().describe('What the preview shows in its place.'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doclift/workflows-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "MCP server over the Doclift workflow authoring API",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.doclift.io/docs/getting-started",
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "type": "module",
16
16
  "bin": {
17
- "doclift-workflows-mcp": "./dist/index.js"
17
+ "doclift-workflows-mcp": "dist/index.js"
18
18
  },
19
19
  "files": [
20
20
  "dist"