MCP Server Boilerplate
MCP Server Boilerplate
Production-ready Model Context Protocol server boilerplate with TypeScript, authentication, and multiple transports.
Features
Interactive CLI —
npx mcp-server-boilerplate initto scaffold a new project in secondsTwo transports — stdio (local) and Streamable HTTP (remote)
Authentication — API key, JWT, and OAuth 2.1 with pluggable providers
TOML configuration — human-readable
config.tomlwith env var overrides5 example tools — calculator, echo, fetch-api, file-ops, in-memory database
3 example resources — server config, dynamic key-value store, user directory
2 example prompts — code review, summarization
Full test suite — Vitest with in-memory MCP client/server
Docker ready — multi-stage Dockerfile + docker-compose
CI/CD — GitHub Actions with lint, test, build, and npm publish
Tech Stack
Node.js 24 LTS / TypeScript 6
@modelcontextprotocol/sdkv1.29+Express 5 / Zod / pino / jose / smol-toml
Quick Start
Create a new project (recommended)
npx mcp-server-boilerplate init my-serverThe interactive CLI will ask you to pick:
Transport mode (stdio, HTTP, or both)
Authentication (none, API key, or OAuth 2.1)
Whether to include example tools/resources/prompts
Whether to install dependencies
Or clone the boilerplate directly
git clone https://github.com/jeandbonicel/mcp-server-boilerplate.git
cd mcp-server-boilerplate
npm install
# Run in development (stdio)
npm run dev:stdio
# Run in development (HTTP)
npm run dev:http
# Build for production
npm run build
# Run tests
npm testUsage with Claude Desktop
Add to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/mcp-server-boilerplate/dist/transports/stdio.js"]
}
}
}Usage as Remote Server
# Start with no auth (development)
npm run start:http
# Start with API key auth
MCP_AUTH_MODE=api-key MCP_API_KEYS=my-secret-key npm run start:http
# Start with OAuth 2.1 (demo provider)
MCP_AUTH_MODE=oauth npm run start:httpThen connect from any MCP client to http://localhost:3000/mcp.
Configuration
Configuration uses TOML (config.toml) with environment variable overrides. Edit config.toml directly for most settings. Env vars take precedence when set.
config.toml
[server]
name = "mcp-server"
version = "1.0.0"
[http]
port = 3000
host = "127.0.0.1"
[logging]
level = "info" # fatal | error | warn | info | debug | trace
[auth]
mode = "none" # "none" | "api-key" | "oauth"
# keys = ["my-secret-key-1", "my-secret-key-2"]
# [auth.jwt]
# issuer = "https://auth.example.com"
# audience = "mcp-server"
# secret = "your-shared-secret"
# jwks_uri = "https://auth.example.com/.well-known/jwks.json"
# [auth.oauth]
# issuer_url = "https://auth.example.com"Environment Variable Overrides
Env vars override TOML values when set. Useful for Docker, CI, or secrets.
Variable | TOML key | Default | Description |
|
|
| Server name |
|
|
| Server version |
|
|
| HTTP port |
|
|
| HTTP bind host |
|
|
| Log level |
|
|
| Auth mode |
|
| — | Comma-separated API keys |
|
| — | JWT issuer |
|
| — | JWT audience |
|
| — | JWT shared secret |
|
| — | JWKS endpoint URL |
|
| — | OAuth server URL |
| — |
| Custom path to TOML config |
Authentication
No Auth (default)
Best for local development with stdio transport. No configuration needed.
API Key
Static bearer tokens. In config.toml:
[auth]
mode = "api-key"
keys = ["my-secret-key-1", "my-secret-key-2"]Or via env: MCP_AUTH_MODE=api-key MCP_API_KEYS=key1,key2. Clients send Authorization: Bearer key1 with every request.
OAuth 2.1
Full OAuth flow with browser-based login. Set auth.mode = "oauth" in config.toml or MCP_AUTH_MODE=oauth. The boilerplate includes a demo in-memory OAuth provider that auto-approves all requests.
For production, replace DemoOAuthProvider in src/auth/oauth-provider.ts with your real identity provider, or use JwtVerifier to validate tokens from an external OAuth server (Auth0, Keycloak, etc.):
// In src/transports/http.ts, replace the oauth block:
const verifier = new JwtVerifier({
jwksUri: "https://your-auth-server.com/.well-known/jwks.json",
issuer: "https://your-auth-server.com",
audience: "your-mcp-server",
});
authMiddleware = requireBearerAuth({ verifier });Adding Custom Auth
Create a new file in
src/auth/implementingOAuthTokenVerifier:import type { OAuthTokenVerifier } from "@modelcontextprotocol/sdk/server/auth/provider.js"; import type { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js"; export class MyVerifier implements OAuthTokenVerifier { async verifyAccessToken(token: string): Promise<AuthInfo> { // Your verification logic here return { token, clientId: "...", scopes: ["..."] }; } }Add your auth mode to the config enum in
src/config.tsWire it in
src/transports/http.ts
Adding Your Own Tools
Each tool is a module that exports a register(server) function:
// src/tools/my-tool.ts
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
export function register(server: McpServer): void {
server.registerTool("my-tool", {
title: "My Tool",
description: "Does something useful",
inputSchema: {
input: z.string().describe("The input"),
},
}, async ({ input }) => ({
content: [{ type: "text", text: `Result: ${input}` }],
}));
}Then register it in src/tools/index.ts:
import * as myTool from "./my-tool.js";
export function registerAll(server: McpServer): void {
// ...existing tools...
myTool.register(server);
}Project Structure
config.toml — TOML configuration (human-readable)
src/
cli.ts — Interactive project scaffolder
config.ts — TOML + env loader, Zod-validated
logger.ts — pino structured logging
server.ts — McpServer factory + registration
transports/
stdio.ts — CLI entry point (bin)
http.ts — Express + Streamable HTTP + auth
auth/
api-key-verifier.ts — Bearer token verification
jwt-verifier.ts — JWT/JWKS verification
oauth-provider.ts — Demo OAuth 2.1 server
tools/ — Example tools (echo, calculator, etc.)
resources/ — Example resources (config, items, users)
prompts/ — Example prompts (code-review, summarize)
tests/ — Vitest test suiteDocker
# Build and run
docker compose up --build
# Or manually
docker build -t mcp-server .
docker run -p 3000:3000 --env-file .env mcp-serverScripts
Script | Description |
| Development with stdio (tsx) |
| Development with HTTP (tsx) |
| Compile TypeScript |
| Production stdio |
| Production HTTP |
| Run tests |
| Lint with ESLint |
| Format with Prettier |
| Type check without emitting |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jeandbonicel/mcp-server-boilerplate'
If you have feedback or need assistance with the MCP directory API, please join our Discord server