UI widgets for rendering MCP (Model Context Protocol) tool responses in AI assistants like ChatGPT.
When an MCP tool returns data, AI assistants can display it using custom UI widgets instead of plain text. This package provides ready-to-use widgets that can be embedded via a simple <script> tag.
npm install mcp-widgets
# or
pnpm add mcp-widgets| Widget | Framework | Size | Description |
|---|---|---|---|
data-card |
Web Widget | ~3KB | Simple key-value data display |
rich-data-card |
React | ~148KB | Enhanced card with sections, icons, footer |
Load widgets via CDN and use them as custom HTML elements:
<!-- Load the widget -->
<script src="https://unpkg.com/mcp-widgets/cdn/data-card.js"></script>
<!-- Use it -->
<mcp-data-card
title="Weather"
data='{"temperature": "72°F", "conditions": "Sunny"}'
status="success"
></mcp-data-card>import { RichDataCard } from 'mcp-widgets'
function MyWidget() {
return (
<RichDataCard
title="Order Summary"
icon="🛒"
data={{ orderId: '#12345', total: '$89.99' }}
sections={[{ title: 'Shipping', data: { method: 'Express' } }]}
status="success"
/>
)
}- User asks a question in ChatGPT (e.g., "What's the weather?")
- ChatGPT calls your MCP tool which returns structured data
- Your tool response includes HTML with a
<script>tag pointing to a CDN-hosted widget - ChatGPT renders the HTML in a sandboxed iframe
- The widget loads and displays the data visually
When your MCP server handles a tool call, return HTML that embeds a widget:
// In your MCP server tool handler
function handleWeatherTool(location) {
const data = fetchWeather(location)
return {
content: [
{
type: 'text',
text: `
<script src="https://unpkg.com/mcp-widgets/cdn/data-card.js"></script>
<mcp-data-card
title="Weather in ${location}"
data='${JSON.stringify(data)}'
status="success"
></mcp-data-card>
`,
},
],
}
}The loader handles communication with the ChatGPT host via window.openai. Widgets themselves should NOT call these APIs directly - the loader manages height notifications and prop extraction.
Available host APIs (used by the loader):
// Notify ChatGPT of widget height (takes a number)
window.openai.notifyIntrinsicHeight(document.body.scrollHeight)
// Access tool response metadata for props
window.openai.toolResponseMetadata._metaSee the OpenAI Apps SDK docs for the full window.openai API reference.
- Widgets run in a sandboxed iframe with limited capabilities
- Data is passed via HTML attributes (must be JSON-stringified)
- No direct access to the parent page or user session
- CDN URLs should use HTTPS
A lightweight Web Widget (no React dependency).
| Attribute | Type | Description |
|---|---|---|
title |
string | Card title |
data |
JSON string | Key-value pairs to display |
status |
success | error | warning | info |
Status indicator styling |
A React-based widget with more features.
| Attribute | Type | Description |
|---|---|---|
title |
string | Card title |
description |
string | Subtitle text |
icon |
string | Emoji or icon character |
data |
JSON string | Main data section |
sections |
JSON string | Array of {title, data} sections |
footer |
string | Footer text |
status |
success | error | warning | info |
Status styling |
# Install dependencies
pnpm install
# Start Storybook
pnpm dev
# Run tests
pnpm test
# Build everything
pnpm build
# Build CDN bundles only
pnpm build:cdn- Create a folder in
src/widgets/{widget-name}/ - Add required files:
WidgetName.ts(Web Widget) orWidgetName.tsx(React)manifest.json- Widget metadatacdn.tsorcdn.tsx- CDN entry pointindex.ts- Library export
- Export from
src/widgets/index.ts - Run
pnpm buildto generate bundles
This repository is designed to be forked! You have two options:
Fork this repo to create your own private widget library:
- Fork this repository to your GitHub account/organization
- Add your widgets following the structure above
- Host privately by publishing to a private npm registry or serving CDN bundles from your own infrastructure
- Use in your MCP tools by pointing to your private CDN URLs
This is ideal for:
- Proprietary UI widgets with custom branding
- Internal tools with sensitive designs
- Widgets that integrate with private APIs
We welcome community contributions! If you build a widget that could benefit others:
- Fork this repository
- Create your widget following the existing patterns
- Add tests and Storybook stories
- Submit a Pull Request with a description of your widget
Good candidates for community widgets:
- Generic data visualizations (charts, tables, maps)
- Common tool response patterns (search results, confirmations)
- Accessibility improvements
- Performance optimizations
If you fork and want to self-host your CDN bundles:
# Build the CDN bundles
pnpm build:cdn
# The cdn/ directory contains all bundles
# Upload to your preferred hosting:
# - GitHub Pages
# - Cloudflare R2/Pages
# - AWS S3 + CloudFront
# - Vercel/NetlifyThen reference your hosted bundles in MCP tool responses:
<script src="https://your-cdn.example.com/widgets/my-widget.js"></script>MIT