@fenfill/mcp 0.1.0 → 0.2.0
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/README.md +96 -15
- package/THIRD_PARTY_NOTICES +1 -1
- package/dist/index.js +3276 -711
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,8 @@ are stamped into the PDF locally and are never sent to fenfill or anywhere else.
|
|
|
19
19
|
on your machine. If a box is misplaced, missing or mislabeled, **`edit_template`** fixes it in a
|
|
20
20
|
local working copy that filling uses at once, and **`save_template`** keeps the fix in a saved
|
|
21
21
|
template.
|
|
22
|
+
5. **`reanalyze_template`** re-runs fenfill on some pages of a saved template (a page that was
|
|
23
|
+
never analyzed, or one that came out badly), from the blank PDF already stored with it.
|
|
22
24
|
|
|
23
25
|
### What is sent where
|
|
24
26
|
|
|
@@ -30,6 +32,7 @@ are stamped into the PDF locally and are never sent to fenfill or anywhere else.
|
|
|
30
32
|
| Saved templates (blank PDF, fields, your logo) | Downloaded from fenfill to fill locally |
|
|
31
33
|
| Page previews (`preview_page`) | **No**: rendered on your machine |
|
|
32
34
|
| Layout corrections (`edit_template`) | Only on `save_template`, and then only the layout and the form's own wording |
|
|
35
|
+
| Re-analysis (`reanalyze_template`) | Only the template id, pages, kind and version: nothing is uploaded |
|
|
33
36
|
|
|
34
37
|
`analyze_form` refuses PDFs whose form fields already hold answers, and PDFs this server wrote
|
|
35
38
|
itself, so a filled-in form isn't uploaded by mistake.
|
|
@@ -101,6 +104,7 @@ On native Windows, if the client can't find `npx`, use `"command": "cmd"` with
|
|
|
101
104
|
| `preview_page` | Renders one page (PNG) with every field box outlined and tagged, locally. |
|
|
102
105
|
| `edit_template` | Moves, resizes, relabels, retypes, adds, deletes or regroups fields, locally. |
|
|
103
106
|
| `save_template` | Saves `edit_template`'s working copy to a saved template. |
|
|
107
|
+
| `reanalyze_template` | Re-analyzes some pages of a saved template, with no upload, and shows the diff. |
|
|
104
108
|
|
|
105
109
|
`analyze_form` options: `pages` (e.g. `"1-3,5"`; long PDFs can be analyzed in chunks, and
|
|
106
110
|
`fill_form` merges them), `save_as_template` (also keep it as a fenfill template), `access`
|
|
@@ -130,16 +134,59 @@ workspace, free native-field (AcroForm) ones included.
|
|
|
130
134
|
`preview_page` takes `path` (an analyzed PDF) or `template_id`, a 1-based `page`, optional
|
|
131
135
|
`values` (to see them stamped; the same shapes as `fill_form`, e.g. `table_rows` =
|
|
132
136
|
`[{columnId: value}, …]`, `multiselect` = an array of option ids or labels) and `dpi` (default
|
|
133
|
-
110, max 200). It returns a PNG image plus a legend: each box's tag, id, type, label and `box
|
|
134
|
-
|
|
137
|
+
110, max 200). It returns a PNG image plus a legend: each box's tag, id, type, label and `box`;
|
|
138
|
+
a text/date field's stored `format` and `font_pt` (the size its value starts at; `font_auto`
|
|
139
|
+
when that follows the box height); a choice's options with their own boxes; a table's cells by
|
|
140
|
+
`(row, col)`, its `orientation` and headers (also printed on the image inside, or beside, the
|
|
141
|
+
first cell of each line as `R: …` / `C: …`); a `table_rows` table's columns and printed cells
|
|
142
|
+
with their boxes (fill values still go by column id). `warnings` and `placement_warnings` are
|
|
143
|
+
always present (`[]` = checked and clean): placement covers every box shown, so a plain preview
|
|
144
|
+
is a read-only placement audit (see the checks under `edit_template`). `crop`
|
|
145
|
+
(`{x, y, w, h}`, fractions) with `zoom` (default 2, max 8) renders just a region, magnified, and
|
|
146
|
+
lists only what it shows; `legend: "changed"` returns only the rows that changed since your last
|
|
147
|
+
preview of that page (the first time: since fenfill's version), each with only its changed
|
|
148
|
+
options/cells/columns (`members_changed` counts them, so a header edit doesn't list the whole
|
|
149
|
+
grid), plus `removed` ids and `moved_into` (ids that now sit inside a table or group), and
|
|
150
|
+
`legend: "none"` omits the legend. It renders the local working copy (`edit_template`) when there is one, otherwise the saved
|
|
135
151
|
template or analyzed version; `edited: true` / `false` in the result says which. The page is rendered on your machine by
|
|
136
152
|
PDFium (WebAssembly, shipped in the package; nothing native is installed), nothing is written to
|
|
137
153
|
disk, and the image goes only to the calling client.
|
|
138
154
|
|
|
139
|
-
`edit_template` takes `path` or `template_id` and up to 200 `ops`:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
`
|
|
155
|
+
`edit_template` takes `path` or `template_id` and up to 200 `ops`:
|
|
156
|
+
|
|
157
|
+
- fields: `set_box` (absolute `{id, x, y, w, h}` in one step), `move`, `resize`, `relabel`,
|
|
158
|
+
`retype`, `add`, `delete`, `set_format` (`date_format` is one of `DD/MM/YYYY`, `MM/DD/YYYY`,
|
|
159
|
+
`YYYY-MM-DD`, `DD.MM.YYYY`, `DD-MM-YYYY`), `set_required`, `set_description`,
|
|
160
|
+
`set_placeholder`, `set_autofill` (a browser autofill token such as `name` or `postal-code`,
|
|
161
|
+
or `null` to clear it);
|
|
162
|
+
- choices and combs: `group` (`kind: "choice" | "comb"`), `ungroup`, `set_options`, and
|
|
163
|
+
`add_option` / `remove_option`, which keep the group's id;
|
|
164
|
+
- tables: `group` with `kind: "table"` (a `cells` grid of field ids, rows × columns with `null`
|
|
165
|
+
for a gap, or `ids` laid out from their boxes; `header_cols`, `header_rows`, `orientation`,
|
|
166
|
+
`format`), `table_insert` / `table_delete` (a row or column; a new line's geometry is
|
|
167
|
+
interpolated from its neighbours unless you pass it), `table_add_cell` (fill an empty slot),
|
|
168
|
+
`table_adopt` (move a loose field into an empty slot), `set_column_type`, `set_orientation`
|
|
169
|
+
and `set_header` / `set_headers` (`{id, axis, texts: [...], start?}`, several in one op). Every cell of one column (or row, for `orientation: "row"`) has one type,
|
|
170
|
+
as in the web editor; `set_format` on a table cell applies to its whole column or row;
|
|
171
|
+
- order: `reorder {page, ids}` moves those top-level entries together, in that order, to where
|
|
172
|
+
the first of them sat, and stamps an explicit `order` on every entry of the page (the web
|
|
173
|
+
editor's layer-panel convention), so a later sub-pixel move no longer reshuffles questions.
|
|
174
|
+
|
|
175
|
+
Any id can be shortened to an unambiguous prefix of 6+ characters (the length of the preview
|
|
176
|
+
tags); an ambiguous prefix is rejected with the candidates. `add`, `move` and `set_box` take an
|
|
177
|
+
optional `snap`: `"underline"` fits the box onto the printed rule under it, `"cell"` into the
|
|
178
|
+
ruled box around it, `"answer"` into that cell's blank part (below a caption printed at its top,
|
|
179
|
+
or after one at its left), read from the page render on your machine; when nothing fits near the
|
|
180
|
+
box, the box is kept and a warning says so. Snap finds printed rules with its own simple line
|
|
181
|
+
finder (one ink threshold per page, not the web editor's wand): a very faint rule on a tinted
|
|
182
|
+
scan can be missed, and an underline box is one line of handwriting tall (as tall as the clear
|
|
183
|
+
space above the rule, within about 11–16 pt). `diff_summary.ops` lists every applied op with
|
|
184
|
+
`snapped: true/false` (when it asked for a snap) and `noop: true` when it changed nothing. After
|
|
185
|
+
each edit, the boxes you touched are checked for three placement problems: a value that would
|
|
186
|
+
print much larger than the page's other fields (an Auto box's text size follows its height), a
|
|
187
|
+
box over printed text (text layer only, so not on scans), and a box that runs a little past the
|
|
188
|
+
ruled cell it sits in (from the page render, so scans too). `set_format` merges into the stored
|
|
189
|
+
format (a date field keeps its date format when you only set `font_size`).
|
|
143
190
|
Coordinates are fractions of the page (0–1) with a top-left origin, the same as the legend's
|
|
144
191
|
`box`. Each op is checked against the rules fenfill applies when saving and is rejected with a
|
|
145
192
|
reason if it breaks them; ops apply in order, all-or-nothing each, except that a box only has to
|
|
@@ -160,7 +207,39 @@ memory). A working copy edited in an earlier session can't be checked against th
|
|
|
160
207
|
answers: `save_template` then answers `confirm_wording_needed` with the changed ids and
|
|
161
208
|
properties (never their text); review them and call again with `confirm_wording: true`. An
|
|
162
209
|
unsaved analysis can be edited for filling but not saved: to keep corrections,
|
|
163
|
-
analyze with `save_as_template: true` and edit that template.
|
|
210
|
+
analyze with `save_as_template: true` and edit that template. With nothing to save, it succeeds
|
|
211
|
+
with `saved: false, nothing_to_save: true`. `get_template` says `has_local_edits` (its fields
|
|
212
|
+
are fenfill's saved version; `preview_page` shows the working copy) and gives `field_count`
|
|
213
|
+
(entries listed) and `field_count_total` (the whole form); `save_template`'s `field_count` is
|
|
214
|
+
the whole saved template.
|
|
215
|
+
|
|
216
|
+
### Re-analyzing pages of a saved template
|
|
217
|
+
|
|
218
|
+
A template saved from only some pages (`analyze_form` with `pages` and `save_as_template`) has
|
|
219
|
+
pages fenfill never looked at: `get_template` lists them as `unanalyzed_pages`, and
|
|
220
|
+
`list_templates` shows `analyzed_pages` next to `page_count`. `reanalyze_template` takes
|
|
221
|
+
`template_id`, `pages` and a `kind`:
|
|
222
|
+
|
|
223
|
+
| `kind` | Use it to |
|
|
224
|
+
| --------------- | --------------------------------------------------------------------------------- |
|
|
225
|
+
| `scratch` | analyze a never-analyzed page, or replace a badly analyzed page's fields entirely |
|
|
226
|
+
| `find` | add blanks the first pass missed, keeping everything already there |
|
|
227
|
+
| `relabel` | re-derive labels, types, groups and sections, keeping the boxes |
|
|
228
|
+
| `label_missing` | fill in only the labels that are missing |
|
|
229
|
+
|
|
230
|
+
`kind` can be left out only when the pages have no fields (it then means `scratch`). Each page
|
|
231
|
+
costs one page scan; `label_missing` is free within the workspace's monthly free-label
|
|
232
|
+
allowance. `estimate: true` prices the run and starts nothing. `relabel` may reset table column
|
|
233
|
+
types and orientation, so check the template with `get_template` afterwards.
|
|
234
|
+
|
|
235
|
+
It uses the PDF already stored with the template, so nothing is uploaded. It refuses while the
|
|
236
|
+
template has unsaved `edit_template` edits (`local_edits_pending`): save them with
|
|
237
|
+
`save_template` first, or pass `discard: true` to drop them when the run finishes. The result
|
|
238
|
+
lists, per changed page, the fields `added`, `removed` and `changed` (label, type, box, or a
|
|
239
|
+
group's cells), then the new fields of those pages; review them with `preview_page` and correct
|
|
240
|
+
them with `edit_template` + `save_template`. Like `analyze_form`, it waits out capacity
|
|
241
|
+
refusals, and if it answers `"running"`, calling it again with the same arguments follows the
|
|
242
|
+
same run at no extra charge.
|
|
164
243
|
|
|
165
244
|
### Value shapes
|
|
166
245
|
|
|
@@ -168,7 +247,7 @@ analyze with `save_as_template: true` and edit that template.
|
|
|
168
247
|
| ------------------- | --------------------------------------------------------------------------- |
|
|
169
248
|
| `text`, `multiline` | string, stamped exactly as given |
|
|
170
249
|
| `comb` | string, one character per cell |
|
|
171
|
-
| `date` | `"YYYY-MM-DD"`, printed
|
|
250
|
+
| `date` | `"YYYY-MM-DD"`, printed in the field's `date_format` (e.g. `DD/MM/YYYY`) |
|
|
172
251
|
| `checkbox` | `true` / `false` |
|
|
173
252
|
| `radio` | option id, option label, or the bare option text (`"No"` for `"Smoke? No"`) |
|
|
174
253
|
| `multiselect` | array of those |
|
|
@@ -192,12 +271,12 @@ fenfill web app for that workspace (for example, your logo if you have set one u
|
|
|
192
271
|
|
|
193
272
|
## Configuration
|
|
194
273
|
|
|
195
|
-
| Variable | Default | Notes
|
|
196
|
-
| ------------------------------ | ------------------------- |
|
|
197
|
-
| `FENFILL_API_KEY` | (none) | `ff_live_…` from fenfill → Settings → API keys.
|
|
198
|
-
| `FENFILL_API_URL` | `https://api.fenfill.com` | https only (http allowed for localhost).
|
|
199
|
-
| `FENFILL_CACHE_DIR` | the OS cache folder | Holds schemas and blank forms only, never answers.
|
|
200
|
-
| `FENFILL_ANALYZE_WAIT_SECONDS` | `50` | How long `analyze_form`
|
|
274
|
+
| Variable | Default | Notes |
|
|
275
|
+
| ------------------------------ | ------------------------- | ---------------------------------------------------------------------------- |
|
|
276
|
+
| `FENFILL_API_KEY` | (none) | `ff_live_…` from fenfill → Settings → API keys. |
|
|
277
|
+
| `FENFILL_API_URL` | `https://api.fenfill.com` | https only (http allowed for localhost). |
|
|
278
|
+
| `FENFILL_CACHE_DIR` | the OS cache folder | Holds schemas and blank forms only, never answers. |
|
|
279
|
+
| `FENFILL_ANALYZE_WAIT_SECONDS` | `50` | How long `analyze_form` / `reanalyze_template` wait before saying "running". |
|
|
201
280
|
|
|
202
281
|
`fill_form` works without an API key once a form has been analyzed.
|
|
203
282
|
|
|
@@ -238,7 +317,9 @@ fenfill web app for that workspace (for example, your logo if you have set one u
|
|
|
238
317
|
| `request_too_large` | The edited template is too large to save in one request. |
|
|
239
318
|
| `answer_in_template` | Edited wording matches an answer from this session, so nothing was sent. Put the form's own wording back with `edit_template`. |
|
|
240
319
|
| `confirm_wording_needed` | The working copy has wording edited in an earlier session. Review the ids and properties in `changed`, then `save_template` with `confirm_wording: true`. |
|
|
241
|
-
| `
|
|
320
|
+
| `local_edits_pending` | `reanalyze_template` won't run over unsaved edits: `save_template` them first, or pass `discard: true`. |
|
|
321
|
+
| `kind_required` | The pages already have fields: pass `kind` (`find`, `relabel`, `label_missing`, or `scratch` to replace them). |
|
|
322
|
+
| `job_in_progress` | A job is already running on the template; wait and retry (call `reanalyze_template` again with the same arguments if you started it). |
|
|
242
323
|
| `upload_outcome_unknown` | An earlier upload was interrupted. To avoid charging twice, the same file isn't re-uploaded for about 10 minutes; check `get_account` meanwhile. |
|
|
243
324
|
|
|
244
325
|
## API
|
package/THIRD_PARTY_NOTICES
CHANGED