MCP Server Scaffold
Try itGenerate 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
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
| Component | Role |
|---|---|
| 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 |
- Host (Claude Desktop, Cursor, Claude Code) discovers the MCP server
- Server registers its capabilities (tools, resources, prompts)
- AI model sees available capabilities and decides when to use them
- Server executes requests and returns results
- 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
- Enter server name — auto-sanitised to kebab-case
- Choose runtime — Bun (recommended for speed) or Node.js
- Select template — pick a starter that matches your use case
- 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:
| Host | Config 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:
| Capability | List Handler | Execute Handler |
|---|---|---|
| Tools | ListToolsRequestSchema | CallToolRequestSchema |
| Resources | ListResourcesRequestSchema | ReadResourceRequestSchema |
| Prompts | ListPromptsRequestSchema | GetPromptRequestSchema |
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
| Problem | Cause | Solution |
|---|---|---|
| Server not found | Wrong cwd path in config | Use absolute path to project directory |
| Tools not appearing | Missing capabilities: { tools: {} } | Ensure capabilities object includes tools |
| Server crashes silently | console.log() in handler | Use console.error() for all logging |
| Timeout errors | Long-running tool with no response | Add progress updates or increase timeout |
| JSON parse errors | Invalid response format | Ensure 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
| Specification | Value |
|---|---|
| Protocol | JSON-RPC 2.0 over stdio |
| SDK | @modelcontextprotocol/sdk ^1.12.0 |
| Transport | StdioServerTransport |
| Language | TypeScript (ESNext, NodeNext) |
| Runtime | Bun or Node.js (via tsx) |
| Storage | None — runs in-process |
| Network | None by default (tools may make requests) |
Package Dependencies
| Package | Purpose |
|---|---|
@modelcontextprotocol/sdk | Core MCP protocol implementation |
typescript | Type checking and compilation |
@types/node | Node.js type definitions |
tsx | TypeScript execution for Node.js (not needed for Bun) |
Security Considerations
- Validate all inputs — Tool arguments come from the AI model, which interprets user requests. Always validate and sanitise.
- Principle of least privilege — Only expose capabilities the AI genuinely needs. A database tool shouldn't have write access unless explicitly required.
- Sandbox file access — If your server reads/writes files, restrict paths to a specific directory. Never allow arbitrary file system access.
- Protect secrets — Use environment variables for API keys and database credentials. Never hardcode them in the server code.
- Log carefully — Don't log sensitive data (passwords, tokens, PII) to stderr. Logs may be visible to the host application.
- 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
- MCP Specification — Full protocol specification
- MCP TypeScript SDK — SDK source code and examples
- MCP Inspector — Testing and debugging tool
Host Configuration Guides
- Claude Desktop — Settings → Developer → Edit Config
- Cursor — Settings → Features → MCP Servers
- Claude Code — Add
.mcp.jsonto 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