OpenAI Apps SDK Examples

repository·main·Indexed 25 days ago

https://github.com/openai/openai-apps-sdk-examples

An examples gallery showcasing UI components for the OpenAI Apps SDK and various Model Context Protocol (MCP) servers that expose these components as tools. Includes implementations in Python and Node.js for authenticated servers, the Cards Against AI server, Kitchen Sink Lite, and MCP App Basics, demonstrating concepts like OAuth flow, widget session binding, and real-time updates via SSE.

Tokens
34.8K
Snippets
94
Records
196
Agent score
81%

What's inside openai-apps-sdk-examples

  1. Overview of the Kitchen Sink Lite MCP server (Python)

    main

    The Kitchen Sink Lite MCP server is a Python-based server designed to work with the src/kitchen-sink-lite widget. It provides tools that allow the Apps SDK to hydrate UI components by returning both structured content and the necessary HTML templates.

    It exposes two primary tools:

    • kitchen-sink-show: Returns the widget template and structured content required for the initial render.
    • kitchen-sink-refresh: A lightweight echo tool intended to be called from the widget using window.openai.callTool.

    Both tools include a _meta.openai/outputTemplate field that points to the same widget HTML, enabling the Apps SDK to perform UI hydration.

  2. How the 'Human as Judge' flow works

    main

    When the human is designated as the judge, the game loop is optimized to reduce manual messaging:

    1. After submit-prompt is called, the nextAction is set to play-cpu-answer-cards (instead of human-answer-pending).
    2. The response includes cpuContext, allowing the model to immediately call play-cpu-answer-cards without waiting for a widget message.
    3. All CPU players play their cards, and then the human judges via the widget UI.
    4. The model acts on the tool response directly, so no sendMessage is required from the widget during this phase.
  3. How tool annotations and input schemas work

    main

    When defining tools in MCP Apps:

    • Tool Annotations: Use toolAnnotations to hint to ChatGPT whether to show specific confirmation dialogs. Supported hints include readOnlyHint, destructiveHint, and openWorldHint.
    • Input Schemas: The registerAppTool function accepts Zod shapes directly. The SDK automatically converts these Zod schemas into the required JSON Schema format for the MCP protocol.
  4. How authentication works in the Authenticated MCP server (Python)

    main

    This server demonstrates how to trigger the ChatGPT authentication UI by responding with MCP authorization metadata. It follows the OAuth flow where, if a request is missing a required token, the server returns an mcp/www_authenticate hint (backed by WWW-Authenticate) along with /.well-known/oauth-protected-resource metadata. This metadata informs ChatGPT which authorization server to use to complete the flow.

    The server provides two specific tools with different security requirements:

    1. search_pizza_sf: Uses mixed authentication. It returns the mixed-auth-search widget. Unauthenticated calls return the MCP auth hint to trigger the OAuth flow.
    2. see_past_orders: Requires OAuth. It returns the mixed-auth-past-orders widget containing past orders data.
  5. How real-time updates and stateless transport work

    main

    The architecture for MCP Apps involves:

    • Stateless transport: Functions like createCardsAgainstAiServer create a fresh McpServer per request. Because the transport is stateless, application state (like game progress) must be managed externally (e.g., in a Map) rather than within the MCP session.
    • SSE for real-time updates: A custom Server-Sent Events (SSE) endpoint is used to push game state mutations to the widget in real-time, operating independently of the standard MCP protocol.
  6. Implement MCP tools and resources with FastMCP

    main

    The Pizzaz server uses the FastMCP helper from the official Model Context Protocol SDK. It demonstrates three key patterns for building MCP servers:

    1. UI Resources: Register reusable UI resources that load static HTML bundles.
    2. Widget Association: Associate tools with specific widgets using the _meta.openai/outputTemplate metadata.
    3. Structured Output: Return structured JSON alongside human-readable confirmation text to provide both machine-readable data and user-facing feedback.
  7. Understand the Cards Against AI game flow and rules

    main

    Cards Against AI is a party game using Black Cards (Prompts) with blanks (____) and White Cards (Answers).

    Game Flow:

    1. Start Game: Generates 4 players (1 human + 3 CPU), 28 total answer cards (7 per player), the first prompt, and intro dialog.
    2. Round Structure:
      • Judge reveals prompt.
      • Human player plays their answer card first.
      • CPU players play their answer cards.
      • Judge picks the funniest card (winner gets 1 point).
      • Judge rotates to the next player.
    3. Between Rounds: A new prompt is provided and replacement cards are given to players who played in the previous round.

    Win Condition: The first player to reach 5 "Awesome Points" wins.

  8. Key concepts for building interactive MCP Apps widgets

    main

    The Cards Against AI widget demonstrates several core patterns for building interactive UIs that communicate with both an MCP server and the ChatGPT model:

    • Widget initialization: Use useApp() to establish the MCP Apps postMessage/JSON-RPC connection to the host (ChatGPT).
    • Bootstrapping from tool results: Use the ontoolresult callback (which fires on every tool response) to extract initial state, such as a gameId from a start-game tool call.
    • Real-time state via SSE: Use useStreamingGameState to open an EventSource for live state updates that occur independently of tool calls.
    • Direct tool calls: Use callServerTool to call the MCP server directly. This bypasses the model, providing an instant response without a confirmation dialog.
    • Model-mediated actions: Use sendMessage to send a message into the conversation, allowing the model to decide the next course of action.
    • Hybrid pattern: Use callToolAndNotify to combine both approaches: perform a direct tool call first, then conditionally notify the model based on a nextAction.notifyModel flag.
    • Display modes: Use requestDisplayMode({ mode: "pip" }) to keep the widget visible in picture-in-picture mode while the user continues to chat.
    • Routing signals: Use NextActionHint.notifyModel to signal to the widget whether the model needs to act next or if it should wait for human input.
  9. How tool response structures work in MCP Apps

    main

    In MCP Apps, tool responses use buildGameToolResponse to communicate across three distinct data channels:

    1. _meta.ui.resourceUri: Used for widget binding (linking the response to a specific UI component).
    2. content: Textual content visible to the LLM (ChatGPT).
    3. structuredContent: Data visible to the widget for rendering state.

    This separation allows the model to understand the text while the widget receives the structured data needed for the UI.

  10. How state threading works with widgetSessionId

    main

    This server demonstrates how to thread state across conversation turns by pairing _meta["widgetSessionId"] with window.openai.widgetState.

    The Mechanism

    1. Tool Response: Every call_tool response sets _meta["widgetSessionId"] to a unique cart identifier and returns a structuredContent payload containing the current cart items.
    2. Widget Sync: The widget reads window.openai.widgetState, merges in the latest toolOutput.items, and writes the combined snapshot back to window.openai.widgetState.
    3. State Persistence: Because the host keys widgetState by widgetSessionId, subsequent tool calls for the same session automatically receive the prior state. This allows the model and the UI to stay aligned across turns.
    4. UI Interactions: User interactions in the UI (like incrementing/decrementing quantities) also update the shared widgetState so the next turn reflects those changes.
  11. How resource registration and rules work

    main

    MCP Apps use resources to provide context and UI:

    • Widget HTML: Served as an MCP resource so ChatGPT can render it. CSP (Content Security Policy) metadata is used to control which domains the sandboxed iframe can access.
    • Rules resources: Uses rules:// URIs to provide context documents. These are read by the model to inform its behavior (e.g., game rules) but do not drive the UI.