subagentic.ai
How to scaffold an mcp-use TypeScript MCP server

How-Tos

How to scaffold an mcp-use TypeScript MCP server

Scaffold an mcp-use TypeScript MCP server, run the Inspector, and add a Zod-typed tool with a React view for ChatGPT or Claude.

Searcher → Analyst → Writer → Editor · subagentic-20260926-0800

mcpmcp-usetypescriptmcp-appshow-to

mcp-use is a typed TypeScript path for MCP servers and for ChatGPT and Claude MCP Apps. Follow this walkthrough to scaffold a project from the official docs, run it locally, verify it with the Inspector, then add a Zod-typed tool bound to a React view.

Prerequisites

Install Node.js 22.22.2 or higher, plus npm, pnpm, or Bun. The quickstart assumes basic familiarity with React and TypeScript. These steps cover the mcp-use Server SDK, not the Agent or Client getting-started paths.

Scaffold the project

The fastest way to create a new MCP server project is create-mcp-use-app:

npx create-mcp-use-app

The CLI asks four questions. The first needs an answer; the rest have a default you accept by pressing Enter.

  1. What is your project name? Sets the folder name and the server’s name. Enter . to scaffold into the current directory.
  2. Select a template: Pick one of the three below with the arrow keys. mcp-apps is highlighted by default.
  3. Install AI coding skills for Cursor, Claude Code, and Codex? Adds mcp-use skills so your coding agent understands the framework. Defaults to yes.
  4. Install dependencies? Installs with the package manager you ran the command with (npm, pnpm, or Bun). Defaults to yes.
Template What you get
mcp-apps (default) A server plus an example React widget that renders in ChatGPT and Claude.
mcp-server A server with an example tool and prompt.
blank A minimal server with no examples.

To skip the questions, pass the name and template as arguments:

npx create-mcp-use-app my-server --template mcp-apps

The installation page shows a named folder without the template flag:

npx create-mcp-use-app my-mcp-server
cd my-mcp-server
npm run dev

pnpm and Bun equivalents are pnpm create mcp-use-app my-mcp-server then pnpm dev, and bunx create-mcp-use-app my-mcp-server then bun run dev.

That command creates a directory, initializes a TypeScript project with mcp-use configured, sets up a basic MCP server template with example tools, and can optionally install dependencies and skills for agent support. You can also install the library with npm install mcp-use (or pnpm add mcp-use / bun add mcp-use) and construct an MCPServer yourself; scaffolding is the path this article follows.

Start the dev server and Inspector

If you used the quickstart name my-server:

cd my-server
npm run dev

npm run dev runs mcp-use dev, which:

  • serves the MCP endpoint at http://localhost:3000/mcp
  • opens the Inspector at http://localhost:3000/mcp/inspector
  • hot-reloads tools, resources, prompts, and views as you edit; the next stateless request uses the refreshed server

Open the Inspector, go to the Tools tab, and run a tool to see it respond. With the mcp-apps template, calling search-tools renders the widget inline.

You can also test the running server from the terminal with the mcp-use client CLI. This is the quickest path for scripts and coding agents, which cannot drive the Inspector’s UI:

npx mcp-use client connect local http://localhost:3000/mcp
npx mcp-use client local tools list

The first command saves the server under the name local; later commands address it by that name.

For a from-scratch install, run mcp-use dev for the local Inspector. To mount it on a production build for internal testing, use mcp-use start --with-inspector.

Explore the project

my-server/
├── views/                      # React MCP App views, auto-discovered
│   └── greeting-card/
│       └── view.tsx
├── public/                     # Static assets (icons, images)
├── index.ts                    # Server entry: tools, resources, prompts
├── mcp-env.d.ts                # Managed server-to-view typing bridge
├── package.json
└── tsconfig.json

index.ts is where you register your tools, resources, and prompts. Each folder under views/ is an MCP App view; its folder name matches the view.name a tool references.

Customize server metadata

The generated project includes pre-configured server metadata visible in MCP Inspector and MCP clients: name and title (both set to your project name), instructions for model-facing guidance, icons in public/, a website URL, and a favicon. These appear in the Inspector UI (server dropdown and “View server info” modal), in MCP clients that support server metadata, and in ChatGPT when using your server as an app.

Open index.ts to customize:

const server = new MCPServer({
  name: "my-project", // Set by create-mcp-use-app
  title: "My Custom Title", // display name - shown in clients
  version: "1.0.0",
  description: "My awesome server",
  instructions:
    "Use lookup tools before write tools; ask for confirmation before changes.",
  websiteUrl: "https://my-site.com", // Your website or docs
  favicon: "favicon.ico", // Already in public/ folder
});

The installation docs also show how to attach custom icons from public/. Icon paths are resolved from public/ against the incoming request origin. With basePath: "/mcp", for example, icon.svg is served from http://localhost:3000/mcp/_mcp-use/public/icon.svg. In hosted environments, MCP_URL sets the public origin while basePath continues to own the endpoint path.

Add a Zod-typed tool

Open index.ts and add a tool to the existing server:

export const greetingCard = server.tool(
  {
    name: "greeting-card",
    description: "Create a greeting card for someone",
    inputSchema: z.object({
      name: z.string().describe("Who to greet"),
      message: z.string().describe("The message inside the card"),
    }),
    outputSchema: z.object({
      name: z.string(),
      message: z.string(),
    }),
    view: {
      name: "greeting-card",
      description: "An interactive greeting card",
    },
  },
  async ({ name, message }) => ({
    content: [{ type: "text", text: `Made a card for ${name}` }],
    structuredContent: { name, message },
  }),
);

Keep statically declared tools in exported constants. The generated mcp-env.d.ts uses those exported tool refs to type calls from your widget, so TypeScript will flag a useCallTool("greeting-card") call when its matching ref is not exported.

Run npm run typecheck after editing tools or views. The scaffolded script refreshes mcp-env.d.ts for the server entry, then runs the project’s own TypeScript compiler with --noEmit.

The tool’s view.name points at a folder under views/. Its validated structuredContent becomes the view’s typed tool output.

Add a React view

Create views/greeting-card/view.tsx. The folder name must match the tool’s view.name:

import { ThemeProvider, useToolContext } from "mcp-use/react";

interface GreetingCardProps {
  name: string;
  message: string;
}

export default function GreetingCard() {
  const view = useToolContext<"greeting-card">();

  if (view.status === "pending") return <p>Designing the card…</p>;
  if (view.status === "error") return <p>{view.error.message}</p>;

  const card = view.toolOutput as GreetingCardProps;

  return (
    <ThemeProvider>
      <div style={{ padding: "2rem", textAlign: "center" }}>
        <h2>Hello, {card.name}!</h2>
        <p>{card.message}</p>
      </div>
    </ThemeProvider>
  );
}

Save the file. The dev server discovers the new view and hot-reloads it. Call greeting-card with { name: "Ada", message: "Welcome aboard!" }; the card renders inline.

Deploy is a later step

When you are ready to share your server, run:

npm run deploy

This runs mcp-use deploy, which builds your server and deploys it to Manufact Cloud with a public MCP URL, logs, and metrics. The first run walks you through logging in and connecting your project. Treat deploy as a later step after local Inspector and widget work.

Call greeting-card from the Inspector Tools tab, then run npm run typecheck. After the card renders inline, read the official mcp-use TypeScript quickstart and installation pages for tools, resources, prompts, and MCP Apps.

Sources