MCP Auth Template
by vcz-Chan
README.md
# MCP Auth Template
실습용 MCP 템플릿입니다.
이 프로젝트는 두 가지 목적을 같이 다룹니다.
- `HTTP 기반 MCP 서버`에서 인증이 어떻게 붙는지 연습
- `stdio 기반 MCP 서버`를 Codex 같은 로컬 MCP 클라이언트에 연결
현재 포함된 기능은 최소 구성입니다.
- `GET /healthz`
- `POST /mcp` with `Bearer token`
- `stdio` MCP entrypoint
- `hello` tool 1개
## 구성
핵심 파일은 아래와 같습니다.
- `src/mcp-server.js`
- 공통 MCP 서버 정의
- `hello` tool 등록
- `src/server.js`
- HTTP MCP 서버
- `/healthz`
- `/mcp` Bearer 인증
- `src/stdio.js`
- stdio MCP 서버
- Codex 같은 로컬 클라이언트용
툴을 추가하는 방법은 별도 문서로 분리했습니다.
- [`docs/ADDING_TOOLS.md`](/Users/leeseungchan/develop/mcp/docs/ADDING_TOOLS.md)
- [`docs/AUTH_SERVER_UPGRADE.md`](/Users/leeseungchan/develop/mcp/docs/AUTH_SERVER_UPGRADE.md)
## 빠른 시작
### 1. 설치
```bash
npm install
```
### 2. 환경 변수 준비
```bash
cp .env.example .env
```
기본값은 아래와 같습니다.
```env
PORT=3000
HOST=127.0.0.1
MCP_BEARER_TOKEN=dev-token
```
## 실행 방식
### HTTP 서버 실행
```bash
npm start
```
또는:
```bash
npm run start:http
```
실행 후:
- health check: `http://127.0.0.1:3000/healthz`
- MCP endpoint: `http://127.0.0.1:3000/mcp`
### stdio 서버 실행
```bash
npm run start:stdio
```
이 방식은 포트를 열지 않습니다.
로컬 MCP 클라이언트가 프로세스를 직접 실행해서 `stdin/stdout`으로 통신합니다.
## Transport 차이
### HTTP
- 네가 직접 서버를 띄워야 함
- `Authorization: Bearer <token>` 필요
- 인증 연습에 적합
### stdio
- MCP 클라이언트가 서버 프로세스를 직접 실행
- 포트 불필요
- Codex 연결에 적합
- HTTP Bearer 인증은 사용하지 않음
중요한 차이:
- `HTTP`: 네가 서버를 먼저 실행
- `stdio`: Codex가 필요할 때 서버를 실행
## HTTP 인증
`/mcp` 요청은 모두 아래 헤더가 필요합니다.
```http
Authorization: Bearer dev-token
```
값은 `.env`의 `MCP_BEARER_TOKEN`으로 변경할 수 있습니다.
인증 실패 시:
- `401 Unauthorized`
- `WWW-Authenticate` 헤더 반환
## HTTP MCP 실습 예제
### 1. Health check
```bash
curl -i http://127.0.0.1:3000/healthz
```
### 2. initialize
```bash
curl -i \
-X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Authorization: Bearer dev-token' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-05",
"capabilities": {},
"clientInfo": {
"name": "curl-client",
"version": "0.1.0"
}
}
}'
```
응답 헤더의 `Mcp-Session-Id` 값을 다음 요청에 재사용합니다.
### 3. initialized notification
```bash
curl -i \
-X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Authorization: Bearer dev-token' \
-H 'Mcp-Session-Id: <session-id>' \
-d '{
"jsonrpc": "2.0",
"method": "notifications/initialized",
"params": {}
}'
```
### 4. tools/list
```bash
curl -i \
-X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Authorization: Bearer dev-token' \
-H 'Mcp-Session-Id: <session-id>' \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'
```
### 5. hello tool 호출
```bash
curl -i \
-X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Authorization: Bearer dev-token' \
-H 'Mcp-Session-Id: <session-id>' \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "hello",
"arguments": {
"name": "MCP"
}
}
}'
```
예상 응답 예시:
```json
{
"result": {
"content": [
{
"type": "text",
"text": "Hello, MCP! This response came from a authenticated HTTP MCP tool at 2026-03-18T05:06:22.258Z."
}
],
"structuredContent": {
"greeting": "Hello, MCP!",
"accessMode": "http",
"server": "mcp-auth-template",
"timestamp": "2026-03-18T05:06:22.258Z"
}
},
"jsonrpc": "2.0",
"id": 3
}
```
## Codex에 연결하기
이 프로젝트를 Codex에 붙일 때는 `HTTP`가 아니라 `stdio`를 사용합니다.
이유:
- Codex가 MCP 서버를 자식 프로세스로 직접 실행할 수 있음
- 포트를 따로 열 필요가 없음
- 로컬 실습이 더 단순함
### Codex 설정
`~/.codex/config.toml`에 아래를 추가합니다.
```toml
[mcp_servers.hello_local]
command = "node"
args = ["/Users/leeseungchan/develop/mcp/src/stdio.js"]
```
이 프로젝트에서 Codex를 바로 쓰려면 trusted project 설정도 있으면 편합니다.
```toml
[projects."/Users/leeseungchan/develop/mcp"]
trust_level = "trusted"
```
### Codex 실행
```bash
cd /Users/leeseungchan/develop/mcp
codex
```
### Codex 안에서 테스트
Codex에 아래처럼 물어보면 됩니다.
```text
사용 가능한 MCP 도구 보여줘
```
```text
hello_local의 hello 툴 호출해줘
```
```text
hello_local의 hello 툴을 name=MCP 로 호출해줘
```
### stdio 방식에서 중요한 점
- `npm run start:stdio`를 미리 켜둘 필요는 없음
- Codex가 필요할 때 `node /Users/leeseungchan/develop/mcp/src/stdio.js`를 직접 실행
- Codex 세션이 끝나면 같이 종료되는 쪽으로 이해하면 됨
## Claude 연결 튜토리얼
이 프로젝트를 Claude 쪽에 붙일 때도 `stdio` 방식을 쓰는 편이 가장 단순합니다.
### 방법 1. Claude Code CLI에서 바로 추가
Anthropic 공식 문서 기준으로 Claude Code는 로컬 stdio MCP 서버를 아래 형태로 추가할 수 있습니다.
```bash
claude mcp add hello-local -- node /Users/leeseungchan/develop/mcp/src/stdio.js
```
추가 후 확인:
```bash
claude mcp list
```
세부 설정 보기:
```bash
claude mcp get hello-local
```
이후 Claude Code를 실행한 뒤 다음처럼 요청하면 됩니다.
```text
사용 가능한 MCP 도구 보여줘
```
```text
hello-local의 hello 툴 호출해줘
```
### 방법 2. Claude Desktop 설정 파일에 직접 추가
Anthropic 공식 문서에는 Claude Desktop에서 `claude_desktop_config.json`의 `mcpServers` 항목으로 MCP 서버를 등록하는 예시가 나옵니다.
이 프로젝트를 붙일 때는 아래처럼 넣으면 됩니다.
```json
{
"mcpServers": {
"hello-local": {
"command": "node",
"args": ["/Users/leeseungchan/develop/mcp/src/stdio.js"],
"env": {}
}
}
}
```
Claude Desktop을 다시 열고 아래처럼 물어보면 됩니다.
```text
사용 가능한 MCP 도구 보여줘
```
```text
hello-local의 hello 툴을 name=Claude 로 호출해줘
```
### 참고
- Claude 쪽 연결도 `HTTP`가 아니라 `stdio` 사용을 권장
- 즉, `npm run start:stdio`를 미리 켜둘 필요 없음
- Claude가 필요할 때 `node /Users/leeseungchan/develop/mcp/src/stdio.js`를 직접 실행
- 팀 공유가 필요하면 Claude Code 문서의 `--scope` 또는 `.mcp.json` 방식을 쓰는 편이 좋음
## 지금 프로젝트에서 확인된 흐름
직접 확인한 동작은 아래입니다.
- HTTP 서버 기동
- `GET /healthz` 정상 응답
- 인증 없는 `/mcp` 요청에 `401`
- 인증된 `initialize`
- `tools/list`
- `tools/call`
- stdio 서버에서 `initialize -> notifications/initialized -> tools/list -> tools/call`
- Codex용 `~/.codex/config.toml`에 `hello_local` 등록
## 다음 확장 포인트
이 템플릿은 여기서 확장하면 됩니다.
- `hello` 말고 툴 추가
- 툴 파일 분리
- Bearer 토큰 비교를 `JWT` 검증으로 교체
- 최종적으로 `OAuth` 기반 인증으로 확장
- `resources` / `prompts` 추가
## 참고
- HTTP 인증 로직: `src/server.js`
- 공통 MCP 툴 등록: `src/mcp-server.js`
- Codex 연결용 stdio 엔트리: `src/stdio.js`
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues