Skip to main content
skill CX Codex

mcp-builder · mcp-use — Claude Code skill: what it does, how to install

This skill guides MCP server development with mcp-use, from project scaffolding to local inspection and deployment.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add mcp-use/skills --skill mcp-builder -a claude-code
Open on GitHub

What mcp-builder does

mcp-builder helps create MCP servers with the mcp-use framework. It starts projects through npx create-mcp-use-app, lets you choose starter, mcp-apps, or blank, and covers tools, resources, and prompts. Parameter schemas use zod; server responses can carry text, objects, Markdown, HTML, images, audio, or binary data.

The starter and mcp-apps templates scan resources/ for React widgets. They read each widget’s metadata, expose it as an MCP Tool and MCP Resource, then build the bundle with Vite. Local work uses yarn dev, yarn build, and yarn start, with inspection at http://localhost:3000/inspector. The workflow should begin with npx create-mcp-use-app, since bootstrapping through that generator is part of the skill’s setup.

For ChatGPT testing, the skill covers mcp-use start --port 3000 --tunnel and npx @mcp-use/tunnel 3000. Cloud deployment uses npx mcp-use login followed by yarn deploy.

What it helps with

  • scaffold an MCP server project
  • validate tool inputs with schemas
  • expose application data as resources
  • define reusable AI prompts
  • connect a React widget to an MCP app

Example prompts for the agent

  • Create an MCP server with mcp-use for the data in this project and choose the right template.
  • Add a tool with zod input validation, a JSON resource, and a reusable prompt.
  • Set up local testing, inspect the server at http://localhost:3000/inspector, and prepare its deployment.

How to install mcp-builder

1Skills CLI (Vercel)

npx skills add mcp-use/skills --skill mcp-builder -a claude-code

2Manually: put the files in place

~/.claude/skills/mcp-builder/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/mcp-builder/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about mcp-builder

How do I install mcp-builder in Claude Code?

Run npx skills add mcp-use/skills --skill mcp-builder -a claude-code, then open ~/.claude/skills/mcp-builder/SKILL.md.

What does mcp-builder do?

It guides MCP server work with mcp-use, including tools, resources, prompts, widgets, local inspection, tunneling, and deployment.

Which project templates does it support?

The generator offers starter with MCP primitives and widgets, mcp-apps with a ChatGPT example, and blank for a minimal base.

Source text

SKILL.md · Apache-2.0
---
name: mcp-builder
description: Build Model Context Protocol (MCP) servers with mcp-use framework. Use when creating MCP servers, defining tools/resources/prompts, working with mcp-use, bootstrapping MCP projects, deploying MCP servers, or when user mentions MCP development, MCP tools, MCP resources, or MCP prompts.
---

# 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`:**

```bash
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

```bash
# 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:**
1. Server scans `resources/` folder at startup
2. Finds `.tsx` files or `widget.tsx` in folders
3. Extracts `widgetMetadata` from each component
4. Registers as MCP Tool (e.g., `weather-display`)
5. Registers as MCP Resource (e.g., `ui://widget/weather-display.html`)
6. 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:

```typescript
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:

```typescript
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:**

```typescript
// 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:

```typescript
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):**
```bash
yarn dev
```

**Production mode:**
```bash
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:
```bash
mcp-use start --port 3000 --tunnel
```

Option 2 - Separate tunnel:
```bash
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):**

```bash
# Login first (if not already)
npx mcp-use login

# Deploy
yarn deploy
```

**If authentication error:**
```bash
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:

```tsx
// 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:

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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:**
```typescript
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):**
```typescript
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:**
```typescript
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

© mcp-use · Apache-2.0 · mcp-use/skills

Similar skills

All skills for Backend and APIs →

mcp-builder by other authors comes first.

mcp-builder official anthropics This skill walks through building an MCP server in TypeScript or Python, from reading the protocol spec to writing tests and evaluation questions. 130,949installs mcp-builder jezweb A skill that takes a short brief and turns it into a deployable MCP server on Python with FastMCP, complete with local tests and a pre-deploy checklist. CX Codex +1 1,400installs mcp-builder microsoft Guide for building Model Context Protocol servers in TypeScript, Python, or C# to connect LLMs with custom APIs. 108installs mcp-builder shareAI-lab A skill that walks you through writing MCP servers in Python and TypeScript: tools, resources, testing and config registration. CX Codex +1 ★ 79,238repo stars claude-api official anthropics Reference skill for the Claude API and Anthropic SDK that enforces valid model IDs, adaptive thinking, and streaming. 74,198installs lark-im larksuite This skill lets an agent work with Lark IM messages, chats, files, and interactive cards. Use it when coding tasks need access to team conversations. CX Codex +1 472,900installs lark-event larksuite Listens to Lark/Feishu events and streams them as NDJSON. Use it for bots, message processing, and long-running subscribers. CX Codex +1 466,800installs caveman-discover JuliusBrussee Finds and labels every LLM workflow in your repository so Caveman Cloud breaks down spend by actual job rather than grouping everything into one bucket. CX Codex +1 104,400installs migration JuliusBrussee Enforces reversible, compatibility-safe transitions for schema, data, and API updates. Useful whenever data loss or rollout downtime is unacceptable. CX Codex +1 103,900installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor