streamable-httpupdated 7mo ago
TypeScript MCP SDK๋ฅผ ํ์ฉํ์ฌ Model Context Protocol (MCP) ์๋ฒ๋ฅผ ๋น ๋ฅด๊ฒ ๊ฐ๋ฐํ ์ ์๋ ๋ณด์ผ๋ฌํ๋ ์ดํธ ํ๋ก์ ํธ์ ๋๋ค.
ยฟQuรฉ puedes hacer con devbrother2024 typescript mcp server boilerplate?
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
Instalaciรณn
Aรฑade devbrother2024 typescript mcp server boilerplate a tu cliente. Elige el que uses.
claude mcp add --transport http devbrother2024-typescript-mcp-server-boi https://server.smithery.ai/@devbrother2024/typescript-mcp-server-boilerplate/mcpcodex mcp add devbrother2024-typescript-mcp-server-boi --url https://server.smithery.ai/@devbrother2024/typescript-mcp-server-boilerplate/mcp{
"mcpServers": {
"devbrother2024-typescript-mcp-server-boi": {
"url": "https://server.smithery.ai/@devbrother2024/typescript-mcp-server-boilerplate/mcp"
}
}
}Add to `~/.cursor/mcp.json`, or `.cursor/mcp.json` for a single project.
{
"servers": {
"devbrother2024-typescript-mcp-server-boi": {
"type": "http",
"url": "https://server.smithery.ai/@devbrother2024/typescript-mcp-server-boilerplate/mcp"
}
}
}Add to `.vscode/mcp.json` in your workspace.
{
"mcpServers": {
"devbrother2024-typescript-mcp-server-boi": {
"url": "https://server.smithery.ai/@devbrother2024/typescript-mcp-server-boilerplate/mcp"
}
}
}Add to `claude_desktop_config.json`, then restart Claude Desktop.
{
"mcpServers": {
"devbrother2024-typescript-mcp-server-boi": {
"serverUrl": "https://server.smithery.ai/@devbrother2024/typescript-mcp-server-boilerplate/mcp"
}
}
}Add to `~/.codeium/windsurf/mcp_config.json`.
Puntuaciรณn
39 / 100
Incompleta
- Documentaciรณn21/25
- Mantenimiento9/25
- Confianza6/20
- Capacidad0/15
- Instalaciรณn12/15
- Documents what it does and how to connect
- Has a resolvable package or endpoint
- Exposes at least one tool, prompt or resource
- README has substantive content
- Includes a code example
- Documents its configuration
- Mentions credentials or security posture
- Last commit 212 days ago
- Has a release history
- Repository is not archived
- No licence detected
- Namespace verified in the official MCP registry
- Claimed by its owner
- Published under an organisation
- 0 tool(s) documented
- Provides prompt templates
- Provides resources
- 6 documented install method(s)
- Published to a package registry
- Offers a hosted endpoint โ no local install
Historial de versiones
| Versiones | Publicada |
|---|---|
| 1.0.0รltima | 20 sept 2025 |