Skip to main content
Glama

TypeScript MCP Server (Streamable HTTP + stdio)

Next.js와 mcp-handler로 동작하는 MCP(Model Context Protocol) 서버입니다. Vercel에 배포 가능한 Streamable HTTP 전송을 기본으로 하고, 로컬 디버깅용 stdio 진입점도 함께 제공합니다.

📁 프로젝트 구조

├── app/
│   ├── layout.tsx, page.tsx, globals.css   # 사용 방법을 안내하는 랜딩 페이지
│   ├── api/[transport]/route.ts            # MCP 엔드포인트 (/api/mcp)
│   └── api/server-info/route.ts            # server-info 리소스용 JSON 엔드포인트
├── src/
│   ├── mcp/register.ts                     # 도구/리소스/프롬프트 등록 (HTTP·stdio 공용)
│   └── stdio.ts                            # 로컬 stdio 진입점
├── next.config.ts
├── tsconfig.json                           # Next.js용
└── tsconfig.stdio.json                     # stdio 빌드용 (tsc → build/)

도구 정의는 전송 방식과 무관하게 src/mcp/register.ts 한 곳에만 존재하고, 환경 차이(토큰 출처, 파일 저장 가능 여부, 리소스 URI)는 옵션으로 주입합니다.

🚀 시작하기

npm install
npm run dev          # http://localhost:3000 , MCP 엔드포인트는 /api/mcp

스크립트

명령

설명

npm run dev

Next.js 개발 서버 (Streamable HTTP)

npm run build / npm start

Next.js 프로덕션 빌드/실행

npm run build:stdio

stdio 진입점을 build/stdio.js로 컴파일

npm run start:stdio

컴파일된 stdio 서버 실행

npm run typecheck

두 tsconfig 모두 타입 검사

🔌 MCP 클라이언트 연결

Streamable HTTP (권장)

.cursor/mcp.json에 URL과 헤더를 지정합니다. 이 파일은 토큰을 포함하므로 .gitignore에 등록되어 있습니다.

{
    "mcpServers": {
        "My_MCP_Server_1": {
            "url": "https://<your-deployment>.vercel.app/api/mcp",
            "headers": {
                "x-hf-token": "hf_..."
            }
        }
    }
}

로컬 개발 중에는 http://localhost:3000/api/mcp를 사용하세요. stdio만 지원하는 클라이언트는 mcp-remote로 연결할 수 있습니다.

stdio (로컬 디버깅)

{
    "mcpServers": {
        "My_MCP_Server_1": {
            "command": "node",
            "args": ["/ABSOLUTE/PATH/TO/build/stdio.js"],
            "env": { "HF_TOKEN": "hf_..." }
        }
    }
}

🔑 HF_TOKEN 전달 (x-hf-token)

generate-image 도구는 HuggingFace Inference API를 사용하므로 토큰이 필요합니다. 토큰은 다음 순서로 결정됩니다.

  1. 요청의 x-hf-token 커스텀 헤더 (클라이언트가 요청 단위로 전달, 서버에 저장되지 않음)

  2. 서버 환경변수 HF_TOKEN (Vercel 프로젝트 환경변수 또는 stdio 실행 시 env)

헤더는 app/api/[transport]/route.ts에서 요청마다 읽어 도구 등록 시점에 주입합니다.

const handler = async (request: Request) => {
    const hfToken =
        request.headers.get('x-hf-token')?.trim() || process.env.HF_TOKEN
    // ...요청마다 createMcpHandler를 생성
}

토큰이 없으면 도구가 실패 대신 설정 안내 메시지를 반환합니다.

🛠️ 제공 기능

종류

이름

설명

Tool

greet

이름과 언어로 인사말 생성

Tool

calculator

두 숫자와 연산자(+, -, *, /) 계산

Tool

get-time

IANA timezone 또는 도시 이름으로 현재 시간 조회

Tool

geocode

도시/주소 → 위도·경도 (Nominatim)

Tool

get-weather

도시/주소 → 현재 날씨 (Open-Meteo)

Tool

generate-image

프롬프트 → 이미지 생성 (FLUX.1-schnell)

Tool

get-server-info

서버 이름/버전/도구 목록 반환

Resource

server-info

서버 기본 정보 JSON

Prompt

code-review

규칙 기반 코드 리뷰 프롬프트

전송 방식에 따른 차이

Vercel 서버리스 함수는 파일시스템이 읽기 전용이므로 다음 동작이 갈립니다.

항목

HTTP (Vercel)

stdio (로컬)

generate-image 결과

base64 이미지로만 반환

generated-images/에 저장 후 경로 반환

server-info 리소스 URI

https://<host>/api/server-info

~/.cursor/mcp-resources/.../server-info.json

HF 토큰 출처

x-hf-token 헤더 → HF_TOKEN

HF_TOKEN 환경변수

☁️ Vercel 배포

npx vercel
npx vercel env add HF_TOKEN     # 헤더 미전달 시 사용할 fallback (선택)
npx vercel --prod

배포 후 https://<deployment>/api/mcp를 클라이언트에 등록하면 됩니다. 인증이 필요하면 mcp-handlerwithMcpAuth로 OAuth를 추가할 수 있습니다.

🧪 로컬 테스트

npx @modelcontextprotocol/inspector

Inspector에서 전송 방식을 Streamable HTTP로 선택하고 http://localhost:3000/api/mcp에 연결합니다.

📦 주요 의존성

  • next, react: HTTP 라우트 및 랜딩 페이지

  • mcp-handler: MCP 서버를 Web 표준 Request 핸들러로 변환 (Streamable HTTP)

  • @modelcontextprotocol/sdk: MCP 프로토콜 구현 (mcp-handler@1.x1.26.0을 요구하므로 버전 고정)

  • @huggingface/inference: 이미지 생성

  • zod: 입력/출력 스키마 정의

🔗 참고 자료

📄 라이선스

MIT