Skip to content

feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps #7852

Merged
michaelneale merged 8 commits intomainfrom
aharvard/autovisualiser-mcp-apps
Mar 16, 2026
Merged

feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps #7852
michaelneale merged 8 commits intomainfrom
aharvard/autovisualiser-mcp-apps

Conversation

@aharvard
Copy link
Collaborator

@aharvard aharvard commented Mar 13, 2026

Summary

Migrate the autovisualiser extension to MCP Apps and improve the visualization experience.

goose-viz-dark.mov
goose-viz-light.mov

Changes

MCP Apps Migration

  • Convert all 9 visualization templates to MCP Apps protocol (postMessage bridge, display mode support)
  • Extract shared mcp-app-bridge.js and mcp-app-base.css for consistent behavior across all chart types
  • Support inline, fullscreen, and picture-in-picture display modes

Fullscreen Support

  • Charts and diagrams dynamically expand to fill the viewport in fullscreen/pip modes
  • CSS data-display-mode attribute drives layout overrides (flex: 1 for chart areas)
  • Suppress size reporting feedback loop on fullscreen → inline transition (300ms debounce in McpAppRenderer)

Dark Mode

  • All templates respond to dynamic theme changes via the bridge onTheme callback
  • Map tiles switch between CartoDB light and dark variants
  • Text color fallbacks use isDark checks for chart/radar labels, grid lines, and legends
  • Base CSS tokens use light-dark() syntax for proper fallback colors

Data Resilience

  • Sankey: DFS cycle detection breaks circular links with synthetic "Node ↩" nodes instead of rendering blank
  • Sankey: Validates links against known nodes, filters invalid values
  • All D3 visualizations wrapped in try/catch with user-visible error messages

UX Polish

  • Increased inline heights: charts 360→520px, radar 420→580px, chord 460→580px
  • Larger title/subtitle font sizes (heading-md, text-md)
  • Line charts: removed muddy fills, added data point dots (pointRadius: 3)
  • Legend: larger filled circle dots (10px), bigger font (13px), consistent across chart types
  • Tooltip positioning: shared positionTooltip() helper with viewport edge detection
  • Map: tighter fit bounds (pad(0.05)), preserves user zoom on mode change

Files Changed

Area Files
Shared assets mcp-app-bridge.js, mcp-app-base.css
Templates chart, radar, donut, sankey, chord, treemap, map, mermaid
Rust mod.rs (tool description update)
Desktop McpAppRenderer.tsx (transition suppression)

Testing

  • cargo build -p goose-mcp
  • ✅ 15 autovisualiser tests pass
  • ✅ TypeScript compiles, ESLint clean
  • ✅ Manual testing across all 9 chart types in light/dark, inline/fullscreen

aharvard and others added 7 commits March 11, 2026 23:54
- All 8 tools now return structuredContent + text fallback + _meta.ui.resourceUri
- Templates rewritten with MCP Apps lifecycle: ui/initialize handshake,
  tool-input/tool-result postMessage listeners, host theme support,
  spec-compliant size reporting
- Added enable_resources(), list_resources(), read_resource() for static
  ui:// resource registration
- Removed baked HTML blob generation (base64 encoding, debug file writes)
- All templates include overflow:hidden to prevent scrollbars in iframe

Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
- All Chart.js templates (chart, radar, donut) now read theme colors
  from CSS variables at render time via cssVar() helper
- All templates re-render on host-context-changed notification by
  caching currentData and calling render again after applying new vars
- Grid lines, tick labels, legend text, and axis titles use
  --color-text-primary, --color-text-secondary, --color-border-primary
- Fixed duplicate currentData declaration in radar template
- Consistent applyTheme pattern: set colorScheme for both light/dark

Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
… chart template

- Add mcp-app-bridge.js: shared MCP Apps protocol layer (messaging, lifecycle, theming, size reporting)
- Add mcp-app-base.css: shared foundation styles using 70+ host theme tokens
- Redesign chart_template.html: remove gradient header, stats panels, card-in-card; use theme-native colors
- Fix dark mode: resolve light-dark() CSS values for Chart.js via probe element
- Set prefersBorder: true on resource meta for host border treatment
- Curated 8-color palette that works in both light and dark themes

Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
…red bridge/CSS

Apply the same pattern from chart_template to all 7 remaining templates:
- sankey, chord, radar, donut, treemap, map, mermaid

All templates now:
- Use mcp-app-bridge.js (no duplicated MCP Apps protocol code)
- Use mcp-app-base.css (transparent bg with light-dark overlay, shared tokens)
- Use the curated 8-color palette consistent across all chart types
- Remove gradient headers, stats panels, card containers, emoji
- Use theme tokens for all text, grid, tooltip, and border colors
- Support dark mode via light-dark() probe resolution

Total: 2047 → 1344 lines across templates (-700 lines, -34%)
Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
Fullscreen & sizing:
- Charts expand to fill viewport in fullscreen/pip via data-display-mode CSS
- Suppress size report feedback loop on fullscreen-to-inline transition
- Increase inline heights for chart (520px), radar (580px), chord (580px)
- Dynamic height/width for treemap and chord in fullscreen

Dark mode:
- Add isDark text color fallbacks for chart and radar templates
- Use light-dark() syntax in base CSS token fallbacks
- Switch map tiles to CartoDB with dark/light variant support
- Swap tile layer on theme change with invalidateSize()

UX polish:
- Bump title/subtitle font sizes across all chart types
- Line charts: remove fill, add point dots with matching colors
- Fix legend circle distortion (match boxWidth/boxHeight, drop pointStyleWidth)
- Custom generateLabels for consistent filled circle legends
- Add positionTooltip() helper with edge detection (sankey, chord, treemap)
- Increase legend font size and dot dimensions

Data resilience:
- Sankey: DFS cycle detection with synthetic node fallback
- Sankey: validate links against known nodes, filter invalid values
- Sankey: try/catch with error message rendering
- Update render_sankey tool description to warn against circular links

Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
- Fix donut schema: rename data→values to eliminate data.data nesting
- Add .validate() on all data types (sankey, radar, donut, chord, treemap, chart, map)
- Add McpAppBridge.showError() and wrap all template onData in try/catch
- Add mermaid input guard for missing/non-string code
- 17 new validation tests (38 total)

Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
@aharvard aharvard changed the title feat(autovisualiser): MCP Apps compliance with fullscreen, dark mode, and UX improvements feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps Mar 13, 2026
@aharvard aharvard marked this pull request as ready for review March 13, 2026 15:01
…mplates; enhance chart canvas size

Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 803e60732b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

appInfo: appIdentity,
clientInfo: appIdentity,
appCapabilities: {
availableDisplayModes: ["inline", "fullscreen"],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include PiP in declared display modes

ui/initialize advertises only ['inline','fullscreen'], so the desktop host will treat PiP as unsupported (useDisplayMode.ts reads appCapabilities.availableDisplayModes and gates controls/requests from that list). As a result, none of these migrated visualizers can enter PiP even though their templates/style logic handle data-display-mode="pip", making the new PiP flow unreachable.

Useful? React with 👍 / 👎.

onTheme: function () {
if (map) setTimeout(function () {
map.invalidateSize();
if (savedBounds) map.fitBounds(savedBounds.pad(0.05));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid resetting map bounds on host-context updates

The map theme callback always runs map.fitBounds(savedBounds.pad(0.05)), and McpAppBridge.applyTheme() invokes onTheme for any host-context change (including display-mode transitions). With default autoFit, this snaps the viewport back to initial bounds whenever the user toggles fullscreen/PiP or theme, discarding any manual pan/zoom state.

Useful? React with 👍 / 👎.

@michaelneale
Copy link
Collaborator

nice - did you get a chance to check if it works with code mode?

@@ -0,0 +1 @@
Goose <goose@block.xyz>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you mean to add this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, was added by goose and was supposed to be cleaned in a commit hook. will remove

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, wow that was actually from another repo I was multitasking. whoops. I think my agent session got confused on my PWD

@michaelneale michaelneale enabled auto-merge March 16, 2026 01:58
Copy link
Collaborator

@michaelneale michaelneale left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not. I think good improvement. One Q on a random file but yeah lets go. Also would be nice to know if works with code mode but that is not something to block this over.

@michaelneale michaelneale added this pull request to the merge queue Mar 16, 2026
Merged via the queue into main with commit f697e8d Mar 16, 2026
28 of 29 checks passed
@michaelneale michaelneale deleted the aharvard/autovisualiser-mcp-apps branch March 16, 2026 02:11
lifeizhou-ap added a commit that referenced this pull request Mar 16, 2026
* main:
  updated canonical models (#7920)
  feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps  (#7852)
jh-block added a commit that referenced this pull request Mar 16, 2026
* main: (65 commits)
  feat(otel): propagate session.id to spans and log records (#7490)
  fix(test): add env_lock to is_openai_reasoning_model tests (#7917)
  fix(acp): pass session_id when loading extensions so skills are discovered (#7868)
  updated canonical models (#7920)
  feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps  (#7852)
  fix: add tool_choice and parallel_tool_calls to chatgpt_codex provider (#7867)
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  Keep messages in sync (#7850)
  More acp tools (#7843)
  fix: skip upgrade-insecure-requests CSP for external HTTP backends (#7714)
  fix(shell): prevent hang when command backgrounds a child process (#7689)
  Remove include from Cargo.toml in goose-mcp (#7838)
  Exit agent loop when tool call JSON fails to parse (#7840)
  chore: remove redundant husky prepare script (#7829)
  ...
@aharvard
Copy link
Collaborator Author

nice - did you get a chance to check if it works with code mode?

no i did not try

aharvard added a commit that referenced this pull request Mar 16, 2026
This file was accidentally merged in via #7852
and should have been removed.

Co-authored-by: Goose <opensource@block.xyz>
Ai-assisted: true
wpfleger96 added a commit that referenced this pull request Mar 16, 2026
…oken-retry

* origin/main: (21 commits)
  Remove java/.ai-usage-marker directory (#7925)
  test(acp): add terminal delegation fixtures and fix shell singleton (#7923)
  fix: bump pctx_code_mode to 0.3.0 for iterator type checking fix (#7892)
  feat: persist GooseMode per-session via session DB (#7854)
  feat(otel): propagate session.id to spans and log records (#7490)
  fix(test): add env_lock to is_openai_reasoning_model tests (#7917)
  fix(acp): pass session_id when loading extensions so skills are discovered (#7868)
  updated canonical models (#7920)
  feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps  (#7852)
  fix: add tool_choice and parallel_tool_calls to chatgpt_codex provider (#7867)
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  Keep messages in sync (#7850)
  More acp tools (#7843)
  fix: skip upgrade-insecure-requests CSP for external HTTP backends (#7714)
  ...
@jh-block
Copy link
Collaborator

re. code mode: #7787

wpfleger96 added a commit that referenced this pull request Mar 16, 2026
* origin/main: (72 commits)
  No Check do Check (#7942)
  Log 500 errors and also show error for direct download (#7936)
  fix: retry on authentication failure with credential refresh (#7812)
  Remove java/.ai-usage-marker directory (#7925)
  test(acp): add terminal delegation fixtures and fix shell singleton (#7923)
  fix: bump pctx_code_mode to 0.3.0 for iterator type checking fix (#7892)
  feat: persist GooseMode per-session via session DB (#7854)
  feat(otel): propagate session.id to spans and log records (#7490)
  fix(test): add env_lock to is_openai_reasoning_model tests (#7917)
  fix(acp): pass session_id when loading extensions so skills are discovered (#7868)
  updated canonical models (#7920)
  feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps  (#7852)
  fix: add tool_choice and parallel_tool_calls to chatgpt_codex provider (#7867)
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  ...
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.

3 participants