---
name: chatgpt-app-builder-a4f765e34263
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:
  author: Bayram Annakov (onsa.ai)
  version: "1.0.0"
  category: development
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](references/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](references/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:

```markdown
# [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](references/chatgpt_app_best_practices.md).

For each tool, specify:
```yaml
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](references/widget_development.md) for patterns.

### Step 3: Plan Authentication
If accessing user-specific data or write operations, auth is required.

See [oauth_integration.md](references/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:

```markdown
## 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:

```bash
# 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](references/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):
```typescript
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
```

2. **Tool definitions with JSON Schema**:
```typescript
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 }
}];
```

3. **Handler registration**:
```typescript
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/):

```typescript
// 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](references/widget_development.md) for React hooks and patterns.

### Step 4: Build
```bash
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](references/apps_sdk_ui_tokens.md))
- [ ] Implements dark mode with CSS variable architecture
- [ ] Uses LoadingDots pattern for loading states (see [widget_ui_patterns.md](references/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](references/widget_loading_patterns.md))
- [ ] SVG animations use `.style` property, not `setAttribute()` (see [widget_development.md](references/widget_development.md#common-widget-gotchas))

#### Security Requirements
- [ ] All user input is validated (see [security_patterns.md](references/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](references/troubleshooting.md#critical-multi-connection-session-routing))
- [ ] Response size under 300KB total (remove duplicates, limit images)

#### Production Readiness (if deploying to production)
- [ ] OAuth tokens stored in database, not in-memory (see [oauth_integration.md](references/oauth_integration.md#production-considerations-token-storage))
- [ ] Mutation tools include idempotency checks (see [chatgpt_app_best_practices.md](references/chatgpt_app_best_practices.md#idempotency-keys))
- [ ] Disambiguation pattern for multi-match scenarios (see [chatgpt_app_best_practices.md](references/chatgpt_app_best_practices.md#disambiguation-pattern))
- [ ] Confirmation receipts for all mutations (see [chatgpt_app_best_practices.md](references/chatgpt_app_best_practices.md#confirmation-receipts))

**Output**: Complete project in working directory

---

## Phase 4: Testing

**Goal**: Verify the app works correctly.

### Step 1: Local Testing with MCP Inspector
```bash
# 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
```bash
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](references/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):
```bash
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](references/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

- [OpenAI Apps SDK Docs](https://developers.openai.com/apps-sdk)
- [Apps SDK Examples](https://github.com/openai/openai-apps-sdk-examples)
- [Apps SDK UI Kit](https://openai.github.io/apps-sdk-ui)
- [MCP Protocol Spec](https://modelcontextprotocol.io)


---
Source attribution: Bayram Annakov (onsa.ai)
Original project: https://github.com/aiskillstore/marketplace/blob/3012aed76b16bfe12407f2d24b1cf11ac56eb7bb/skills/bayramannakov/chatgpt-app-builder/SKILL.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Mega AI Hub.

## Upstream license notice

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



# Mega AI Hub resource metadata

Creator / publisher: Bayram Annakov (onsa.ai)
Original project: https://github.com/aiskillstore/marketplace/blob/3012aed76b16bfe12407f2d24b1cf11ac56eb7bb/skills/bayramannakov/chatgpt-app-builder/SKILL.md
Attribution basis: Source repository record

Fields of work: Product Management, Development & Engineering, Design
Roles: Product Manager, Growth Product Manager, Frontend Developer, Backend Developer, UX Designer
Specialties: API, Backend
Tools: Ngrok, Npm, Node
Country applicability: Country not specified
Classification basis: Source category, role and specialization labels
Instruction SHA-256: 713c23281736e8619bcfb3460baf57a4d123a11ce7ad86948c7691bc6933d200
