Provides an MCP server with interactive React components for ChatGPT Apps, enabling calculator widgets and custom UI components that render inline in ChatGPT with state persistence and bidirectional communication.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ChatGPT Apps MCP Servershow me a calculator"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Server for ChatGPT Apps
A Model Context Protocol (MCP) server with interactive React components for ChatGPT Apps.
What is This?
This project implements an MCP server that works with ChatGPT Apps SDK, featuring:
SSE-based MCP server - HTTP server using Server-Sent Events
Interactive React widgets - Components that render inline in ChatGPT
Calculator example - A fully functional calculator with history
Modern build system - Vite + React + TypeScript + Tailwind CSS
Project Structure
mcp-server/
├── server/
│ └── src/
│ └── server.ts # MCP server with SSE transport
├── web/
│ └── src/
│ ├── calculator/ # Calculator React component
│ ├── types.ts # TypeScript definitions for window.openai
│ ├── use-openai-global.ts # Hook for ChatGPT state
│ ├── use-widget-state.ts # Hook for widget persistence
│ └── index.css # Global styles
├── assets/ # Built components (generated)
├── scripts/
│ └── post-build.js # HTML generation script
├── vite.config.ts # Vite build configuration
├── tailwind.config.ts # Tailwind CSS config
└── package.json # Root dependenciesInstallation
1. Install Dependencies
# Install root dependencies (React, Vite, Tailwind)
npm install
# Install server dependencies (MCP SDK)
cd server && npm install && cd ..2. Build Components
npm run buildThis generates bundled React components in the assets/ directory.
Running the Server
Start the MCP Server
npm run serverThe server will start on http://localhost:8000 with these endpoints:
GET /mcp- SSE streamPOST /mcp/messages?sessionId=...- Message handler
Testing with ChatGPT
Option 1: Local Testing with ngrok
Start the server:
npm run serverExpose with ngrok:
ngrok http 8000Add to ChatGPT:
Go to ChatGPT Settings > Connectors
Add connector with URL:
https://YOUR-ID.ngrok-free.app/mcp
Use in ChatGPT:
Add the connector to your conversation
Ask: "Show me a calculator" or "Open calculator"
The interactive calculator widget will appear!
Option 2: Production Deployment
Set base URL for assets:
export BASE_URL=https://your-cdn.com npm run buildDeploy:
Upload
assets/to a CDN or static hosting (with CORS enabled)Deploy the MCP server with HTTPS
Register in ChatGPT with your server URL
Available Tools
1. Calculator (with React UI)
Tool:
calculatorDescription: Interactive calculator widget with history
Features:
Basic arithmetic operations
Calculation history (last 5 calculations)
Dark/light theme support
State persistence across turns
2. Get Current Time
Tool:
get_current_timeReturns: Current time in ISO format
3. Echo
Tool:
echoReturns: Echoes back your message
Development
Run Dev Server (with hot reload)
npm run devVisit http://localhost:4444 to preview components.
Adding New Components
Create component in
web/src/your-component/index.tsx:
import React from "react";
import { createRoot } from "react-dom/client";
import { useOpenAiGlobal } from "../use-openai-global";
function App() {
const toolOutput = useOpenAiGlobal("toolOutput");
const theme = useOpenAiGlobal("theme");
return (
<div className={theme === "dark" ? "dark" : ""}>
<h1>Your Component</h1>
{/* Your UI */}
</div>
);
}
createRoot(document.getElementById("your-component-root")!).render(<App />);Update Vite config (
vite.config.ts):
input: {
calculator: path.resolve(__dirname, "web/src/calculator/index.tsx"),
"your-component": path.resolve(__dirname, "web/src/your-component/index.tsx"),
},Update post-build script (
scripts/post-build.js):
const components = ["calculator", "your-component"];Add widget to server (
server/src/server.ts):
const widgets: Widget[] = [
// ... existing widgets
{
id: "your-component",
title: "Your Component",
templateUri: "ui://widget/your-component.html",
invoking: "Loading your component",
invoked: "Component ready",
html: readWidgetHtml("your-component"),
responseText: "Component rendered!",
},
];Build and test:
npm run build
npm run serverKey Features
window.openai API
Components have access to:
window.openai.theme // "light" | "dark"
window.openai.displayMode // "inline" | "pip" | "fullscreen"
window.openai.toolOutput // Data from tool call
window.openai.widgetState // Persisted component state
window.openai.callTool(name, args) // Call MCP tools
window.openai.sendFollowUpMessage({ prompt }) // Send to ChatGPTCustom Hooks
// Subscribe to ChatGPT state
const theme = useOpenAiGlobal("theme");
// Persist component state
const [state, setState] = useWidgetState({ count: 0 });Troubleshooting
"Widget assets not found"
Run npm run build to generate component bundles.
CORS errors
Ensure your server has CORS enabled (already configured in server.ts).
Components not rendering
Check browser console for errors
Verify assets are accessible at BASE_URL
Ensure HTML files reference correct JS/CSS paths
Resources
License
ISC
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.