Skip to main content
Glama
chry8822

MCP Server Starter (TypeScript)

by chry8822

MCP Server Starter (TypeScript)

MCP TypeScript Node.js License

A minimal, production-ready TypeScript starter template for building Model Context Protocol (MCP) servers.

🎯 Motivation

The Model Context Protocol (MCP) is an open protocol that standardizes how AI applications connect to data sources and tools. Think of it as "USB-C for AI" - a universal standard that allows any AI model to connect with any data source or tool through a consistent interface.

graph LR A[AI] <-->|MCP| B[Server] B <--> C[Tools] B <--> D[Resources]

This starter template provides:

  • βœ… Minimal boilerplate to get you started quickly

  • βœ… Auto-loading architecture for tools, resources, and prompts

  • βœ… TypeScript best practices with strict typing

  • βœ… Production-ready structure that scales with your project

  • βœ… Working example (echo tool) to demonstrate the pattern

Whether you're building integrations for databases, APIs, file systems, or custom business tools, this template helps you create MCP servers that can be used by any MCP-compatible client (like Claude Desktop, IDEs, or custom applications).

πŸ“‹ Table of Contents

✨ Features

  • πŸš€ Auto-loading Module System - Drop new tools, resources, or prompts into their directories and they're automatically registered

  • πŸ› οΈ TypeScript First - Full type safety with strict TypeScript configuration

  • πŸ“¦ Minimal Dependencies - Only essential packages included

  • πŸ§ͺ Built-in Testing - Uses Node.js native test runner

  • πŸ” MCP Inspector Support - Test your server with the official MCP Inspector

  • πŸ“ Extensible Architecture - Clear patterns for adding new capabilities

  • 🎯 Example Implementation - Working echo tool demonstrates the pattern

  • ⚑ Code Generators - Hygen scaffolding for rapid module creation

  • 🌐 Dual Transport Support - Both stdio and HTTP (SSE + JSON-RPC) transports

  • 🐳 Docker Ready - Containerized deployment with multi-stage builds

πŸ“š Prerequisites

IMPORTANT

Ensure you have Node.js version 20.11.0 or higher installed before proceeding.

  • Node.js >= 20.11.0

  • npm or yarn

  • Basic understanding of TypeScript

  • Familiarity with the Model Context Protocol concepts

πŸ“¦ Installation

Clone and Setup

# Clone the repository git clone https://github.com/alexanderop/mcp-server-starter-ts.git cd mcp-server-starter-ts # Install dependencies npm install # Build the project npm run build

Using as a Template

You can also use this as a GitHub template:

  1. Click "Use this template" on GitHub

  2. Create your new repository

  3. Clone and start building your MCP server

πŸš€ Quick Start

TIP

Use the MCP Inspector to test your server interactively during development!

  1. Build the server:

    npm run build
  2. Test with MCP Inspector:

    npm run inspect

    This opens the MCP Inspector where you can interact with your server's tools, resources, and prompts.

  3. Run tests:

    npm test

πŸš€ Transport Modes

This server supports two transport modes: stdio (default) and HTTP (Streamable SSE + JSON-RPC).

Stdio Mode (Default)

Traditional stdio transport for local development and desktop clients:

# Run with stdio transport npm run serve:stdio # Or simply (defaults to stdio) npm run build && node build/index.js

HTTP Mode (SSE + JSON-RPC)

Streamable HTTP transport for web deployments and remote access:

# Run with HTTP transport on port 3000 npm run serve:http # Test with MCP Inspector npm run inspect:http

The HTTP transport exposes:

  • SSE endpoint (GET): http://localhost:3000/mcp - For server-sent events

  • JSON-RPC endpoint (POST): http://localhost:3000/mcp - For requests

Environment Variables

Configure the server behavior using environment variables:

Variable

Description

Default

STARTER_TRANSPORT

Transport mode: stdio or http

stdio

PORT

HTTP server port (HTTP mode only)

3000

CORS_ORIGIN

CORS allowed origins (HTTP mode only)

*

Configuration Examples

VS Code (mcp.json or .vscode/mcp.json)

{ "servers": { "starter-stdio": { "type": "stdio", "command": "node", "args": ["./build/index.js"] }, "starter-http": { "type": "http", "url": "http://localhost:3000/mcp" } } }

Claude Desktop

Add to your Claude Desktop configuration:

{ "mcpServers": { "mcp-server-starter": { "command": "node", "args": ["/path/to/mcp-server-starter/build/index.js"] } } }

🐳 Docker Support

The server includes Docker support for easy deployment:

Quick Start with Docker

# Build and run with Docker Compose docker compose up --build # Or run the pre-built image docker run -p 3000:3000 ghcr.io/alexanderopalic/mcp-server-starter-ts:latest

Docker Configuration

The Docker container runs in HTTP mode by default. Override settings with environment variables:

docker run -p 3000:3000 \ -e CORS_ORIGIN="https://example.com" \ -e PORT=3000 \ ghcr.io/alexanderopalic/mcp-server-starter-ts:latest

Development with Docker

Use the development profile for hot reload:

docker compose --profile dev up mcp-server-starter-dev

This mounts your source code and enables live reloading on port 3001.

πŸ“ Project Structure

mcp-server-starter-ts/ β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ index.ts # Main entry point β”‚ β”œβ”€β”€ registry/ # Auto-loading system β”‚ β”‚ β”œβ”€β”€ auto-loader.ts # Module auto-discovery β”‚ β”‚ └── types.ts # TypeScript interfaces β”‚ β”œβ”€β”€ tools/ # Tool implementations β”‚ β”‚ └── echo.ts # Example echo tool β”‚ β”œβ”€β”€ resources/ # Resource implementations (empty by default) β”‚ └── prompts/ # Prompt implementations (empty by default) β”œβ”€β”€ tests/ # Test files β”œβ”€β”€ _templates/ # Hygen generator templates β”‚ β”œβ”€β”€ tool/new/ # Tool generator β”‚ β”œβ”€β”€ prompt/new/ # Prompt generator β”‚ └── resource/new/ # Resource generator β”œβ”€β”€ build/ # Compiled JavaScript (generated) β”œβ”€β”€ mcp.json # MCP server configuration β”œβ”€β”€ package.json # Node.js dependencies β”œβ”€β”€ tsconfig.json # TypeScript configuration β”œβ”€β”€ eslint.config.js # ESLint configuration └── README.md

How Auto-Loading Works

flowchart TB A[Start] --> B[Scan] B --> C[Register] C --> D[Ready]
TIP

Simply drop your module files into the appropriate directory (tools/, resources/, or prompts/) and they'll be automatically loaded when the server starts!

πŸ› οΈ Development Guide

Using Code Generators

TIP

The fastest way to create new modules is using the built-in Hygen generators!

This project includes Hygen scaffolding for rapid module creation. Each generator creates both the implementation file and a corresponding test file.

Generate a New Tool

npm run gen:tool

You'll be prompted for:

  • Name: Enter in kebab-case (e.g., text-transform)

  • Description: Brief description of what the tool does

Generate a New Prompt

npm run gen:prompt

You'll be prompted for:

  • Name: Enter in kebab-case (e.g., code-review)

  • Description: Brief description of the prompt template

Generate a New Resource

npm run gen:resource

You'll be prompted for:

  • Name: Enter in kebab-case (e.g., app-status)

  • Description: Brief description of the resource

Command Line Usage

You can also provide parameters directly:

npx hygen tool new --name my-tool --description "Does something useful" npx hygen prompt new --name my-prompt --description "Generates helpful text" npx hygen resource new --name my-resource --description "Provides data"

Generated files:

  • Implementation: src/{tools|prompts|resources}/[name].ts

  • Test: tests/[name].test.ts

The auto-loader automatically discovers and registers all generated modules - no additional configuration needed!

Module Types Overview

graph TD A[MCP] --> B[Tools] A --> C[Resources] A --> D[Prompts]

Adding a New Tool

NOTE

Tools are functions that can be called by the AI to perform specific actions or computations.

Tools allow your MCP server to perform actions. Create a new file in src/tools/:

// src/tools/calculate.ts import { z } from 'zod'; import type { RegisterableModule } from '../registry/types.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; const calculateModule: RegisterableModule = { type: 'tool', name: 'calculate', description: 'Perform basic arithmetic calculations', register(server: McpServer) { server.tool( 'calculate', 'Perform basic arithmetic calculations', { operation: z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The arithmetic operation to perform'), a: z.number().describe('First number'), b: z.number().describe('Second number'), }, (args) => { let result: number; switch (args.operation) { case 'add': result = args.a + args.b; break; case 'subtract': result = args.a - args.b; break; case 'multiply': result = args.a * args.b; break; case 'divide': if (args.b === 0) throw new Error('Division by zero'); result = args.a / args.b; break; } return { content: [ { type: 'text', text: `Result: ${result}`, }, ], }; } ); }, }; export default calculateModule;

Adding a Resource

NOTE

Resources provide read-only access to data that can be consumed by AI clients.

Resources provide data that can be read by clients. Create a new file in src/resources/:

// src/resources/config.ts import type { RegisterableModule } from '../registry/types.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; const configResource: RegisterableModule = { type: 'resource', name: 'config', description: 'Application configuration', register(server: McpServer) { server.resource('config://app/settings', 'Application settings', 'application/json', async () => { const settings = { version: '1.0.0', environment: process.env.NODE_ENV || 'development', features: { autoSave: true, darkMode: false, }, }; return { contents: [ { uri: 'config://app/settings', mimeType: 'application/json', text: JSON.stringify(settings, null, 2), }, ], }; }); }, }; export default configResource;

Adding a Prompt

NOTE

Prompts are reusable templates that help structure interactions with the AI model.

Prompts are reusable prompt templates. Create a new file in src/prompts/:

// src/prompts/code-review.ts import { z } from 'zod'; import type { RegisterableModule } from '../registry/types.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; const codeReviewPrompt: RegisterableModule = { type: 'prompt', name: 'code-review', description: 'Generate a code review prompt', register(server: McpServer) { server.prompt( 'code-review', 'Generate a comprehensive code review', { language: z.string().describe('Programming language'), code: z.string().describe('Code to review'), focus: z.string().optional().describe('Specific areas to focus on'), }, (args) => { return { messages: [ { role: 'user', content: { type: 'text', text: `Please review the following ${args.language} code: \`\`\`${args.language} ${args.code} \`\`\` ${args.focus ? `Focus areas: ${args.focus}` : ''} Please provide: 1. Code quality assessment 2. Potential bugs or issues 3. Performance considerations 4. Security concerns 5. Suggestions for improvement`, }, }, ], }; } ); }, }; export default codeReviewPrompt;

πŸ” Testing with MCP Inspector

The MCP Inspector is a powerful tool for testing your server:

npm run inspect

This command:

  1. Builds your TypeScript code

  2. Launches the MCP Inspector

  3. Connects to your server

  4. Provides an interactive UI to test tools, resources, and prompts

Interactive Development Mode

For rapid testing and development, use the interactive dev mode:

npm run dev

This starts an interactive REPL where you can paste JSON-RPC messages directly and see responses in real-time. Perfect for testing your MCP server during development!

JSON-RPC Examples for Dev Mode

Once you run npm run dev, you can paste these JSON-RPC messages directly.

IMPORTANT

>MCP Protocol Handshake Required

The MCP protocol requires a specific initialization sequence before you can use tools, resources, or prompts:

  1. Initialize Request - Client sends capabilities and receives server capabilities

  2. Initialized Notification - Client confirms it's ready (no response expected)

Why is the initialized notification needed?

  • It confirms the client has processed the initialization response and is ready

  • It enables bidirectional communication - after this, the server can send requests to the client

  • Without it, the server won't send notifications (like tools/list_changed) or make requests (like sampling/createMessage)

  • This follows a pattern similar to TCP's handshake, ensuring both parties are ready before actual communication begins

The dev server does NOT automatically perform this handshake. You must send these messages manually first.

1. Initialize Connection (Required First!)

Step 1 - Send initialize request:

{ "jsonrpc": "2.0", "method": "initialize", "params": { "protocolVersion": "1.0.0", "capabilities": {}, "clientInfo": { "name": "dev-client", "version": "1.0.0" } }, "id": 1 }

Step 2 - After receiving the response, send initialized notification:

{ "jsonrpc": "2.0", "method": "notifications/initialized" }

Now the server is ready to handle requests!

2. List Available Tools

{ "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 2 }

3. Call the Echo Tool

{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "echo", "arguments": { "text": "Hello, MCP!" } }, "id": 3 }

4. List Resources

{ "jsonrpc": "2.0", "method": "resources/list", "params": {}, "id": 4 }

5. Read a Resource

{ "jsonrpc": "2.0", "method": "resources/read", "params": { "uri": "timestamp://current/iso" }, "id": 5 }

6. List Prompts

{ "jsonrpc": "2.0", "method": "prompts/list", "params": {}, "id": 6 }

7. Get a Prompt

{ "jsonrpc": "2.0", "method": "prompts/get", "params": { "name": "generate-readme", "arguments": { "projectName": "My Project", "description": "A cool project" } }, "id": 7 }
TIP

>Using Dev Mode:

  1. Run npm run dev to start the interactive server

  2. Copy any JSON-RPC message above and paste it into the terminal

  3. The server will show the response with syntax highlighting

  4. Type help for available commands or exit to quit

Important: Always send the initialize message first to establish the connection!

βš™οΈ Configuration

TypeScript Configuration

The project uses strict TypeScript settings for maximum type safety. Key configurations in tsconfig.json:

  • Target: ES2022

  • Module: ES2022 with Node module resolution

  • Strict mode enabled

  • Source maps for debugging

Available Scripts

Command

Description

npm run build

Compile TypeScript to JavaScript

npm run lint

Run ESLint checks

npm run lint:fix

Auto-fix ESLint issues

npm run typecheck

Type-check without building

npm test

Run tests

npm run test:watch

Run tests in watch mode

npm run inspect

Launch MCP Inspector

npm run dev

Interactive development mode

npm run gen:tool

Generate a new tool with test

npm run gen:prompt

Generate a new prompt with test

npm run gen:resource

Generate a new resource with test

πŸ”Œ Integration

How MCP Integration Works

sequenceDiagram IDE->>MCP: Connect MCP-->>IDE: Ready IDE->>MCP: Call MCP-->>IDE: Response
TIP

The easiest way to use your MCP server is through VS Code with MCP support extensions.

  1. Build your server:

    npm run build
  2. Open the project in VS Code:

    code .
  3. Use the included

    The project includes an mcp.json file that VS Code MCP extensions can use to automatically start your server:

    { "servers": { "starter": { "type": "stdio", "command": "node", "args": ["./build/index.js"] } } }
  4. Install a VS Code MCP extension:

    • Open VS Code Extensions (β‡§βŒ˜X on macOS, Ctrl+Shift+X on Windows/Linux)

    • Search for "MCP" or "Model Context Protocol"

    • Install an MCP-compatible extension

    • The extension will automatically detect and use your mcp.json configuration

NOTE

Themcp.json file tells VS Code how to start your MCP server. When you open a project with this file, compatible extensions will automatically recognize it as an MCP server project.

With Claude Desktop

IMPORTANT

Make sure to build your server before configuring Claude Desktop. The server must be compiled to JavaScript.

  1. Build your server:

    npm run build
  2. Add to Claude Desktop configuration:

    WARNING

    Configuration file location varies by operating system:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

    • Windows: %APPDATA%\Claude\claude_desktop_config.json

    • Linux: ~/.config/Claude/claude_desktop_config.json

    { "mcpServers": { "my-server": { "command": "node", "args": ["/path/to/your/server/build/index.js"] } } }
  3. Restart Claude Desktop

CAUTION

Always use absolute paths in your configuration. Relative paths may not work correctly.

With Custom Clients

Use the MCP SDK to connect to your server:

import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; const transport = new StdioClientTransport({ command: 'node', args: ['/path/to/your/server/build/index.js'], }); const client = new Client( { name: 'my-client', version: '1.0.0', }, { capabilities: {} } ); await client.connect(transport);

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

  1. Fork the repository

  2. Create your feature branch (git checkout -b feature/AmazingFeature)

  3. Commit your changes (git commit -m 'Add some AmazingFeature')

  4. Push to the branch (git push origin feature/AmazingFeature)

  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ”— Resources

πŸ› Troubleshooting

WARNING

Common issues and their solutions:

Issue

Solution

Cannot find module errors

Ensure you've run npm run build before starting the server

Server not connecting

Check that you're using absolute paths in configuration

Tools not loading

Verify your module exports match the RegisterableModule interface

TypeScript errors

Run npm run typecheck to identify type issues

Auto-loading fails

Check file names and ensure modules are in correct directories

Development

  • βœ… Type Safety: Use TypeScript's strict mode for catching errors early

  • βœ… Modular Design: Keep tools, resources, and prompts focused on single responsibilities

  • βœ… Error Handling: Always handle errors gracefully and provide meaningful messages

  • βœ… Validation: Use Zod schemas to validate all inputs

  • βœ… Testing: Write tests for critical functionality


Built with ❀️ for the MCP community

Report Issues Β· Request Features Β· Documentation

Project-specific Guide (This Repository)

This project is a Fitness & Nutrition themed MCP server with ready-to-use tools and examples. Use the commands below to build, run, and inspect the server locally.

Included Tools

  • echo

    • Description: Echo back the provided text

    • Example call (Inspector β†’ tools/call):

      { "name": "echo", "arguments": { "text": "Hello, MCP!" } }
  • generate_workout_plan

    • Description: Generate a weekly workout plan tailored to your goal and environment

    • Arguments:

      • goal: "fatLoss" | "muscleGain" | "boxingSkill" | "endurance"

      • daysPerWeek: number (2-6)

      • experienceLevel: "beginner" | "intermediate" | "advanced"

      • hasGymAccess: boolean

      • targetBodyParts?: ["chest" | "back" | "legs" | "shoulders" | "arms" | "core" | "fullBody"][]

    • Example:

      { "name": "generate_workout_plan", "arguments": { "goal": "muscleGain", "daysPerWeek": 3, "experienceLevel": "beginner", "hasGymAccess": true } }
  • supplement_recommendations

    • Description: Recommend supplements for your training goal and conditions (KR arguments)

    • Arguments:

      • λͺ©ν‘œ: "muscleGain" | "fatLoss" | "boxingSkill" | "endurance" | "recovery"

      • μ£Όλ‹Ήμš΄λ™νšŸμˆ˜: number (2-7)

      • κ΄€μ ˆλΆ€μƒν†΅μ¦: boolean

      • ν”Όλ‘œνšŒλ³΅ν•„μš”_μ—¬λΆ€: boolean

      • budget?: "low" | "medium" | "high"

    • Example:

      { "name": "supplement_recommendations", "arguments": { "λͺ©ν‘œ": "fatLoss", "μ£Όλ‹Ή_μš΄λ™_횟수": 4, "κ΄€μ ˆ_뢀상_톡증": false, "ν”Όλ‘œ_회볡_ν•„μš”_μ—¬λΆ€": true, "budget": "medium" } }

Included Resources

  • timestamp://current/iso

  • system-info://host/env

Example (Inspector β†’ resources/read):

{ "uri": "timestamp://current/iso" }

Included Prompts

  • generate-readme

  • code-analyzer

Example (Inspector β†’ prompts/get):

{ "name": "generate-readme", "arguments": { "projectName": "My Project", "description": "A cool project" } }

How to Run (Windows/PowerShell)

Prerequisites:

  • Node.js >= 20.11.0

Build:

npm run build

Stdio mode (default):

npm start # or node build/index.js

Interactive dev REPL:

npm run dev # If needed: node dev.js

HTTP mode (SSE + JSON-RPC):

$env:STARTER_TRANSPORT = 'http' npm start # Server endpoint: http://localhost:3000/mcp

Using MCP Inspector

Inspect a stdio server:

npx @modelcontextprotocol/inspector node build/index.js

Inspect an HTTP server:

$env:STARTER_TRANSPORT = 'http' npm start npx @modelcontextprotocol/inspector http://localhost:3000/mcp

Windows Notes / Troubleshooting

  • Error: "AbortController is not defined" when running Inspector

    • Cause: Running under an older Node version (< 18)

    • Fix: Use Node 20+ (this repo recommends >= 20.11.0)

    • Check versions/paths:

      node -v where node

ν•œκ΅­μ–΄ λ²ˆμ—­

🎯 동기(Motivation)

Model Context Protocol(MCP)λŠ” AI μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 데이터 μ†ŒμŠ€μ™€ 도ꡬ에 μ—°κ²°ν•˜λŠ” 방식을 ν‘œμ€€ν™”ν•˜λŠ” κ°œλ°©ν˜• ν”„λ‘œν† μ½œμž…λ‹ˆλ‹€. μ‰½κ²Œ 말해, AI μ„Έκ³„μ˜ β€œUSB‑C”와 κ°™μ•„μ„œ μ–΄λ–€ AI도 μΌκ΄€λœ μΈν„°νŽ˜μ΄μŠ€λ‘œ μ–΄λ–€ λ„κ΅¬λ‚˜ 데이터 μ†ŒμŠ€μ™€ μ—°κ²°ν•  수 있게 ν•©λ‹ˆλ‹€.

graph LR A[AI] <-->|MCP| B["μ„œλ²„"] B <--> C["도ꡬ(Tools)"] B <--> D["λ¦¬μ†ŒμŠ€(Resources)"]

이 μŠ€νƒ€ν„° ν…œν”Œλ¦Ώμ€ λ‹€μŒμ„ μ œκ³΅ν•©λ‹ˆλ‹€:

  • βœ… μ΅œμ†Œν•œμ˜ λ³΄μΌλŸ¬ν”Œλ ˆμ΄νŠΈλ‘œ λΉ λ₯Έ μ‹œμž‘

  • βœ… 도ꡬ/λ¦¬μ†ŒμŠ€/ν”„λ‘¬ν”„νŠΈ μžλ™ λ‘œλ”© μ•„ν‚€ν…μ²˜

  • βœ… μ—„κ²©ν•œ νƒ€μž…μ˜ TypeScript 베슀트 ν”„λž™ν‹°μŠ€

  • βœ… ν™•μž₯ κ°€λŠ₯ν•œ ν”„λ‘œλ•μ…˜ μ€€λΉ„ ꡬ쑰

  • βœ… λ™μž‘ν•˜λŠ” 예제(echo 툴) 포함

MCP μ„œλ²„λŠ” λ°μ΄ν„°λ² μ΄μŠ€, API, 파일 μ‹œμŠ€ν…œ, μ»€μŠ€ν…€ λΉ„μ¦ˆλ‹ˆμŠ€ 도ꡬ λ“±κ³Όμ˜ 톡합에 μ ν•©ν•˜λ©°, Claude Desktopμ΄λ‚˜ IDE, λ˜λŠ” μ»€μŠ€ν…€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ“± MCP ν˜Έν™˜ ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

✨ κΈ°λŠ₯(Features)

  • πŸš€ μžλ™ λ‘œλ”© λͺ¨λ“ˆ μ‹œμŠ€ν…œ: 디렉터리에 νŒŒμΌμ„ μΆ”κ°€ν•˜λ©΄ μžλ™ 등둝

  • πŸ› οΈ TypeScript First: μ—„κ²©ν•œ TS μ„€μ •μœΌλ‘œ μ™„μ „ν•œ νƒ€μž… μ•ˆμ •μ„±

  • πŸ“¦ μ΅œμ†Œ μ˜μ‘΄μ„±

  • πŸ§ͺ Node.js λ‚΄μž₯ ν…ŒμŠ€νŠΈ λŸ¬λ„ˆ μ‚¬μš©

  • πŸ” MCP Inspector 지원

  • πŸ“ ν™•μž₯ κ°€λŠ₯ν•œ μ•„ν‚€ν…μ²˜

  • 🎯 λ™μž‘ 예제 제곡(echo)

  • ⚑ μ½”λ“œ μ œλ„ˆλ ˆμ΄ν„°(Hygen) λ‚΄μž₯

  • 🌐 이쀑 전솑 지원(stdio, HTTP/SSE+JSON‑RPC)

  • 🐳 Docker 지원

πŸ“š 사전 μ€€λΉ„(Prerequisites)

  • Node.js >= 20.11.0

  • npm λ˜λŠ” yarn

  • 기본적인 TypeScript 이해

  • MCP κ°œλ…μ— λŒ€ν•œ μΉœμˆ™ν•¨

IMPORTANT


μ§„ν–‰ μ „ Node.js 20.11.0 이상이 μ„€μΉ˜λ˜μ–΄ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

πŸ“¦ μ„€μΉ˜(Installation)

# μ €μž₯μ†Œ 클둠 git clone https://github.com/alexanderop/mcp-server-starter-ts.git cd mcp-server-starter-ts # μ˜μ‘΄μ„± μ„€μΉ˜ npm install # λΉŒλ“œ npm run build

λ˜λŠ” GitHub ν…œν”Œλ¦ΏμœΌλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€(β€œUse this template” β†’ μƒˆ μ €μž₯μ†Œ 생성 β†’ 클둠).

πŸš€ λΉ λ₯Έ μ‹œμž‘(Quick Start)

TIP


개발 μ€‘μ—λŠ” MCP Inspector둜 μ„œλ²„λ₯Ό μƒν˜Έμž‘μš© λ°©μ‹μœΌλ‘œ ν…ŒμŠ€νŠΈν•˜μ„Έμš”!

  1. λΉŒλ“œ:

npm run build
  1. MCP Inspector둜 ν…ŒμŠ€νŠΈ:

npm run inspect
  1. ν…ŒμŠ€νŠΈ μ‹€ν–‰:

npm test

πŸš€ 전솑 λͺ¨λ“œ(Transport Modes)

이 μ„œλ²„λŠ” 두 λͺ¨λ“œλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€: κΈ°λ³Έ stdio, 그리고 HTTP(Streamable SSE + JSON‑RPC).

Stdio λͺ¨λ“œ(κΈ°λ³Έ)

# stdio μ „μ†‘μœΌλ‘œ μ‹€ν–‰ npm run serve:stdio # λ˜λŠ” (κΈ°λ³Έκ°’: stdio) npm run build && node build/index.js

HTTP λͺ¨λ“œ(SSE + JSON‑RPC)

# 3000 ν¬νŠΈμ—μ„œ HTTP 전솑 μ‹€ν–‰ npm run serve:http # MCP Inspector둜 ν…ŒμŠ€νŠΈ npm run inspect:http

λ…ΈμΆœ μ—”λ“œν¬μΈνŠΈ:

  • SSE(GET): http://localhost:3000/mcp

  • JSON‑RPC(POST): http://localhost:3000/mcp

ν™˜κ²½ λ³€μˆ˜(Environment Variables)

λ³€μˆ˜

μ„€λͺ…

κΈ°λ³Έκ°’

STARTER_TRANSPORT

전솑 λͺ¨λ“œ: stdio λ˜λŠ” http

stdio

PORT

HTTP μ„œλ²„ 포트(HTTP λͺ¨λ“œλ§Œ)

3000

CORS_ORIGIN

CORS ν—ˆμš© μ˜€λ¦¬μ§„(HTTP λͺ¨λ“œλ§Œ)

*

ꡬ성 μ˜ˆμ‹œ(Configuration Examples)

VS Code (mcp.json λ˜λŠ” .vscode/mcp.json)

{ "servers": { "starter-stdio": { "type": "stdio", "command": "node", "args": ["./build/index.js"] }, "starter-http": { "type": "http", "url": "http://localhost:3000/mcp" } } }

Claude Desktop

{ "mcpServers": { "mcp-server-starter": { "command": "node", "args": ["/path/to/mcp-server-starter/build/index.js"] } } }

🐳 Docker 지원(Docker Support)

λΉ λ₯Έ μ‹œμž‘:

docker compose up --build

λ˜λŠ”:

docker run -p 3000:3000 ghcr.io/alexanderopalic/mcp-server-starter-ts:latest

ν™˜κ²½ λ³€μˆ˜λ‘œ μ„€μ • μ˜€λ²„λΌμ΄λ“œ:

docker run -p 3000:3000 \ -e CORS_ORIGIN="https://example.com" \ -e PORT=3000 \ ghcr.io/alexanderopalic/mcp-server-starter-ts:latest

개발 ν”„λ‘œν•„(ν•« λ¦¬λ‘œλ“œ):

docker compose --profile dev up mcp-server-starter-dev

πŸ“ ν”„λ‘œμ νŠΈ ꡬ쑰(Project Structure)

mcp-server-starter-ts/ β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ index.ts # 메인 μ—”νŠΈλ¦¬ β”‚ β”œβ”€β”€ registry/ # μžλ™ λ‘œλ”© μ‹œμŠ€ν…œ β”‚ β”‚ β”œβ”€β”€ auto-loader.ts # λͺ¨λ“ˆ μžλ™ 탐색 β”‚ β”‚ └── types.ts # νƒ€μž… μ •μ˜ β”‚ β”œβ”€β”€ tools/ # 툴 κ΅¬ν˜„ β”‚ β”‚ └── echo.ts # 예제 echo 툴 β”‚ β”œβ”€β”€ resources/ # λ¦¬μ†ŒμŠ€ κ΅¬ν˜„ β”‚ └── prompts/ # ν”„λ‘¬ν”„νŠΈ κ΅¬ν˜„ β”œβ”€β”€ tests/ # ν…ŒμŠ€νŠΈ β”œβ”€β”€ _templates/ # Hygen μ œλ„ˆλ ˆμ΄ν„° ν…œν”Œλ¦Ώ β”œβ”€β”€ build/ # 컴파일된 JS(생성물) β”œβ”€β”€ mcp.json # MCP μ„œλ²„ μ„€μ • β”œβ”€β”€ package.json # μ˜μ‘΄μ„± β”œβ”€β”€ tsconfig.json # TS μ„€μ • β”œβ”€β”€ eslint.config.js # ESLint μ„€μ • └── README.md

μžλ™ λ‘œλ”© κ°œλ…:

flowchart TB A[Start] --> B[Scan] B --> C[Register] C --> D[Ready]

πŸ› οΈ 개발 κ°€μ΄λ“œ(Development Guide)

μ½”λ“œ μ œλ„ˆλ ˆμ΄ν„° μ‚¬μš©(Using Code Generators)

npm run gen:tool npm run gen:prompt npm run gen:resource

직접 νŒŒλΌλ―Έν„° 전달:

npx hygen tool new --name my-tool --description "Does something useful" npx hygen prompt new --name my-prompt --description "Generates helpful text" npx hygen resource new --name my-resource --description "Provides data"

생성물:

  • κ΅¬ν˜„: src/{tools|prompts|resources}/[name].ts

  • ν…ŒμŠ€νŠΈ: tests/[name].test.ts

  • μžλ™ λ‘œλ”©μ΄ μ‹œμž‘ μ‹œ μžλ™μœΌλ‘œ λ“±λ‘ν•©λ‹ˆλ‹€.

μƒˆ 툴 μΆ”κ°€(Adding a New Tool)

μ•„λž˜ μ˜ˆμ‹œμ™€ λ™μΌν•œ νŒ¨ν„΄μœΌλ‘œ κ΅¬ν˜„ νŒŒμΌμ„ μΆ”κ°€ν•˜λ©΄ λ©λ‹ˆλ‹€(μ½”λ“œ 블둝은 원문 μœ μ§€).

// src/tools/calculate.ts import { z } from 'zod'; import type { RegisterableModule } from '../registry/types.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; const calculateModule: RegisterableModule = { type: 'tool', name: 'calculate', description: 'Perform basic arithmetic calculations', register(server: McpServer) { server.tool( 'calculate', 'Perform basic arithmetic calculations', { operation: z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The arithmetic operation to perform'), a: z.number().describe('First number'), b: z.number().describe('Second number'), }, (args) => { let result: number; switch (args.operation) { case 'add': result = args.a + args.b; break; case 'subtract': result = args.a - args.b; break; case 'multiply': result = args.a * args.b; break; case 'divide': if (args.b === 0) throw new Error('Division by zero'); result = args.a / args.b; break; } return { content: [ { type: 'text', text: `Result: ${result}`, }, ], }; } ); }, }; export default calculateModule;

λ¦¬μ†ŒμŠ€ μΆ”κ°€(Adding a Resource)

// src/resources/config.ts import type { RegisterableModule } from '../registry/types.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; const configResource: RegisterableModule = { type: 'resource', name: 'config', description: 'Application configuration', register(server: McpServer) { server.resource('config://app/settings', 'Application settings', 'application/json', async () => { const settings = { version: '1.0.0', environment: process.env.NODE_ENV || 'development', features: { autoSave: true, darkMode: false, }, }; return { contents: [ { uri: 'config://app/settings', mimeType: 'application/json', text: JSON.stringify(settings, null, 2), }, ], }; }); }, }; export default configResource;

ν”„λ‘¬ν”„νŠΈ μΆ”κ°€(Adding a Prompt)

// src/prompts/code-review.ts import { z } from 'zod'; import type { RegisterableModule } from '../registry/types.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; const codeReviewPrompt: RegisterableModule = { type: 'prompt', name: 'code-review', description: 'Generate a code review prompt', register(server: McpServer) { server.prompt( 'code-review', 'Generate a comprehensive code review', { language: z.string().describe('Programming language'), code: z.string().describe('Code to review'), focus: z.string().optional().describe('Specific areas to focus on'), }, (args) => { return { messages: [ { role: 'user', content: { type: 'text', text: `Please review the following ${args.language} code: \`\`\`${args.language} ${args.code} \`\`\` ${args.focus ? `Focus areas: ${args.focus}` : ''} Please provide: 1. Code quality assessment 2. Potential bugs or issues 3. Performance considerations 4. Security concerns 5. Suggestions for improvement`, }, }, ], }; } ); }, }; export default codeReviewPrompt;

πŸ” MCP Inspector둜 ν…ŒμŠ€νŠΈ(Testing with MCP Inspector)

npm run inspect

μΈν„°λž™ν‹°λΈŒ 개발 λͺ¨λ“œ:

npm run dev

개발 λͺ¨λ“œμ—μ„œμ˜ JSON‑RPC μ˜ˆμ‹œ(ν•Έλ“œμ…°μ΄ν¬ ν•„μˆ˜):

  1. Initialize μš”μ²­

{ "jsonrpc": "2.0", "method": "initialize", "params": { "protocolVersion": "1.0.0", "capabilities": {}, "clientInfo": { "name": "dev-client", "version": "1.0.0" } }, "id": 1 }
  1. Initialized μ•Œλ¦Ό

{ "jsonrpc": "2.0", "method": "notifications/initialized" }

도ꡬ λͺ©λ‘:

{ "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 2 }

Echo 호좜:

{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "echo", "arguments": { "text": "Hello, MCP!" } }, "id": 3 }

βš™οΈ ꡬ성(Configuration)

TypeScript μ£Όμš” μ„€μ •:

  • Target: ES2022

  • Module: ES2022 + Node 해석

  • Strict λͺ¨λ“œ

  • μ†ŒμŠ€λ§΅

μ‚¬μš© κ°€λŠ₯ν•œ 슀크립트(Available Scripts)

λͺ…λ Ή

μ„€λͺ…

npm run build

TypeScript 컴파일

npm run lint

ESLint 체크

npm run lint:fix

ESLint μžλ™ μˆ˜μ •

npm run typecheck

λΉŒλ“œ 없이 νƒ€μž… 체크

npm test

ν…ŒμŠ€νŠΈ μ‹€ν–‰

npm run test:watch

μ›ŒμΉ˜ λͺ¨λ“œ ν…ŒμŠ€νŠΈ

npm run inspect

MCP Inspector μ‹€ν–‰

npm run dev

μƒν˜Έμž‘μš© 개발 λͺ¨λ“œ

npm run gen:tool

μƒˆ 툴 생성

npm run gen:prompt

μƒˆ ν”„λ‘¬ν”„νŠΈ 생성

npm run gen:resource

μƒˆ λ¦¬μ†ŒμŠ€ 생성

πŸ”Œ 톡합(Integration)

λ™μž‘ κ°œμš”:

sequenceDiagram IDE->>MCP: Connect MCP-->>IDE: Ready IDE->>MCP: Call MCP-->>IDE: Response

VS Code 연동(ꢌμž₯)

  1. λΉŒλ“œ:

npm run build
  1. ν”„λ‘œμ νŠΈ μ—΄κΈ°:

code .
  1. ν¬ν•¨λœ mcp.json μ‚¬μš©(μžλ™ 인식)

  2. MCP ν™•μž₯ μ„€μΉ˜ 및 μ‚¬μš©

Claude Desktop

  1. λΉŒλ“œ:

npm run build
  1. μš΄μ˜μ²΄μ œλ³„ μ„€μ • 파일 μœ„μΉ˜μ— ꡬ성 μΆ”κ°€(μ ˆλŒ€κ²½λ‘œ ꢌμž₯)

  2. μ•± μž¬μ‹œμž‘

μ»€μŠ€ν…€ ν΄λΌμ΄μ–ΈνŠΈ

import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; const transport = new StdioClientTransport({ command: 'node', args: ['/path/to/your/server/build/index.js'], }); const client = new Client( { name: 'my-client', version: '1.0.0', }, { capabilities: {} } ); await client.connect(transport);

🀝 Contributing

κΈ°μ—¬λŠ” μ–Έμ œλ‚˜ ν™˜μ˜ν•©λ‹ˆλ‹€! 큰 λ³€κ²½ μ „μ—λŠ” λ¨Όμ € 이슈λ₯Ό μ—΄μ–΄ λ°©ν–₯을 λ…Όμ˜ν•΄ μ£Όμ„Έμš”.

πŸ“„ License

λ³Έ ν”„λ‘œμ νŠΈλŠ” MIT Licenseλ₯Ό λ”°λ¦…λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ LICENSE νŒŒμΌμ„ μ°Έκ³ ν•˜μ„Έμš”.

πŸ”— μ°Έκ³  자료(Resources)

  • MCP λ¬Έμ„œ: https://modelcontextprotocol.io

  • MCP SDK μ €μž₯μ†Œ: https://github.com/modelcontextprotocol/sdk

  • MCP μ„œλ²„ λͺ¨μŒ: https://github.com/modelcontextprotocol/servers

  • MCP Inspector: https://github.com/modelcontextprotocol/inspector

πŸ› 문제 ν•΄κ²°(Troubleshooting)

자주 λ°œμƒν•˜λŠ” μ΄μŠˆμ™€ ν•΄κ²° 방법:

이슈

ν•΄κ²° 방법

Cannot find module 였λ₯˜

μ‹€ν–‰ μ „ npm run build μˆ˜ν–‰

μ„œλ²„ μ—°κ²° μ‹€νŒ¨

섀정에 μ ˆλŒ€κ²½λ‘œ μ‚¬μš© μ—¬λΆ€ 확인

도ꡬ가 λ‘œλ“œλ˜μ§€ μ•ŠμŒ

RegisterableModule μΈν„°νŽ˜μ΄μŠ€ μ€€μˆ˜ 확인

TypeScript 였λ₯˜

npm run typecheck μ‹€ν–‰

μžλ™ λ‘œλ”© μ‹€νŒ¨

파일λͺ…/κ²½λ‘œκ°€ μ˜¬λ°”λ₯Έμ§€ 확인

개발 팁:

  • βœ… νƒ€μž… μ•ˆμ „μ„±: TS strict λͺ¨λ“œ 적극 ν™œμš©

  • βœ… λͺ¨λ“ˆν™”: 툴/λ¦¬μ†ŒμŠ€/ν”„λ‘¬ν”„νŠΈλŠ” 단일 μ±…μž„ 원칙

  • βœ… μ—λŸ¬ 처리: μΉœμ ˆν•˜κ³  μœ μ˜λ―Έν•œ λ©”μ‹œμ§€

  • βœ… 검증: λͺ¨λ“  μž…λ ₯은 Zod둜 검증

  • βœ… ν…ŒμŠ€νŠΈ: 핡심 κΈ°λŠ₯μ—λŠ” λ°˜λ“œμ‹œ ν…ŒμŠ€νŠΈ

ν”„λ‘œμ νŠΈ μ „μš© κ°€μ΄λ“œ(μš”μ•½)

이 μ €μž₯μ†ŒλŠ” ν”ΌνŠΈλ‹ˆμŠ€/μ˜μ–‘ ν…Œλ§ˆ MCP μ„œλ²„μž…λ‹ˆλ‹€.

  • 포함 도ꡬ

    • echo: μž…λ ₯ ν…μŠ€νŠΈλ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜

    • generate_workout_plan: λͺ©ν‘œ/μˆ™λ ¨λ„/μ£Όλ‹Ή 횟수/ν—¬μŠ€μž₯ 유무둜 루틴 생성

    • supplement_recommendations: λͺ©ν‘œ/μ˜ˆμ‚°/κ΄€μ ˆ/ν”Όλ‘œ κΈ°μ€€ μ˜μ–‘μ œ μΆ”μ²œ(인자: ν•œκ΅­μ–΄ ν‚€)

  • 포함 λ¦¬μ†ŒμŠ€

    • timestamp://current/iso, system-info://host/env

  • 포함 ν”„λ‘¬ν”„νŠΈ

    • generate-readme, code-analyzer

μ‹€ν–‰(Windows/PowerShell):

npm run build npm start # stdio $env:STARTER_TRANSPORT='http'; npm start # http npm run dev # μΈν„°λž™ν‹°λΈŒ λͺ¨λ“œ

Inspector:

npx @modelcontextprotocol/inspector node build/index.js # λ˜λŠ” http λͺ¨λ“œ: npx @modelcontextprotocol/inspector http://localhost:3000/mcp

Windows μ°Έκ³ :

  • "AbortController is not defined" λ°œμƒ μ‹œ Node 20+둜 μ „ν™˜ν•˜μ„Έμš”.

-
security - not tested
F
license - not found
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chry8822/workout-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server