template-mcp
template-mcp
TypeScript、Zodバリデーション、デュアルトランスポート(stdio/HTTP)をサポートしたMCP(Model Context Protocol)サーバーテンプレート。Claude Code、Claude Desktop、Cursor、VS Code Copilot、Windsurf、Clineなど、あらゆるMCPクライアントと互換性があります。
特徴
デュアルトランスポート: stdio(ローカル)およびStreamable HTTP(リモート)
TypeScript strict: ESMモジュール対応
Zodバリデーション: ツール入力スキーマ用
Joi環境変数バリデーション: 起動時に即時失敗
Pinoロギング: stderrへ出力(stdioセーフ)
モジュール式アーキテクチャ: ツール、リソース、プロンプトを個別のモジュールとして構成
ファクトリパターン: テスト容易性のための
createServer()完全なテストスイート: MCP SDKのインメモリトランスポートを使用
高品質なツール: ESLint + Prettier + Husky + lint-staged
Docker対応: マルチステージビルド
CI/CD: GitHub Actionsパイプライン
Related MCP server: xmcp Application
クイックスタート
pnpm install
pnpm devスクリプト
スクリプト | 説明 |
| ホットリロードで起動 (tsx watch) |
| TypeScriptのコンパイル + エイリアスの解決 |
| コンパイル済みサーバーの実行 |
| テストの実行 |
| ソースコードのLint |
| 型チェック(出力なし) |
設定
.env.example を .env にコピーして調整してください:
変数 | デフォルト | 説明 |
|
| トランスポート: |
|
| HTTPポート ( |
|
| Pinoログレベル |
|
| 環境 |
プロジェクト構造
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)新しいツールの追加
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}` }],
}),
);
}src/tools/index.tsに登録:
import { registerMyTool } from './my-tool.tool.js';
export function registerTools(server: McpServer): void {
registerGreetTool(server);
registerMyTool(server); // add here
}src/tools/__tests__/my-tool.tool.spec.tsにテストを追加
クライアント設定
Claude Code
.claude/settings.json に追加:
{
"mcpServers": {
"template-mcp": {
"command": "node",
"args": ["/absolute/path/to/template-mcp/dist/main.js"]
}
}
}Claude Desktop
claude_desktop_config.json に追加:
{
"mcpServers": {
"template-mcp": {
"command": "node",
"args": ["/absolute/path/to/template-mcp/dist/main.js"]
}
}
}Cursor
Cursorの設定 > MCP Servers に追加:
{
"mcpServers": {
"template-mcp": {
"command": "node",
"args": ["/absolute/path/to/template-mcp/dist/main.js"]
}
}
}VS Code (Copilot)
.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技術スタック
Node.js 22 + TypeScript (strict, ESM)
MCP SDK v1 (
@modelcontextprotocol/sdk)Zod (ツール入力バリデーション)
Joi (環境変数バリデーション)
Pino (stderrロギング)
Vitest (テスト)
ESLint + Prettier + Husky
検証
以下はすべて確認済みで、100%動作しています。
コード品質
チェック | コマンド |
Lint + フォーマット |
|
厳格な型チェック |
|
ビルド (tsc + alias) |
|
ユニットテスト (11/11)
pnpm testスイート | カバレッジ |
| リスト、カジュアル/フォーマル/熱狂的スタイル、空の名前の拒否 |
| リスト、JSONフィールド (name, version, uptime, timestamp) |
| リスト、簡潔/箇条書きスタイル、数値強制、デフォルト値 |
ネットワークやポートは不要 — SDKの InMemoryTransport を使用。
ランタイム — stdioトランスポート (デフォルトモード)
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.jsstdoutにJSON-RPCレスポンス、stderrにログを出力。
ランタイム — 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検証済みエンドポイント | 期待される結果 |
|
|
| name, version, uptime, nodeVersion, timestamp を含むJSON |
Docker
docker build -t template-mcp . # multi-stage: base → deps → build → production
docker run -p 3000:3000 template-mcp # arranca en HTTP modeCI (GitHub Actions)
pnpm install → pnpm lint → pnpm build → pnpm test
main/masterへの各プッシュおよびPRで実行。
コミットパイプライン (ローカル)
git commit → husky → lint-staged → eslint --fix + prettier --write (ステージングされたファイルのみ)
既知のギャップ
自動テストのないHTTPトランスポート (中): ユニットテストは
InMemoryTransportを使用。HTTPトランスポート (StreamableHTTPServerTransport) はcurlで手動検証済み。リモート本番環境向けには実際のセッションを用いた統合テストを追加することMCPクライアントとの統合 (中):
.claude/settings.jsonまたはCursorに追加し、ツール/リソース/プロンプトがクライアントに表示されることを手動で確認すること極端なツール入力 (低): 非常に長い文字列、不正なUnicode — Zodは拒否するが、HTTP経由のエラーレスポンスはテストされていない
同時セッション (低): テンプレートのスコープ外
Available Tools
1 toolgreetGreet UserARead-onlyIdempotent
Generates a personalized greeting message. Use this tool when you need to greet someone by name with an optional custom greeting style.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name of the person to greet | |
| style | No | The greeting style to use | casual |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true, destructiveHint=false, and idempotentHint=true, so the description does not need to repeat those. It adds the behavioral detail that the greeting is 'personalized' and that style is optional with a default value, which is sufficient given the high annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, clear sentence that is front-loaded with the main action and immediately provides usage guidance. Every word is necessary and there is no redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 parameters, no output schema, no nested objects) and the rich annotations, the description is complete enough. It covers the purpose and usage adequately. No output schema is needed as the return is self-evident.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters thoroughly (name with length constraints, style with enum and default). The description adds no new parameter information beyond what's in the schema, earning a baseline score of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool generates a personalized greeting message, with a specific verb ('greet') and resource ('someone by name'). It also mentions the optional custom greeting style, distinguishing it from any potential siblings (though none exist).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use this tool when you need to greet someone by name with an optional custom greeting style,' providing clear usage context. However, it does not specify when not to use it or mention any alternatives, but since there are no siblings, this is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v1.0.0- First observed
greet
TDQS
Scored across 1 tool
Only one tool exists, so there is no ambiguity in choosing between tools.
With only one tool, consistency is not applicable, but the name 'greet' is clear and follows a common verb pattern.
A single tool for a server called 'template-mcp' suggests an extremely narrow scope, which is likely insufficient for meaningful tasks.
The server only offers a greeting function, which is too limited for any substantial workflow; missing any broader functionality.
Maintenance
Related MCP Connectors
A simple Typescript MCP server built using the official MCP Typescript SDK and smithery/cli. This…
A TypeScript MCP server for Home Assistant, enabling programmatic management of entities, automati…
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA TypeScript-based template for rapidly developing MCP servers with modular tool architecture, built-in validation using Zod schemas, and comprehensive error handling.9 npmMIT
- FlicenseNot gradedqualityDmaintenanceA Model Context Protocol (MCP) server template designed for building structured tools, prompts, and resources with built-in support for HTTP and STDIO transports. It provides a standardized framework for developers to create and deploy AI-driven services using TypeScript and Zod schema validation.8 npm-
- AlicenseNot gradedqualityBmaintenanceA feature-complete MCP server template in TypeScript demonstrating tools, resources, prompts, and both stdio and HTTP transports.8MIT
- AlicenseNot gradedqualityDmaintenanceA minimal TypeScript MCP server template with example tool, Zod validation, stdio transport, and dotenv setup.8 npmMIT