mcp-data-platform-v1.58.3
Two improvements to the public share viewers in this release: collection viewer mobile parity with the asset viewer, plus Open Graph / Twitter Card metadata so shared links unfurl with previews.
TL;DR — what changed
| Before v1.58.3 | After v1.58.3 | |
|---|---|---|
| Public collection viewer on mobile | Different theme toggle, expiration crowded into the header, implementor logos with width="100%" could overflow on narrow viewports. |
Same single sun/moon toggle as the asset viewer, expiration in a .notice band below the header, defensive display:block; max-width:100% on .brand-logo svg. |
| Link previews in Slack / iMessage / Twitter / LinkedIn | Pasted share URL → bare URL (no preview). | Title, description, site name, and a preview image — summary_large_image Twitter card when an image is available, summary otherwise. |
| Theme preference across viewers | Resetting per page; collection viewer used mdp-theme keys with a system value the asset viewer didn't understand. |
Persisted under the same mdp-theme key, dark/light only. Toggle in the asset viewer carries over to a collection share opened next. |
| Flash-of-light on dark mode | Collection viewer briefly painted light then re-painted dark on first load. | Theme applied from <head> before <body> paints (matches asset viewer). |
Operator action on upgrade: none required. Existing deployments pick up the changes on the next pod roll. If you've configured portal.public_base_url, OG tags will use it; otherwise the platform derives the base URL from the inbound request (X-Forwarded-Proto + Host), so OG tags work out-of-the-box behind a typical reverse-proxy setup.
Header parity / mobile fit
PR #359 brought the collection viewer's header structure into rough alignment with the asset viewer's, but several details still diverged in ways that affected mobile:
- 3-button theme toggle (Light / Dark / System) replaced with the single sun/moon icon button used by the asset viewer. The 3-button group ate horizontal space and forced other elements to compress on narrow viewports.
- Expiration moved into a
.noticeband below the header instead of being inlined alongside the theme toggle inheader-right. - SVG defense for both viewers:
.brand-logo svgnow setsdisplay: block; max-width: 100%, and.brand-implementor .brand-logo svgaddsmax-width: 100%. Operator-supplied SVGs whose root element carrieswidth="100%" height="100%"attributes (common from many SVG editors) no longer overflow the header on narrow viewports. - Theme persistence unified: both viewers persist the chosen theme under the same
mdp-themelocalStorage key. Legacysystemvalues are treated as "follow OS preference at render time" then upgrade to the resolved theme on click. - Flash-of-light fix: an early-execution theme script in
<head>applies the saved theme before<body>paints, mirroring the asset viewer.
Open Graph / Twitter Card metadata
When a public share URL is pasted into Slack, iMessage, X/Twitter, LinkedIn, or any social-media client, the unfurler reads <meta> tags. Both viewers now emit:
og:type="website"og:title(asset / collection name)og:description(when description is non-empty)og:url(canonical share URL)og:site_name(portal.brand_name)og:image(when an image source is available — see priority below)- Twitter Card variants:
twitter:card,twitter:title,twitter:description,twitter:image. The card upgrades tosummary_large_imagewhen an image is present and downgrades tosummaryotherwise.
og:image source priority
| Viewer | Priority |
|---|---|
| Single asset | image-typed asset content → asset thumbnail → none |
| Collection | collection's own thumbnail → first item with a thumbnail → none |
When no image source resolves, og:image is omitted entirely and the Twitter card downgrades cleanly.
Two new public endpoints serving the OG image
GET /portal/view/{token}/thumbnail— asset thumbnail for a single-asset share. 404 when the share is a collection share, when no thumbnail key is set, or when S3 fetch fails.GET /portal/view/{token}/collection-thumbnail— collection's own thumbnail for a collection share. 404 when the share is an asset share, when no thumbnail is uploaded, or when S3 fetch fails.
Both endpoints are rate-limited via the same middleware as the existing …/items/{assetId}/thumbnail handler and set Cache-Control: public, max-age=3600.
Base URL resolution
portal.public_base_url (when set) wins. Otherwise the platform derives the base URL from the inbound request:
- Direct-TLS requests (
r.TLS != nil) ignoreX-Forwarded-Protoso an attacker-supplied header cannot downgradeog:urltohttp://. - Non-TLS requests honor the header but only when its first comma-separated token (multi-proxy chains can produce
"https, http") is exactlyhttporhttps. Bogus values fall back to the default scheme. This keepsog:urlwell-formed regardless of upstream proxy quirks. - When neither config nor request resolves, the absolute-URL OG tags are omitted entirely rather than emitting relative URLs that crawlers reject.
What's in this release
6c07b75 feat(portal): collection viewer header parity + OG/Twitter card metadata (#363)
Installation
Homebrew (macOS)
brew install txn2/tap/mcp-data-platformClaude Code CLI
claude mcp add mcp-data-platform -- mcp-data-platformDocker
docker pull ghcr.io/txn2/mcp-data-platform:v1.58.3Verification
All release artifacts are signed with Cosign. Verify with:
cosign verify-blob --bundle mcp-data-platform_1.58.3_linux_amd64.tar.gz.sigstore.json \
mcp-data-platform_1.58.3_linux_amd64.tar.gz