@fractal-mcp/oai-preview
v2.2.5
Published
React component for previewing OpenAI Apps SDK widgets in development
Readme
@fractal-mcp/oai-preview
⚠️ Development/Testing Tool Only - Use this in your mcp preview applications, but NOT in your chats.
React component for previewing and testing OpenAI Apps SDK widgets during development.
Installation
npm install --save-dev @fractal-mcp/oai-previewUsage
import { WidgetDisplayComponent } from "@fractal-mcp/oai-preview";
function WidgetPreview() {
const htmlSnippet = `
<div id="root"></div>
<script>
const root = document.getElementById("root");
root.innerHTML = '<h1>Hello Widget</h1>';
</script>
`;
return (
<WidgetDisplayComponent
htmlSnippet={htmlSnippet}
toolInput={{ name: "World" }}
toolOutput={{ greeting: "Hello, World!" }}
theme="dark"
displayMode="inline"
maxHeight={800}
onToolCall={async (toolName, params) => {
console.log("Tool called:", toolName, params);
return { success: true };
}}
onOpenExternal={(href) => {
console.log("Opening external URL:", href);
// Custom handling - could show modal, log analytics, etc.
window.open(href, '_blank');
}}
onRequestDisplayMode={(mode) => {
console.log("Display mode requested:", mode);
}}
/>
);
}Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| htmlSnippet | string | Yes | The HTML snippet to render in an iframe |
| toolInput | Record<string, any> | No | Input args, available as window.openai.toolInput |
| toolOutput | any | No | Output data, available as window.openai.toolOutput |
| toolId | string | No | Unique ID for state persistence |
| onToolCall | (name, params) => Promise<any> | No | Called when widget calls window.openai.callTool() |
| onSendFollowup | (message) => void | No | Called when widget calls window.openai.sendFollowupTurn() |
| onSetWidgetState | (state) => void | No | Called when widget calls window.openai.setWidgetState() |
| onRequestDisplayMode | (mode) => void | No | Called when widget calls window.openai.requestDisplayMode() |
| onOpenExternal | (href) => void | No | Called when widget calls window.openai.openExternal() |
| className | string | No | CSS class for container |
| displayMode | DisplayMode | No | Display mode: "inline", "pip", "fullscreen" (default: "inline") |
| maxHeight | number | No | Maximum height constraint in pixels (default: 600) |
| theme | Theme | No | Theme: "light" or "dark" (default: "light") |
| locale | string | No | Locale string (default: "en-US") |
| safeArea | SafeArea | No | Safe area insets for mobile (default: zero insets) |
| userAgent | UserAgent | No | Device and capability info (default: desktop with hover) |
What It Does
The component:
- Renders your widget HTML in a sandboxed iframe
- Injects
window.openaiandwindow.webplusAPIs - Handles postMessage communication between iframe and parent
- Simulates the ChatGPT widget runtime
Testing
npm testTests use Playwright to verify rendering, messaging, and data access.
Credits
This package was built by studying and learning from:
MCPJam Inspector - An excellent open-source MCP testing platform. We drew heavy inspiration from these specific implementations:
server/routes/mcp/resources.ts- Resource handling patternsclient/src/components/chat/openai-component-renderer.tsx- Widget rendering and iframe communication
ChatGPT Widget Source Code - OpenAI's widget runtime implementation provided invaluable insights into the
window.openaiAPI design
Special thanks to the MCPJam team for making their code open source and advancing the MCP ecosystem!
License
MIT
