MCP-HTML-Bridge

Render any MCP tool's JSON data as zero-dependency, self-contained HTML. LLM-powered semantic rendering with automatic structural fallback.

npm GitHub MIT 中文 README

Live Demo

These are actual rendered outputs from the engine — zero dependencies, self-contained HTML. Each demo is generated from a single function call.

[
  { "name": "Alice", "role": "Admin", "status": "Active", "email": "alice@example.com" },
  { "name": "Bob", "role": "Editor", "status": "Active", "email": "bob@example.com" },
  { "name": "Charlie", "role": "Viewer", "status": "Inactive", "email": "charlie@example.com" },
  { "name": "Diana", "role": "Admin", "status": "Active", "email": "diana@example.com" }
]
{
  "project": "MCP-HTML-Bridge",
  "version": "0.5.1",
  "totalDownloads": 12483,
  "weeklyGrowth": 23.5,
  "openIssues": 7,
  "stars": 342,
  "license": "MIT",
  "dependencies": 0,
  "status": "stable"
}
{
  "type": "object",
  "properties": {
    "query": { "type": "string", "description": "Search keywords" },
    "category": { "type": "string", "enum": ["Books", "Electronics", "Clothing", "Food"] },
    "maxPrice": { "type": "number", "minimum": 0, "maximum": 10000 },
    "inStock": { "type": "boolean", "default": true }
  },
  "required": ["query"]
}

This is the structural fallback mode (no LLM). With an LLM configured, the output is even richer — the model understands data semantics and renders SVGs, markdown, charts, etc.

Quick Start

# 1. Install
npm install -g @mcp-html-bridge/claude-skill

# 2. Configure your LLM provider once
mcp-html-skill config --api-url http://localhost:11434/v1 --model qwen2

# 3. Render any JSON
echo '{"name":"Alice","scores":[98,85,92]}' > /tmp/data.json
mcp-html-skill render --data /tmp/data.json --open

# Or skip LLM, use structural rendering
mcp-html-skill render --data /tmp/data.json --no-llm --open

Or without installing:

npx @mcp-html-bridge/claude-skill render --data /tmp/data.json --open

LLM Configuration

Configure once, use everywhere. Supports any OpenAI-compatible API.

mcp-html-skill config --api-url <url> --model <model> [--api-key <key>]

Provider Examples

# Local Ollama (no API key needed)
mcp-html-skill config --api-url http://localhost:11434/v1 --model qwen2

# DeepSeek
mcp-html-skill config --api-url https://api.deepseek.com/v1 \
  --api-key sk-xxx --model deepseek-chat

# Baidu ERNIE
mcp-html-skill config \
  --api-url https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop \
  --api-key xxx --model ernie-4.0-8k

Manage Config

mcp-html-skill config --show     # View current config
mcp-html-skill config --clear    # Clear config

Resolution Priority

CLI flags > Environment variables > Config file > No LLM (structural fallback)

Env vars: MCP_HTML_LLM_API_URL / MCP_HTML_LLM_API_KEY / MCP_HTML_LLM_MODEL

Config file: ~/.mcp-html-bridge/config.json

Rendering Modes

LLM Semantic Rendering

The model understands what the data means and produces the best HTML. No hardcoded patterns. Handles SVGs, markdown, charts, images, code — anything.

Structural Fallback

When no LLM is configured. Maps JSON shapes to HTML mechanically: arrays → tables, objects → key-value pairs, nesting → collapsible sections.

JSON ShapeRendered As
Array of objectsSortable table
Flat objectKey-value pairs
Nested objectCollapsible sections
Primitive valueInline display
Mixed / complexAuto-detected composite
Auto-link URLs Embed images XSS-safe Heterogeneous arrays Deep nesting (30 levels) Graceful fallback Dark mode

Library API

Async LLM Rendering

import { renderFromData } from '@mcp-html-bridge/ui-engine';

const html = await renderFromData(data, {
  title: 'API Result',
  llm: {
    apiUrl: 'http://localhost:11434/v1',
    model: 'qwen2',
  },
});

Sync Structural Rendering

import { renderFromDataSync } from '@mcp-html-bridge/ui-engine';

const html = renderFromDataSync(data, { title: 'API Result' });

Form from JSON Schema

import { renderFromSchema } from '@mcp-html-bridge/ui-engine';

const html = renderFromSchema({
  type: 'object',
  properties: {
    query: { type: 'string', description: 'Search query' },
    category: { type: 'string', enum: ['Books', 'Electronics'] },
    maxPrice: { type: 'number', minimum: 0 },
  },
  required: ['query'],
}, {
  toolName: 'search_products',
});

Form Widget Mapping

Schema TypeWidget
stringText input
string + enumCapsule radio group
string + format: "date"Date picker
number / integerNumber input with min/max
booleanToggle switch
object + propertiesCollapsible nested section
arrayTextarea (JSON input)

CLI Usage

# Render with LLM (auto-loads config)
mcp-html-skill render --data result.json --open

# Force structural, no LLM
mcp-html-skill render --data result.json --no-llm --open

# Schema → interactive form
mcp-html-skill render --schema tool-schema.json --open

# Inline JSON
mcp-html-skill render --json '{"users":[{"name":"Alice"}]}' --open

# Stdout
mcp-html-skill render --data result.json --stdout > output.html

All Options

FlagDescription
--data <file>Input JSON data file
--schema <file>Input JSON Schema (renders as form)
--json <string>Inline JSON string
--titlePage title
--debugAdd debug playground panel
--openAuto-open in browser
--stdoutPrint raw HTML to stdout
--no-llmForce structural rendering
--api-url / --api-key / --modelOverride LLM config for this call

Claude Code Integration

# Install /mcp-render command
mcp-html-skill install

# Then in any Claude Code conversation:
/mcp-render

Tailwind Utility Classes

Every generated page includes Tailwind-compatible atomic classes mapped to the CSS variable theme. Both the LLM and hand-written HTML can use them.

Layout

flex grid block hidden flex-col grid-cols-1~4

Alignment

items-center justify-between justify-center shrink-0 grow

Spacing

gap-1~8 p-0~8 px-* py-* m-* mx-auto

Typography

text-xs~3xl font-bold font-mono text-center truncate

Colors

text-primary bg-primary bg-elevated bg-accent-subtle bg-success-subtle

Borders & Effects

border rounded-lg shadow-md overflow-hidden transition

Responsive Prefixes

sm:grid-cols-2  sm:flex-row  sm:text-lg  sm:p-6    /* ≥640px */
md:grid-cols-3  md:flex-row  md:text-2xl  md:p-8    /* ≥768px */

Bridge Protocol

Every generated page includes a bridge script for bidirectional iframe communication.

Inside the HTML

__mcpBridge.callTool('search_products', { query: 'laptop' });
__mcpBridge.onResult(function(data) { console.log(data); });

From the Parent Frame

window.addEventListener('message', (evt) => {
  if (evt.data?.type === 'MCP_TOOL_CALL') {
    iframe.contentWindow.postMessage({ type: 'MCP_RESULT', data: result }, '*');
  }
  if (evt.data?.type === 'MCP_RESIZE') {
    iframe.style.height = evt.data.height + 'px';
  }
});

Architecture

JSON Data \u2502 \u251C\u2500 LLM configured \u2192 JSON + prompt \u2192 Model \u2192 Semantic HTML \u2502 \u2514\u2500 No LLM \u2192 JSON shape \u2192 Structural HTML \u2502 \u25BC Theme CSS + Utility CSS + Bridge JS \u2192 Self-contained HTML file

Proxy Mode

Transparently forwards all MCP messages while appending rendered HTML to tool results.

npx @mcp-html-bridge/proxy "npx -y @modelcontextprotocol/server-filesystem /tmp"
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@mcp-html-bridge/proxy",
               "npx -y @modelcontextprotocol/server-filesystem /tmp"]
    }
  }
}

Packages

PackageDescription
@mcp-html-bridge/ui-engineCore engine (LLM renderer + structural fallback + Tailwind utilities)
@mcp-html-bridge/claude-skillClaude Code integration (CLI + /mcp-render)
@mcp-html-bridge/mcp-clientLightweight MCP stdio client
@mcp-html-bridge/cliCLI adapter (mcp-bridge)
@mcp-html-bridge/proxyMCP proxy server

Recipes

Embed in React (sync)

import { renderFromDataSync } from '@mcp-html-bridge/ui-engine';

function MCPViewer({ data }) {
  const html = useMemo(() => renderFromDataSync(data), [data]);
  return <iframe srcDoc={html} sandbox="allow-scripts"
           style={{ width: '100%', border: 'none' }} />;
}

Embed in React (async LLM)

import { renderFromData } from '@mcp-html-bridge/ui-engine';

function MCPViewer({ data }) {
  const [html, setHtml] = useState('');
  useEffect(() => {
    renderFromData(data, {
      llm: { apiUrl: 'http://localhost:11434/v1', model: 'qwen2' },
    }).then(setHtml);
  }, [data]);
  if (!html) return <div>Rendering...</div>;
  return <iframe srcDoc={html} sandbox="allow-scripts"
           style={{ width: '100%', border: 'none' }} />;
}

在线演示

以下是引擎的实际渲染输出 —— 零依赖、自包含 HTML。每个 demo 来自一次函数调用。

这是结构化兜底模式(无 LLM)。配置 LLM 后,输出更加丰富 —— 模型理解数据语义,自动渲染 SVG、markdown、图表等。

快速开始

# 1. 安装
npm install -g @mcp-html-bridge/claude-skill

# 2. 配置一次 LLM
mcp-html-skill config --api-url http://localhost:11434/v1 --model qwen2

# 3. 渲染任意 JSON
echo '{"name":"Alice","scores":[98,85,92]}' > /tmp/data.json
mcp-html-skill render --data /tmp/data.json --open

# 跳过 LLM,纯结构化渲染
mcp-html-skill render --data /tmp/data.json --no-llm --open

LLM 配置

mcp-html-skill config --api-url <url> --model <model> [--api-key <key>]

示例

# 本地 Ollama
mcp-html-skill config --api-url http://localhost:11434/v1 --model qwen2

# DeepSeek
mcp-html-skill config --api-url https://api.deepseek.com/v1 \
  --api-key sk-xxx --model deepseek-chat

# 百度文心
mcp-html-skill config \
  --api-url https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop \
  --api-key xxx --model ernie-4.0-8k

CLI 参数 > 环境变量 > 配置文件 > 无 LLM

渲染模式

LLM 语义渲染

模型理解数据语义,自己决定最佳渲染方式。代码零模式匹配。

结构化兜底

没配 LLM 时按 JSON 形状机械映射:数组 → 表格,对象 → 键值对。

库 API

// 异步 LLM 渲染
const html = await renderFromData(data, {
  title: '结果',
  llm: { apiUrl: 'http://localhost:11434/v1', model: 'qwen2' },
});

// 同步结构化渲染(无网络)
const html = renderFromDataSync(data, { title: '结果' });

// Schema → 表单
const html = renderFromSchema(schema, { toolName: 'search' });

CLI 使用

mcp-html-skill render --data result.json --open          # LLM 渲染
mcp-html-skill render --data result.json --no-llm --open # 结构化
mcp-html-skill render --schema schema.json --open        # 表单

Claude Code 集成

mcp-html-skill install    # 安装 /mcp-render 命令
/mcp-render               # 在 Claude Code 中使用

Tailwind 原子化样式

每个生成的页面自动包含 Tailwind 兼容原子类,映射到 CSS 变量主题系统。

布局

flex grid flex-col grid-cols-1~4

间距

gap-* p-* m-* px-* py-*

文字

text-xs~3xl font-bold text-center

颜色 & 边框

text-primary bg-elevated border rounded-lg shadow-md

包一览

包名说明
@mcp-html-bridge/ui-engine核心引擎
@mcp-html-bridge/claude-skillClaude Code 集成
@mcp-html-bridge/mcp-clientMCP 客户端
@mcp-html-bridge/cliCLI 工具
@mcp-html-bridge/proxyMCP 代理