mcp-server-blueprint
v1.0.0
Published
Production-ready MCP server template with 10 example tools across 5 modules. Build custom AI-agent tooling for Claude, Cursor, and any MCP client in minutes.
Maintainers
Readme
MCP Server Starter Kit
A production-ready Model Context Protocol server template. Build custom tools for Claude, Cursor, Windsurf, and any MCP-compatible AI client — in minutes, not hours.
What You Get
- 10 working tools across 5 modules, covering the patterns you'll use most
- Modular architecture — each tool module is a separate file, easy to add or remove
- TypeScript + Zod validation with strict types and runtime input checking
- Shared response helpers (
success()/failure()) for consistent output - Error handling patterns that produce structured, AI-readable error messages
- Test suite using Node's built-in test runner (zero extra dependencies)
- Docker support for containerized deployment
- CLAUDE.md template to teach AI assistants about your project
Quick Start
# 1. Install dependencies
npm install
# 2. Build TypeScript
npm run build
# 3. Verify it compiles
npm start
# (Press Ctrl+C — the server runs on stdio, so it waits for input)Connect to Claude Code
Add to .mcp.json in your project root:
{
"mcpServers": {
"my-mcp-server": {
"command": "node",
"args": ["/absolute/path/to/mcp-server-starter/dist/index.js"],
"env": {
"MCP_SERVER_NAME": "my-mcp-server"
}
}
}
}Restart Claude Code. Your tools appear automatically.
Connect to Cursor
Settings > MCP Servers > Add:
{
"my-mcp-server": {
"command": "node",
"args": ["/absolute/path/to/mcp-server-starter/dist/index.js"]
}
}Included Tools
Calculator (src/tools/calculator.ts)
| Tool | Description |
|------|-------------|
| calculate | Math operations: add, subtract, multiply, divide, percentage, power |
Pattern demonstrated: Pure synchronous logic, enum-based dispatch, input validation edge cases.
Web Fetcher (src/tools/web-fetcher.ts)
| Tool | Description |
|------|-------------|
| fetch_url | Fetch any URL — supports GET/POST/PUT/DELETE, custom headers, timeouts |
Pattern demonstrated: Async HTTP with fetch, AbortSignal timeouts, response truncation, JSON auto-detection.
File Manager (src/tools/file-manager.ts)
| Tool | Description |
|------|-------------|
| read_file | Read a file (auto-detects JSON for pretty output) |
| write_file | Write or append to a file (creates parent dirs) |
| list_files | List directory contents (flat or recursive) |
Pattern demonstrated: File I/O with path traversal prevention, security sandboxing via FILE_ROOT, recursive directory walking with limits.
Database Query (src/tools/database-query.ts)
| Tool | Description |
|------|-------------|
| db_list_tables | List all tables with row counts |
| db_describe_table | Show column schema for a table |
| db_query | Execute read-only SELECT queries |
| db_execute | Execute write statements (INSERT/UPDATE/DELETE/CREATE) |
Pattern demonstrated: Embedded SQLite with better-sqlite3, parameterized queries (SQL injection prevention), read/write separation, graceful degradation when the optional dependency is missing.
Note: Database tools require
better-sqlite3(listed as an optional dependency). They return a helpful install message if it's missing — the server still works fine without it.
API Caller (src/tools/api-caller.ts)
| Tool | Description |
|------|-------------|
| api_list | List all configured API endpoints |
| api_call | Call a pre-configured API by name |
Pattern demonstrated: Registry pattern (configure APIs once, call by name), environment-based configuration, auth header injection, URL construction.
Project Structure
mcp-server-starter/
src/
index.ts # Server entry point — imports and registers all tool modules
types.ts # Shared types: ToolResponse, success(), failure()
tools/
calculator.ts # Sync computation pattern
web-fetcher.ts # Async HTTP fetch pattern
file-manager.ts # File I/O with security pattern
database-query.ts # SQLite CRUD pattern
api-caller.ts # REST API registry pattern
test/
tools.test.ts # Tests for all tools
dist/ # Compiled JavaScript (generated by npm run build)
package.json
tsconfig.json
.env.example # Environment variable template
CLAUDE.md # Template for teaching AI about your project
Dockerfile # Containerized deployment
README.md # This fileHow to Add Your Own Tool
Step 1: Create the tool file
Create src/tools/my-tool.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { success, failure } from "../types.js";
export function registerMyTools(server: McpServer): void {
server.tool(
"my_tool_name",
"Clear description of what this tool does (the AI reads this to decide when to call it)",
{
query: z.string().describe("What to search for"),
limit: z.number().optional().default(10).describe("Max results to return"),
},
async ({ query, limit }) => {
try {
// Your logic here
const results = await doSomething(query, limit);
return success({ query, results, count: results.length });
} catch (err) {
return failure(
`Operation failed: ${err instanceof Error ? err.message : String(err)}`,
"Check your input and try again."
);
}
}
);
}Step 2: Register it in index.ts
import { registerMyTools } from "./tools/my-tool.js";
// ... after other registrations:
registerMyTools(server);Step 3: Build and test
npm run build
npm testTool Checklist
When building a new tool, ensure:
- [ ] Tool name is unique and uses
snake_case - [ ] Description is specific enough for the AI to know when to use it
- [ ] Every Zod parameter has
.describe("...")— the AI reads these - [ ] Errors return
failure()with a helpful hint, never throw - [ ] Optional parameters have
.default()values - [ ] Response uses
success()for consistent formatting
Configuration
All configuration happens through environment variables. Copy .env.example to .env and customize:
cp .env.example .envYou can also pass env vars through the MCP client config:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["dist/index.js"],
"env": {
"DATABASE_PATH": "./my-data.db",
"FILE_ROOT": "/home/user/projects",
"API_CONFIG": "[{\"name\":\"github\",\"base_url\":\"https://api.github.com\",\"headers\":{\"Authorization\":\"Bearer ghp_xxxx\"}}]"
}
}
}
}| Variable | Default | Description |
|----------|---------|-------------|
| MCP_SERVER_NAME | my-mcp-server | Server name shown in client UIs |
| FILE_ROOT | Current working directory | Sandbox root for file operations |
| DATABASE_PATH | ./data.db | SQLite database file path |
| API_CONFIG | Public test APIs | JSON array of API endpoint configs |
Development Workflow
# Watch mode — auto-rebuilds on file changes
npm run dev
# In another terminal, restart your MCP client to pick up changes
# Claude Code: Cmd/Ctrl+Shift+P > "MCP: Restart"
# Run tests
npm test
# Clean build artifacts
npm run cleanDeployment Options
Local (most common)
Point your MCP client config at dist/index.js. This is the simplest and most common setup.
Docker
# Build the image
docker build -t my-mcp-server .
# Run with stdin (required for MCP stdio transport)
docker run -i my-mcp-server
# Run with environment variables and a data volume
docker run -i \
-e API_CONFIG='[{"name":"github","base_url":"https://api.github.com","headers":{"Authorization":"Bearer ghp_xxxx"}}]' \
-v ./data:/app/data \
my-mcp-servernpm package
To publish as an installable package (users run via npx):
- Update
nameinpackage.jsonto your package name - Set
"files": ["dist/", "README.md"](already configured) - Run
npm publish - Users add to their MCP config:
"command": "npx", "args": ["-y", "your-package-name"]
How MCP Works (60-Second Version)
- Your server runs as a subprocess spawned by the AI client
- Communication happens over stdio (stdin/stdout) using JSON-RPC 2.0
- At startup, the client calls
tools/listto discover your tools - Each tool has a name, description, and input schema (Zod)
- When the LLM decides to use a tool, the client sends a
tools/callrequest - Your handler runs, and returns structured data (JSON in a text content block)
- The LLM incorporates your response into its answer to the user
No HTTP servers, no WebSockets, no API keys. Just a subprocess that speaks JSON-RPC over stdin/stdout.
Requirements
- Node.js 18+ (for built-in
fetchand test runner) - TypeScript 5.4+
- An MCP-compatible client (Claude Code, Cursor, Windsurf, or any MCP client)
License
MIT
