WIP: Add MCP Apps interactive UI extensions#920
Draft
manusa wants to merge 12 commits intocontainers:mainfrom
Draft
WIP: Add MCP Apps interactive UI extensions#920manusa wants to merge 12 commits intocontainers:mainfrom
manusa wants to merge 12 commits intocontainers:mainfrom
Conversation
ef72fed to
324beec
Compare
7da0b28 to
4a8603d
Compare
Add comprehensive living specification for the MCP Apps integration (issue containers#753). Covers architecture, configuration, frontend stack decisions, MCP postMessage protocol, output layer design, per-tool resource URIs, VS Code compatibility, and YAML syntax highlighting. Signed-off-by: Marc Nuri <marc@marcnuri.com>
Add MCP Apps support as an opt-in feature (--apps flag, apps_enabled
config). When enabled, tools return structuredContent alongside text
and expose per-tool ui:// resource URIs for interactive HTML viewers.
Infrastructure:
- AppsEnabled config field with CLI flag and TOML support
- Server capability negotiation (io.modelcontextprotocol/ui extension)
- Per-tool resource registration with VS Code pre-fetch compatibility
- WithAppsMeta() tool mutator for centralized _meta.ui injection
Viewer (Preact + HTM + Chart.js, no build step):
- MCP postMessage protocol implementation (~80 lines)
- Dual-flow viewer: spec-compliant tool-result + fallback tool-input
- SortableTable, TableView, MetricsTable, GenericView components
- CSS theming with light-dark() fallbacks for host integration
Output layer:
- PrintObjStructured() on Output interface for generic extraction
- NewToolCallResultFull() constructor for text + structured content
- ensureStructuredObject() wraps arrays in {"items": [...]} per spec
- tableToStructured() converts Kubernetes Table API to []map[string]any
Signed-off-by: Marc Nuri <marc@marcnuri.com>
Add self-describing structured content for metrics tools and browser integration tests for the MCP Apps viewer. Metrics: - extractNodesTopStructured() with CPU/memory and percentage utilization - Self-describing format with columns, chart config, and items Browser tests (Rod + wrapper iframe): - Protocol handshake, table rendering, sorting, metrics charts - YAML highlighting, theme application, data routing - Items envelope unwrapping, error handling Signed-off-by: Marc Nuri <marc@marcnuri.com>
Add Prism.js (core + YAML grammar, ~9.4 KB) for syntax-highlighted YAML output in the MCP Apps viewer. Tools returning Kubernetes resource YAML now render with color-coded keys, strings, numbers, and comments. - YamlView component with Prism.highlight() and useMemo - looksLikeYaml() heuristic for Kubernetes resource detection - Custom theme CSS using light-dark() for host theme integration - Prism.manual = true to prevent auto-highlighting Signed-off-by: Marc Nuri <marc@marcnuri.com>
Add Section 12 documenting the content vs structuredContent model context visibility contract. structuredContent is for UI rendering only — the model sees only the content field. References ext-apps spec, SEP-1624, and PR #2200. Includes current client behavior matrix, eval accountability steps, and open questions. Signed-off-by: Marc Nuri <marc@marcnuri.com>
- Guard ensureStructuredObject against invalid reflect.Value on nil - Fix stale closure in tool-input handler by using useRef for toolName - Use LoadOrStore in ViewerHTMLForTool to avoid redundant replacement - Unify nodes_top/pods_top to use NewToolCallResultFull consistently - Document postMessage wildcard origin and items unwrapping heuristic - Update spec code snippets to match implementation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Marc Nuri <marc@marcnuri.com>
Replace Prism.highlight() with Prism.tokenize() + custom renderTokens() that explicitly HTML-escapes all text segments. This removes reliance on Prism's internal encode() as the sole XSS barrier for dangerouslySetInnerHTML. Add browser tests verifying script injection, attribute injection, and span-breaking payloads are escaped. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Marc Nuri <marc@marcnuri.com>
Add TestScreenshots to the browser suite capturing PNGs of every view (table, metrics, YAML, generic) in light and dark themes. Screenshots are saved to _output/screenshots/ for offline review and diffing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Marc Nuri <marc@marcnuri.com>
…d softer headers Wrap tables in a card container matching chart/pre visual treatment. Add zebra striping for horizontal scanning, softer uppercase headers to shift emphasis to data, and move item count outside the card as a right-aligned caption. Fix pre blocks to use overflow-wrap: break-word and increase line-height for readability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Marc Nuri <marc@marcnuri.com>
- Clean up stale ui:// resources on toolset reload via RemoveResources - Merge _meta.ui into existing tool Meta instead of skipping - Guard ensureStructuredObject against typed nil slices - Prevent duplicate Namespace key in tableToStructured - Remove redundant loop variable capture (Go 1.22+ semantics) - Use plain object instead of ES6 Map in protocol.js for consistency Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Marc Nuri <marc@marcnuri.com>
…rge, namespace dedup) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Marc Nuri <marc@marcnuri.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Marc Nuri <marc@marcnuri.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
Add MCP Apps support as an opt-in feature (
--appsflag /apps_enabledconfig) that enables tools to return interactive HTML-based UIs rendered in sandboxed iframes by MCP hosts (VS Code, Claude Desktop, ChatGPT, etc.).Viewer built with Preact + HTM + Chart.js + Prism.js (~230 KB, no build step), served via
embed.FSwith per-toolui://resource URIs.Closes #753
What's done
tool-result+ fallbacktool-input), SortableTable, MetricsTable (Chart.js), YamlView (Prism.js), GenericView, theming withlight-dark()CSS fallbacksPrintObjStructuredon Output interface,tableToStructuredfor Kubernetes Table API,ensureStructuredObjectarray wrappingpods_list,pods_list_in_namespace,pods_top,nodes_top,namespaces_list,projects_list,resources_list_meta.uikeysWhat's pending
callServerTool(), height management, filtering/paginationdocs/configuration.mdforapps_enabled)