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 컴파일 + 별칭 해결 |
| 컴파일된 서버 실행 |
| 테스트 실행 |
| 소스 코드 린트 |
| 내보내기 없이 타입 체크 |
구성
.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% 작동합니다.
코드 품질
체크 | 명령어 |
린트 + 포맷팅 |
|
엄격한 타입 |
|
빌드 (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
메인/마스터 브랜치로의 모든 푸시 및 PR 시 실행.
커밋 파이프라인 (로컬)
git commit → husky → lint-staged → eslint --fix + prettier --write (스테이징된 파일만)
알려진 격차
자동 테스트가 없는 HTTP 전송 (중간): 단위 테스트는
InMemoryTransport를 사용하며, HTTP 전송(StreamableHTTPServerTransport)은 curl을 통해 수동으로만 확인되었습니다. 원격 프로덕션 환경을 위해서는 실제 세션을 사용한 통합 테스트를 추가해야 합니다.MCP 클라이언트 통합 (중간):
.claude/settings.json또는 Cursor에 추가하여 도구/리소스/프롬프트가 클라이언트에 나타나는지 수동으로 확인해야 합니다.극단적인 도구 입력 (낮음): 매우 긴 문자열, 잘못된 유니코드 등 — 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