my-mcp-server
TypeScript MCP Server — Vercel 배포용 보일러플레이트
Model Context Protocol (MCP) 서버 보일러플레이트입니다. 하나의 도구 정의를 두 개의 트랜스포트가 공유합니다.
Streamable HTTP — Next.js App Router 라우트(
/api/mcp), Vercel 배포용stdio — 로컬에서
node build/index.js로 실행하는 기존 방식
📁 프로젝트 구조
typescript-mcp-server-boilerplate/
├── app/
│ ├── api/mcp/route.ts # Streamable HTTP 엔드포인트 (mcp-handler)
│ ├── layout.tsx # 랜딩 페이지 레이아웃
│ ├── page.tsx # 서버 정보 안내 페이지
│ ├── page.module.css
│ └── globals.css
├── src/
│ ├── mcp/register.ts # 도구/프롬프트/리소스 정의 (공용)
│ └── index.ts # stdio 진입점
├── build/ # stdio 빌드 산출물
├── next.config.ts
├── tsconfig.json # Next.js용
├── tsconfig.stdio.json # stdio 빌드용
└── package.json핵심은 src/mcp/register.ts의 registerAll(server, options) 함수입니다. 도구를 추가하려면 이 파일만 수정하면 HTTP와 stdio 양쪽에 동시에 반영됩니다.
🛠️ 제공 기능
도구 | 설명 | 토큰 필요 |
| 이름과 언어로 인사말 생성 | |
| 두 숫자의 사칙연산 | |
| timezone 또는 도시명의 현재 시각 | |
| 도시명 → 위경도 (Open-Meteo) | |
| 위경도 → 현재 날씨와 일별 예보 (Open-Meteo) | |
| 프롬프트 → 이미지 생성 (FLUX.1-schnell) | ✅ |
이 외에 프롬프트 code-review와 리소스 server-info(info://server)를 제공합니다.
🔑 HuggingFace 토큰 전달 방식
generate-image 도구는 HuggingFace 토큰이 필요합니다. 토큰은 https://hf.co/settings/tokens 에서 발급합니다.
HTTP 트랜스포트는 두 가지 경로를 지원하며, 헤더가 환경변수보다 우선합니다.
x-hf-token 헤더 → 없으면 → 서버의 HF_TOKEN 환경변수덕분에 서버에 토큰을 두지 않고도 각 클라이언트가 자기 토큰을 쓸 수 있습니다. stdio 트랜스포트는 HF_TOKEN 환경변수만 사용합니다.
mcp-handler 1.x가 사용하는
StreamableHTTPServerTransport는 도구 콜백에 HTTP 헤더를 전달하지 않습니다. 그래서 app/api/mcp/route.ts에서 요청마다 헤더를 읽어registerAll에 클로저로 주입합니다.
🚀 로컬 개발 (HTTP)
1. 의존성 설치
npm install2. 환경변수 설정 (선택)
x-hf-token 헤더로 토큰을 전달할 계획이라면 생략해도 됩니다.
cp .env.example .env.local
# .env.local 에 HF_TOKEN=hf_xxx 입력3. 개발 서버 실행
npm run devMCP 엔드포인트: http://localhost:3000/api/mcp
안내 페이지: http://localhost:3000
4. MCP Inspector로 테스트
npx @modelcontextprotocol/inspector브라우저에서 http://127.0.0.1:6274 접속
왼쪽 드롭다운에서 Streamable HTTP 선택
URL에
http://localhost:3000/api/mcp입력Configuration 을 펼쳐 터미널에 출력된 Proxy Session Token 붙여넣기
Connect → List Tools 로 도구 확인
generate-image를 테스트하려면 Inspector의 커스텀 헤더 설정에 x-hf-token을 추가하세요.
🖥️ 로컬 개발 (stdio)
npm run build:stdio
npm run start:stdio☁️ Vercel 배포
npm i -g vercel
vercel또는 GitHub 저장소를 Vercel 프로젝트에 연결하면 push마다 자동 배포됩니다.
배포 후 서버 쪽 폴백 토큰이 필요하면 환경변수를 등록합니다.
vercel env add HF_TOKEN배포 URL의 엔드포인트는 https://<your-project>.vercel.app/api/mcp 입니다.
app/api/mcp/route.ts는
runtime = 'nodejs'로 설정되어 있습니다.generate-image가Buffer를 사용하므로 Edge 런타임에서는 동작하지 않습니다.
🔧 MCP 클라이언트 연결
Cursor
.cursor/mcp.json (프로젝트) 또는 ~/.cursor/mcp.json (전역):
{
"mcpServers": {
"my-mcp-server": {
"url": "https://<your-project>.vercel.app/api/mcp",
"headers": {
"x-hf-token": "hf_xxx"
}
}
}
}로컬 개발 중이라면 URL만 http://localhost:3000/api/mcp로 바꿉니다.
Streamable HTTP를 지원하지 않는 클라이언트
mcp-remote로 stdio ↔ HTTP 브릿지를 사용합니다.
{
"mcpServers": {
"my-mcp-server": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://<your-project>.vercel.app/api/mcp",
"--header",
"x-hf-token:hf_xxx"
]
}
}
}테스트 명령어
"5 더하기 3은 얼마야?" (
calculator)"삿포로 날씨 알려줘" (
geocode→get-weather)"우주를 나는 고양이 이미지 만들어줘" (
generate-image)
🧩 도구 추가하기
src/mcp/register.ts의 registerAll 안에 server.registerTool을 추가합니다.
server.registerTool(
'reverse-text',
{
description: '입력한 문자열을 뒤집어 반환합니다.',
inputSchema: z.object({
text: z.string().describe('뒤집을 문자열')
}),
outputSchema: textOutputSchema('뒤집힌 문자열')
},
async ({ text }) => toolResult([...text].reverse().join(''))
)외부 비밀정보가 필요한 도구라면 process.env를 직접 읽지 말고 RegisterOptions에 필드를 추가해 주입받으세요. 그래야 클라이언트별 헤더 전달이 가능합니다.
🔧 스크립트
스크립트 | 설명 |
| Next.js 개발 서버 (HTTP 트랜스포트) |
| Next.js 프로덕션 빌드 |
| Next.js 프로덕션 서버 |
| stdio 서버를 |
| 컴파일된 stdio 서버 실행 |
| 양쪽 tsconfig 타입 검사 |
📦 주요 의존성
next: App Router 라우트 핸들러로 HTTP 엔드포인트 제공
mcp-handler: MCP 서버를 Web 표준
Request → Response핸들러로 변환 (1.0.6 고정 — 상위 버전은 SDK 버전을 정확히 고정하므로 peer 충돌)@modelcontextprotocol/sdk: MCP 공식 SDK
@huggingface/inference: 이미지 생성
zod: 스키마 검증
🔗 참고 자료
📄 라이선스
MIT