template-mcp

template-mcp

A TypeScript MCP server template with Zod validation, dual transport (stdio/HTTP), and modular architecture for building MCP-compatible tools, resources, and prompts.

Category
Visit Server

README

template-mcp

MCP (Model Context Protocol) server template with TypeScript, Zod validation, and dual transport support (stdio/HTTP). Compatible with any MCP client: Claude Code, Claude Desktop, Cursor, VS Code Copilot, Windsurf, Cline, and more.

Features

  • Dual transport: stdio (local) and Streamable HTTP (remote)
  • TypeScript strict with ESM modules
  • Zod validation for tool input schemas
  • Joi env validation (fail-fast on startup)
  • Pino logging to stderr (stdio-safe)
  • Modular architecture: tools, resources, and prompts as separate modules
  • Factory pattern: createServer() for testability
  • Full test suite with MCP SDK in-memory transport
  • Quality tooling: ESLint + Prettier + Husky + lint-staged
  • Docker ready: multi-stage build
  • CI/CD: GitHub Actions pipeline

Quick Start

pnpm install
pnpm dev

Scripts

Script Description
pnpm dev Start with hot reload (tsx watch)
pnpm build Compile TypeScript + resolve aliases
pnpm start Run compiled server
pnpm test Run tests
pnpm lint Lint source code
pnpm type-check Type check without emit

Configuration

Copy .env.example to .env and adjust:

Variable Default Description
MCP_TRANSPORT stdio Transport: stdio or http
PORT 3000 HTTP port (only for http transport)
LOG_LEVEL info Pino log level
NODE_ENV development Environment

Project Structure

src/
├── main.ts              # Entrypoint: transport selection
├── server.ts            # createServer() factory
├── config/              # Env validation + constants
├── common/              # Logger, error helpers, types
├── tools/               # MCP tools (callable by LLMs)
├── resources/           # MCP resources (read-only data)
└── prompts/             # MCP prompts (reusable templates)

Adding a New Tool

  1. Create src/tools/my-tool.tool.ts:
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';

export function registerMyTool(server: McpServer): void {
  server.registerTool(
    'my_tool',
    {
      title: 'My Tool',
      description: 'What this tool does',
      inputSchema: {
        param: z.string().describe('Parameter description'),
      },
      annotations: {
        readOnlyHint: true,
        destructiveHint: false,
        idempotentHint: true,
        openWorldHint: false,
      },
    },
    async ({ param }) => ({
      content: [{ type: 'text', text: `Result: ${param}` }],
    }),
  );
}
  1. Register in src/tools/index.ts:
import { registerMyTool } from './my-tool.tool.js';

export function registerTools(server: McpServer): void {
  registerGreetTool(server);
  registerMyTool(server); // add here
}
  1. Add tests in src/tools/__tests__/my-tool.tool.spec.ts

Client Configuration

Claude Code

Add to .claude/settings.json:

{
  "mcpServers": {
    "template-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/template-mcp/dist/main.js"]
    }
  }
}

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "template-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/template-mcp/dist/main.js"]
    }
  }
}

Cursor

Add to Cursor Settings > MCP Servers:

{
  "mcpServers": {
    "template-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/template-mcp/dist/main.js"]
    }
  }
}

VS Code (Copilot)

Add to .vscode/settings.json:

{
  "mcp": {
    "servers": {
      "template-mcp": {
        "command": "node",
        "args": ["/absolute/path/to/template-mcp/dist/main.js"]
      }
    }
  }
}

Docker

# Build
docker build -t template-mcp .

# Run (HTTP mode, used for remote access)
docker run -p 3000:3000 template-mcp

Tech Stack

  • Node.js 22 + TypeScript (strict, ESM)
  • MCP SDK v1 (@modelcontextprotocol/sdk)
  • Zod (tool input validation)
  • Joi (env validation)
  • Pino (stderr logging)
  • Vitest (testing)
  • ESLint + Prettier + Husky

Verificación

Todo lo siguiente está comprobado y funcionando al 100%.

Calidad de código

Check Comando
Lint + formato pnpm lint
Tipado estricto pnpm type-check
Build (tsc + alias) pnpm build

Tests unitarios (11/11)

pnpm test
Suite Cubre
greet.tool.spec.ts (5) Listado, estilos casual/formal/enthusiastic, rechazo de nombre vacío
server-info.resource.spec.ts (2) Listado, campos JSON (name, version, uptime, timestamp)
summarize.prompt.spec.ts (4) Listado, estilos brief/bullet-points, coerción numérica, defaults

Sin red ni puertos — usa InMemoryTransport del SDK.

Runtime — transporte stdio (modo por defecto)

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' \
  | MCP_TRANSPORT=stdio node dist/main.js

Respuesta JSON-RPC en stdout, logs en stderr.

Runtime — transporte HTTP

MCP_TRANSPORT=http PORT=3100 node dist/main.js &
# Initialize → capturar Mcp-Session-Id del header
# tools/list, resources/list, prompts/list, tools/call greet, resources/read info://server
Endpoint verificado Resultado esperado
tools/call greet {"name":"Freddy","style":"casual"} "Hey Freddy! How's it going?"
resources/read info://server JSON con name, version, uptime, nodeVersion, timestamp

Docker

docker build -t template-mcp .  # multi-stage: base → deps → build → production
docker run -p 3000:3000 template-mcp  # arranca en HTTP mode

CI (GitHub Actions)

pnpm installpnpm lintpnpm buildpnpm test
Corre en cada push y PR a main/master.

Pipeline de commits (local)

git commit → husky → lint-staged → eslint --fix + prettier --write (solo archivos staged)

Gaps conocidos

  • HTTP transport sin tests automáticos (medio): los unit tests usan InMemoryTransport; el transporte HTTP (StreamableHTTPServerTransport) solo se verificó manualmente con curl. Para producción remota añadir tests de integración con sesión real
  • Integración con cliente MCP (medio): verificar manualmente agregando a .claude/settings.json o Cursor y confirmando que tools/resources/prompts aparecen en el cliente
  • Tool inputs extremos (bajo): strings muy largos, unicode malformado — Zod los rechaza pero el error response no está testeado vía HTTP
  • Sesiones concurrentes (bajo): fuera del scope de un template

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured