Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fractal-mcp/sdk

Repository files navigation

Fractal SDK

A comprehensive toolkit for embedding interactive UIs in chat applications. This monorepo provides everything you need to create rich, interactive widget applications using the Model Context Protocol (MCP) and cross-iframe messaging.

Getting Started

Head to our OpenAI Apps SDK quickstart if you would like to skip straight to building!

Want to understand how everything works first? Check out How It Works.

What is this?

This SDK provides tools for embedding UIs in chat applications including:

  • OpenAI Apps SDK - Build interactive widgets for ChatGPT
  • MCP-UI Protocol - Build embeddable UIs with cross-iframe messaging
  • Custom embedding solutions - Use our messaging layer for any iframe-based UI embedding

The SDK makes it easier to:

  • Build MCP servers with custom widget UIs
  • Create widget UI components using React hooks
  • Embed UIs using cross-iframe messaging protocols
  • Bundle and deploy your widgets for production
  • Preview widgets before deployment

This toolkit provides production-ready packages to start building today.

Packages Overview

OpenAI Apps SDK Packages

MCP-UI / Cross-iframe Messaging Packages

Bundling & Deployment

Server Utilities

Package Details

OpenAI Apps SDK

React hooks for building widget UIs that communicate with ChatGPT.

npm install @fractal-mcp/oai-hooks

Key features:

  • Access widget props from server
  • Manage persistent widget state
  • Respond to layout changes (display mode, max height)
  • Access ChatGPT's global context (theme, safe area)

Example:

import { useWidgetProps, useWidgetState } from "@fractal-mcp/oai-hooks";

function WeatherWidget() {
  const props = useWidgetProps<{ location: string; temp: number }>();
  const [state, setState] = useWidgetState({ unit: "fahrenheit" });
  
  return (
    <div>
      <h2>Weather in {props.location}</h2>
      <p>{props.temp}°{state.unit === "celsius" ? "C" : "F"}</p>
    </div>
  );
}

Full Documentation


Server-side toolkit for building MCP servers with custom widget UIs.

npm install @fractal-mcp/oai-server

Key features:

  • Register tools with custom UI widgets
  • Serve widget HTML and assets via MCP resources
  • Handle SSE transport for real-time communication
  • Type-safe input validation with Zod

Example:

import { McpServer, registerOpenAIWidget, startOpenAIWidgetHttpServer } from "@fractal-mcp/oai-server";

const server = new McpServer({ name: "my-app", version: "1.0.0" });

registerOpenAIWidget(
  server,
  {
    id: "weather",
    title: "Get Weather",
    templateUri: "ui://widget/weather.html",
    html: `<div id="root"></div>`,
    // ... more config
  },
  async (args) => ({
    content: [{ type: "text", text: "Weather data" }],
    structuredContent: { temp: 72, location: args.location }
  })
);

startOpenAIWidgetHttpServer({ port: 8000, serverFactory: () => server });

Full Documentation


Development/Testing Tool - React component for previewing and testing widgets.

npm install --save-dev @fractal-mcp/oai-preview

Example:

import { WidgetDisplayComponent } from "@fractal-mcp/oai-preview";

<WidgetDisplayComponent
  htmlSnippet={widgetHtml}
  toolInput={{ location: "San Francisco" }}
  toolOutput={{ temp: 72, condition: "Sunny" }}
  onToolCall={async (name, params) => {/* handle tool calls */}}
/>

Credits: Built by studying MCPJam Inspector and ChatGPT's widget source code.

Full Documentation


MCP-UI / Cross-iframe Messaging

Low-level RPC communication layer for iframe messaging.

npm install @fractal-mcp/shared-ui

Key features:

  • RPC-style request/response messaging
  • Event emission and listening
  • Message correlation tracking
  • Works with any iframe messaging protocol

Full Documentation


MCP-UI compatible cross-iframe messenger for embeddable UIs.

npm install @fractal-mcp/mcp-ui-messenger

Key features:

  • Implements MCP-UI Embeddable UI Protocol
  • Automatic iframe lifecycle management
  • Render data handling
  • Intent, notification, prompt, and tool messaging
  • Auto-resize observer

Example:

import { initUIMessenger } from '@fractal-mcp/mcp-ui-messenger';

const messenger = await initUIMessenger({ rootElId: 'root' });
const renderData = messenger.getRenderData();

messenger.emitIntent({ 
  intent: 'button-clicked',
  params: { timestamp: Date.now() }
});

Full Documentation


React hooks for MCP-UI cross-iframe messaging.

npm install @fractal-mcp/mcp-ui-hooks

Key features:

  • Dead simple React integration
  • Automatic initialization and cleanup
  • All MCP-UI message types supported
  • TypeScript support

Example:

import { useUIMessenger } from '@fractal-mcp/mcp-ui-hooks';

function App() {
  const { ready, renderData, emitIntent } = useUIMessenger();
  
  if (!ready) return <div>Loading...</div>;
  
  return (
    <div>
      <h1>Theme: {renderData?.theme}</h1>
      <button onClick={() => emitIntent({ intent: 'action' })}>
        Click Me
      </button>
    </div>
  );
}

Note: For OpenAI Apps SDK, use @fractal-mcp/oai-hooks instead.

Full Documentation


Bundling & Deployment

Bundling utilities for React components, JS/TS entry points, and HTML files.

npm install @fractal-mcp/bundle

Key features:

  • Bundle React components into standalone HTML files
  • Multiple output formats (full HTML, snippets, separate assets)
  • Framework-agnostic (React, Vue, Svelte)
  • Powered by Vite for fast builds
  • Built-in testing utilities with Playwright

Example:

import { bundleReactComponent } from '@fractal-mcp/bundle';

await bundleReactComponent({
  entrypoint: './src/MyWidget.tsx',
  out: './dist'
});
// Outputs: dist/index.html (single file with everything inlined)

Full Documentation


Command-line tools for bundling widgets.

npm install -g @fractal-mcp/cli
# or use with npx

Usage:

# Bundle a React component
npx @fractal-mcp/cli bundle --entrypoint=./src/Widget.tsx --out=./dist

# Bundle an HTML application
npx @fractal-mcp/cli bundle --entrypoint=./index.html --out=./dist

Full Documentation


Server Utilities

Utilities for serving MCP servers with Express, including connection to Fractal's registry.

npm install @fractal-mcp/mcp-express

Full Documentation


Quick Start

1. Create a Widget UI Component

// ui/WeatherWidget.tsx
import { useWidgetProps } from "@fractal-mcp/oai-hooks";

export default function WeatherWidget() {
  const props = useWidgetProps<{ location: string; temp: number }>();
  
  return (
    <div>
      <h2>{props.location}</h2>
      <p>{props.temp}°F</p>
    </div>
  );
}

2. Bundle the Widget

npx @fractal-mcp/cli bundle --entrypoint=./ui/WeatherWidget.tsx --out=./dist

This creates dist/index.html with your widget bundled as a single HTML file.

3. Create an MCP Server

// server/index.ts
import { McpServer, registerOpenAIWidget, startOpenAIWidgetHttpServer } from "@fractal-mcp/oai-server";
import { z } from "zod";
import fs from "fs";

function createServer() {
  const server = new McpServer({ name: "weather-server", version: "1.0.0" });
  
  // Read bundled widget HTML
  const widgetHtml = fs.readFileSync("./dist/index.html", "utf-8");
  
  registerOpenAIWidget(
    server,
    {
      id: "get-weather",
      title: "Get Weather",
      description: "Show weather for a location",
      templateUri: "ui://widget/weather.html",
      invoking: "Fetching weather...",
      invoked: "Weather loaded!",
      html: widgetHtml,
      responseText: "Here's the weather",
      inputSchema: z.object({
        location: z.string().describe("City name")
      })
    },
    async (args) => ({
      content: [{ type: "text", text: `Weather in ${args.location}` }],
      structuredContent: { 
        location: args.location, 
        temp: 72 
      }
    })
  );
  
  return server;
}

startOpenAIWidgetHttpServer({
  port: 8000,
  serverFactory: createServer
});

4. Run Your Server

npm run build
node dist/server/index.js

Your MCP server is now running at http://localhost:8000 and ready to be connected to ChatGPT!

Examples

Check out the examples directory for complete working examples:

  • oai-apps - Full example showing server and UI integration

Data Flow

  1. User invokes tool in ChatGPT
  2. Server handler processes request and returns:
    • content: Text/resources for the chat
    • structuredContent: Props for the widget
  3. ChatGPT renders widget using the bundled HTML
  4. Widget UI receives props via useWidgetProps() and renders
  5. User interacts with widget, state persists via useWidgetState()

Package Relationships

┌──────────────────┐
│   oai-hooks      │  React hooks for widget UI
└────────┬─────────┘
         │ used by
         ↓
┌──────────────────┐
│   Your Widget    │  Your React components
└────────┬─────────┘
         │ bundled by
         ↓
┌──────────────────┐
│   bundle/cli     │  Bundling tools
└────────┬─────────┘
         │ produces HTML for
         ↓
┌──────────────────┐
│   oai-server     │  MCP server with widgets
└──────────────────┘

Development

Setup

# Install dependencies
npm install

# Build all packages
npm run build

# Run tests
npm test

Package Structure

sdk/
├── packages/
│   ├── OpenAI Apps SDK:
│   │   ├── oai-hooks/      # UI hooks for ChatGPT widgets
│   │   ├── oai-server/     # Server toolkit for MCP with widgets
│   │   └── oai-preview/    # 🧪 Dev/testing tool
│   ├── MCP-UI:
│   │   ├── shared-ui/      # RPC layer for iframe communication
│   │   ├── mcp-ui-messenger/ # MCP-UI compatible messenger
│   │   └── mcp-ui-hooks/   # React hooks for MCP-UI
│   ├── Bundling:
│   │   ├── bundle/         # Bundling library
│   │   └── cli/            # CLI tools
│   └── Server Utilities:
│       └── mcp-express/    # Express utilities
└── apps/
    └── examples/       # Example applications

Publishing

Each package can be published independently to npm:

cd packages/[package-name]
npm publish

Requirements

  • Node.js 18+
  • React 18+ (for widget UIs)
  • TypeScript 5+ (recommended)

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

License

Apache License, Version 2.0

Resources

OpenAI Apps SDK

MCP & MCP-UI

Other resources

Credits

This SDK provides tools for embedding UIs in chat applications, supporting multiple protocols and frameworks. Special thanks to:

  • OpenAI for pioneering the Apps SDK and widget approach to building interactive AI applications
  • MCP-UI for creating the embeddable UI protocol specification
  • MCPJam Inspector for their excellent open-source MCP testing platform, which helped inform our development tooling
  • The MCP community for building an ecosystem of tools and servers