Docs/tools/developers/mcp scaffold

MCP Server Scaffold

Try it

Generate production-ready Model Context Protocol servers with tools, resources, and prompts for Claude Desktop, Cursor, and Claude Code

Overview

The MCP Server Scaffold generates a complete, ready-to-run Model Context Protocol (MCP) server project. MCP is an open standard created by Anthropic that enables AI models like Claude to interact with external tools, databases, APIs, and file systems.

Key features:

  • 5 starter templates — Weather API, SQL Database, File System, HTTP API, or blank
  • Capability toggles — Tools, Resources, and Prompts with working handler code
  • Runtime choice — Bun or Node.js with correct configurations
  • IDE-style interface — VS Code-like editor with syntax highlighting and ligatures
  • Download setup script — One shell command creates the entire project
  • MCP Inspector integration — Built-in npm script for testing
  • Claude Desktop / Cursor / Claude Code config — Ready-to-paste JSON
Try it

What Is MCP?

The Model Context Protocol is a JSON-RPC-based protocol that standardises how AI applications communicate with external data sources and tools. Think of it as a USB-C for AI — a universal connector between language models and the outside world.

The Problem MCP Solves

Without MCP, every AI integration is custom-built:

  • Copy-paste data into chat windows
  • Write bespoke API wrappers for each AI platform
  • No standardised way to expose capabilities to AI
  • Tools locked to specific AI providers

How MCP Works

ComponentRole
AI Host (Claude Desktop, Cursor, Claude Code)Discovers the MCP server and sends JSON-RPC requests over stdio
MCP Server (your code)Registers capabilities, handles requests, returns results
External Services (APIs, databases, files)The actual data sources your server connects to
  1. Host (Claude Desktop, Cursor, Claude Code) discovers the MCP server
  2. Server registers its capabilities (tools, resources, prompts)
  3. AI model sees available capabilities and decides when to use them
  4. Server executes requests and returns results
  5. AI model incorporates results into its response

MCP Capabilities

MCP servers can expose three types of capabilities:

Tools

Callable functions that the AI can invoke. Tools are the most common capability — they let the AI perform actions like querying databases, calling APIs, or manipulating files.

// Tool definition
{
  name: "query_database",
  description: "Execute a read-only SQL query",
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string", description: "SQL SELECT query" },
    },
    required: ["query"],
  },
}

When AI calls this tool, your server receives the arguments, executes the query, and returns the result as text content.

Resources

URI-addressable data that the AI can read. Resources are like GET endpoints — they expose data without performing actions.

// Resource definition
{
  uri: "my-server://status",
  mimeType: "application/json",
  name: "Server Status",
  description: "Current server status and uptime",
}

Resources are read-only — they provide context to the AI without side effects.

Prompts

Reusable prompt templates with arguments. Prompts help standardise common interactions.

// Prompt definition
{
  name: "summarize",
  description: "Summarize the given text",
  arguments: [
    { name: "text", description: "Text to summarize", required: true },
    { name: "maxLength", description: "Max words", required: false },
  ],
}

Prompts are user-triggered — unlike tools (which the AI decides to call), prompts are explicitly selected by the user.


How to Use the Scaffold

Step 1: Configure

  1. Enter server name — auto-sanitised to kebab-case
  2. Choose runtime — Bun (recommended for speed) or Node.js
  3. Select template — pick a starter that matches your use case
  4. Toggle capabilities — enable Resources and/or Prompts if needed

Step 2: Get the Code

Option A: Download setup script Click "Download setup.sh" and run:

bash setup-my-mcp-server.sh

This creates the project directory, writes all files, and runs bun install or npm install.

Option B: Copy individual files Click the Copy button on each file tab (index.ts, package.json, tsconfig.json) and create the files manually.

Step 3: Test with MCP Inspector

cd my-mcp-server
bun run inspect    # or: npm run inspect

The MCP Inspector opens in your browser and lets you:

  • See all registered tools, resources, and prompts
  • Call tools with test arguments
  • Read resources
  • Verify JSON-RPC communication works correctly

Step 4: Connect to an AI Host

Copy the config from the mcp-config.json tab and add it to your host:

HostConfig File
Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
Cursor.cursor/mcp.json in your project root
Claude Code.mcp.json in your project root

After adding the config, restart the host application. Your tools will appear automatically.


Template Guide

Weather API

A simple example that demonstrates the basic MCP tool pattern — receiving input, processing it, and returning structured data.

Generated tools: get_weather

What to learn from it:

  • Tool definition with typed input schema
  • Argument extraction and validation
  • Returning structured JSON responses
  • Where to plug in real API calls (OpenWeatherMap, etc.)

Extend it by:

  • Adding a real weather API key
  • Supporting forecasts, not just current weather
  • Adding unit conversion logic

SQL Database

A read-only database query tool with SQL injection protection.

Generated tools: query_database, list_tables

What to learn from it:

  • Input validation (rejecting non-SELECT queries)
  • Parameterised queries for safety
  • Multi-tool servers with different schemas
  • Where to plug in your database client (better-sqlite3, pg, mysql2)

Extend it by:

  • Connecting to a real database
  • Adding schema introspection tools
  • Implementing write operations with confirmation

File System

Read, write, and search local files. Useful for building code assistants or document processors.

Generated tools: read_file, write_file

What to learn from it:

  • Async file I/O with Node.js fs/promises
  • Dynamic imports inside tool handlers
  • Path handling and security considerations

Extend it by:

  • Adding glob-based file search
  • Implementing directory listing
  • Adding file type detection
  • Restricting paths to a sandbox directory

HTTP API Wrapper

A generic REST API client tool that lets the AI make HTTP requests.

Generated tools: api_request

What to learn from it:

  • fetch() usage in MCP context
  • Header and body passthrough
  • Response formatting (auto-detecting JSON)
  • Error handling for network failures

Extend it by:

  • Adding authentication (Bearer tokens, API keys)
  • Implementing rate limiting
  • Adding response caching
  • Supporting specific APIs (GitHub, Jira, Slack)

Blank

An empty server with no example tools. For experienced developers who want to start from scratch.


Server Architecture

Project Structure

The scaffold generates three core files:

my-mcp-server/
├── index.ts          # Server logic, tool/resource/prompt handlers
├── package.json      # Dependencies, scripts (start, build, inspect)
└── tsconfig.json     # TypeScript config (ESNext, NodeNext, strict)

Communication Flow

MCP servers communicate over stdio (standard input/output):

Host Process ──stdin──► MCP Server Process
              ◄─stdout──
              ◄─stderr── (logging only)

This means:

  • console.log() sends data to the host (breaks protocol)
  • console.error() is safe for logging (goes to stderr)
  • The server runs as a child process of the host

The Server Object

const server = new Server(
  { name: "my-server", version: "1.0.0" },
  {
    capabilities: {
      tools: {},        // Enable tool discovery
      resources: {},    // Enable resource access
      prompts: {},      // Enable prompt templates
    },
  }
);

Request Handlers

Each capability requires a pair of handlers:

CapabilityList HandlerExecute Handler
ToolsListToolsRequestSchemaCallToolRequestSchema
ResourcesListResourcesRequestSchemaReadResourceRequestSchema
PromptsListPromptsRequestSchemaGetPromptRequestSchema

Advanced Patterns

Error Handling

Return errors gracefully instead of throwing:

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  try {
    // ... tool logic
  } catch (error) {
    return {
      content: [{
        type: "text",
        text: `Error: ${error instanceof Error ? error.message : "Unknown error"}`,
      }],
      isError: true,  // Signals error to the AI
    };
  }
});

Logging

Always use console.error() for logging — console.log() writes to stdout which is the JSON-RPC communication channel:

console.error("Processing request...");     // ✅ Goes to stderr (safe)
console.log("Processing request...");       // ❌ Goes to stdout (breaks protocol)

Environment Variables

Access secrets via environment variables set in the host config:

{
  "mcpServers": {
    "my-server": {
      "command": "bun",
      "args": ["run", "index.ts"],
      "cwd": "/path/to/my-server",
      "env": {
        "DATABASE_URL": "postgresql://...",
        "API_KEY": "sk-..."
      }
    }
  }
}

Multiple Tools

A single server can expose many tools. Organise handlers with a switch or dispatch pattern:

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case "search_users":
      return handleSearchUsers(args);
    case "create_ticket":
      return handleCreateTicket(args);
    case "get_metrics":
      return handleGetMetrics(args);
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});

Typed Arguments

For better type safety, define argument interfaces:

interface SearchArgs {
  query: string;
  limit?: number;
  offset?: number;
}

function handleSearch(args: Record<string, unknown>) {
  const { query, limit = 10, offset = 0 } = args as SearchArgs;
  // ...
}

Testing and Debugging

MCP Inspector

The scaffold includes an inspect script:

bun run inspect    # Opens browser-based testing UI

The Inspector lets you:

  • Browse all registered tools, resources, and prompts
  • Execute tools with custom arguments
  • View JSON-RPC request/response pairs
  • Identify schema mismatches

Manual Testing with stdio

You can test by piping JSON-RPC messages directly:

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | bun run index.ts

Common Issues

ProblemCauseSolution
Server not foundWrong cwd path in configUse absolute path to project directory
Tools not appearingMissing capabilities: { tools: {} }Ensure capabilities object includes tools
Server crashes silentlyconsole.log() in handlerUse console.error() for all logging
Timeout errorsLong-running tool with no responseAdd progress updates or increase timeout
JSON parse errorsInvalid response formatEnsure all content items have type field

Real-World Examples

Internal Knowledge Base

// Search company docs with vector similarity
{
  name: "search_docs",
  description: "Search internal documentation",
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string" },
      department: { type: "string", enum: ["engineering", "hr", "finance"] },
    },
    required: ["query"],
  },
}

Jira Integration

// Create and manage tickets
tools: [
  { name: "create_ticket", description: "Create a Jira ticket" },
  { name: "update_ticket", description: "Update ticket status" },
  { name: "search_tickets", description: "Search Jira with JQL" },
]

Database Admin

// Safe database operations with audit logging
tools: [
  { name: "query", description: "Read-only SQL query" },
  { name: "list_tables", description: "Show all tables" },
  { name: "describe_table", description: "Show table schema" },
  { name: "show_indexes", description: "List table indexes" },
]

Technical Details

SpecificationValue
ProtocolJSON-RPC 2.0 over stdio
SDK@modelcontextprotocol/sdk ^1.12.0
TransportStdioServerTransport
LanguageTypeScript (ESNext, NodeNext)
RuntimeBun or Node.js (via tsx)
StorageNone — runs in-process
NetworkNone by default (tools may make requests)

Package Dependencies

PackagePurpose
@modelcontextprotocol/sdkCore MCP protocol implementation
typescriptType checking and compilation
@types/nodeNode.js type definitions
tsxTypeScript execution for Node.js (not needed for Bun)

Security Considerations

  1. Validate all inputs — Tool arguments come from the AI model, which interprets user requests. Always validate and sanitise.
  2. Principle of least privilege — Only expose capabilities the AI genuinely needs. A database tool shouldn't have write access unless explicitly required.
  3. Sandbox file access — If your server reads/writes files, restrict paths to a specific directory. Never allow arbitrary file system access.
  4. Protect secrets — Use environment variables for API keys and database credentials. Never hardcode them in the server code.
  5. Log carefully — Don't log sensitive data (passwords, tokens, PII) to stderr. Logs may be visible to the host application.
  6. Rate limiting — If your tool calls external APIs, implement rate limiting to prevent abuse or unexpected costs.

Limitations

  • No SSE transport — This scaffold uses stdio transport only. For HTTP-based servers (remote deployment), additional setup is required.
  • Single process — The server runs as a single process. For high-concurrency scenarios, consider a queue-based architecture.
  • No authentication — The scaffold doesn't include authentication. For production deployments, implement auth at the transport layer.
  • Template scope — Generated tool handlers use placeholder logic. You'll need to connect real databases, APIs, and services.

Resources

Official Documentation

Host Configuration Guides

  • Claude Desktop — Settings → Developer → Edit Config
  • Cursor — Settings → Features → MCP Servers
  • Claude Code — Add .mcp.json to project root

Privacy & Security

  • 100% client-side — The scaffold generator runs entirely in your browser
  • No data transmitted — Your server name, code, and configuration never leave your device
  • No tracking — Tool usage is not logged or monitored
  • Download only — Files are generated as browser blobs, not uploaded anywhere
  • Open patterns — All generated code uses standard MCP SDK patterns with no proprietary dependencies