Skip to main content
Glama
README.md
# 강원대 MCP 서버 (비공식)

강원대학교 춘천캠퍼스의 **공개 정보**를 조회하는 MCP(Model Context Protocol) 서버입니다.
Claude Desktop, Cursor, Cline 등 MCP를 지원하는 클라이언트에서 자연어로 학사일정·학식·공지·버스 정보를 조회할 수 있습니다. 여러 tool을 조합해 "이번주 학식이랑 수강신청 공지 정리해줘" 같은 통합 질문에 한 번에 답하는 것을 목표로 합니다.

강원대는 공식 API가 없어, 이 서버가 사실상 유일한 프로그래매틱 접근점입니다.

> ⚠️ **비공식 프로젝트입니다.** 강원대학교와 무관한 학생 제작 도구이며, 공개 웹페이지 및 공공데이터포털 API에서 정보를 수집합니다. 학교 사이트 구조가 바뀌면 일부 기능이 동작하지 않을 수 있습니다. 로그인이 필요한 정보(수강신청·성적·도서관 좌석 등)는 제공하지 않습니다.

## 설치

```bash
uv sync
```

## 로컬 클라이언트 등록 (Claude Desktop 예시)

`claude_desktop_config.json`에 추가:

```json
{
  "mcpServers": {
    "kangwon": {
      "command": "uv",
      "args": ["run", "--directory", "/절대경로/knu-mcp", "knu-mcp"],
      "env": { "KNU_BUS_API_KEY": "발급받은_공공데이터포털_인증키" }
    }
  }
}
```

`KNU_BUS_API_KEY`는 버스 도착 정보 tool에만 필요합니다(아래 참조). 없으면 버스 tool만 에러를 반환하고 나머지는 정상 동작합니다.

## 제공 도구

| tool | 설명 |
|------|------|
| `get_academic_calendar(year=올해)` | 학사일정(해당 연도 전체) |
| `get_cafeteria_menu(restaurant="백록관", week=0)` | 학식 식단. restaurant: 백록관/천지관/두리, week: 0=이번주,1=다음주 |
| `get_all_cafeteria_menus(week=0)` | 3식당 학식 일괄 |
| `search_notices(query, limit=10)` | 학사공지(메인 홈페이지) 최근분에서 제목 검색 |
| `get_shuttle_schedule()` | 교내 순환버스(두리버스) 시간표. 정규학기만 운영 |
| `get_next_shuttle()` | 두리버스 현재 시각 기준 다음 출발 |
| `get_bus_arrival(stop="강원대정문", route="300")` | 시내버스 실시간 도착. stop: 강원대정문/후문/중앙도서관/백록관/학병원/남춘천역/춘천역/시외버스터미널 |

## 버스 API 키 (get_bus_arrival 전용)

시내버스 실시간 도착은 [공공데이터포털](https://www.data.go.kr) TAGO 버스도착정보 API를 사용합니다.

1. data.go.kr 로그인 → "국토교통부_(TAGO)_버스도착정보" 활용신청(개발계정, 즉시 승인)
2. 발급된 **일반 인증키(Decoding)** 를 환경변수 `KNU_BUS_API_KEY`로 설정

키는 코드에 하드코딩하지 말고 환경변수로만 전달합니다.

## 전송 모드

기본은 로컬 클라이언트용 **stdio**. 원격(클라우드/PlayMCP) 배포 시 **streamable-http**:

```bash
KNU_MCP_TRANSPORT=streamable-http PORT=8000 uv run knu-mcp
# 엔드포인트: http://<host>:<PORT>/mcp
```

환경변수: `KNU_MCP_TRANSPORT`(stdio|sse|streamable-http, 기본 stdio), `PORT`(http 포트, 기본 8000).

## Docker로 배포

원격 배포는 컨테이너 이미지로 하는 것이 간단합니다. streamable-http 전송이 기본으로 설정되어 있습니다.

```bash
docker build -t knu-mcp .
docker run -d --restart unless-stopped -p 8000:8000 \
  -e KNU_BUS_API_KEY=<공공데이터포털_인증키> knu-mcp
# 엔드포인트: http://<host>:8000/mcp
```

- `PORT` 환경변수를 주입하면 그 포트로 뜹니다(클라우드 플랫폼이 자동 주입하는 경우 그대로 동작).
- 이미지에 `HEALTHCHECK`가 포함되어 있어 `/mcp` 핸드셰이크로 상태를 확인합니다.
- API 키는 이미지에 넣지 말고 런타임에 `-e`로만 주입하세요.

## 프로젝트 구조

```
knu_mcp/
  server.py       # FastMCP 서버, tool 7개 등록
  http.py         # 공용 HTTP(get/post) + 10분 TTL 캐시
  academic.py     # 학사일정 (scheduleData 파싱)
  cafeteria.py    # 학식 (POST + 표 파싱)
  notices.py      # 공지 검색 (목록 파싱)
  shuttle.py      # 두리버스 시간표 / 다음 차
  bus.py          # 시내버스 실시간 도착 (TAGO API)
tests/            # 파서 단위 테스트 (fixture 기반, 네트워크 안 탐)
scripts/e2e_smoke.py  # 실 네트워크 E2E 스모크
```

각 소스 모듈은 하나의 데이터 소스만 담당하며 서로 의존하지 않습니다.

## 데이터 출처

- 학사일정·학식·공지·두리버스: `www.kangwon.ac.kr` 공개 페이지 (스크래핑)
- 시내버스 실시간 도착: [공공데이터포털](https://www.data.go.kr) 국토교통부 TAGO 버스도착정보 API

## 개발

```bash
uv run pytest              # 단위 테스트 (네트워크 안 탐, fixture 기반)
KNU_BUS_API_KEY=<키> uv run python scripts/e2e_smoke.py   # E2E 스모크 (실 네트워크 왕복)
```

새 기능은 파서 단위 테스트를 먼저 작성(TDD)하고, 외부 사이트/API 실패 시 예외 대신 `{"error": ...}`를 반환하는 규칙을 따릅니다.

## 라이선스

MIT

TDQS

A3.8/5.0

Scored across 7 tools

Disambiguation4/5

Most tools target distinct resources: notices, bus arrivals, academic calendar, etc. The main overlap is between get_cafeteria_menu and get_all_cafeteria_menus (single vs. all restaurants), and between get_next_shuttle and get_shuttle_schedule (next departure vs. full timetable), but the descriptions make these differences clear.

Naming Consistency4/5

The naming pattern is predominantly get_<noun>, with one search_notices exception. All names use lower_snake_case and are readable, but the mix of 'get' and 'search' plus the get_ vs get_all_ prefix variation creates minor inconsistency.

Tool Count5/5

Seven tools is well within the ideal 3-15 range for a university information server. Each tool addresses a distinct user need (meals, notices, shuttles, city buses, calendar) without redundancy or bloat.

Completeness4/5

The tool surface covers the main information needs for the university domain: cafeteria, shuttle, bus, notices, and academic calendar. Minor gaps exist, such as no direct route info for shuttles or detailed notice content retrieval, but these are workable limitations rather than critical dead ends.

Maintenance

ActivitySlowing
ResponsivenessNo issues