Skip to content

Releases: txn2/mcp-data-platform

mcp-data-platform-v1.40.4

12 Mar 20:08
9d1c503

Choose a tag to compare

Fix: Markdown Thumbnail Capture Race Condition

v1.40.2 and v1.40.3 attempted to fix blank markdown thumbnails but failed — v1.40.2 speculated visibility: hidden was the cause (it wasn't), and v1.40.3 changed positioning without addressing the real issue. This release fixes the actual root cause.

Root Cause

DomCapture used setTimeout(doCapture, 500) — an arbitrary 500ms delay — to wait for ReactMarkdown to finish rendering before capturing the thumbnail. ReactMarkdown renders asynchronously, and if it hadn't completed within 500ms, toPng captured a container with no rendered content, producing a blank PNG.

Fix

Replaced the arbitrary timeout with a MutationObserver that watches for actual rendered elements (p, h1h3, li, pre, blockquote, table) to appear in the DOM. Once content is detected, capture fires after one requestAnimationFrame to let layout settle. SVG content (set synchronously via dangerouslySetInnerHTML) is caught by an initial element check before the observer is attached.

The existing CAPTURE_TIMEOUT_MS (15s) safety net remains as a fallback.

Verified

Tested end-to-end in the browser with VITE_MSW=true:

  • toPng produced a valid 11.8KB PNG blob from the DomCapture container
  • thumbnail_s3_key set after capture completed
  • Save-triggered regeneration re-captured successfully
  • Zero console errors

Also Included

  • Mock PUT /assets/:id/thumbnail handlers added to MSW so thumbnail capture can be tested in dev mode without a real backend.

Changed Files

  • ui/src/components/ThumbnailGenerator.tsxDomCapture: MutationObserver replaces setTimeout
  • ui/src/mocks/handlers.ts — mock thumbnail upload endpoints for dev testing

mcp-data-platform-v1.40.3

12 Mar 18:45
a6ebb94

Choose a tag to compare

Fix: Blank Markdown Thumbnails

Markdown (and SVG) assets were producing blank/transparent thumbnail images due to the DomCapture component using visibility: hidden to hide its off-screen render container.

Root Cause

The html-to-image library (toPng) works by cloning the target DOM node and serializing it into an SVG foreignObject, preserving all computed styles — including visibility: hidden. The cloned content was therefore invisible, producing a blank PNG on every capture attempt.

Fix

Replaced visibility: hidden with left: -9999; top: -9999 off-screen positioning — the same pattern already used by IframeCapture for HTML/JSX assets. The element retains full layout (required for accurate capture) but is positioned outside the viewport.

Changed Files

  • ui/src/components/ThumbnailGenerator.tsxDomCapture container: removed visibility: hidden and zIndex: -1, switched to off-screen positioning

mcp-data-platform-v1.40.2

12 Mar 17:19
b5d01fa

Choose a tag to compare

Thumbnail Capture Quality Fixes

This release fixes four distinct quality issues with the asset thumbnail capture system introduced in v1.40.0.

JSX Asset Rendering

JSX assets now produce rendered dashboard thumbnails instead of blank or raw-source captures. A new buildJsxThumbnailHtml function transpiles JSX via sucrase and scaffolds a complete HTML document with an import map and auto-mount — the same rendering pipeline used by JsxRenderer — with a 2-second ready delay to allow async esm.sh module loads before capture.

Desktop-Scale Viewport for HTML Assets

HTML iframe captures now render at 1280×960 and scale down to the 400×300 thumbnail via html2canvas, so desktop-designed dashboard layouts appear realistic instead of being squeezed into a mobile-width viewport. New RENDER_WIDTH / RENDER_HEIGHT constants control the pre-scale dimensions.

Markdown Prose Rendering

Markdown thumbnails previously rendered blank because the DomCapture component relied on Tailwind prose classes that weren't available in the off-screen container. The fix replaces Tailwind classes with self-contained inline CSS styles (.thumb-prose) and switches from left: -9999 positioning to visibility: hidden so layout flow is preserved for html-to-image.

Thumbnail Regeneration on Save

Editing and saving an asset's content now triggers automatic thumbnail regeneration. A thumbnailStale flag is set on successful save, which remounts the ThumbnailGenerator with the updated content via a React key change. The flag resets on capture completion or failure through new onDone / onFailed callbacks.

Changed Files

  • ui/src/components/AssetViewer.tsx — thumbnailStale state, save-triggered regen, onDone/onFailed wiring
  • ui/src/components/ThumbnailGenerator.tsx — JSX content type routing, RENDER_WIDTH/HEIGHT viewport, Markdown inline styles
  • ui/src/lib/thumbnail.ts — buildJsxThumbnailHtml, RENDER_WIDTH/HEIGHT constants, html2canvas scale config

mcp-data-platform-v1.40.1

12 Mar 16:43
2b58b6a

Choose a tag to compare

Asset Thumbnail System

This release adds automatic thumbnail generation for portal assets and fixes a bug that prevented thumbnails from being captured.

New: Client-Side Thumbnail Capture (#232)

Assets that support visual preview (HTML, JSX, Markdown, SVG) now get automatic PNG thumbnails. The My Assets page displays these as a card grid with 4:3 thumbnail previews instead of the previous text-only list.

How it works:

  • HTML/JSX assets render in a sandboxed iframe; the parent captures the content using the bundled html2canvas library
  • Markdown assets render with ReactMarkdown and are captured using html-to-image
  • SVG assets are sanitized with DOMPurify, rendered inline, and captured using html-to-image
  • A background queue on the My Assets page detects assets missing thumbnails and processes them one at a time
  • Viewing a single asset also triggers thumbnail generation if one is missing
  • Updating asset content automatically clears the old thumbnail so a fresh one is generated on next view

Backend:

  • New database migration (000020_portal_asset_thumbnails) adds thumbnail_s3_key column to portal_assets
  • New endpoints on both portal and admin routers:
    • PUT /assets/{id}/thumbnail — upload PNG thumbnail (max 512 KB, image/png only)
    • GET /assets/{id}/thumbnail — retrieve thumbnail with appropriate Cache-Control headers
  • Thumbnail S3 key is derived from the asset's existing S3 key (same directory, filename thumbnail.png)
  • AssetUpdate.ThumbnailS3Key uses *string to distinguish "no change" (nil) from "clear" (pointer to empty string)

Frontend:

  • ThumbnailGenerator — hidden off-screen component with two capture strategies (iframe for HTML/JSX, DOM for Markdown/SVG)
  • ThumbnailQueue — background processor that finds assets without thumbnails and captures them sequentially; tracks processed IDs to prevent duplicate work on refetch
  • 15-second capture timeout with onFailed callback prevents the queue from stalling if a capture hangs
  • My Assets page redesigned as a card grid with content type badges and share indicators overlaid on thumbnails
  • New npm dependencies: html2canvas, html-to-image

Fix: Thumbnail Capture Never Fired (#233)

The iframe sandbox was set to allow-scripts allow-same-origin (required for html2canvas to access contentDocument), but the postMessage origin validation still checked for "null". With allow-same-origin, blob: iframes inherit the parent's origin, so every thumbnail-ready message was silently rejected. Changed the check to window.location.origin.

Files Changed

Area Files
Backend (portal) pkg/portal/handler.go, pkg/portal/types.go, pkg/portal/store.go
Backend (admin) pkg/admin/assets.go
Migration pkg/database/migrate/migrations/000020_portal_asset_thumbnails.{up,down}.sql
Frontend (capture) ui/src/lib/thumbnail.ts, ui/src/components/ThumbnailGenerator.tsx, ui/src/components/ThumbnailQueue.tsx
Frontend (UI) ui/src/pages/assets/MyAssetsPage.tsx, ui/src/components/AssetViewer.tsx
Frontend (API) ui/src/api/portal/client.ts, ui/src/api/portal/hooks.ts, ui/src/api/portal/types.ts
Tests pkg/portal/handler_test.go, pkg/portal/store_test.go, pkg/admin/assets_test.go

Upgrade Notes

  • Database migration required: Run migrations to add the thumbnail_s3_key column. Thumbnails will generate automatically as users visit their assets.
  • No configuration changes needed: Thumbnail storage uses the existing S3 bucket and derives keys from the asset's content key.

Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v1.40.1

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_1.40.1_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_1.40.1_linux_amd64.tar.gz

mcp-data-platform-v1.40.0

12 Mar 07:43
b797fca

Choose a tag to compare

Changelog

Bug Fixes

  • b797fca: fix: public viewer markdown scroll and source editor position retention (#231) (@cjimti)

Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v1.40.0

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_1.40.0_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_1.40.0_linux_amd64.tar.gz

mcp-data-platform-v1.39.8

12 Mar 06:42
b797fca

Choose a tag to compare

Bug Fixes

Public Viewer: Markdown Content Scroll Restored

The iframe layout fixes in v1.39.5–v1.39.7 (#228#230) introduced overflow: hidden on the .content container in the public viewer template. This prevented markdown and other non-iframe content from scrolling, since those render as regular divs rather than iframes.

Fix: Changed overflow: hidden to overflow: auto on .content, allowing non-iframe content to scroll while preserving the flex layout that makes iframes fill the viewport.

Affected file: pkg/portal/templates/public_viewer.html

Source Editor: Position Retained Across Tab Switches

Toggling between Source and Preview in the asset viewer previously unmounted the CodeMirror SourceEditor component, destroying scroll position, cursor placement, selections, and undo history. Users had to re-navigate to their editing position every time they previewed changes.

Fix: The SourceEditor now stays mounted when switching to Preview, hidden via display: none instead of being removed from the DOM. All CodeMirror internal state (scroll, cursor, selections, undo history) is preserved across tab switches. The ContentRenderer (preview) still unmounts when switching to Source, which is fine since preview is stateless.

Affected file: ui/src/components/AssetViewer.tsx


Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v1.39.8

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_1.39.8_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_1.39.8_linux_amd64.tar.gz

mcp-data-platform-v1.39.7

12 Mar 03:05
ae9df50

Choose a tag to compare

Bug Fixes

  • Public viewer: iframe fills viewport with no footer gap — The wrapper div inside .content defaulted to flex: 0 1 auto, so it did not stretch to fill its parent. The iframe's flex: 1 had no effect because its parent was not a flex container. Added .content > div as a flex column so the iframe expands to fill all remaining viewport space. (#230)

Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v1.39.7

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_1.39.7_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_1.39.7_linux_amd64.tar.gz

mcp-data-platform-v1.39.6

12 Mar 01:42
0bb5f56

Choose a tag to compare

Bug Fixes

  • Public viewer: iframe fills viewport with no footer gap — The JsxRenderer component sets an inline height: 80vh on iframes, which overrode the stylesheet's flex layout. Added height: auto !important to neutralize the inline style, letting flex: 1 stretch the iframe to fill all remaining viewport space. (#229)

Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v1.39.6

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_1.39.6_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_1.39.6_linux_amd64.tar.gz

mcp-data-platform-v1.39.5

12 Mar 00:08
b6a794c

Choose a tag to compare

Public Viewer CSS Fix

The public viewer's global CSS reset (* { margin: 0; padding: 0; box-sizing: border-box; }) was unlayered, which per the CSS cascade spec always beats @layer styles regardless of specificity. This killed every Tailwind prose style — paragraph margins, table cell padding, horizontal rules, card borders — making markdown rendering in the public viewer look completely different from the internal SPA portal.

This release scopes the reset to html, body only and removes the min-height: 100vh body stretching. Content inside #content-root is now styled purely by the Tailwind CSS bundle, rendering identically to the internal viewer.

Changelog

Bug Fixes

  • b6a794c: fix: remove unlayered CSS global reset that overrides Tailwind prose styles (#228) (@cjimti)

Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v1.39.5

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_1.39.5_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_1.39.5_linux_amd64.tar.gz

mcp-data-platform-v1.39.4

11 Mar 22:28
5ce4037

Choose a tag to compare

Fix: Public Content Viewer Blank Page

If you are on v1.39.3, upgrade immediately. The public content viewer (/portal/view/<token>) was completely broken — pages showed "Loading..." indefinitely with no rendered content.

What Happened

The v1.39.3 release introduced a shared content renderer that moves all public viewer rendering client-side via an embedded React IIFE bundle. However, the GoReleaser before hook that builds the release binary was never updated to build this new bundle. It only built the SPA (npm run buildinternal/ui/dist/), leaving internal/contentviewer/dist/ empty.

Because the Go binary uses //go:embed to bake the bundle into the binary at compile time, the released binary contained empty strings for both contentviewer.JS and contentviewer.CSS. The public viewer template rendered <script></script> (empty JS) and the page was permanently stuck on the "Loading..." placeholder.

What Changed

.goreleaser.yml — Extended the release build hook to also:

  1. Build the content viewer IIFE bundle (npx vite build --config vite.content-viewer.config.ts)
  2. Copy content-viewer.js to internal/contentviewer/dist/
  3. Copy the SPA's CSS output as content-viewer.css to internal/contentviewer/dist/

This mirrors what make frontend-build does locally.

Impact

  • Affected: Any deployment running v1.39.3 where the public content viewer is used
  • Symptom: Public share links show header/chrome but content area displays "Loading..." forever
  • Resolution: Upgrade to v1.39.4

Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v1.39.4

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_1.39.4_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_1.39.4_linux_amd64.tar.gz