Skip to main content
Glama
mcp-server-template

mcp-server-template

MCP Server Template

CI License: MIT Node

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, with no mocks. Full write-up in ARCHITECTURE.md.

Related MCP server: my-mcp-server

Enterprise architecture

Pillar

How the template applies it

Resilience

a thrown tool handler is contained per call (returned as an error result), so 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, so 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:

  1. 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}!`),
      );
    }
  2. Register it in src/tools/index.ts (one line).

  3. 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, so 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

Available Tools

6 tools
get_weatherA

Current weather for a city via the free Open-Meteo API (no API key required).

Inputs: city (required), units.

note_deleteC

Delete a note by key.

Inputs: key (required).

note_getC

Read a note by key.

Inputs: key (required).

note_listA

List all saved note keys.

Inputs: no named parameters.

note_setC

Save or overwrite a note by key.

Inputs: key (required), value (required).

text_statsB

Count characters, words, and lines in a piece of text.

Inputs: text (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 6 tools

    Disambiguation5/5

    Each tool targets a distinct operation: weather lookup, note CRUD (create, read, list, delete), and text analysis. There is no overlap or ambiguity.

    Naming Consistency3/5

    Note tools follow a noun_verb pattern (e.g., note_delete), but get_weather uses verb_noun and text_stats uses noun_noun, creating inconsistency. While readable, the pattern is mixed.

    Tool Count5/5

    With 6 tools, the server demonstrates core functionalities without being too sparse or bloated. It's well-scoped for a template.

    Completeness5/5

    For the intended demo purpose, the notes have full CRUD, weather provides a single essential query, and text stats cover basic analysis. No obvious gaps.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      A production-ready MCP server with tools for weather, calculator, and mock database queries, plus resources and prompt templates, featuring a glassmorphism admin dashboard and WebSocket support.
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      A minimal starter template for building Model Context Protocol (MCP) servers using TypeScript and FastMCP, including an example weather tool for demonstration.
      34 npm
      1
      ISC
    • A
      license
      Not graded
      quality
      C
      maintenance
      A production-ready template for developing MCP servers with Python and FastMCP, including example tools like a multiply calculator and code review prompt generator.
      Apache 2.0
    • A
      license
      Not graded
      quality
      D
      maintenance
      A minimal MCP server starter template with a simple hello-world tool and Docker support for building AI assistant tools.
      -