Universal Menu
An interactive decision menu for ChatGPT Apps SDK connectors. Surface contextual choices on every assistant turn—at the start of a reply, at the end, or both. If your agent returns `proposedItems`,
Description
Universal Menu (Apps SDK)
An interactive decision menu for ChatGPT Apps SDK connectors.
Surface contextual choices on every assistant turn—at the start of a reply, at the end, or both.
If your agent returns proposedItems, the widget renders them; otherwise, the server falls back to defaults (no OpenAI autogen).
Features
- Encourages continuous choice-making by rendering a menu on every assistant message.
- Works with pre-computed menus (
proposedItems) or a lightweight default set. - Streamable HTTP transport compatible with Smithery and other MCP clients.
- React widget packaged as an iframe resource (
ui://widget/menu.html).
Requirements
- Node.js 18+ (Node 20+ recommended)
- Smithery account & API key (for
smithery dev/build) - HTTPS endpoint when connecting from ChatGPT (ngrok, Cloudflare Tunnel, etc.)
Setup
npm install
cp .env.example .env # optional: adjust PORT/DEFAULT_TITLE for local HTTP mode
Smithery Quickstart
The project mirrors the Smithery TypeScript quickstart so you can develop and deploy with the official CLI.
- Run the single build pipeline once (bundles the widget, embeds it, compiles TS, and produces the Smithery artifact):
npm run build - Start the widget watcher in a dedicated terminal whenever you iterate on
web/src:
After iterating, re-runnpm run dev:webnpm run buildso the embedded bundle insrc/generatedstays in sync. - In another terminal, run the MCP server through Smithery (requires
SMITHERY_API_KEY):
This establishes an ngrok tunnel to the Smithery Playground. Prompt with “Use the Universal Menu connector and show next steps.”export SMITHERY_API_KEY=... # or set via smithery login npm run dev # internally runs `smithery dev` - When you are ready to ship, run the same production build:
Push the repo to GitHub, open https://smithery.ai/, and press Deploy to ship the server.npm run build
Local HTTP Server (without Smithery)
If you need to self-host or tunnel manually:
npm run build
npm start # runs Express+Streamable HTTP on PORT (default 2091)
# POST http://127.0.0.1:2091/mcp with Accept: application/json, text/event-stream
Installing via Smithery
To install Universal Menu automatically via Smithery:
npx -y @smithery/cli install @arhgap11b/appsdk-universal-menu
Widget Preview
npm run build
nohup python3 -m http.server 3333 --directory web >/tmp/menu.preview.log 2>&1 &
# open http://127.0.0.1:3333/preview.html
Stop the preview server with pkill -f "http.server 3333".
Sample screenshot: docs/menu-preview.png.
Quick Check with MCP Inspector
npx @modelcontextprotocol/inspector@latest
# connect to http://127.0.0.1:2091/mcp and invoke the get_menu tool
ChatGPT Developer Mode Setup
- Start a new chat → “+” near the composer → Developer mode.
- Add the MCP server via HTTPS URL pointing to
/mcp(e.g.ngrok http 2091). - Enable the connector and prompt the model to call
get_menuat the start or end of each reply, e.g. “On every response, use the ‘Universal Menu’ connector to offer available next steps.”
Deployment Notes
- Works on Fly.io, Render, Railway, Cloud Run, Azure Container Apps, or Kubernetes ingresses that support streaming responses.
- For quick demos,
ngrok http 2091gives an HTTPS tunnel likehttps://<subdomain>.ngrok.app/mcp.
Architecture
- Tool
get_menureturns supplied items (or defaults) and should be invoked on every turn to keep options fresh. - Tool
do_actionhandles a chosen option, performs follow-up logic, and returns an updated menu. - React widget (
web/src/Menu.tsx) renders the actions, persists widget state, and uses MCP callbacks (callTool,sendFollowupMessage, etc.).
Environment Variables
PORT— HTTP port fornpm start(default2091)DEFAULT_TITLE— fallback menu title when the caller does not specify one
Project Structure
appsdk-universal-menu/
├─ package.json
├─ smithery.yaml
├─ tsconfig.json
├─ src/
│ ├─ index.ts # Smithery entry point (default export createServer)
│ ├─ server.ts # Local Express transport for npm start
│ └─ menu/
│ └─ generator.ts
├─ web/
│ ├─ preview.html
│ └─ src/
│ ├─ index.tsx
│ └─ Menu.tsx
└─ docs/
└─ menu-preview.png
License
MIT
Reviews (0)
No reviews yet. Be the first to review!
Comments (0)
No comments yet. Be the first to share your thoughts!