Skip to main content
Glama
vcz-Chan

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`