MCP Apps Server MCP Server

An MCP server template for building ChatGPT-compatible React widgets

README.md

MCP Apps Server

An MCP server template with OpenAI Apps SDK integration for ChatGPT-compatible widgets.

Features

  • šŸ¤– OpenAI Apps SDK: Full compatibility with ChatGPT widgets
  • šŸŽØ Official UI Components: Integrated OpenAI Apps SDK UI components for consistent, accessible widgets
  • šŸ›’ Ecommerce Widgets: Complete ecommerce example with carousel, search, map, and order confirmation
  • šŸ”„ Automatic Registration: Widgets auto-register from resources/ folder
  • šŸ“¦ Props Schema: Zod schema validation for widget props
  • šŸŒ™ Theme Support: Dark/light theme detection via useWidget hook
  • šŸ› ļø TypeScript: Complete type safety
  • šŸ”§ Widget Capabilities: Full support for callTool, sendFollowUpMessage, and persistent state

What's New: Apps SDK Integration

This template demonstrates how to build ChatGPT-compatible widgets using OpenAI's Apps SDK:

import { useWidget } from 'mcp-use/react';

const MyWidget: React.FC = () => {
  const { props, theme } = useWidget<MyProps>();

  // props contains validated inputs from OpenAI
  // theme is 'dark' or 'light' based on ChatGPT setting
}

Getting Started

Development

# Install dependencies
npm install

# Start development server
npm run dev

This starts:

  • MCP server on port 3000
  • Widget serving at /mcp-use/widgets/*
  • Inspector UI at /inspector

Production

# Build the server and widgets
npm run build

# Run the built server
npm start

Project Structure

mcp-apps/
ā”œā”€ā”€ resources/                          # React widget components
│   ā”œā”€ā”€ display-weather.tsx              # Weather widget example
│   ā”œā”€ā”€ ecommerce-carousel.tsx           # Ecommerce product carousel
│   ā”œā”€ā”€ product-search-result.tsx        # Product search with filters
│   ā”œā”€ā”€ stores-locations-map.tsx         # Store locations map
│   └── order-confirmation.tsx           # Order confirmation widget
ā”œā”€ā”€ index.ts                             # Server entry point (includes brand info tool)
ā”œā”€ā”€ package.json
ā”œā”€ā”€ tsconfig.json
└── README.md

How Automatic Registration Works

All React components in the resources/ folder are automatically registered as MCP tools and resources when they export widgetMetadata:

import { z } from 'zod';
import type { WidgetMetadata } from 'mcp-use/react';

const propSchema = z.object({
  city: z.string().describe('The city name'),
  temperature: z.number().describe('Temperature in Celsius'),
});

export const widgetMetadata: WidgetMetadata = {
  description: 'My widget description',
  props: propSchema,
};

const MyWidget: React.FC = () => {
  const { props } = useWidget<z.infer<typeof propSchema>>();
  // Your widget implementation
};

export default MyWidget;

This automatically creates:

  • Tool: display-weather - Accepts parameters via OpenAI
  • Resource: ui://widget/display-weather - Static access

Building Widgets with Apps SDK

Using the `useWidget` Hook

import { useWidget } from 'mcp-use/react';

interface MyProps {
  title: string;
  count: number;
}

const MyWidget: React.FC = () => {
  const { props, theme, isPending } = useWidget<MyProps>();

  // IMPORTANT: Widgets render before tool execution completes
  // Always check isPending to handle the loading state
  if (isPending) {
    return Loading...;
  }

  // Now props are safely available
  // props are validated and typed based on your schema
  // theme is automatically set by ChatGPT

  return (
    
      <h1>{props.title}</h1>
      Count: {props.count}
    
  );
};

Note: Widgets render before the tool execution completes. On first render, props will be empty {} and isPending will be true. Always check isPending before accessing props. See the Widget Lifecycle documentation for more details.

Defining Widget Metadata

Use Zod schemas to define widget inputs:

import { z } from 'zod';
import type { WidgetMetadata } from 'mcp-use/react';

const propSchema = z.object({
  name: z.string().describe('Person name'),
  age: z.number().min(0).max(120).describe('Age in years'),
  email: z.string().email().describe('Email address'),
});

export const widgetMetadata: WidgetMetadata = {
  description: 'Display user information',
  props: propSchema,
};

Theme Support

Automatically adapt to ChatGP

Tools 1

display-weatherDisplays weather information based on city and temperature

Try it

→Show me the weather widget for London at 15 degrees.
→Display the ecommerce product carousel for the latest items.
→Show the store locations map for my current area.
→Display the order confirmation widget for order #12345.

Frequently Asked Questions

What are the key features of MCP Apps Server?

Full compatibility with ChatGPT widgets using OpenAI Apps SDK. Automatic registration of React components as MCP tools and resources. Built-in ecommerce widgets including carousel, search, and maps. Zod schema validation for widget props. Automatic dark/light theme detection via useWidget hook.

What can I use MCP Apps Server for?

Building interactive UI components for ChatGPT interfaces. Creating ecommerce storefronts with product search and carousels. Developing location-aware widgets like store maps. Standardizing widget development with TypeScript and Zod validation.

How do I install MCP Apps Server?

Install MCP Apps Server by running: npm install && npm run build

What MCP clients work with MCP Apps Server?

MCP Apps Server works with any MCP-compatible client including Claude Desktop, Claude Code, Cursor, and other editors with MCP support.

Turn this server into reusable context

Keep MCP Apps Server docs, env vars, and workflow notes in Conare so your agent carries them across sessions.

Open Conare