Back to Bloggeneral

How to Build Your First MCP App: A Step-by-Step Tutorial

MCP Apps Team·
·
7 min read

How to Build Your First MCP App: A Step-by-Step Tutorial

Published: February 16, 2026
Reading time: 12 minutes
Tags: #MCP #Tutorial #React #AI-Apps #Claude #ChatGPT


Introduction

Want to build interactive UI components that render directly inside Claude, ChatGPT, and VS Code? MCP Apps make it possible.

MCP (Model Context Protocol) Apps are self-contained, interactive components that AI assistants can render natively. Instead of describing a chart or dashboard with text, you can build a real React component that users interact with inside their AI chat.

In this tutorial, you'll build your first MCP App from scratch—a simple counter component that demonstrates the core concepts. By the end, you'll know how to:

  • Set up an MCP App project
  • Connect it to Claude Desktop
  • Handle user interactions
  • Deploy for others to use

Let's get started.


What You'll Build

A live counter app that Claude can render and control:

  • Displays a counter value
  • Has + and - buttons to adjust it
  • Shows a reset button
  • Updates in real-time as you interact

Simple? Yes. But this foundation scales to complex dashboards, data visualizations, and interactive tools.


Prerequisites

Before starting, ensure you have:

  • Node.js 18+ installed (node --version)
  • Claude Desktop (free version works)
  • Basic knowledge of React and TypeScript
  • A code editor (VS Code recommended)

Step 1: Initialize Your MCP App

The fastest way to start is with the official starter template.

# Clone the official React starter
npx degit github:modelcontextprotocol/ext-apps/basic-react my-counter-app
cd my-counter-app

# Install dependencies
npm install

This gives you a pre-configured project with:

  • React + TypeScript setup
  • MCP protocol handlers
  • Development server with hot reload
  • Production build scripts

Project Structure

my-counter-app/
├── src/
│   ├── App.tsx           # Your main component
│   ├── main.tsx          # Entry point
│   └── mcp-client.ts     # MCP protocol client
├── public/
├── index.html
├── vite.config.ts        # Vite dev server
└── package.json

Key file: src/App.tsx — this is where your UI lives.


Step 2: Build the Counter Component

Open src/App.tsx and replace the contents:

import { useState } from 'react';

function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md">
      <h2 className="text-xl font-bold text-gray-800 mb-4">
        Live Counter
      </h2>
      
      <div className="text-center mb-6">
        <span className="text-5xl font-bold text-blue-600">
          {count}
        </span>
      </div>
      
      <div className="flex gap-2 justify-center">
        <button
          onClick={() => setCount(c => c - 1)}
          className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-lg font-semibold"
        >
          −
        </button>
        
        <button
          onClick={() => setCount(0)}
          className="px-4 py-2 bg-red-100 hover:bg-red-200 text-red-700 rounded-lg font-semibold"
        >
          Reset
        </button>
        
        <button
          onClick={() => setCount(c => c + 1)}
          className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg font-semibold"
        >
          +
        </button>
      </div>
    </div>
  );
}

export default App;

What this does:

  • Creates a centered card with a counter display
  • Three buttons: decrement, reset, increment
  • Uses React state for real-time updates
  • Styled with Tailwind CSS classes

Step 3: Test Locally

Start the development server:

npm run dev

Your app runs at http://localhost:5173. Open it in your browser to verify the counter works.

But here's the magic: MCP Apps aren't just web pages. They're designed to render inside AI assistants.


Step 4: Connect to Claude Desktop

This is where MCP Apps shine. Let's wire your app to Claude.

4.1: Install the MCP CLI

npm install -g @anthropic-ai/mcp-cli

4.2: Register Your App

Create an mcp.json config file in your project root:

{
  "name": "counter-app",
  "version": "1.0.0",
  "entrypoint": "http://localhost:5173",
  "description": "A simple interactive counter",
  "permissions": ["render"]
}

4.3: Add to Claude Desktop

Open Claude Desktop settings (Cmd/Ctrl + ,) and add your MCP server:

{
  "mcpServers": {
    "counter-app": {
      "command": "npx",
      "args": ["mcp-cli", "serve", "/path/to/my-counter-app/mcp.json"]
    }
  }
}

Restart Claude Desktop.


Step 5: Use Your App in Claude

Open a conversation in Claude Desktop and type:

"Show me the counter app"

Claude will recognize the request and render your app directly in the chat:

![Counter app rendering inside Claude chat interface]

Try it:

  • Click the + and − buttons
  • Watch the counter update live
  • Ask Claude: "Set the counter to 42"
  • Claude can call functions in your app to control it programmatically

Step 6: Add Two-Way Communication

Static apps are nice. Interactive apps are powerful. Let's add a function Claude can call.

Update src/App.tsx:

import { useState, useEffect } from 'react';

// Expose functions to MCP
 declare global {
   interface Window {
     mcp?: {
       registerFunction: (name: string, fn: Function) => void;
     };
   }
 }

function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // Register function for Claude to call
    if (window.mcp) {
      window.mcp.registerFunction('setCounter', (value: number) => {
        setCount(value);
        return { success: true, newValue: value };
      });
    }
  }, []);

  return (
    <div className="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md">
      <h2 className="text-xl font-bold text-gray-800 mb-2">
        Live Counter
      </h2>
      <p className="text-sm text-gray-600 mb-4">
        Try saying: "Set counter to 100"
      </p>
      
      <div className="text-center mb-6">
        <span className="text-5xl font-bold text-blue-600">
          {count}
        </span>
      </div>
      
      <div className="flex gap-2 justify-center">
        <button
          onClick={() => setCount(c => c - 1)}
          className="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-lg font-semibold"
        >
          −
        </button>
        
        <button
          onClick={() => setCount(0)}
          className="px-4 py-2 bg-red-100 hover:bg-red-200 text-red-700 rounded-lg font-semibold"
        >
          Reset
        </button>
        
        <button
          onClick={() => setCount(c => c + 1)}
          className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg font-semibold"
        >
          +
        </button>
      </div>
    </div>
  );
}

export default App;

Now Claude can:

  • Render the app visually
  • Call setCounter(100) to set the value
  • Read the current state
  • Combine app control with its reasoning

Step 7: Build for Production

Ready to share your app? Build the production bundle:

npm run build

This creates a dist/ folder with optimized assets.

Deployment Options

OptionBest ForComplexity
VercelQuick sharing, automatic deploysLow
NetlifyGenerous free tier, simple configLow
GitHub PagesOpen source projectsLow
Self-hostedEnterprise, custom domainsMedium

Deploy to Vercel (easiest):

npm i -g vercel
vercel --prod

Update your mcp.json with the production URL:

{
  "name": "counter-app",
  "version": "1.0.0",
  "entrypoint": "https://my-counter-app.vercel.app",
  "description": "A simple interactive counter",
  "permissions": ["render"]
}

Common Issues & Solutions

ProblemCauseSolution
App doesn't render in ClaudeMCP server not runningCheck npx mcp-cli serve is active
CORS errorsMissing headersAdd cors: true to vite.config.ts
Functions not recognizedWindow.mcp not availableWait for DOM load, check registration
Styling looks wrongCSS not loadedEnsure Tailwind classes are correct
Hot reload not workingVite config issueRestart dev server, check port 5173

Next Steps: What to Build

Your counter app proves the concept. Now scale it:

Data Visualization

  • Build charts with Recharts or D3
  • Create interactive dashboards
  • Display real-time metrics

Productivity Tools

  • Form builders with validation
  • Note-taking interfaces
  • Task managers

Creative Apps

  • Image editors with filters
  • Music players
  • Drawing canvases

Developer Tools

  • API testers
  • Database browsers
  • Log viewers

Browse mcp-apps.co for inspiration—see how others have built cohort heatmaps, 3D renderers, PDF viewers, and more.


Conclusion

You now know how to build, test, and deploy MCP Apps. The counter app you created is small, but the pattern scales to complex, production-ready tools.

Key takeaways:

  • MCP Apps are React components that render in AI assistants
  • Two-way communication lets AI control your UI
  • The development loop is fast: code → test in Claude → iterate
  • Deployment is standard web hosting

Ready to build something bigger?

Check out our MCP Apps Directory for 28+ open-source examples you can study, fork, and extend. From data visualization to 3D renderers, there's a starting point for every use case.

Have questions? Join the MCP Community Discord or browse the official documentation.


Resources


Want this tutorial as a video? Let us know on Twitter/X.

M
MCP Apps Team

The team behind MCP Apps, curating the best interactive components for AI assistants.

@mcpappsgithub.com/mcp-apps

Subscribe to our newsletter

Get the latest tutorials, showcases, and MCP Apps updates delivered to your inbox.

No spam. Unsubscribe at any time.