Skip to main content
Definitions: The UI of a ChatGPT App is an MCP Resource. We will use these terms interchangeably. More on MCP here.
This documentation is available via MCP at https://docs.sunpeak.ai/mcp, use it in your coding agent!

Overview

sunpeak is an npm package that helps you build ChatGPT Apps (MCP Resources) while keeping your MCP server client-agnostic. sunpeak consists of:

The sunpeak Library

  1. Runtime APIs: Strongly typed APIs for interacting with the ChatGPT runtime, architected to support future platforms (Gemini, Claude, etc.).
  2. ChatGPT Simulator: React component replicating ChatGPT’s runtime to test Apps locally and automatically.
  3. MCP Server: Serve Resources with mock data to the real ChatGPT with HMR (no more cache issues or 5-click manual refreshes).

The sunpeak Framework

Next.js for ChatGPT Apps. Using a Review page as an example, sunpeak projects look like:
my-app/
├── src/resources/
│   └── review/
│       ├── review-resource.tsx                 # Review UI component.
│       └── review-resource.json                # Review UI MCP metadata.
├── tests/simulations/
│   └── review/
│       ├── review-{scenario1}-simulation.json  # Mock state for testing.
│       └── review-{scenario2}-simulation.json  # Mock state for testing.
└── package.json
  1. Project Scaffold: Complete development setup with the sunpeak library.
  2. UI Components: Production-ready components following ChatGPT design guidelines and using OpenAI apps-sdk-ui React components.
  3. Convention over configuration:
    • Create UIs by creating a -resource.tsx component file (example) and -resource.json MCP metadata file (example).
    • Create test state (simulations) for local dev, ChatGPT dev, automated testing, and demos by creating a -simulation.json file (example).

The sunpeak CLI

Commands for managing ChatGPT Apps. Includes a client for the sunpeak Resource Repository. The repository helps you & your CI/CD decouple your App from your client-agnostic MCP server while also providing a hosted runtime to collaborate, demo, and share your ChatGPT Apps. Think Docker Hub for ChatGPT Apps:
  1. Tag your app builds with version numbers and environment names (like v1.0.0 and prod)
  2. push built Apps to a central location
  3. pull built Apps to be run in different environments, like your production MCP server.
  4. Share your fully-functional demo Apps with teammates, prospects, and strangers!

Examples

Example sunpeak resource & simulation files for an MCP Resource called “Review”.

Resource Component

React component defining a UI (MCP Resource) in your ChatGPT App.
// src/resources/review/review-resource.tsx
import { Card } from './components';

export function ReviewResource() {
  return (
    <Card
      image="https://cdn.sunpeak.ai/demo/austin1.jpeg"
      imageAlt="Lady Bird Lake"
      header="Lady Bird Lake"
      metadata="⭐ 4.5 • Austin, TX"
      button1={{ children: 'Visit', isPrimary: true, onClick: () => {} }}
      button2={{ children: 'Learn More', onClick: () => {} }}
    >
      Scenic lake perfect for kayaking, paddleboarding, and trails.
    </Card>
  );
}

Resource MCP Metadata

MCP metadata for your UI. Version your resource metadata alongside the resource itself. This is an official MCP Resource object.
// src/resources/review/review-resource.json
{
  "name": "review",
  "title": "Review",
  "description": "Visualize and review a proposed set of changes or actions",
  "mimeType": "text/html+skybridge",
  "_meta": {
    "openai/widgetDomain": "https://sunpeak.ai",
    "openai/widgetCSP": {
      "resource_domains": ["https://cdn.openai.com"]
    }
  }
}

Simulation

Testing a ChatGPT App requires setting a lot of state: state in your backend (accessed via MCP tool), the stored widget runtime, and ChatGPT itself. Simulation files let you define key App states for development, automated testing, and demo purposes. Simulation files contain an official MCP Tool object and an official MCP CallToolResult object. ChatGPT state (like light/dark mode) is not set on the simulation, but rather on the sunpeak ChatGPTSimulator itself via UI, props, or URL params.
// tests/simulations/review/review-diff-simulation.json
{
  "userMessage": "Refactor the authentication module",
  "tool": {
    "name": "review-diff",
    "description": "Show a review dialog for a proposed code diff",
    "inputSchema": { "type": "object", "properties": {}, "additionalProperties": false },
    "title": "Diff Review",
    "annotations": { "readOnlyHint": false },
    "_meta": {
      "openai/toolInvocation/invoking": "Preparing changes",
      "openai/toolInvocation/invoked": "Changes ready for review",
      "openai/widgetAccessible": true,
      "openai/resultCanProduceWidget": true
    }
  },
  "callToolResult": {
    "structuredContent": {
    },
    "_meta": {}
  }
}