mcp-server-template
A production-ready MCP server template with typed tools, schema validation, tests, and Docker support, including example tools for text stats, weather, and notes.
README
MCP Server Template
A production-ready starting point for a Model Context Protocol server: typed tools with schema-validated inputs, real tests, a multi-stage Docker image, and a CI pipeline — the boring parts done right so the next MCP server starts at mile 10.
It ships with three example tools that cover the shapes you'll actually build: a pure tool, a networked tool, and a stateful tool.
Architecture
flowchart TD
Client["MCP client<br/>Claude Desktop · IDE · agent"] -->|JSON-RPC over stdio| Entry["index.ts<br/>load env · connect transport"]
Entry --> Server["server.ts<br/>buildServer()"]
Server --> Tools["tools/*<br/>name + zod schema + handler"]
Tools --> Lib["lib/*<br/>logger · result · http · env"]
Construction is kept separate from transport, so the same server runs over stdio in production and over an in-memory transport in tests — no mocks. Full write-up in ARCHITECTURE.md.
Enterprise architecture
| Pillar | How the template applies it |
|---|---|
| Resilience | a thrown tool handler is contained per call (returned as an error result) — one bad call never crashes the server |
| Observability | structured, leveled logging to stderr (stdout is reserved for the MCP protocol) |
| Reproducibility | committed lockfile + Node pinned via .nvmrc, and tests that run the real server over an in-memory transport — no mocks |
Features
- 🧩 Modular tools — one file per tool group, registered in one place
- ✅ Schema-validated inputs via zod — bad calls fail fast
- 🧪 Real tests — an in-memory client/server harness, no mocks (
node:test) - 🐳 Multi-stage Docker image that runs as a non-root user
- 🤖 CI — format, type-check, test, build, and a Docker build, on every push/PR
- 🔇 Protocol-safe logging — stdout is reserved for MCP; logs go to stderr
- 🔑 No secrets in the repo — config via env, with a
.env.example
Quickstart
nvm use # or Node 20+
npm install
npm run dev # run the server over stdio (Ctrl-C to stop)
npm test # run the test suite
npm run build # compile to dist/
Example tools
| Tool | Kind | What it shows |
|---|---|---|
text_stats |
pure | Validated input → structured output, no side effects |
get_weather |
networked | External API (Open-Meteo, no key), timeouts, error handling |
note_set / note_get / note_list / note_delete |
stateful | File-backed persistence shared across tools |
Adding your own tool
This is the whole point of the template — it's a three-step change:
-
Create
src/tools/my-thing.ts:import { z } from "zod"; import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { text } from "../lib/result.js"; export function registerMyThingTools(server: McpServer): void { server.tool( "greet", "Say hello to someone.", { name: z.string().describe("Who to greet") }, async ({ name }) => text(`Hello, ${name}!`), ); } -
Register it in
src/tools/index.ts(one line). -
Done — transport, validation, error handling, tests, and Docker need no changes.
Connect it to a client
Build first (npm run build), then point your MCP client at dist/index.js.
Example config (e.g. Claude Desktop) in examples/mcp-config.json:
{
"mcpServers": {
"template": {
"command": "node",
"args": ["/absolute/path/to/mcp-server-template/dist/index.js"]
}
}
}
Testing
npm test builds the real server, connects a real MCP client over an in-memory
transport, and exercises tools end to end (schema validation included). Network
tools aren't hit in CI — tests stay fast and deterministic.
Docker
docker build -t mcp-server-template .
docker run --rm -i mcp-server-template # -i: MCP talks over stdio
Project structure
src/
├── index.ts # entrypoint: load env, build server, connect stdio
├── server.ts # buildServer() — construction, transport-agnostic
├── lib/
│ ├── logger.ts # stderr-only logging
│ ├── result.ts # text() / errorResult() content helpers
│ ├── http.ts # fetchJson() with timeout
│ └── env.ts # minimal .env loader
└── tools/
├── index.ts # registerAllTools() — add new groups here
├── text.ts # pure tool
├── weather.ts # networked tool
└── notes.ts # stateful tool
test/ # in-memory client/server tests
License
MIT © Eric Agyemang
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.