Claude Code Plugins

Community-maintained marketplace

Feedback
13
0

|

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name chatgpt-app-builder
description Build ChatGPT Apps using the Apps SDK and MCP. Use when users want to: (1) Evaluate if their product should become a ChatGPT App (2) Design and implement MCP servers with widgets (3) Test apps locally and in ChatGPT (4) Prepare for App Store submission Triggers: "ChatGPT app", "Apps SDK", "build for ChatGPT", "ChatGPT integration", "MCP server for ChatGPT", "submit to ChatGPT"
license MIT
compatibility Requires Node.js 18+, npm. Network access needed for testing with ngrok. Intended for Claude Code and similar filesystem-based agents.
metadata [object Object]
allowed-tools Bash(npm:*) Bash(npx:*) Bash(node:*) Bash(ngrok:*) Read Write Edit Glob Grep

ChatGPT App Builder

Build production-ready ChatGPT Apps from concept to App Store submission.

Quick Start

New app?           → Start at Phase 1 (Fit Evaluation)
Have app-spec.md?  → Start at Phase 3 (Implementation)
App built?         → Start at Phase 4 (Testing)
Ready to ship?     → Start at Phase 5 (Deployment)

Phase 1: Fit Evaluation

Goal: Determine if a ChatGPT App is right for this product.

Step 1: Gather Context

Ask the user:

  1. What does your product do?
  2. Who are your users?
  3. What API/data does it expose?
  4. What actions can users take?

Step 2: Apply Know/Do/Show Framework

Evaluate against three value pillars (see fit_evaluation.md):

Pillar Question Strong Signal
Know Does it provide data ChatGPT lacks? Live prices, user-specific data, internal metrics
Do Can it take real actions? Create, update, delete, send, schedule
Show Can it display better than text? Lists, charts, maps, media galleries

Minimum requirement: At least one pillar must be strong.

Step 3: Check Blockers

Review fit_evaluation.md for:

  • Prohibited categories (gambling, adult, crypto speculation)
  • Data restrictions (no PCI, PHI, SSN, API keys)
  • Age requirements (13+ audience)

Step 4: Create Golden Prompt Set

Draft prompts for discovery testing:

  • 5 direct prompts: Explicitly name your product ("Show my TaskFlow tasks")
  • 5 indirect prompts: Describe intent without naming ("What should I work on?")
  • 3 negative prompts: Similar but shouldn't trigger ("Create a reminder")

Step 5: Write app-spec.md

Create the specification file:

# [Product Name] ChatGPT App Spec

## Product Context
- Name: [Product name]
- API Base: [API URL]
- Auth: [Bearer token / OAuth / None]

## Value Proposition
- Know: [What data does it provide?]
- Do: [What actions can it take?]
- Show: [What UI is needed?]

## Golden Prompts
### Direct (should trigger)
1. ...

### Indirect (should trigger)
1. ...

### Negative (should NOT trigger)
1. ...

Output: app-spec.md in project directory


Phase 2: App Design

Goal: Define complete technical specification.

Step 1: Define Tools (2-5)

Follow one-job-per-tool principle. See chatgpt_app_best_practices.md.

For each tool, specify:

name: service_verb_noun  # e.g., taskflow_get_tasks
title: Human Readable Name
description: Use this when the user wants to... [be specific]
annotations:
  readOnlyHint: true/false
  destructiveHint: true/false
  openWorldHint: true/false
inputSchema:
  param1: type (required/optional)
  param2: enum["a", "b", "c"]
outputStructure:
  content: [text summary for model]
  structuredContent: {machine-readable data}
  _meta: {widget-only data}

Step 2: Decide Widget Needs

Does the app need custom UI?

Use Case Widget Needed? Component Type
Task list with checkboxes Yes List with actions
Data display only Maybe Could use text
Maps, charts, media Yes Specialized
Multi-step workflow Yes Stateful widget

See widget_development.md for patterns.

Step 3: Plan Authentication

If accessing user-specific data or write operations, auth is required.

See oauth_integration.md for:

  • Well-known endpoint setup
  • Provider-specific guides (Auth0, Stytch)
  • Tool-level securitySchemes

Step 4: Update app-spec.md

Add technical specification:

## Tools

### 1. service_get_items
- **Annotations**: readOnlyHint: true
- **Input**: { status?: "active" | "completed", limit?: number }
- **Output**:
  - content: "Found N items"
  - structuredContent: { items: [...] }
  - _meta: { fullData: [...] }

### 2. service_create_item
- **Annotations**: openWorldHint: true
- **Input**: { title: string, description?: string }
- **Output**: { id, title, created_at }

## Widget
- Type: List with action buttons
- Display modes: inline, fullscreen
- State: { selectedId, filter }

## Authentication
- Required: Yes
- Provider: Auth0
- Scopes: read:items, write:items

Output: Updated app-spec.md with full technical spec


Phase 3: Implementation

Goal: Generate complete working project.

Step 1: Initialize Project

Copy from assets and customize:

# Project structure
myapp-chatgpt/
├── package.json
├── tsconfig.json
├── src/
│   ├── index.ts          # MCP server entry
│   ├── tools/            # Tool handlers
│   ├── widget/           # Widget source
│   └── types/            # TypeScript types
└── scripts/
    └── build-widget.ts   # Widget bundler

See node_chatgpt_app.md for complete patterns.

Step 2: Implement MCP Server

Key components (from assets/server/):

  1. HTTP server with SSE transport (required for ChatGPT Apps):
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";

// GET /mcp - SSE stream connection
// POST /mcp/messages - Message handling
  1. Tool definitions with JSON Schema:
const tools: Tool[] = [{
  name: "service_get_items",
  title: "Get Items",
  description: "Use this when the user wants to see items...",
  inputSchema: { type: "object", properties: {...} },
  _meta: {
    "openai/outputTemplate": "ui://widget/app.html",
    "openai/widgetAccessible": true
  },
  annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false }
}];
  1. Handler registration:
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  // Handle tool calls...
  return {
    content: [{ type: "text", text: `Found ${items.length} items` }],
    structuredContent: { items: items.slice(0, 10) },
    _meta: { fullItems: items }
  };
});

Step 3: Implement Widget

Key patterns (from assets/widget/):

// Access data
const output = window.openai.toolOutput;
const meta = window.openai.toolResponseMetadata;

// Invoke tools
await window.openai.callTool("service_action", { id: "123" });

// Persist state
window.openai.setWidgetState({ selectedId: "123" });

// Layout control
window.openai.notifyIntrinsicHeight(400);
await window.openai.requestDisplayMode({ mode: "fullscreen" });

See widget_development.md for React hooks and patterns.

Step 4: Build

npm install
npm run build  # Compiles server + bundles widget

Step 5: Implementation Checklist

Before moving to testing, verify:

Widget Requirements

  • Uses Apps SDK UI design tokens (see apps_sdk_ui_tokens.md)
  • Implements dark mode with CSS variable architecture
  • Uses LoadingDots pattern for loading states (see widget_ui_patterns.md)
  • Calls notifyIntrinsicHeight() after all DOM changes
  • Includes copy button feedback for copyable content
  • Has show more/less for long lists (>3 items)
  • Works on mobile (test at 375px width)
  • Loading UI guards against re-initialization (see widget_loading_patterns.md)
  • SVG animations use .style property, not setAttribute() (see widget_development.md)

Security Requirements

  • All user input is validated (see security_patterns.md)
  • HTML output uses safe DOM methods (textContent, createElement)
  • External image URLs are proxied with domain whitelist and size limits (200KB)
  • Rate limiting is implemented per session with LRU eviction

Server Requirements

  • /.well-known/openai-apps-challenge endpoint returns challenge token
  • /privacy endpoint returns HTML privacy policy
  • /terms endpoint returns HTML terms of service
  • /mcp endpoint handles SSE connections
  • /health or / returns health check JSON
  • CORS configured for ChatGPT domains only
  • Security headers set on all responses
  • Session routing uses direct lookup by sessionId (CRITICAL - see troubleshooting.md)
  • Response size under 300KB total (remove duplicates, limit images)

Production Readiness (if deploying to production)

Output: Complete project in working directory


Phase 4: Testing

Goal: Verify the app works correctly.

Step 1: Local Testing with MCP Inspector

# Terminal 1: Start server
npm run dev
# Server runs at http://localhost:8000

# Terminal 2: Run inspector
npx @modelcontextprotocol/inspector@latest http://localhost:8000/mcp

Verify:

  • All tools appear in inspector
  • Tool calls return expected structure
  • Widget renders without errors

Step 2: Create HTTPS Tunnel

ngrok http 8000
# Copy the https://xxx.ngrok.app URL

Step 3: Create ChatGPT Connector

  1. Go to ChatGPT → Settings → Connectors
  2. Enable Developer Mode (Settings → Apps & Connectors → Advanced)
  3. Create new connector:
    • Name: Your app name
    • Description: From app-spec.md
    • URL: https://xxx.ngrok.app/mcp
  4. Click Create and verify tools appear

Step 4: Test Golden Prompts

In a new ChatGPT conversation:

  1. Enable your connector (+ button → More → select connector)
  2. Test each golden prompt from app-spec.md
  3. Verify:
    • Direct prompts trigger correctly
    • Indirect prompts trigger correctly
    • Negative prompts do NOT trigger
    • Widget renders properly
    • Actions work (if applicable)

Step 5: Iterate

If issues found:

  1. Fix code
  2. Rebuild: npm run build
  3. Refresh connector in ChatGPT settings
  4. Re-test

See troubleshooting.md for common issues and solutions.

Output: Working app tested in ChatGPT


Phase 5: Deployment & Submission

Goal: Ship to production and App Store.

Step 1: Deploy to Production

Generate deployment configs from assets/deploy/:

Fly.io (recommended):

fly launch
fly deploy

Vercel/Cloudflare: Ensure streaming HTTP support.

Step 2: Update Connector

  1. Replace ngrok URL with production URL
  2. Verify connection in ChatGPT settings

Step 3: Pre-Submission Checklist

See submission_requirements.md:

Required:

  • Organization verified on OpenAI Platform
  • All tools have clear descriptions
  • Annotations correct (readOnlyHint, destructiveHint, openWorldHint)
  • No prohibited content/commerce
  • No restricted data collection
  • Widget renders on mobile
  • Test credentials with sample data prepared

If auth required:

  • Well-known endpoints accessible
  • Test account credentials documented
  • OAuth flow completes successfully

Step 4: Submit

  1. Go to platform.openai.com/apps-manage
  2. Enter MCP server URL
  3. Add OAuth metadata (if applicable)
  4. Complete submission form
  5. Submit for review

Step 5: Post-Submission

  • Monitor email for review status
  • Address any reviewer feedback
  • Click Publish after approval

Output: App live in ChatGPT App Store


External Resources