1. Conduid
  2. Developer Tools
  3. Oai App Composer
MCP server · Developer Tools

Oai App Composer

MCP server: Oai App Composer

Unclaimed last commit 10 months ago devtools
39Low

Scored 4 months ago · breakdown

About Oai App Composer

Oai App Composer is an MCP server published by itsnikhil in the Developer Tools category: mCP server: Oai App Composer. It has been installed 0 times through Conduid.

The repository has 7 stars and 0 forks, with the last commit 10 months ago. Six months or more without a commit doesn't mean the server is broken, but check the open issues (0) before depending on it in production.

Install

Install
npx oai-app-composer

This server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.

Ask AI

Ask AI about Oai App Composer

Powered by Claude · Grounded in docs

I know everything about Oai App Composer. Ask me about installation, configuration, usage, or troubleshooting.

Security checks

  • ·README presentNot checked yet.
  • ·License declaredNot checked yet.
  • ·Tests presentNot checked yet.
  • ·Dependencies pinnedNot checked yet.
  • ·No dynamic code executionNot checked yet.
  • !Scoped permissionsDoesn't declare a permission scope. Assume it can do anything its process can.

README

Component Development Tool

A Storybook-like IDE for developing and testing ChatGPT MCP (Model Context Protocol) components in isolation. Build, preview, and export custom UI components that integrate with ChatGPT Apps SDK.

Component Development Tool React TypeScript Vite

Features

  • 🎨 Component Development: Build React components with hot-reload and live preview
  • 📦 Monorepo Structure: Organize components in isolated directories with their own mock data
  • 🔍 Mock Data Management: Create and edit multiple mock states using Monaco Editor
  • 🎭 Sandboxed Preview: Test components in iframe with ChatGPT-like environment
  • 🌐 window.openai API: Full implementation matching ChatGPT's behavior for state management
  • 📤 Export: Generate MCP server code (Node.js/Python) for production deployment
  • 💾 State Management: Supports both ephemeral UI state and cross-session state patterns

Table of Contents

Additional Documentation

Installation

# Install dependencies
npm install

# Start development server
npm run dev

The tool will start on http://localhost:3000

Quick Start

1. Create Your First Component

  1. Click "New Component" in the sidebar
  2. Enter a name and description
  3. The tool will scaffold a complete component with:
    • manifest.json - Component metadata
    • component.tsx - React component boilerplate
    • mocks/ - Mock data directory with default states

2. Edit Mock Data

  1. Select your component from the sidebar
  2. Use the Mock Data Editor on the right to edit JSON data
  3. Switch between different mock states to test various scenarios
  4. Changes are persisted automatically

3. Preview Your Component

The component renders in real-time with the selected mock data, exactly as it would appear in ChatGPT.

4. Export for Production

  1. Click "Export" in the toolbar
  2. Choose Node.js or Python
  3. Copy the generated MCP server code
  4. Deploy to your production environment

Architecture

The tool is built with modern web technologies and follows the ChatGPT Apps SDK architecture:

┌─────────────────────────────────────────────┐
│           Development Tool (Host)            │
│  ┌────────────┐  ┌──────────────────────┐   │
│  │  Sidebar   │  │   Canvas + Editor    │   │
│  │            │  │                      │   │
│  │ Component  │  │  ┌────────────────┐ │   │
│  │   List     │  │  │  Sandboxed     │ │   │
│  │            │  │  │  iframe        │ │   │
│  │            │  │  │                │ │   │
│  └────────────┘  │  │  window.openai │ │   │
│                  │  │  - toolOutput  │ │   │
│                  │  │  - callTool    │ │   │
│                  │  │  - getState    │ │   │
│                  │  │  - setState    │ │   │
│                  │  └────────────────┘ │   │
│                  └──────────────────────┘   │
└─────────────────────────────────────────────┘

Key Components

  • Component Registry: Auto-discovers components from /components directory
  • Iframe Bridge: Implements window.openai API via PostMessage
  • Widget State Store: IndexedDB-based storage for ephemeral UI state
  • Component Builder: Transforms TSX to runnable JavaScript bundle
  • File System Service: Manages component files via Vite middleware

Creating Components

Component Structure

Each component lives in its own directory:

components/
  my-component/
    ├── manifest.json      # Component metadata
    ├── component.tsx      # React component
    └── mocks/
        ├── default.json   # Default mock state
        ├── empty.json     # Empty state
        └── loaded.json    # Loaded state

manifest.json

{
  "name": "My Component",
  "description": "A custom widget for ChatGPT",
  "version": "1.0.0",
  "entry": "component.tsx",
  "metadata": {
    "prefersBorder": true,
    "csp": {
      "connect_domains": [],
      "resource_domains": []
    }
  }
}

component.tsx

import { useEffect, useState } from 'react';
import { useToolOutput } from '@/hooks/useOpenAiGlobal';

const DEFAULT_OUTPUT = { title: '', items: [] };

export default function MyComponent() {
  const toolOutput = useToolOutput<typeof DEFAULT_OUTPUT>() ?? DEFAULT_OUTPUT;
  const [widgetState, setWidgetState] = useState<any>({});

  // Load widget state (ephemeral UI state)
  useEffect(() => {
    if (window.openai?.getWidgetState) {
      window.openai.getWidgetState(window.openai.widgetId).then((state) => {
        if (state) setWidgetState(state);
      });
    }
  }, []);

  // Save widget state when it changes
  const updateWidgetState = (newState: any) => {
    setWidgetState(newState);
    window.openai?.setWidgetState?.(window.openai.widgetId, newState);
  };

  return (
    <div>
      <h1>{toolOutput.title || 'My Component'}</h1>
      {/* Your component UI */}
    </div>
  );
}

State Management

The tool implements the ChatGPT Apps SDK state management patterns:

1. Business Data (toolOutput)

Source of truth data from the MCP server, available via window.openai.toolOutput and kept in sync through the openai:set_globals event. The toolkit provides a helper hook:

import { useToolOutput } from '@/hooks/useOpenAiGlobal';

const toolOutput = useToolOutput<MyData>();

2. UI State (Ephemeral)

Ephemeral UI state scoped to the widget instance, persisted in IndexedDB:

const [widgetState, setWidgetState] = useState({ selectedId: null });

// Load state
useEffect(() => {
  window.openai.getWidgetState(window.openai.widgetId).then((state) => {
    if (state) setWidgetState(state);
  });
}, []);

// Save state
const updateState = (newState) => {
  setWidgetState(newState);
  window.openai.setWidgetState(window.openai.widgetId, newState);
};

3. Cross-Session State

For preferences that persist across sessions, use tool calls:

const savePreferences = async (prefs) => {
  const result = await window.openai.callTool('save_preferences', { preferences: prefs });
  // Handle result
};

Mock Data

Mock data files are JSON files that represent different states of your component's data:

default.json

{
  "_description": "Default state with sample data",
  "title": "My Component",
  "items": [
    { "id": 1, "name": "Item 1" },
    { "id": 2, "name": "Item 2" }
  ]
}

empty.json

{
  "_description": "Empty state with no data",
  "title": "My Component",
  "items": []
}

The _description field is optional metadata that doesn't appear in window.openai.toolOutput.

Creating New Mock States

  1. Click "+ New State" in the Mock Data Editor
  2. Enter a name (e.g., "error", "loading", "success")
  3. Edit the JSON data
  4. Click "Create"

Exporting Components

Generate MCP Server Code

  1. Click "Export" in the component toolbar

  2. Choose your framework:

    • Node.js / TypeScript: Using @modelcontextprotocol/sdk
    • Python: Using FastMCP
  3. The tool generates complete MCP server code including:

    • Resource registration for your component HTML
    • Tool definition with proper metadata
    • Content Security Policy configuration
    • Widget state management hooks

Deployment Steps

  1. Copy the generated code to your MCP server
  2. Build your component assets
  3. Place built files in your server's public directory
  4. Deploy to production (Heroku, Vercel, Railway, etc.)
  5. Connect from ChatGPT using your server URL

Reference: OpenAI Apps SDK Deployment Guide

Project Structure

/
├── src/
│   ├── components/          # UI components
│   │   ├── Sidebar.tsx      # Component list navigation
│   │   ├── Canvas.tsx       # Main preview area
│   │   ├── ComponentFrame.tsx   # Sandboxed iframe
│   │   ├── MockDataEditor.tsx   # JSON editor
│   │   ├── ComponentCreator.tsx # Component scaffolding
│   │   └── ExportModal.tsx      # Export functionality
│   ├── hooks/               # React hooks
│   │   ├── useComponentLoader.ts
│   │   ├── useMockData.ts
│   │   └── useHotReload.ts
│   ├── services/            # Core services
│   │   ├── fileSystem.ts        # File operations
│   │   ├── componentRegistry.ts # Component discovery
│   │   ├── componentBuilder.ts  # Build pipeline
│   │   ├── iframeBridge.ts      # PostMessage communication
│   │   └── widgetStateStore.ts  # IndexedDB storage
│   ├── store/
│   │   └── appStore.ts      # Zustand global state
│   └── types/
│       ├── component.ts     # Component types
│       └── openai.ts        # window.openai API types
├── components/              # User components (monorepo)
│   └── example-kanban/      # Example component
└── public/
    └── iframe-loader.html   # Iframe bootstrap

API Reference

window.openai API

The tool provides a complete implementation of the ChatGPT Apps SDK window.openai API:

window.openai.toolOutput

const toolOutput: Record<string, any>

The structured data from the MCP server tool response.

window.openai.widgetId

const widgetId: string

Unique identifier for the widget instance.

window.openai.callTool(toolName, args)

async function callTool(
  toolName: string, 
  args: Record<string, any>
): Promise<OpenAIToolCallResult>

Call a tool on the MCP server.

window.openai.getWidgetState(widgetId)

async function getWidgetState<T>(widgetId: string): Promise<T | null>

Get persisted UI state for this widget instance.

window.openai.setWidgetState(widgetId, state)

async function setWidgetState<T>(widgetId: string, state: T): Promise<void>

Save UI state for this widget instance.

window.openai.openExternal(url)

function openExternal(url: string): void

Open an external URL (punchout behavior).

File System Service

import { fileSystem } from '@/services/fileSystem';

// Read file
const content = await fileSystem.readFile('path/to/file.txt');

// Write file
await fileSystem.writeFile('path/to/file.txt', 'content');

// Read JSON
const data = await fileSystem.readJSON('path/to/file.json');

// Write JSON
await fileSystem.writeJSON('path/to/file.json', { key: 'value' });

// List directory
const files = await fileSystem.listDirectory('path/to/dir');

// Create directory
await fileSystem.createDirectory('path/to/dir');

Component Registry Service

import { componentRegistry } from '@/services/componentRegistry';

// Load all components
const registry = await componentRegistry.loadRegistry();

// Get specific component
const component = await componentRegistry.getComponent('component-id');

// Refresh registry
await componentRegistry.refresh();

// Add mock state
await componentRegistry.addMockState('component-id', mockState);

// Update mock state
await componentRegistry.updateMockState('component-id', 'state-name', data);

Development

Running Tests

npm run test

Building for Production

npm run build

Linting

npm run lint

Resources

License

MIT

Contributing

Contributions are welcome! Please read the contributing guidelines before submitting PRs.


Built with ❤️ for the ChatGPT developer community

README mirrored from the source repository 4 months ago. The original is authoritative.

Questions

About Oai App Composer

How do I install Oai App Composer?

Run npx oai-app-composer, then add the server to your MCP client's configuration. Conduid has recorded 0 installs, so the command is known to work with current clients.

Is Oai App Composer safe to use with an AI agent?

Its trust score is 39 out of 100 (low). It passes 0 of 1 static security checks; the failures are listed above. It has no ConduID identity yet, so agent calls to it are not receipted.

Is Oai App Composer still maintained?

The last commit was 10 months ago, with 0 open issues. That's long enough that you should check whether the maintainer is responding to issues before depending on it.