Interactive MCP visual output via @json-render/mcp: upgrade plain JSON tool responses to dashboards rendered in sandboxed iframes inside MCP clients like Claude, Cursor, and ChatGPT. Use when a tool result would read better as a stat grid, data table, or status badge than as text. For the server itself (transport, auth, tool handlers, security) reach for ork:mcp-patterns.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
La commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Explorateur de fichiers
11 fichiers
Affichage de SKILL.md
SKILL.md
Instructions source · Aperçu en lecture seule
name
mcp-visual-output
compatibility
Claude Code 2.1.220+
description
Interactive MCP visual output via @json-render/mcp: upgrade plain JSON tool responses to dashboards rendered in sandboxed iframes inside MCP clients like Claude, Cursor, and ChatGPT. Use when a tool result would read better as a stat grid, data table, or status badge than as text. For the server itself (transport, auth, tool handlers, security) reach for ork:mcp-patterns.
Upgrade plain MCP tool responses to interactive dashboards rendered inside AI conversations. Built on @json-render/mcp, which bridges the json-render spec system with MCP's tool/resource model -- the AI generates a typed JSON spec, and a sandboxed iframe renders it as an interactive UI.
Building an MCP server from scratch? Use ork:mcp-patterns for server setup, transport, and security. This skill focuses on the visual output layer after your server is running.
Need the full component catalog? See ork:json-render-catalog for all available components, props, and composition patterns.
Decision Tree -- Which File to Read
What are you doing?
|
+-- Setting up visual output for the first time
| +-- New MCP server -----------> rules/mcp-app-setup.md
| +-- Existing MCP server ------> rules/mcp-app-setup.md (registerJsonRenderTool section)
|
+-- Configuring security / sandbox
| +-- CSP declarations ----------> rules/sandbox-csp.md
| +-- Iframe permissions --------> rules/sandbox-csp.md
|
+-- Rendering strategy
| +-- Progressive streaming -----> rules/streaming-output.md
| +-- Dashboard layouts ----------> rules/dashboard-patterns.md
|
+-- API reference
| +-- Server-side API -----------> references/mcp-integration.md
| +-- Component recipes ----------> references/component-recipes.md
Quick Reference
Category
Rule
Impact
Key Pattern
Setup
mcp-app-setup.md
HIGH
createMcpApp() and registerJsonRenderTool()
Security
sandbox-csp.md
HIGH
CSP declarations, iframe sandboxing
Rendering
streaming-output.md
MEDIUM
Progressive rendering via JSON Patch
Patterns
dashboard-patterns.md
MEDIUM
Stat grids, status badges, data tables
Total: 4 rules across 3 categories
How It Works
Define a catalog -- typed component schemas using defineCatalog() + Zod
Register with MCP -- for new servers or for existing ones
createMcpApp()
registerJsonRenderTool()
AI generates specs -- the model produces a JSON spec conforming to the catalog
Iframe renders it -- a bundled React app inside a sandboxed iframe renders the spec with useJsonRenderApp() + <Renderer />
The AI never writes HTML or CSS. It produces a structured JSON spec that references catalog components by type. The iframe app renders those components using a pre-built registry.
Quick Start -- New MCP Server
import { createMcpApp } from'@json-render/mcp'import { StdioServerTransport } from'@modelcontextprotocol/sdk/server/stdio.js'import { buildAppHtml } from'@json-render/mcp/app'import { catalog } from'./catalog'// Generate the iframe HTML from the bundled JS/CSS (docs-prescribed generator).const bundledHtml = buildAppHtml({ entry: './app.tsx' })
// 1. Create the MCP app (async; returns an McpServer, no .start()/.close()).// name + version are required; tool config nests under `tool`// (default tool name is 'render-ui'). There is no top-level `csp`.const server = awaitcreateMcpApp({
name: 'my-app',
version: '1.0.0',
catalog, // component schemas the AI can usehtml: bundledHtml, // pre-built iframe app (single HTML file)tool: {
name: 'render-dashboard',
description: 'Render an interactive dashboard from a json-render spec',
},
})
// 2. Connect a transport -- stdio, Streamable HTTP, or any MCP transportawait server.connect(newStdioServerTransport())
Quick Start -- Enhance Existing Server with Visual Output
import { McpServer } from'@modelcontextprotocol/sdk/server/mcp.js'import { registerJsonRenderTool, registerJsonRenderResource } from'@json-render/mcp'import { buildAppHtml } from'@json-render/mcp/app'import { catalog } from'./catalog'const server = newMcpServer({ name: 'my-server', version: '1.0.0' })
// Generate the iframe HTML from the bundled JS/CSS (docs-prescribed generator).const bundledHtml = buildAppHtml({ entry: './app.tsx' })
const resourceUri = 'ui://my-server/dashboard'// Register the render tool (lets the model return specs).// name, title, description, and resourceUri are all required.registerJsonRenderTool(server, {
catalog,
name: 'render-dashboard',
title: 'Render Dashboard',
description: 'Render an interactive dashboard from a json-render spec',
resourceUri,
})
// Serve the bundled HTML iframe app as a resource (new in 0.15).// resourceUri must match the tool's resourceUri.registerJsonRenderResource(server, { resourceUri, html: bundledHtml })
registerJsonRenderResource() was added in 0.15 to separate tool registration from UI resource serving — useful when the host caches the bundled HTML (clients: Claude, ChatGPT, Cursor, VS Code Copilot, Goose, Postman). Transports: stdio and Streamable HTTP (Express) both supported. This skill is verified against @json-render/mcp0.19.0.
Client-Side Iframe App
The iframe app receives specs from the MCP host and renders them:
createMcpApp() for new; registerJsonRenderTool() to add to existing
CSP policy
Minimal -- only declare domains you actually need
Streaming
Always enable progressive rendering; never wait for full spec
Dashboard depth
Keep element trees flat (2-3 levels max) for streamability
Component count
3-5 component types per catalog covers most dashboards
Visual vs text
Use visual output for multi-metric views; plain text for single values
CC 2.1.113 fixed MCP concurrent-call timeout handling — hanging tool calls now error cleanly instead of blocking the queue. Parallel tool invocation from dashboards is safer; no workarounds needed.
When to Use Visual Output vs Plain Text
Scenario
Use Visual Output
Use Plain Text
Multiple metrics at a glance
Yes -- StatGrid
No
Tabular data (5+ rows)
Yes -- DataTable
No
Status of multiple systems
Yes -- StatusBadge grid
No
Single value answer
No
Yes
Error message
No
Yes
File content / code
No
Yes
Common Mistakes
Returning raw HTML strings from MCP tools instead of json-render specs (breaks type safety, no streaming)
Deeply nested component trees that cannot stream progressively (keep flat)
Using script-src 'unsafe-inline' in CSP declarations (security risk, unnecessary)
Waiting for the full spec before rendering (defeats progressive rendering)
Defining 20+ component types in a single catalog (increases prompt token cost)
Missing html bundle in createMcpApp() config (iframe has nothing to render)
Related Skills
ork:mcp-patterns -- MCP server building, transport, security
ork:json-render-catalog -- Full component catalog and composition patterns
ork:multi-surface-render -- Rendering across Claude, Cursor, ChatGPT, web
ork:ai-ui-generation -- GenUI patterns for AI-generated interfaces