Skip to main content
Glama
README.md
# Dify 1.13 HTTP MCP 회의실 예약 목업

인증 서버 없이 Dify 1.13의 정적 `Authorization` 헤더로 회의실 예약 MCP를 검증하는 프로젝트입니다.

```text
Dify 1.13 ── Bearer <고정 JWT> ──> MCP 서버 ── 내부 API 키 ──> 회의실 API
```

현재 범위에서는 JWT의 `name=dify`가 실제 사용자 이름이 아니라 고정 서비스 식별자 역할만 합니다. 각 환경에서 토큰을 직접 발급하고, 동일한 토큰을 Dify 헤더와 MCP 서버의 `MCP_STATIC_TOKEN`에 등록해야 합니다.

자세한 절차는 [정적 토큰 연동 가이드](STATIC-TOKEN-DIFY-1.13-GUIDE.md)를 참고하세요.

## 제공 기능

- 회의실 목록 조회
- 회의실 예약 및 시간 중복 방지
- 고정 서비스의 예약 목록 조회
- 토큰 없음·불일치·만료·`name` 누락 시 HTTP 401
- 예약 성공 시 `dify님 예약이 완료되었습니다.` 반환

## 빠른 실행

Docker 설치 과정은 이 문서에서 다루지 않습니다.

```bash
cp .env.example .env

docker compose run --rm --no-deps mcp-server \
  python scripts/mint_dev_token.py
```

출력된 JWT를 `.env`에 등록합니다.

```dotenv
MCP_STATIC_TOKEN=eyJ...
```

서버를 실행합니다.

```bash
docker compose up -d --build --force-recreate
docker compose ps
```

서비스 주소:

- MCP: `http://localhost:8001/mcp`
- 회의실 API 상태: `http://localhost:8000/health`

Dify가 다른 서버에 있다면 `localhost` 대신 Dify에서 접근 가능한 HTTPS URL을 `MCP_PUBLIC_URL`과 Dify MCP 설정에 동일하게 등록합니다.

## Dify 1.13 설정

| 항목 | 값 |
|---|---|
| 서버 URL | `https://<공개주소>/mcp` |
| 헤더 이름 | `Authorization` |
| 헤더 값 | `Bearer eyJ...` |
| OAuth 설정 | 사용하지 않음 |

정적 헤더이므로 Dify 사용자가 달라져도 JWT와 `name=dify`는 바뀌지 않습니다.

## 주요 파일

| 파일 | 역할 |
|---|---|
| `meeting_mock/auth.py` | 고정 토큰 비교, 만료·`sub`·`name` 검사 |
| `meeting_mock/mcp_server.py` | Streamable HTTP MCP와 도구 3개 |
| `meeting_mock/meeting_api.py` | 회의실 및 메모리 예약 저장소 |
| `scripts/mint_dev_token.py` | 각자 사용할 목업 JWT 발급 |
| `scripts/e2e_dify_legacy_client.py` | Dify 1.13 정적 토큰 E2E |

## 테스트

```bash
PYTHONPATH=. uv run --isolated --extra test pytest -q
```

Docker E2E:

```bash
docker compose up -d --build --force-recreate
docker compose exec -T mcp-server python scripts/e2e_dify_legacy_client.py
```

## 목업 한계

- JWT 서명을 인증 서버 공개키로 검증하지 않습니다.
- MCP 서버의 `.env`에 고정된 토큰 문자열 하나만 허용합니다.
- 사용자별 신원을 구분할 수 없습니다.
- 예약 데이터는 컨테이너 재생성 시 초기화됩니다.
- 운영 전환 시 인증 서버, 서명 검증, 짧은 만료, 키 회전, 사용자별 토큰 전달이 필요합니다.