
⚡ MCP 고급 과정 - 커스텀 서버 개발과 프로덕션
고급 과정에 오신 것을 환영합니다!
이제 직접 MCP 서버를 만들고, 프로덕션 환경에 배포하는 방법을 배웁니다.
- TypeScript로 커스텀 MCP 서버 개발
- 인증 및 보안 구현
- 성능 최적화 및 모니터링
- Docker를 활용한 배포
- 실전: 엔터프라이즈급 MCP 서버
📋 사전 준비
- ✅ MCP 초급 + 중급 완료
- ✅ JavaScript/TypeScript 기본
- ✅ Node.js 개발 경험
- ✅ Git 및 npm 사용법
실습 1⭐⭐⭐⭐
첫 커스텀 MCP 서버 만들기
1단계: 프로젝트 초기화
mkdir my-mcp-server
cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript @types/node tsx
2단계: tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true
}
}
3단계: 기본 서버 (src/index.ts)
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({
name: "my-calculator",
version: "1.0.0"
}, {
capabilities: { tools: {} }
});
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: "calculate",
description: "수학 계산",
inputSchema: {
type: "object",
properties: {
op: { type: "string", enum: ["add","sub","mul","div"] },
a: { type: "number" },
b: { type: "number" }
},
required: ["op","a","b"]
}
}]
}));
server.setRequestHandler(CallToolRequestSchema, async (req) => {
if (req.params.name === "calculate") {
const {op,a,b} = req.params.arguments;
let result;
if(op==="add") result=a+b;
else if(op==="sub") result=a-b;
else if(op==="mul") result=a*b;
else if(op==="div") result=a/b;
return { content: [{ type: "text", text: `결과: ${result}` }] };
}
throw new Error("알 수 없는 도구");
});
const transport = new StdioServerTransport();
await server.connect(transport);
4단계: 빌드 및 연결
npm run build
# Claude Desktop 설정
{
"my-calculator": {
"command": "node",
"args": ["/절대경로/my-mcp-server/dist/index.js"]
}
}
실습 2⭐⭐⭐⭐
외부 API 연동 - 날씨 서비스
날씨 도구 추가
npm install node-fetch
// tools/weather.ts
export async function getWeather(city: string) {
const res = await fetch(
`https://wttr.in/${city}?format=j1`
);
const data = await res.json();
const curr = data.current_condition[0];
return `${city} 날씨:
온도: ${curr.temp_C}°C
습도: ${curr.humidity}%
날씨: ${curr.weatherDesc[0].value}`;
}
캐싱 구현
const cache = new Map();
const TTL = 5 * 60 * 1000; // 5분
function getCached(key: string) {
const item = cache.get(key);
if (item && Date.now() - item.time < TTL) {
return item.data;
}
return null;
}
function setCache(key: string, data: any) {
cache.set(key, { data, time: Date.now() });
}
실습 3⭐⭐⭐⭐⭐
리소스와 프롬프트 구현
리소스 기능
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [{
uri: "config://settings",
name: "서버 설정",
mimeType: "application/json"
}]
}));
server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
if (req.params.uri === "config://settings") {
return {
contents: [{
uri: req.params.uri,
mimeType: "application/json",
text: JSON.stringify({
version: "1.0.0",
features: ["calculator", "weather"]
})
}]
};
}
});
프롬프트 템플릿
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
prompts: [{
name: "analyze_weather",
description: "날씨 분석",
arguments: [{
name: "city",
required: true
}]
}]
}));
server.setRequestHandler(GetPromptRequestSchema, async (req) => {
const { name, arguments: args } = req.params;
if (name === "analyze_weather") {
return {
messages: [{
role: "user",
content: {
type: "text",
text: `${args.city}의 날씨를 분석하고:
1. 현재 상태
2. 외출 추천
3. 건강 조언을 제공해주세요`
}
}]
};
}
});
실습 4⭐⭐⭐⭐⭐
보안 및 인증
환경 변수 관리
npm install dotenv
// .env
API_KEY=your_secret_key
MAX_REQUESTS=60
// 코드
import dotenv from 'dotenv';
dotenv.config();
const API_KEY = process.env.API_KEY;
if (!API_KEY) {
throw new Error('API_KEY 필요');
}
Rate Limiting
class RateLimiter {
private requests = new Map();
check(id: string, max: number, windowMs: number) {
const now = Date.now();
const reqs = (this.requests.get(id) || [])
.filter(t => now - t < windowMs);
if (reqs.length >= max) return false;
reqs.push(now);
this.requests.set(id, reqs);
return true;
}
}
const limiter = new RateLimiter();
if (!limiter.check('user', 60, 60000)) {
throw new Error('요청 한도 초과');
}
🔒 보안 체크리스트
- API 키 하드코딩 금지
- 모든 입력 검증
- Rate Limiting 구현
- HTTPS 사용
- 정기 업데이트
실습 5⭐⭐⭐⭐⭐
Docker 배포
Dockerfile 작성
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
CMD ["node", "dist/index.js"]
빌드 및 실행
# 이미지 빌드
docker build -t my-mcp-server .
# 컨테이너 실행
docker run -d \
--name mcp-server \
-e API_KEY=your_key \
my-mcp-server
# 로그 확인
docker logs mcp-server
docker-compose.yml
version: '3.8'
services:
mcp-server:
build: .
environment:
- API_KEY=${API_KEY}
- NODE_ENV=production
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
실습 6⭐⭐⭐⭐⭐
실전: 엔터프라이즈 서버
프로젝트 구조
enterprise-mcp/
├── src/
│ ├── index.ts
│ ├── tools/
│ ├── resources/
│ ├── middleware/
│ ├── utils/
│ └── types/
├── tests/
├── docker/
├── docs/
└── .env.example
모니터링 추가
// 메트릭 수집
class Metrics {
private calls = 0;
private errors = 0;
private latencies: number[] = [];
recordCall(duration: number) {
this.calls++;
this.latencies.push(duration);
}
recordError() {
this.errors++;
}
getStats() {
return {
totalCalls: this.calls,
errors: this.errors,
avgLatency: this.latencies.reduce((a,b)=>a+b,0) / this.calls
};
}
}
헬스 체크
// 리소스로 제공
{
uri: "health://status",
name: "서버 상태",
handler: () => ({
status: "healthy",
uptime: process.uptime(),
memory: process.memoryUsage(),
version: "1.0.0"
})
}
🎉 고급 과정 완료!
프로덕션급 MCP 서버를 개발할 수 있는 능력을 갖추었습니다!
🎓 고급 과정 완료 후 능력
- ✅ TypeScript로 커스텀 MCP 서버 개발
- ✅ 보안 및 인증 구현
- ✅ 성능 최적화 및 모니터링
- ✅ Docker 컨테이너화
- ✅ 엔터프라이즈급 아키텍처
🚀 다음 단계
- 실제 서비스에 배포하기
- CI/CD 파이프라인 구축
- 커뮤니티에 기여하기
- 오픈소스 MCP 서버 개발
📚 추가 학습 자료
- 공식 문서: modelcontextprotocol.io
- GitHub: github.com/modelcontextprotocol
- 예제: awesome-mcp-servers
- 커뮤니티: Discord, Reddit
'AI' 카테고리의 다른 글
| MCP로 AI와 엑셀 연결하기 (1) | 2025.12.15 |
|---|---|
| MCP 서버 실습1 (1) | 2025.12.15 |
| MCP 중급 과정 - 데이터베이스와 API 연동 (1) | 2025.12.15 |
| MCP 초급 과정 - AI의 만능 연결 포트 (1) | 2025.12.15 |
| 삼성 갤럭시 휴대폰의 유용한 기능 (3) | 2025.12.11 |