Repository navigation
Fix pdf-server saved-page restore (dead pageCount guard since #329) - #828
Merged
Merged
Conversation
The viewer saves the current page to localStorage and is meant to restore it when a host re-renders the same tool call, but the restore bounds-checked the saved page against structuredContent.pageCount — a field display_pdf stopped sending in #329 (the server no longer pre-parses the PDF). The comparison was always false, so the viewer always fell back to initialPage: annotations survived a re-render, the page never did. - Restore the saved page unconditionally and clamp to totalPages once the document loads (same clamp reloadPdf already has). - Resolve viewUUID from _meta with a structuredContent fallback: the server sends it in both, and some hosts drop _meta on replayed tool results — without the fallback the page had no storage key at all. - Drop the pageCount field from the parsed-result type (never sent). The e2e test plays the host: it captures the display_pdf result from the result panel, navigates via the view's tool, re-posts the result as a ui/notifications/tool-result notification, and asserts the viewer comes back on the saved page — with and without _meta.
@modelcontextprotocol/ext-apps
@modelcontextprotocol/server-basic-preact
@modelcontextprotocol/server-basic-react
@modelcontextprotocol/server-basic-solid
@modelcontextprotocol/server-basic-svelte
@modelcontextprotocol/server-basic-vanillajs
@modelcontextprotocol/server-basic-vue
@modelcontextprotocol/server-budget-allocator
@modelcontextprotocol/server-cohort-heatmap
@modelcontextprotocol/server-customer-segmentation
@modelcontextprotocol/server-debug
@modelcontextprotocol/server-lazy-auth
@modelcontextprotocol/server-map
@modelcontextprotocol/server-pdf
@modelcontextprotocol/server-scenario-modeler
@modelcontextprotocol/server-shadertoy
@modelcontextprotocol/server-sheet-music
@modelcontextprotocol/server-system-monitor
@modelcontextprotocol/server-threejs
@modelcontextprotocol/server-transcript
@modelcontextprotocol/server-video-resource
@modelcontextprotocol/server-wiki-explorer
commit: |
Merged
ochafik
added a commit
that referenced
this pull request
Oct 27, 2026
Patch release: the pdf-server example defaults to a single interact app tool with the per-action tools behind --split-app-tools (#830), the map-server example gains a get-screenshot app tool (#821), the pdf-server viewer restores the saved page on tool-result re-delivery (#828), and the dependency refresh clears the open npm audit findings (solid-js 1.9.17, sharp ^0.35.5 and in-range transitive updates, #827). Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The pdf-server viewer saves the current page to localStorage (keyed by
viewUUID) and is meant to restore it when a host re-renders the same tool call — reopening a conversation, refreshing the page. In practice annotations came back but the page didn't. Root cause: the restore guardcompares against
structuredContent.pageCount, a fielddisplay_pdfstopped sending in #329 when server-side PDF parsing was removed.savedPage <= undefinedis always false, so the saved page has been read and discarded on every load since — dead code for ~9 months.Changes
loadSavedPage()already validates>= 1) and clamp tototalPagesonce the document loads — the same clampreloadPdf()already has; the bounds check simply can't happen before the document is parsed.viewUUIDfrom_metawith astructuredContentfallback. The server sends it in both places, and some hosts drop_metawhen replaying cached tool results — in that case the viewer previously had no storage key at all (so neither page nor, pre-Add get_current_pdf to the pdf-server example (app tool + interact action) #820-era keys aside, anything else keyed on it could restore). This also tracks the broader "dual-channel critical fields" hardening direction.pageCountfrom the parsed-result type — it was never sent, and the lying type is what hid the bug.Test
New e2e (
tests/e2e/pdf-page-restore.spec.ts) that exercises the real restore path: the basic-host test UI doesn't replay tool results (#642), so the test plays the host — it captures thedisplay_pdfCallToolResultfrom the result panel, navigates to another page via the view's ownnavigatetool (which persists it), then re-posts the captured result into the app iframe as aui/notifications/tool-resultnotification and asserts the viewer comes back on the saved page, notinitialPage. Two variants: with the original_meta, and with_metastripped (covers thestructuredContentfallback).Validation
tsc --noEmit(example tsconfig) — cleanbun test examples/pdf-server src— 441 tests, 0 failuresGenerated by Claude Code