| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- import { pageMetadata } from "@/lib/page-metadata"
- export const metadata = pageMetadata("docs/api/mcp")
- # @json-render/mcp
- MCP Apps integration for json-render. Serve json-render UIs as interactive [MCP Apps](https://modelcontextprotocol.io/docs/extensions/apps) inside Claude, ChatGPT, Cursor, VS Code, and other MCP-capable clients.
- ## Install
- ```bash
- npm install @json-render/mcp @json-render/core @modelcontextprotocol/sdk
- ```
- For the iframe-side React UI, also install:
- ```bash
- npm install @json-render/react react react-dom
- ```
- See the [MCP example](https://github.com/vercel-labs/json-render/tree/main/examples/mcp) for a full working example.
- ## Overview
- MCP Apps let MCP servers return interactive HTML UIs that render directly inside chat conversations. `@json-render/mcp` bridges json-render catalogs with the MCP Apps protocol:
- 1. Your **catalog** defines which components and actions the AI can use
- 2. The **MCP server** exposes the catalog as a tool with the spec schema
- 3. The **bundled HTML** renders json-render specs inside the host's sandboxed iframe
- 4. The AI generates a spec, the host renders it, and users interact with the live UI
- ## Server API
- ### createMcpApp
- Create a fully-configured MCP server. This is the main entry point.
- ```typescript
- import { createMcpApp } from "@json-render/mcp";
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
- import fs from "node:fs";
- const server = createMcpApp({
- name: "My Dashboard",
- version: "1.0.0",
- catalog: myCatalog,
- html: fs.readFileSync("dist/index.html", "utf-8"),
- });
- await server.connect(new StdioServerTransport());
- ```
- #### CreateMcpAppOptions
- <table>
- <thead>
- <tr>
- <th>Option</th>
- <th>Type</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><code>name</code></td>
- <td><code>string</code></td>
- <td>Server name shown in client UIs</td>
- </tr>
- <tr>
- <td><code>version</code></td>
- <td><code>string</code></td>
- <td>Server version</td>
- </tr>
- <tr>
- <td><code>catalog</code></td>
- <td><code>Catalog</code></td>
- <td>json-render catalog defining available components</td>
- </tr>
- <tr>
- <td><code>html</code></td>
- <td><code>string</code></td>
- <td>Self-contained HTML for the iframe UI</td>
- </tr>
- <tr>
- <td><code>tool</code></td>
- <td><code>McpToolOptions</code></td>
- <td>Optional tool name/title/description overrides</td>
- </tr>
- </tbody>
- </table>
- ### registerJsonRenderTool
- Register a json-render tool on an existing `McpServer`. Use this when you need to add json-render to a server that has other tools.
- ```typescript
- import { registerJsonRenderTool } from "@json-render/mcp";
- registerJsonRenderTool(server, {
- catalog,
- name: "render-ui",
- title: "Render UI",
- description: "Render an interactive UI",
- resourceUri: "ui://render-ui/view.html",
- });
- ```
- ### registerJsonRenderResource
- Register the UI resource that serves the bundled HTML.
- ```typescript
- import { registerJsonRenderResource } from "@json-render/mcp";
- registerJsonRenderResource(server, {
- resourceUri: "ui://render-ui/view.html",
- html: bundledHtml,
- });
- ```
- ## Client API (`@json-render/mcp/app`)
- These exports run inside the sandboxed iframe rendered by the MCP host.
- ### useJsonRenderApp
- React hook that connects to the MCP host, listens for tool results, and maintains the current json-render spec.
- ```tsx
- import { useJsonRenderApp } from "@json-render/mcp/app";
- import { JSONUIProvider, Renderer } from "@json-render/react";
- function McpAppView({ registry }) {
- const { spec, loading, connected, error } = useJsonRenderApp({
- name: "my-app",
- version: "1.0.0",
- });
- if (error) return <div>Error: {error.message}</div>;
- if (!spec) return <div>Waiting...</div>;
- return (
- <JSONUIProvider registry={registry} initialState={spec.state ?? {}}>
- <Renderer spec={spec} registry={registry} loading={loading} />
- </JSONUIProvider>
- );
- }
- ```
- #### UseJsonRenderAppReturn
- <table>
- <thead>
- <tr>
- <th>Field</th>
- <th>Type</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><code>spec</code></td>
- <td><code>{'Spec | null'}</code></td>
- <td>Current json-render spec</td>
- </tr>
- <tr>
- <td><code>loading</code></td>
- <td><code>boolean</code></td>
- <td>Whether the spec is still being received</td>
- </tr>
- <tr>
- <td><code>connected</code></td>
- <td><code>boolean</code></td>
- <td>Whether connected to the host</td>
- </tr>
- <tr>
- <td><code>connecting</code></td>
- <td><code>boolean</code></td>
- <td>Whether currently connecting</td>
- </tr>
- <tr>
- <td><code>error</code></td>
- <td><code>{'Error | null'}</code></td>
- <td>Connection error, if any</td>
- </tr>
- <tr>
- <td><code>app</code></td>
- <td><code>{'App | null'}</code></td>
- <td>The underlying MCP App instance</td>
- </tr>
- <tr>
- <td><code>callServerTool</code></td>
- <td><code>{'(name, args?) => Promise<void>'}</code></td>
- <td>Call an MCP server tool and update spec from result</td>
- </tr>
- </tbody>
- </table>
- ### buildAppHtml
- Generate a self-contained HTML page from bundled JavaScript and CSS.
- ```typescript
- import { buildAppHtml } from "@json-render/mcp/app";
- import fs from "node:fs";
- const html = buildAppHtml({
- title: "Dashboard",
- js: fs.readFileSync("dist/app.js", "utf-8"),
- css: fs.readFileSync("dist/app.css", "utf-8"),
- });
- ```
- ## Client Configuration
- ### Cursor
- Add to `.cursor/mcp.json`:
- ```json
- {
- "mcpServers": {
- "json-render": {
- "command": "npx",
- "args": ["tsx", "path/to/server.ts", "--stdio"]
- }
- }
- }
- ```
- ### Claude Desktop
- Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
- ```json
- {
- "mcpServers": {
- "json-render": {
- "command": "npx",
- "args": ["tsx", "/absolute/path/to/server.ts", "--stdio"]
- }
- }
- }
- ```
- ## Supported Clients
- MCP Apps are supported by Claude (web and desktop), ChatGPT, VS Code (GitHub Copilot), Cursor, Goose, and Postman.
|