su-myeong/my-mcp-server-20250925
If you are the rightful owner of my-mcp-server-20250925 and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
This project is a boilerplate for quickly developing a Model Context Protocol (MCP) server using the TypeScript MCP SDK.
TypeScript MCP Server 보μΌλ¬νλ μ΄νΈ
TypeScript MCP SDKλ₯Ό νμ©νμ¬ Model Context Protocol (MCP) μλ²λ₯Ό λΉ λ₯΄κ² κ°λ°ν μ μλ 보μΌλ¬νλ μ΄νΈ νλ‘μ νΈμ λλ€.
π νλ‘μ νΈ κ΅¬μ‘°
typescript-mcp-server-boilerplate/
βββ src/
β βββ index.ts # MCP μλ² λ©μΈ μ§μ
μ
βββ build/ # μ»΄νμΌλ JavaScript νμΌ (λΉλ ν μμ±)
βββ package.json # νλ‘μ νΈ μμ‘΄μ± λ° μ€ν¬λ¦½νΈ
βββ tsconfig.json # TypeScript μ€μ
βββ README.md # νλ‘μ νΈ λ¬Έμ
π μμνκΈ°
1. μμ‘΄μ± μ€μΉ
npm install
2. μλ² μ΄λ¦ μ€μ
src/index.ts
νμΌμμ μλ² μ΄λ¦μ μμ νμΈμ:
const server = new McpServer({
name: 'typescript-mcp-server', // μ¬κΈ°λ₯Ό μνλ μλ² μ΄λ¦μΌλ‘ λ³κ²½
version: '1.0.0',
// νμ±ν νκ³ μ νλ κΈ°λ₯ μ€μ
capabilities: {
tools: {},
resources: {}
}
})
π‘ ν: νμ¬ λ³΄μΌλ¬νλ μ΄νΈμλ μ΄λ―Έ κ³μ°κΈ°μ μΈμ¬ λꡬ, κ·Έλ¦¬κ³ μλ² μ 보 리μμ€κ° μμλ‘ κ΅¬νλμ΄ μμ΅λλ€.
3. λΉλ
npm run build
4. μ€ν
node build/index.js
λΉλκ° μ±κ³΅νλ©΄ build/
λλ ν 리μ μ»΄νμΌλ JavaScript νμΌμ΄ μμ±λκ³ , μλ²κ° MCP ν΄λΌμ΄μΈνΈμ μ°κ²°μ λκΈ°ν©λλ€.
π οΈ κ°λ° κ°μ΄λ
MCP λꡬ(Tool) μΆκ°νκΈ°
MCP μλ²μ μλ‘μ΄ λꡬλ₯Ό μΆκ°νλ €λ©΄ server.tool()
λ©μλμ Zod μ€ν€λ§λ₯Ό μ§μ μ μνμ¬ λ±λ‘ν©λλ€:
import { z } from 'zod'
// κ³μ°κΈ° λꡬ μΆκ°
server.tool(
'calculator',
{
operation: z
.enum(['add', 'subtract', 'multiply', 'divide'])
.describe('μνν μ°μ° (add, subtract, multiply, divide)'),
a: z.number().describe('첫 λ²μ§Έ μ«μ'),
b: z.number().describe('λ λ²μ§Έ μ«μ')
},
async ({ operation, a, b }) => {
// μ°μ° μν
let result: number
switch (operation) {
case 'add':
result = a + b
break
case 'subtract':
result = a - b
break
case 'multiply':
result = a * b
break
case 'divide':
if (b === 0) throw new Error('0μΌλ‘ λλ μ μμ΅λλ€')
result = a / b
break
default:
throw new Error('μ§μνμ§ μλ μ°μ°μ
λλ€')
}
const operationSymbols = {
add: '+',
subtract: '-',
multiply: 'Γ',
divide: 'Γ·'
} as const
const operationSymbol =
operationSymbols[operation as keyof typeof operationSymbols]
return {
content: [
{
type: 'text',
text: `${a} ${operationSymbol} ${b} = ${result}`
}
]
}
}
)
λ 볡μ‘ν λꡬ μμ
// λ μ¨ μ 보 μ‘°ν λꡬ
server.tool(
'get_weather',
{
city: z.string().describe('λ μ¨λ₯Ό μ‘°νν λμλͺ
'),
unit: z
.enum(['celsius', 'fahrenheit'])
.optional()
.default('celsius')
.describe('μ¨λ λ¨μ (κΈ°λ³Έκ°: celsius)')
},
async ({ city, unit }) => {
try {
// μ€μ λ μ¨ API νΈμΆ λ‘μ§ (μμ)
const weatherData = await fetchWeatherData(city, unit)
return {
content: [
{
type: 'text',
text: `${city}μ νμ¬ λ μ¨:
μ¨λ: ${weatherData.temperature}Β°${unit === 'celsius' ? 'C' : 'F'}
λ μ¨: ${weatherData.condition}
μ΅λ: ${weatherData.humidity}%
νμ: ${weatherData.windSpeed}km/h`
}
]
}
} catch (error) {
throw new Error(
`λ μ¨ μ 보λ₯Ό κ°μ Έμ¬ μ μμ΅λλ€: ${(error as Error).message}`
)
}
}
)
// λμ°λ―Έ ν¨μ
async function fetchWeatherData(city: string, unit: string) {
// μ€μ λ μ¨ API νΈμΆ ꡬν
// μ¬κΈ°μλ μμ λ°μ΄ν° λ°ν
return {
temperature: unit === 'celsius' ? 22 : 72,
condition: 'λ§μ',
humidity: 65,
windSpeed: 12
}
}
리μμ€ μΆκ°νκΈ°
MCP μλ²μ 리μμ€λ₯Ό μΆκ°νμ¬ μΈλΆ λ°μ΄ν°λ νμΌμ λν μ κ·Όμ μ 곡ν μ μμ΅λλ€:
// 리μμ€ λ±λ‘
server.resource(
'example-file',
'file://example.txt',
{
name: 'μμ ν
μ€νΈ νμΌ',
description: 'μμ ν
μ€νΈ νμΌ μ€λͺ
',
mimeType: 'text/plain'
},
async () => {
return {
contents: [
{
uri: 'file://example.txt',
mimeType: 'text/plain',
text: 'μμ νμΌ λ΄μ©μ
λλ€.'
}
]
}
}
)
// λμ 리μμ€ μμ
server.resource(
'app-settings',
'config://settings',
{
name: 'μ ν리μΌμ΄μ
μ€μ ',
description: 'μ ν리μΌμ΄μ
μ νμ¬ μ€μ μ 보',
mimeType: 'application/json'
},
async () => {
const settings = {
theme: 'dark',
language: 'ko-KR',
notifications: true,
lastUpdated: new Date().toISOString()
}
return {
contents: [
{
uri: 'config://settings',
mimeType: 'application/json',
text: JSON.stringify(settings, null, 2)
}
]
}
}
)
π¦ μ£Όμ μμ‘΄μ±
- @modelcontextprotocol/sdk: MCP νλ‘ν μ½ κ΅¬νμ μν 곡μ SDK
- zod: TypeScript μ°μ μ€ν€λ§ κ²μ¦ λΌμ΄λΈλ¬λ¦¬
- typescript: TypeScript μ»΄νμΌλ¬
π§ μ€ν¬λ¦½νΈ
npm run build
: TypeScriptλ₯Ό JavaScriptλ‘ μ»΄νμΌνκ³ μ€ν κΆν μ€μ
π μ¬μ© μμ
μμ ν μλ² μμ
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { z } from 'zod'
// μλ² μμ±
const server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0',
capabilities: {
tools: {},
resources: {}
}
})
// κ°λ¨ν μΈμ¬ λꡬ
server.tool(
'greet',
{
name: z.string().describe('μΈμ¬ν μ¬λμ μ΄λ¦'),
language: z
.enum(['ko', 'en'])
.optional()
.default('ko')
.describe('μΈμ¬ μΈμ΄ (κΈ°λ³Έκ°: ko)')
},
async ({ name, language }) => {
const greeting =
language === 'ko' ? `μλ
νμΈμ, ${name}λ!` : `Hello, ${name}!`
return {
content: [
{
type: 'text',
text: greeting
}
]
}
}
)
// μμ€ν
μ 보 리μμ€
server.resource(
'system-info',
'system://info',
{
name: 'μμ€ν
μ 보',
description: 'μλ²μ νμ¬ μν λ° μμ€ν
μ 보',
mimeType: 'application/json'
},
async () => {
const systemInfo = {
server: 'my-mcp-server',
version: '1.0.0',
timestamp: new Date().toISOString(),
uptime: process.uptime()
}
return {
contents: [
{
uri: 'system://info',
mimeType: 'application/json',
text: JSON.stringify(systemInfo, null, 2)
}
]
}
}
)
// μλ² μμ
async function main() {
const transport = new StdioServerTransport()
await server.connect(transport)
console.error('MCP μλ²κ° μμλμμ΅λλ€')
}
main().catch(console.error)
π§ Cursor MCP μ°κ²°
κ°λ°ν MCP μλ²λ₯Ό Cursorμμ ν μ€νΈν μ μμ΅λλ€:
μ€μ νμΌ μμ
./.cursor/mcp.json
νμΌμ νΈμ§ν©λλ€:
{
"mcpServers": {
"typescript-mcp-server": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/YOUR/PROJECT/build/index.js"]
}
}
}
μ£Όμ: μ λ κ²½λ‘λ₯Ό μ¬μ©ν΄μΌ ν©λλ€.
pwd
λͺ λ Ήμ΄λ‘ νμ¬ κ²½λ‘λ₯Ό νμΈνμΈμ.
ν μ€νΈ λͺ λ Ήμ΄
Cursor MCPμμ λ€μκ³Ό κ°μ΄ ν μ€νΈν΄λ³Ό μ μμ΅λλ€:
- "5 λνκΈ° 3μ μΌλ§μΌ?" (κ³μ°κΈ° λꡬ ν μ€νΈ)
- "μλ νμΈμ λΌκ³ μΈμ¬ν΄μ€" (μΈμ¬ λꡬ ν μ€νΈ)
- μλ² μ 보 리μμ€ μ‘°ν
π μ°Έκ³ μλ£
- Model Context Protocol 곡μ λ¬Έμ
- MCP TypeScript SDK
- Node.js MCP μλ² κ°λ° κ°μ΄λ
- Zod λ¬Έμ
π λΌμ΄μ μ€
MIT