Skip to content

fix(pdf-server): radio + dropdown in fill_form/save#577

Draft
ochafik wants to merge 2 commits intomainfrom
ochafik/pdf-server-radio-dropdown-fill
Draft

fix(pdf-server): radio + dropdown in fill_form/save#577
ochafik wants to merge 2 commits intomainfrom
ochafik/pdf-server-radio-dropdown-fill

Conversation

@ochafik
Copy link
Copy Markdown
Contributor

@ochafik ochafik commented Mar 30, 2026

Summary

  • Viewer fill_form (mcp-app.ts): radio buttons always selected the first option regardless of the requested value. pdf.js's RadioButtonWidgetAnnotation.render() coerces string storage values via value !== buttonValue — writing "medium" on every widget makes the first non-matching one check itself and clear siblings. New setFieldInStorage() writes {value: true} only on the matching widget, mirroring pdf.js's own change handler. Also covers the localStorage restore path (syncFormValuesToStorage).
  • Save (pdf-annotations.ts): dropdowns and radios were silently dropped — getTextField(name) throws for them and the catch swallowed it. Now dispatches on getFieldMaybe() instanceof …. Radio values are accepted as either option label or numeric buttonValue (viewer stores the latter for PDFs with /Opt).
  • display_pdf result (server.ts): radio groups now show name=<exportValue> [Btn] per widget and dropdowns list options:[…] — previously the model had nothing to go on.

Test plan

  • Unit tests: 4 new cases in pdf-annotations.test.ts covering text/checkbox/dropdown/radio round-trip, numeric buttonValue → label indexing, invalid value, unknown field name. 153 pass / 0 fail.
  • npm run --workspace examples/pdf-server build clean
  • Verified end-to-end in basic-host: size: '2' selects Large, color: 'Green' selects Green, display_pdf shows size=0/size=1/size=2 [Btn] and color [Ch] options:[Red, Green, Blue]
  • Regression check: text/checkbox/dropdown/multi-page still work

ochafik added 2 commits March 30, 2026 19:41
interact's get_screenshot/get_text waited the full 45s for a viewer that
never mounted (host went idle before iframe reached startPolling), then
timed out with a generic message. Now tracks viewsPolled and fails in ~8s
with a recovery hint. Batch errors were also ordered success-first —
hosts that flatten isError to content[0] showed "Queued: Filled N fields"
and dropped the actual failure entirely. Viewer side: poll even when PDF
load throws, and catch connect() rejection instead of silently blanking.
Three related bugs around non-text form fields:

Viewer fill_form (mcp-app.ts): writing a string to annotationStorage on
every radio widget trips pdf.js's inverted string coercion
(`value !== buttonValue` → true) — the first-rendered widget checks
itself and clears the rest, so whatever you ask for, you get the first
option. Fix: extract a setFieldInStorage() helper that writes
{value: true} only on the widget whose buttonValue matches, {value: false}
on siblings, matching pdf.js's own change handler. Also covers the
syncFormValuesToStorage() path (localStorage restore).

Save (pdf-annotations.ts): buildAnnotatedPdfBytes only knew about
getTextField/getCheckBox — dropdowns and radios threw in the try block
and fell through the catch, so they were silently dropped on save.
Fix: instanceof dispatch on getFieldMaybe(). For radios, accept either
the option label or a numeric buttonValue (indexed into getOptions()),
since the viewer stores the latter for PDFs with /Opt.

display_pdf output (server.ts): radio groups showed as N identical
`name [Btn]` lines with no way to tell them apart; dropdowns didn't
list their options. Fix: surface buttonValue as exportValue and the
options array from the annotation data already in hand.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 30, 2026

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/@modelcontextprotocol/ext-apps@577

@modelcontextprotocol/server-basic-preact

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-preact@577

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-react@577

@modelcontextprotocol/server-basic-solid

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-solid@577

@modelcontextprotocol/server-basic-svelte

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-svelte@577

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-vanillajs@577

@modelcontextprotocol/server-basic-vue

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-vue@577

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/@modelcontextprotocol/server-budget-allocator@577

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/@modelcontextprotocol/server-cohort-heatmap@577

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/@modelcontextprotocol/server-customer-segmentation@577

@modelcontextprotocol/server-debug

npm i https://pkg.pr.new/@modelcontextprotocol/server-debug@577

@modelcontextprotocol/server-map

npm i https://pkg.pr.new/@modelcontextprotocol/server-map@577

@modelcontextprotocol/server-pdf

npm i https://pkg.pr.new/@modelcontextprotocol/server-pdf@577

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/@modelcontextprotocol/server-scenario-modeler@577

@modelcontextprotocol/server-shadertoy

npm i https://pkg.pr.new/@modelcontextprotocol/server-shadertoy@577

@modelcontextprotocol/server-sheet-music

npm i https://pkg.pr.new/@modelcontextprotocol/server-sheet-music@577

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/@modelcontextprotocol/server-system-monitor@577

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/@modelcontextprotocol/server-threejs@577

@modelcontextprotocol/server-transcript

npm i https://pkg.pr.new/@modelcontextprotocol/server-transcript@577

@modelcontextprotocol/server-video-resource

npm i https://pkg.pr.new/@modelcontextprotocol/server-video-resource@577

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/@modelcontextprotocol/server-wiki-explorer@577

commit: 7acc125

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant