Build production-ready MCP servers with the mcp-use framework and automatic widget registration. Bootstrap with npx create-mcp-use-app and choose from three templates: starter (full-featured), mcp-apps (ChatGPT-optimized), or blank (minimal) Define tools, resources, and prompts using Zod schemas with automatic validation and clear parameter descriptions Automatically register React widgets from the resources/ folder as MCP Tools and Resources with dual-protocol support for MCP Apps and...
Install
Quick install
npx skills add https://github.com/mcp-use/skills/tree/HEAD/skills/mcp-buildernpx skills add mcp-use/skills --skill mcp-builder --agent claude-codenpx skills add mcp-use/skills --skill mcp-builder --agent cursornpx skills add mcp-use/skills --skill mcp-builder --agent codexnpx skills add mcp-use/skills --skill mcp-builder --agent opencodenpx skills add mcp-use/skills --skill mcp-builder --agent github-copilotnpx skills add mcp-use/skills --skill mcp-builder --agent windsurfMore install options
Shorthand — useful for multi-skill repos:
npx skills add mcp-use/skills --skill mcp-builderManual — clone the repo and drop the folder into your agent's skills directory:
git clone https://github.com/mcp-use/skills.gitcp -r skills/skills/mcp-builder ~/.claude/skills/mcp-builder
Build production-ready MCP servers with the mcp-use framework and automatic widget registration. Bootstrap with npx create-mcp-use-app and choose from three templates: starter (full-featured), mcp-apps (ChatGPT-optimized), or blank (minimal) Define tools, resources, and prompts using Zod schemas with automatic validation and clear parameter descriptions Automatically register React widgets from the resources/ folder as MCP Tools and Resources with dual-protocol support for MCP Apps and...
mcp-builderby mcp-use
Build production-ready MCP servers with the mcp-use framework and automatic widget registration. Bootstrap with npx create-mcp-use-app and choose from three templates: starter (full-featured), mcp-apps (ChatGPT-optimized), or blank (minimal) Define tools, resources, and prompts using Zod schemas with automatic validation and clear parameter descriptions Automatically register React widgets from the resources/ folder as MCP Tools and Resources with dual-protocol support for MCP Apps and...npx skills add https://github.com/mcp-use/skills --skill mcp-builderDownload ZIPGitHub
MCP Server Builder
Build production-ready MCP servers with the mcp-use framework. This Skill provides quick-start instructions and best practices for creating MCP servers.
Quick Start
Always bootstrap with npx create-mcp-use-app:
`npx create-mcp-use-app my-mcp-server
cd my-mcp-server
`
Choose template based on needs:
--template starter- Full-featured with all MCP primitives (tools, resources, prompts) + example widgets
--template mcp-apps- Optimized for ChatGPT widgets with product search example
--template blank- Minimal starting point for custom implementation
`# Example: MCP Apps template
npx create-mcp-use-app my-server --template mcp-apps
cd my-server
yarn install
`
Template Details:
- starter: Best for learning - includes all MCP features plus widgets
- mcp-apps: Best for ChatGPT apps - includes product carousel/accordion example
- blank: Best for experts - minimal boilerplate
MCP Apps Structure
Automatic Widget Registration
The mcp-apps and starter templates automatically discover and register React widgets from the resources/ folder:
Single-file widget pattern:
`resources/
└── weather-display.tsx # Widget name becomes "weather-display"
`
Folder-based widget pattern:
`resources/
└── product-search/ # Widget name becomes "product-search"
├── widget.tsx # Entry point (required name!)
├── components/ # Sub-components
├── hooks/ # Custom hooks
├── types.ts
└── constants.ts
`
What happens automatically:
- Server scans
resources/folder at startup
- Finds
.tsxfiles orwidget.tsxin folders
- Extracts
widgetMetadatafrom each component
- Registers as MCP Tool (e.g.,
weather-display)
- Registers as MCP Resource (e.g.,
ui://widget/weather-display.html)
- Builds widget bundles with Vite
No manual registration needed! Just export widgetMetadata and a default component.
Defining Tools
Tools are executable functions that AI models can call:
`import { MCPServer, text, object } from "mcp-use/server";
import { z } from "zod";
const server = new MCPServer({
name: "my-server",
version: "1.0.0",
description: "My MCP server"
});
// Simple tool
server.tool(
{
name: "greet-user",
description: "Greet a user by name",
schema: z.object({
name: z.string().describe("The user's name"),
formal: z.boolean().optional().describe("Use formal greeting")
})
},
async ({ name, formal }) => {
const greeting = formal ? `Good day, ${name}` : `Hey ${name}!`;
return text(greeting);
}
);
`
Key points:
- Use Zod for schema validation
- Add
.describe()to all parameters
- Return appropriate response types (text, object, widget)
Defining Resources
Resources expose data that clients can read:
`import { object, text, markdown } from "mcp-use/server";
// Static resource
server.resource(
{
uri: "config://settings",
name: "Application Settings",
description: "Current configuration",
mimeType: "application/json"
},
async () => {
return object({
theme: "dark",
version: "1.0.0"
});
}
);
// Dynamic resource
server.resource(
{
uri: "stats://current",
name: "Current Stats",
description: "Real-time statistics",
mimeType: "application/json"
},
async () => {
const stats = await getStats();
return object(stats);
}
);
// Markdown resource
server.resource(
{
uri: "docs://guide",
name: "User Guide",
description: "Documentation",
mimeType: "text/markdown"
},
async () => {
return markdown("# Guide\n\nWelcome!");
}
);
`
Response helpers available:
text(string)- Plain text
object(data)- JSON objects
markdown(string)- Markdown content
html(string)- HTML content
image(buffer, mimeType)- Binary images
audio(buffer, mimeType)- Audio files
binary(buffer, mimeType)- Binary data
mix(...contents)- Combine multiple content types
Advanced response examples:
`// Audio response
import { audio } from 'mcp-use/server';
// From base64 data
return audio(base64Data, "audio/wav");
// From file path (async)
return await audio("/path/to/audio.mp3");
// Binary data (PDFs, etc.)
import { binary } from 'mcp-use/server';
return binary(pdfBuffer, "application/pdf");
// Mix multiple content types
import { mix, text, object, resource } from 'mcp-use/server';
return mix(
text("Analysis complete:"),
object({ score: 95, status: "pass" }),
resource("report://analysis-123", text("Full report..."))
);
`
Defining Prompts
Prompts are reusable templates for AI interactions:
`server.prompt(
{
name: "code-review",
description: "Generate a code review template",
schema: z.object({
language: z.string().describe("Programming language"),
focusArea: z.string().optional().describe("Specific focus area")
})
},
async ({ language, focusArea }) => {
const focus = focusArea ? ` with focus on ${focusArea}` : "";
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Please review this ${language} code${focus}.`
}
}
]
};
}
);
`
Testing Locally
Development mode (hot reload):
`yarn dev
`
Production mode:
`yarn build
yarn start
`
Inspector UI:
Access at http://localhost:3000/inspector to test tools, view resources, and try prompts.
Tunneling (test with ChatGPT before deploying):
Option 1 - Auto-tunnel:
`mcp-use start --port 3000 --tunnel
`
Option 2 - Separate tunnel:
`yarn start # Terminal 1
npx @mcp-use/tunnel 3000 # Terminal 2
`
You'll get a public URL like https://happy-cat.local.mcp-use.run/mcp
Tunnel details:
- Expires after 24 hours
- Closes after 1 hour of inactivity
- Rate limit: 10 creations/hour, max 5 active per IP
Learn more: https://mcp-use.com/docs/tunneling
Deployment
Deploy to mcp-use Cloud (recommended):
`# Login first (if not already)
npx mcp-use login
# Deploy
yarn deploy
`
If authentication error:
`npx mcp-use login
yarn deploy
`
After deployment:
- Public URL provided (e.g.,
https://your-server.mcp-use.com/mcp)
- Auto-scaled and monitored
- HTTPS enabled
- Zero-downtime deployments
Best Practices
Tool Design:
- ✅ One tool = one focused capability
- ✅ Descriptive names and descriptions
- ✅ Use
.describe()on all Zod fields
- ✅ Handle errors gracefully
- ✅ Return helpful error messages
Resource Design:
- ✅ Use clear URI schemes (config://, docs://, stats://)
- ✅ Choose appropriate MIME types
- ✅ Use response helpers for cleaner code
- ✅ Make resources dynamic when needed
Prompt Design:
- ✅ Keep prompts reusable
- ✅ Use system messages for context
- ✅ Parameterize with Zod schemas
- ✅ Include clear instructions
Testing:
- ✅ Test with Inspector UI first
- ✅ Use tunneling to test with real clients before deploying
- ✅ Verify all tools, resources, and prompts work as expected
Deployment:
- ✅ Test locally and with tunneling first
- ✅ Run
npx mcp-use loginif deploy fails
- ✅ Version your server semantically
- ✅ Document breaking changes
Widget Support
Automatic Widget Registration
When using the mcp-apps or starter template, widgets in the resources/ folder are automatically registered:
`// resources/weather-display.tsx
import { useWidget, McpUseProvider, type WidgetMetadata } from 'mcp-use/react';
import { z } from 'zod';
const propSchema = z.object({
city: z.string(),
temperature: z.number()
});
// Required: Export widget metadata
export const widgetMetadata: WidgetMetadata = {
description: "Display weather information",
props: propSchema, // Use 'props', not 'schema'!
};
// Required: Export default component
export default function WeatherDisplay() {
const { props, isPending } = useWidget<z.infer<typeof propSchema>>();
// Always handle loading state
if (isPending) return <div>Loading...</div>;
return (
<McpUseProvider autoSize>
<div>
<h2>{props.city}</h2>
<p>{props.temperature}°C</p>
</div>
</McpUseProvider>
);
}
`
Widget automatically becomes available as:
- MCP Tool:
weather-display
- MCP Resource:
ui://widget/weather-display.html
Content Security Policy (CSP)
Control what external resources widgets can access:
`export const widgetMetadata: WidgetMetadata = {
description: "Weather widget",
props: z.object({ city: z.string() }),
metadata: {
csp: {
// APIs to call
connectDomains: ["https://api.weather.com"],
// Static assets to load
resourceDomains: ["https://cdn.weather.com"],
// Iframes to embed
frameDomains: ["https://embed.weather.com"],
// Script directives
scriptDirectives: ["'unsafe-inline'"],
},
},
};
`
Alternatively, set at server level:
`server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
metadata: {
csp: {
connectDomains: ["https://api.example.com"],
resourceDomains: ["https://cdn.example.com"],
},
},
});
`
Dual-Protocol Widget Support
mcp-use supports the MCP Apps standard (SEP-1865) with automatic dual-protocol support:
`import { MCPServer } from 'mcp-use/server';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000', // Required for widgets
});
// Register a dual-protocol widget
server.uiResource({
type: "mcpApps", // Works with BOTH MCP Apps clients AND ChatGPT
name: "weather-display",
htmlTemplate: `<!DOCTYPE html>...`,
metadata: {
csp: { connectDomains: ["https://api.weather.com"] },
prefersBorder: true,
autoResize: true,
},
});
`
What happens automatically:
MCP Apps clients (Claude, Goose) receive: text/html;profile=mcp-app with _meta.ui.
ChatGPT receives: text/html+skybridge with _meta.openai/
- Same widget code works everywhere!
Custom OpenAI Metadata
Need ChatGPT-specific features? Combine both metadata fields:
`server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
// Unified metadata (dual-protocol)
metadata: {
csp: { connectDomains: ["https://api.example.com"] },
prefersBorder: true,
},
// ChatGPT-specific overrides
appsSdkMetadata: {
"openai/widgetDescription": "ChatGPT-specific description",
"openai/customFeature": "some-value", // Any custom OpenAI metadata
},
});
`
Project Structure
`my-mcp-server/
├── resources/ # React widgets (apps-sdk)
│ └── widget.tsx
├── public/ # Static assets
├── index.ts # Server entry point
├── package.json
├── tsconfig.json
└── README.md
`
Common Patterns
Tool with dual-protocol widget:
`import { MCPServer, widget, text } from 'mcp-use/server';
import { z } from 'zod';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000',
});
server.tool(
{
name: "show-data",
description: "Display data with visualization",
schema: z.object({
query: z.string()
}),
widget: {
name: "data-display", // Must exist in resources/
invoking: "Loading...",
invoked: "Data loaded"
}
},
async ({ query }) => {
const data = await fetchData(query);
return widget({
props: { data },
output: text(`Found ${data.length} results`)
});
}
);
`
Resource template (parameterized):
`server.resourceTemplate(
{
uriTemplate: "user://{userId}/profile",
name: "User Profile",
description: "Get user by ID",
mimeType: "application/json"
},
async ({ userId }) => {
const user = await fetchUser(userId);
return object(user);
}
);
`
Error handling:
`server.tool(
{
name: "divide",
schema: z.object({
a: z.number(),
b: z.number()
})
},
async ({ a, b }) => {
if (b === 0) {
return text("Error: Cannot divide by zero");
}
return text(`Result: ${a / b}`);
}
);
`
Detailed Examples
For comprehensive examples and advanced patterns, connect to the mcp-use MCP server which provides:
- Complete example resources for all primitives
- Full working server examples
- Detailed documentation
- Interactive widgets showcase
Learn More
- Documentation: https://docs.mcp-use.com
- MCP Apps Standard: https://docs.mcp-use.com/typescript/server/mcp-apps (dual-protocol guide)
- Templates: https://docs.mcp-use.com/typescript/server/templates (template comparison)
- Widget Guide: https://docs.mcp-use.com/typescript/server/ui-widgets
- Examples: https://github.com/mcp-use/mcp-use/tree/main/examples
- Tunneling Guide: https://mcp-use.com/docs/tunneling
- Discord: https://mcp-use.com/discord
- GitHub: https://github.com/mcp-use/mcp-use
Quick Reference
Commands:
npx create-mcp-use-app my-server- Bootstrap
yarn dev- Development mode
yarn build- Build for production
yarn start- Run production server
mcp-use start --tunnel- Start with tunnel
npx mcp-use login- Authenticate
yarn deploy- Deploy to cloud
Response helpers:
text(str),object(data),markdown(str),html(str)
image(buf, mime),audio(buf, mime),binary(buf, mime)
mix(...)- Combine multiple content types
widget({ props, output })- Return widget with data
Server methods:
server.tool()- Define executable tool
server.resource()- Define static/dynamic resource
server.resourceTemplate()- Define parameterized resource
server.prompt()- Define prompt template
server.uiResource()- Define widget resource
server.listen()- Start server
Widget metadata fields:
description- Widget description
props- Zod schema for widget props
metadata- Unified config (dual-protocol)
metadata.csp- Content Security Policy
appsSdkMetadata- ChatGPT-specific overrides
Available templates:
starter- Full-featured (tools, resources, prompts, widgets)
mcp-apps- ChatGPT-optimized with product example
blank- Minimal boilerplate
More skills from mcp-use
chatgpt-app-builderby mcp-useDEPRECATED: Use mcp-app-builder instead. Build ChatGPT apps with interactive widgets and zero-config React development. This skill is deprecated; migrate to mcp-app-builder for continued support and updates Enables collaborative UI between human users and LLM through shared interactive widgets Provides server handlers, React widget scaffolding, state management, and built-in hooks for tool calls and follow-up messages Covers display modes (inline, fullscreen, picture-in-picture), theming,...mcp-apps-builderby mcp-useMandatory reference guide for building production MCP servers with tools, resources, prompts, and widgets. Covers foundational concepts (Tool, Resource, Prompt, Widget primitives), server architecture, authentication patterns (OAuth, Supabase, custom), and deployment strategies Includes detailed guides for implementing tools, resources, prompts, response formatting, and widget-based UIs with state management and theming Documents common anti-patterns (missing validation, improper error...mcp-builderby mcp-useDEPRECATED: Build MCP servers with tools, resources, prompts, and interactive widgets using mcp-use. This skill is deprecated; use mcp-app-builder instead Supports defining tools, resources, prompts, and interactive React widgets within a single MCP server Includes response helpers for formatting outputs as text, markdown, HTML, images, objects, and custom widgets Provides server composition and proxying to aggregate multiple MCP servers into a unified interfacechatgpt-app-builderby mcp-useBuild ChatGPT apps with interactive widgets using mcp-use and OpenAI Apps SDK. Use when creating ChatGPT apps, building MCP servers with widgets, defining…---
Source: https://github.com/mcp-use/skills/tree/HEAD/skills/mcp-builder
Author: mcp-use
Discovered via: mcpservers.org
SKILL.md source
---
name: mcp-builder
description: Build production-ready MCP servers with the mcp-use framework and automatic widget registration. Bootstrap with npx create-mcp-use-app and choose from three templates: starter (full-featured), mcp-...
---
# mcp-builder
Build production-ready MCP servers with the mcp-use framework and automatic widget registration. Bootstrap with npx create-mcp-use-app and choose from three templates: starter (full-featured), mcp-apps (ChatGPT-optimized), or blank (minimal) Define tools, resources, and prompts using Zod schemas with automatic validation and clear parameter descriptions Automatically register React widgets from the resources/ folder as MCP Tools and Resources with dual-protocol support for MCP Apps and...
# mcp-builderby mcp-use
Build production-ready MCP servers with the mcp-use framework and automatic widget registration. Bootstrap with npx create-mcp-use-app and choose from three templates: starter (full-featured), mcp-apps (ChatGPT-optimized), or blank (minimal) Define tools, resources, and prompts using Zod schemas with automatic validation and clear parameter descriptions Automatically register React widgets from the resources/ folder as MCP Tools and Resources with dual-protocol support for MCP Apps and...
`npx skills add https://github.com/mcp-use/skills --skill mcp-builder`Download ZIPGitHub
## MCP Server Builder
Build production-ready MCP servers with the mcp-use framework. This Skill provides quick-start instructions and best practices for creating MCP servers.
## Quick Start
Always bootstrap with `npx create-mcp-use-app`:
```
`npx create-mcp-use-app my-mcp-server
cd my-mcp-server
`
```
Choose template based on needs:
* `--template starter` - Full-featured with all MCP primitives (tools, resources, prompts) + example widgets
* `--template mcp-apps` - Optimized for ChatGPT widgets with product search example
* `--template blank` - Minimal starting point for custom implementation
```
`# Example: MCP Apps template
npx create-mcp-use-app my-server --template mcp-apps
cd my-server
yarn install
`
```
Template Details:
* starter: Best for learning - includes all MCP features plus widgets
* mcp-apps: Best for ChatGPT apps - includes product carousel/accordion example
* blank: Best for experts - minimal boilerplate
## MCP Apps Structure
### Automatic Widget Registration
The mcp-apps and starter templates automatically discover and register React widgets from the `resources/` folder:
Single-file widget pattern:
```
`resources/
└── weather-display.tsx # Widget name becomes "weather-display"
`
```
Folder-based widget pattern:
```
`resources/
└── product-search/ # Widget name becomes "product-search"
├── widget.tsx # Entry point (required name!)
├── components/ # Sub-components
├── hooks/ # Custom hooks
├── types.ts
└── constants.ts
`
```
What happens automatically:
* Server scans `resources/` folder at startup
* Finds `.tsx` files or `widget.tsx` in folders
* Extracts `widgetMetadata` from each component
* Registers as MCP Tool (e.g., `weather-display`)
* Registers as MCP Resource (e.g., `ui://widget/weather-display.html`)
* Builds widget bundles with Vite
No manual registration needed! Just export `widgetMetadata` and a default component.
## Defining Tools
Tools are executable functions that AI models can call:
```
`import { MCPServer, text, object } from "mcp-use/server";
import { z } from "zod";
const server = new MCPServer({
name: "my-server",
version: "1.0.0",
description: "My MCP server"
});
// Simple tool
server.tool(
{
name: "greet-user",
description: "Greet a user by name",
schema: z.object({
name: z.string().describe("The user's name"),
formal: z.boolean().optional().describe("Use formal greeting")
})
},
async ({ name, formal }) => {
const greeting = formal ? `Good day, ${name}` : `Hey ${name}!`;
return text(greeting);
}
);
`
```
Key points:
* Use Zod for schema validation
* Add `.describe()` to all parameters
* Return appropriate response types (text, object, widget)
## Defining Resources
Resources expose data that clients can read:
```
`import { object, text, markdown } from "mcp-use/server";
// Static resource
server.resource(
{
uri: "config://settings",
name: "Application Settings",
description: "Current configuration",
mimeType: "application/json"
},
async () => {
return object({
theme: "dark",
version: "1.0.0"
});
}
);
// Dynamic resource
server.resource(
{
uri: "stats://current",
name: "Current Stats",
description: "Real-time statistics",
mimeType: "application/json"
},
async () => {
const stats = await getStats();
return object(stats);
}
);
// Markdown resource
server.resource(
{
uri: "docs://guide",
name: "User Guide",
description: "Documentation",
mimeType: "text/markdown"
},
async () => {
return markdown("# Guide\n\nWelcome!");
}
);
`
```
Response helpers available:
* `text(string)` - Plain text
* `object(data)` - JSON objects
* `markdown(string)` - Markdown content
* `html(string)` - HTML content
* `image(buffer, mimeType)` - Binary images
* `audio(buffer, mimeType)` - Audio files
* `binary(buffer, mimeType)` - Binary data
* `mix(...contents)` - Combine multiple content types
Advanced response examples:
```
`// Audio response
import { audio } from 'mcp-use/server';
// From base64 data
return audio(base64Data, "audio/wav");
// From file path (async)
return await audio("/path/to/audio.mp3");
// Binary data (PDFs, etc.)
import { binary } from 'mcp-use/server';
return binary(pdfBuffer, "application/pdf");
// Mix multiple content types
import { mix, text, object, resource } from 'mcp-use/server';
return mix(
text("Analysis complete:"),
object({ score: 95, status: "pass" }),
resource("report://analysis-123", text("Full report..."))
);
`
```
## Defining Prompts
Prompts are reusable templates for AI interactions:
```
`server.prompt(
{
name: "code-review",
description: "Generate a code review template",
schema: z.object({
language: z.string().describe("Programming language"),
focusArea: z.string().optional().describe("Specific focus area")
})
},
async ({ language, focusArea }) => {
const focus = focusArea ? ` with focus on ${focusArea}` : "";
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Please review this ${language} code${focus}.`
}
}
]
};
}
);
`
```
## Testing Locally
Development mode (hot reload):
```
`yarn dev
`
```
Production mode:
```
`yarn build
yarn start
`
```
Inspector UI:
Access at `http://localhost:3000/inspector` to test tools, view resources, and try prompts.
Tunneling (test with ChatGPT before deploying):
Option 1 - Auto-tunnel:
```
`mcp-use start --port 3000 --tunnel
`
```
Option 2 - Separate tunnel:
```
`yarn start # Terminal 1
npx @mcp-use/tunnel 3000 # Terminal 2
`
```
You'll get a public URL like `https://happy-cat.local.mcp-use.run/mcp`
Tunnel details:
* Expires after 24 hours
* Closes after 1 hour of inactivity
* Rate limit: 10 creations/hour, max 5 active per IP
Learn more: https://mcp-use.com/docs/tunneling
## Deployment
Deploy to mcp-use Cloud (recommended):
```
`# Login first (if not already)
npx mcp-use login
# Deploy
yarn deploy
`
```
If authentication error:
```
`npx mcp-use login
yarn deploy
`
```
After deployment:
* Public URL provided (e.g., `https://your-server.mcp-use.com/mcp`)
* Auto-scaled and monitored
* HTTPS enabled
* Zero-downtime deployments
## Best Practices
Tool Design:
* ✅ One tool = one focused capability
* ✅ Descriptive names and descriptions
* ✅ Use `.describe()` on all Zod fields
* ✅ Handle errors gracefully
* ✅ Return helpful error messages
Resource Design:
* ✅ Use clear URI schemes (config://, docs://, stats://)
* ✅ Choose appropriate MIME types
* ✅ Use response helpers for cleaner code
* ✅ Make resources dynamic when needed
Prompt Design:
* ✅ Keep prompts reusable
* ✅ Use system messages for context
* ✅ Parameterize with Zod schemas
* ✅ Include clear instructions
Testing:
* ✅ Test with Inspector UI first
* ✅ Use tunneling to test with real clients before deploying
* ✅ Verify all tools, resources, and prompts work as expected
Deployment:
* ✅ Test locally and with tunneling first
* ✅ Run `npx mcp-use login` if deploy fails
* ✅ Version your server semantically
* ✅ Document breaking changes
## Widget Support
### Automatic Widget Registration
When using the `mcp-apps` or `starter` template, widgets in the `resources/` folder are automatically registered:
```
`// resources/weather-display.tsx
import { useWidget, McpUseProvider, type WidgetMetadata } from 'mcp-use/react';
import { z } from 'zod';
const propSchema = z.object({
city: z.string(),
temperature: z.number()
});
// Required: Export widget metadata
export const widgetMetadata: WidgetMetadata = {
description: "Display weather information",
props: propSchema, // Use 'props', not 'schema'!
};
// Required: Export default component
export default function WeatherDisplay() {
const { props, isPending } = useWidget<z.infer<typeof propSchema>>();
// Always handle loading state
if (isPending) return <div>Loading...</div>;
return (
<McpUseProvider autoSize>
<div>
<h2>{props.city}</h2>
<p>{props.temperature}°C</p>
</div>
</McpUseProvider>
);
}
`
```
Widget automatically becomes available as:
* MCP Tool: `weather-display`
* MCP Resource: `ui://widget/weather-display.html`
### Content Security Policy (CSP)
Control what external resources widgets can access:
```
`export const widgetMetadata: WidgetMetadata = {
description: "Weather widget",
props: z.object({ city: z.string() }),
metadata: {
csp: {
// APIs to call
connectDomains: ["https://api.weather.com"],
// Static assets to load
resourceDomains: ["https://cdn.weather.com"],
// Iframes to embed
frameDomains: ["https://embed.weather.com"],
// Script directives
scriptDirectives: ["'unsafe-inline'"],
},
},
};
`
```
Alternatively, set at server level:
```
`server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
metadata: {
csp: {
connectDomains: ["https://api.example.com"],
resourceDomains: ["https://cdn.example.com"],
},
},
});
`
```
## Dual-Protocol Widget Support
mcp-use supports the MCP Apps standard (SEP-1865) with automatic dual-protocol support:
```
`import { MCPServer } from 'mcp-use/server';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000', // Required for widgets
});
// Register a dual-protocol widget
server.uiResource({
type: "mcpApps", // Works with BOTH MCP Apps clients AND ChatGPT
name: "weather-display",
htmlTemplate: `<!DOCTYPE html>...`,
metadata: {
csp: { connectDomains: ["https://api.weather.com"] },
prefersBorder: true,
autoResize: true,
},
});
`
```
What happens automatically:
* MCP Apps clients (Claude, Goose) receive: `text/html;profile=mcp-app` with `_meta.ui.*`
* ChatGPT receives: `text/html+skybridge` with `_meta.openai/*`
* Same widget code works everywhere!
### Custom OpenAI Metadata
Need ChatGPT-specific features? Combine both metadata fields:
```
`server.uiResource({
type: "mcpApps",
name: "my-widget",
htmlTemplate: `...`,
// Unified metadata (dual-protocol)
metadata: {
csp: { connectDomains: ["https://api.example.com"] },
prefersBorder: true,
},
// ChatGPT-specific overrides
appsSdkMetadata: {
"openai/widgetDescription": "ChatGPT-specific description",
"openai/customFeature": "some-value", // Any custom OpenAI metadata
},
});
`
```
## Project Structure
```
`my-mcp-server/
├── resources/ # React widgets (apps-sdk)
│ └── widget.tsx
├── public/ # Static assets
├── index.ts # Server entry point
├── package.json
├── tsconfig.json
└── README.md
`
```
## Common Patterns
Tool with dual-protocol widget:
```
`import { MCPServer, widget, text } from 'mcp-use/server';
import { z } from 'zod';
const server = new MCPServer({
name: 'my-server',
version: '1.0.0',
baseUrl: process.env.MCP_URL || 'http://localhost:3000',
});
server.tool(
{
name: "show-data",
description: "Display data with visualization",
schema: z.object({
query: z.string()
}),
widget: {
name: "data-display", // Must exist in resources/
invoking: "Loading...",
invoked: "Data loaded"
}
},
async ({ query }) => {
const data = await fetchData(query);
return widget({
props: { data },
output: text(`Found ${data.length} results`)
});
}
);
`
```
Resource template (parameterized):
```
`server.resourceTemplate(
{
uriTemplate: "user://{userId}/profile",
name: "User Profile",
description: "Get user by ID",
mimeType: "application/json"
},
async ({ userId }) => {
const user = await fetchUser(userId);
return object(user);
}
);
`
```
Error handling:
```
`server.tool(
{
name: "divide",
schema: z.object({
a: z.number(),
b: z.number()
})
},
async ({ a, b }) => {
if (b === 0) {
return text("Error: Cannot divide by zero");
}
return text(`Result: ${a / b}`);
}
);
`
```
## Detailed Examples
For comprehensive examples and advanced patterns, connect to the mcp-use MCP server which provides:
* Complete example resources for all primitives
* Full working server examples
* Detailed documentation
* Interactive widgets showcase
## Learn More
* Documentation: https://docs.mcp-use.com
* MCP Apps Standard: https://docs.mcp-use.com/typescript/server/mcp-apps (dual-protocol guide)
* Templates: https://docs.mcp-use.com/typescript/server/templates (template comparison)
* Widget Guide: https://docs.mcp-use.com/typescript/server/ui-widgets
* Examples: https://github.com/mcp-use/mcp-use/tree/main/examples
* Tunneling Guide: https://mcp-use.com/docs/tunneling
* Discord: https://mcp-use.com/discord
* GitHub: https://github.com/mcp-use/mcp-use
## Quick Reference
Commands:
* `npx create-mcp-use-app my-server` - Bootstrap
* `yarn dev` - Development mode
* `yarn build` - Build for production
* `yarn start` - Run production server
* `mcp-use start --tunnel` - Start with tunnel
* `npx mcp-use login` - Authenticate
* `yarn deploy` - Deploy to cloud
Response helpers:
* `text(str)`, `object(data)`, `markdown(str)`, `html(str)`
* `image(buf, mime)`, `audio(buf, mime)`, `binary(buf, mime)`
* `mix(...)` - Combine multiple content types
* `widget({ props, output })` - Return widget with data
Server methods:
* `server.tool()` - Define executable tool
* `server.resource()` - Define static/dynamic resource
* `server.resourceTemplate()` - Define parameterized resource
* `server.prompt()` - Define prompt template
* `server.uiResource()` - Define widget resource
* `server.listen()` - Start server
Widget metadata fields:
* `description` - Widget description
* `props` - Zod schema for widget props
* `metadata` - Unified config (dual-protocol)
* `metadata.csp` - Content Security Policy
* `appsSdkMetadata` - ChatGPT-specific overrides
Available templates:
* `starter` - Full-featured (tools, resources, prompts, widgets)
* `mcp-apps` - ChatGPT-optimized with product example
* `blank` - Minimal boilerplate
## More skills from mcp-use
chatgpt-app-builderby mcp-useDEPRECATED: Use mcp-app-builder instead. Build ChatGPT apps with interactive widgets and zero-config React development. This skill is deprecated; migrate to mcp-app-builder for continued support and updates Enables collaborative UI between human users and LLM through shared interactive widgets Provides server handlers, React widget scaffolding, state management, and built-in hooks for tool calls and follow-up messages Covers display modes (inline, fullscreen, picture-in-picture), theming,...mcp-apps-builderby mcp-useMandatory reference guide for building production MCP servers with tools, resources, prompts, and widgets. Covers foundational concepts (Tool, Resource, Prompt, Widget primitives), server architecture, authentication patterns (OAuth, Supabase, custom), and deployment strategies Includes detailed guides for implementing tools, resources, prompts, response formatting, and widget-based UIs with state management and theming Documents common anti-patterns (missing validation, improper error...mcp-builderby mcp-useDEPRECATED: Build MCP servers with tools, resources, prompts, and interactive widgets using mcp-use. This skill is deprecated; use mcp-app-builder instead Supports defining tools, resources, prompts, and interactive React widgets within a single MCP server Includes response helpers for formatting outputs as text, markdown, HTML, images, objects, and custom widgets Provides server composition and proxying to aggregate multiple MCP servers into a unified interfacechatgpt-app-builderby mcp-useBuild ChatGPT apps with interactive widgets using mcp-use and OpenAI Apps SDK. Use when creating ChatGPT apps, building MCP servers with widgets, defining…
---
**Source**: https://github.com/mcp-use/skills/tree/HEAD/skills/mcp-builder
**Author**: mcp-use
**Discovered via**: mcpservers.org
Related skills 6
running-claude-code-via-litellm-copilot
Use when routing Claude Code through a local LiteLLM proxy to GitHub Copilot, reducing direct Anthropic spend, configuring ANTHROPIC_BASE_URL or ANTHROPIC_MODEL overrides, or troubleshooting Copilot proxy setup failures such as model-not-found, no localhost traffic, or GitHub 401/403 auth errors.
skills-cli
Use when users ask to discover, install, list, check, update, remove, back up, restore, sync, or initialize Agent Skills, mention `bunx skills`, `npx skills`, `skills.sh`, or `skills-lock.json`, ask "find a skill for X", or want help extending agent capabilities with installable skills.
repo-intake-and-plan
Narrow RigorPilot helper for README-first deep learning repo reproduction. Use when the task is specifically to scan a repository, read the README and common project files, extract documented commands, classify inference, evaluation, and training candidates, and return the smallest trustworthy reproduction plan to the main orchestrator. Do not use for environment setup, asset download, command execution, final reporting, paper lookup, or end-to-end orchestration.
image-to-video
Animate any still image on RunComfy — this skill is a smart router that matches the user's intent to the right i2v model in the RunComfy catalog. Picks HappyHorse 1.0 I2V (Arena #1, native audio, identity preservation) for general animations, Wan 2.7 with `audio_url` for custom-voiceover lip-sync, or Seedance 2.0 Pro for multi-modal animation from image + reference video + reference audio. Bundles each model's documented prompting patterns so the caller gets sharper output without burning ite...
video-edit
Edit existing video on RunComfy — this skill is a smart router that matches the user's intent to the right edit model in the RunComfy catalog. Picks Wan 2.7 Edit-Video (general restyle / background swap / packaging swap, identity + motion preservation), Kling 2.6 Pro Motion Control (transfer precise motion from a reference video to a target character), or Lucy Edit Restyle (lightweight identity-stable restyle / outfit swap). Bundles each model's documented prompting patterns so the skill gets...
nano-banana-2
Generate images with Google Nano Banana 2 (Gemini-family flash-tier text-to-image) on RunComfy — bundled with the model's documented prompting patterns so the skill gets sharper output than naive prompting against the same model. Documents Nano Banana 2's strengths (rapid iteration, in-image typography rendering, predictable framing, optional web-grounded context), the resolution-tier pricing, the safety-tolerance dial, and when to route to Nano Banana Pro / GPT Image 2 / Flux 2 / Seedream in...