Skip to main content
Glama
README.md
# ๐ŸŽ“ CAU e-class MCP

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**๋ธŒ๋ผ์šฐ์ € ์—†์ด Claude์—์„œ ๋ฐ”๋กœ ์ค‘์•™๋Œ€ e-class๋ฅผ ํ™•์ธํ•˜์„ธ์š”!**

๊ณต์ง€์‚ฌํ•ญ, ๊ณผ์ œ, ๊ฐ•์˜์ž๋ฃŒ๋ฅผ Claude์™€ ๋Œ€ํ™”ํ•˜๋ฉด์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” MCP ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.

> โš ๏ธ ํ•™์ƒ์ด ๋งŒ๋“  **๋น„๊ณต์‹** ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ค‘์•™๋Œ€ํ•™๊ต์™€ ๋ฌด๊ด€ํ•˜๋ฉฐ, ์‚ฌ์šฉ์— ๋”ฐ๋ฅธ ์ฑ…์ž„์€ ๋ณธ์ธ์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค.

---

## โœจ ์ด๋Ÿฐ ๊ฑธ ํ•  ์ˆ˜ ์žˆ์–ด์š”

| ๊ธฐ๋Šฅ | ์„ค๋ช… |
|---|---|
| ๐Ÿ“‹ **๋Œ€์‹œ๋ณด๋“œ** | ์ˆ˜๊ฐ• ์ค‘์ธ ์ „์ฒด ๊ณผ๋ชฉ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ |
| ๐Ÿ“… **๋ฐ์ผ๋ฆฌ ๋ธŒ๋ฆฌํ•‘** | ์˜ค๋Š˜ ํ•  ์ผ, ์ชฝ์ง€, ๊ณต์ง€์‚ฌํ•ญ์„ ํ•œ ๋ฒˆ์— ์š”์•ฝ |
| ๐Ÿ“ **ํ†ตํ•ฉ ์ƒ์„ธ ์กฐํšŒ** | ๊ณผ๋ชฉ๋ณ„ ๊ฐ•์˜(์ถœ์„ ํฌํ•จ), ๊ณผ์ œ, ์ž๋ฃŒ์‹ค ์ •๋ณด ์กฐํšŒ |
| ๐ŸŽฅ **VOD ์ง๋งํฌ** | ๋™์˜์ƒ ๊ฐ•์˜์˜ ์‹ค์ œ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฃผ์†Œ ์ถ”์ถœ |
| ๐Ÿ“‚ **์ง€๋Šฅํ˜• ๋‹ค์šด๋กœ๋“œ** | ํŒŒ์ผ๋ช… ๋ณ€๊ฒฝ ๋ฐ ๊ณผ๋ชฉ๋ณ„ ํด๋” ์ž๋™ ๊ด€๋ฆฌ ๋‹ค์šด๋กœ๋“œ |
| ๐ŸŒ **Web UI** | ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ธ์ฆ ์„ค์ • + ์„œ๋ฒ„ ๋ชจ๋‹ˆํ„ฐ๋ง |

---

## ๐Ÿš€ ์‹œ์ž‘ํ•˜๊ธฐ

### ํ•„์š”ํ•œ ๊ฒƒ

- **Python 3.10** ์ด์ƒ
- **์ค‘์•™๋Œ€ ํฌํƒˆ ๊ณ„์ •** (ํ•™๋ฒˆ + ๋น„๋ฐ€๋ฒˆํ˜ธ)
- **Claude Code** ([์„ค์น˜ ๋งํฌ](https://claude.com/code))

### Step 1: ์„ค์น˜

**๋ฐฉ๋ฒ• A) GitHub์—์„œ ๋ฐ”๋กœ ์„ค์น˜** (๊ฐ€์žฅ ๊ฐ„๋‹จ)

```bash
pip install git+https://github.com/legendwon/cau-eclass-mcp.git
```

**๋ฐฉ๋ฒ• B) ์ง์ ‘ ํด๋ก ํ•ด์„œ ์„ค์น˜** (๊ฐœ๋ฐœ์šฉ)

```bash
git clone https://github.com/legendwon/cau-eclass-mcp.git
cd cau-eclass-mcp
pip install -e .
```

> ๐Ÿ’ก **venv๋ฅผ ์“ฐ๊ณ  ์žˆ๋‹ค๋ฉด?** ๋ฐ˜๋“œ์‹œ ํ•ด๋‹น venv์˜ pip์œผ๋กœ ์„ค์น˜ํ•˜์„ธ์š”:
> ```bash
> # Windows
> .\venv\Scripts\pip.exe install -e .
> 
> # macOS/Linux
> ./venv/bin/pip install -e .
> ```

### Step 2: ์ธ์ฆ ์„ค์ •

์ตœ์ดˆ 1ํšŒ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. 3๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์ค‘ ํŽธํ•œ ๊ฑธ ๊ณจ๋ผ์ฃผ์„ธ์š”:

#### ๐Ÿ” ๋ฐฉ๋ฒ• 1: OS ํ‚ค๋ง์— ์ €์žฅ (์ถ”์ฒœ)

๊ฐ€์žฅ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค. ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์šด์˜์ฒด์ œ์˜ ๋ณด์•ˆ ์ €์žฅ์†Œ์— ์•”ํ˜ธํ™”๋˜์–ด ์ €์žฅ๋ผ์š”.

```bash
python -c "from cau_eclass_mcp.utils.credentials import CredentialManager; m = CredentialManager(); m.prompt_for_credentials()"
```

ํ•™๋ฒˆ๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋!

- Windows โ†’ ์ž๊ฒฉ ์ฆ๋ช… ๊ด€๋ฆฌ์ž
- macOS โ†’ ํ‚ค์ฒด์ธ
- Linux โ†’ GNOME Keyring / KWallet

#### ๐ŸŒ ๋ฐฉ๋ฒ• 2: Web UI์—์„œ ์„ค์ •

ํ„ฐ๋ฏธ๋„์ด ๋ถˆํŽธํ•˜๋‹ค๋ฉด ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ๋„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”:

```bash
python -m cau_eclass_mcp --sse
```

๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:8000 ์„ ์—ด๊ณ , ํ•™๋ฒˆ/๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

#### โšก ๋ฐฉ๋ฒ• 3: ํ™˜๊ฒฝ๋ณ€์ˆ˜

์ž„์‹œ๋กœ ์“ฐ๊ฑฐ๋‚˜ CI/CD์—์„œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค:

```bash
# Windows (PowerShell)
$env:CAU_USERNAME="ํ•™๋ฒˆ"
$env:CAU_PASSWORD="๋น„๋ฐ€๋ฒˆํ˜ธ"

# macOS/Linux
export CAU_USERNAME="ํ•™๋ฒˆ"
export CAU_PASSWORD="๋น„๋ฐ€๋ฒˆํ˜ธ"
```

#### ๐Ÿคท ๋ฐฉ๋ฒ• 4: ๊ทธ๋ƒฅ ์‹คํ–‰ํ•˜๊ธฐ

์•„๋ฌด ์„ค์ • ์•ˆ ํ•ด๋„ ์ฒซ ์‹คํ–‰ ์‹œ ์ž๋™์œผ๋กœ ๋ฌผ์–ด๋ด…๋‹ˆ๋‹ค!

### Step 3: Claude Code์— ์—ฐ๊ฒฐ

Claude Code๊ฐ€ ์ด MCP ์„œ๋ฒ„๋ฅผ ์ธ์‹ํ•˜๋„๋ก ์„ค์ • ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.

**๋ชจ๋“  ํ”„๋กœ์ ํŠธ์—์„œ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด** โ†’ `~/.claude/claude.json` ํŽธ์ง‘:

```json
{
  "mcpServers": {
    "cau-eclass": {
      "command": "python",
      "args": ["-m", "cau_eclass_mcp"]
    }
  }
}
```

> Windows ๊ฒฝ๋กœ: `C:\Users\์‚ฌ์šฉ์ž์ด๋ฆ„\.claude\claude.json`

**ํŠน์ • ํ”„๋กœ์ ํŠธ์—์„œ๋งŒ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด** โ†’ ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— `.mcp.json` ์ƒ์„ฑ:

```json
{
  "mcpServers": {
    "cau-eclass": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "cau_eclass_mcp"]
    }
  }
}
```

> ๐Ÿ’ก **venv๋ฅผ ์“ฐ๊ณ  ์žˆ๋‹ค๋ฉด?** `"command"`๋ฅผ venv์˜ python ๊ฒฝ๋กœ๋กœ ๋ฐ”๊ฟ”์ฃผ์„ธ์š”:
> ```json
> {
>   "mcpServers": {
>     "cau-eclass": {
>       "type": "stdio",
>       "command": "D:\\๊ฒฝ๋กœ\\cau-eclass-mcp\\venv\\Scripts\\python.exe",
>       "args": ["-m", "cau_eclass_mcp"],
>       "cwd": "D:\\๊ฒฝ๋กœ\\cau-eclass-mcp",
>       "env": {
>         "PYTHONPATH": "D:\\๊ฒฝ๋กœ\\cau-eclass-mcp\\src"
>       }
>     }
>   }
> }
> ```

์„ค์ • ํ›„ **Claude Code๋ฅผ ์žฌ์‹œ์ž‘**ํ•˜๋ฉด ๋!

---

## ๐Ÿ’ฌ ์‚ฌ์šฉ๋ฒ•

Claude Code์—์„œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋งํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค:

```
๋‚˜: "e-class ์˜ค๋Š˜ ๋ฌด์Šจ ์ผ ์žˆ์–ด?"
Claude: [์˜ค๋Š˜ ๋งˆ๊ฐ์ธ ๊ณผ์ œ, ์ฝ์ง€ ์•Š์€ ์ชฝ์ง€, ์ตœ์‹  ๊ณต์ง€์‚ฌํ•ญ ์š”์•ฝ ํ‘œ์‹œ]

๋‚˜: "์šด์ฒด๋ณด ์ด๋ฒˆ ์ฃผ ๊ฐ•์˜ ๋ชฉ๋ก ๋ณด์—ฌ์ค˜"
Claude: [์ฃผ์ฐจ๋ณ„ ๊ฐ•์˜ ๋ชฉ๋ก + ๋™์˜์ƒ ์‹œ์ฒญ ์™„๋ฃŒ ์—ฌ๋ถ€ ํ‘œ์‹œ]

๋‚˜: "์ธ๊ณต์ง€๋Šฅ ๊ณผ์ œ ํ™•์ธํ•ด์ค˜"
Claude: [๊ณผ์ œ ๋ชฉ๋ก + ๋งˆ๊ฐ์ผ + ์ œ์ถœ ์ƒํƒœ ํ‘œ์‹œ]

๋‚˜: "1์ฃผ์ฐจ ๊ฐ•์˜์•ˆ ๋‹ค์šด๋กœ๋“œํ•ด์ค˜"
Claude: [ํŒŒ์ผ๋ช…์„ '1์ฃผ์ฐจ_๊ฐ•์˜์•ˆ.pdf'๋กœ ๋ฐ”๊พธ๊ณ  '์šด์ฒด๋ณด' ํด๋”์— ์ €์žฅ]

๋‚˜: "๊ฐ•์˜ ์˜์ƒ ๋งํฌ ์ถ”์ถœํ•ด์ค˜"
Claude: [๋™์˜์ƒ ์ง๋งํฌ์™€ ํ™”์งˆ๋ณ„ URL ์ œ๊ณต]
```

---

## ๐ŸŒ Web UI ๋ชจ๋“œ (SSE)

ํ„ฐ๋ฏธ๋„ ๋Œ€์‹  ๋ธŒ๋ผ์šฐ์ €์—์„œ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด SSE ๋ชจ๋“œ๋กœ ์‹คํ–‰ํ•˜์„ธ์š”:

```bash
# ๊ธฐ๋ณธ ์‹คํ–‰ (http://localhost:8000)
python -m cau_eclass_mcp --sse

# ํฌํŠธ ๋ณ€๊ฒฝ
python -m cau_eclass_mcp --sse --port 9000
```

๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:8000 ์„ ์—ด๋ฉด:

- **์ธ์ฆ ์„ค์ •** โ€” ํ•™๋ฒˆ/๋น„๋ฐ€๋ฒˆํ˜ธ ๋“ฑ๋ก, ํ™•์ธ, ์‚ญ์ œ
- **์„œ๋ฒ„ ์ƒํƒœ** โ€” ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง, ์ธ์ฆ ์ƒํƒœ, ๊ฐ€๋™ ์‹œ๊ฐ„
- **API ๋ฌธ์„œ** โ€” http://localhost:8000/docs ์—์„œ Swagger UI ํ™•์ธ

์ข…๋ฃŒํ•˜๋ ค๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ `Ctrl+C`

---

## ๐Ÿ”ง MCP ๋„๊ตฌ ๋ชฉ๋ก

Claude Code์—์„œ ์ž๋™์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋„๊ตฌ๋“ค์ž…๋‹ˆ๋‹ค:

| ๋„๊ตฌ | ์„ค๋ช… | ํŒŒ๋ผ๋ฏธํ„ฐ |
|---|---|---|
| `get_dashboard` | ์ „์ฒด ์ˆ˜๊ฐ• ๊ณผ๋ชฉ ์กฐํšŒ | ์—†์Œ |
| `get_daily_briefing` | **(์ถ”์ฒœ)** ํ†ตํ•ฉ ๋ฐ์ผ๋ฆฌ ๋ธŒ๋ฆฌํ•‘ | ์—†์Œ |
| `get_course_details` | ๊ฐ•์˜/๊ณผ์ œ/์ž๋ฃŒ์‹ค ์ƒ์„ธ ์กฐํšŒ | `course_id`, `content_type` ('weekly', 'assignments', 'files') |
| `download_file` | ์Šค๋งˆํŠธ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ | `course_id`, `file_id`, `save_path` |
| `get_vod_info` | ๋™์˜์ƒ ์ŠคํŠธ๋ฆฌ๋ฐ ๋งํฌ ์ถ”์ถœ | `content_id` |

---

## ๐Ÿ—๏ธ ๊ธฐ์ˆ  ๊ตฌ์กฐ

### CAU-ON & LearningX ํ†ตํ•ฉ

์ค‘์•™๋Œ€๋Š” Canvas ๊ธฐ๋ฐ˜์˜ **CAU-ON**๊ณผ ๋™์˜์ƒ/์ถœ์„ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ **LearningX**๋ฅผ ํ˜ผํ•ฉํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ณธ MCP ์„œ๋ฒ„๋Š” ์ด ๋‘ ์‹œ์Šคํ…œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

1. CAU SSO ํฌํƒˆ์—์„œ RSA ์•”ํ˜ธํ™”๋กœ ๋กœ๊ทธ์ธ
2. API๊ฐ€ ํ™œ์„ฑํ™”๋œ ์„ธ์…˜ ์ฟ ํ‚ค ๋ฐ JWT ํ† ํฐ ํš๋“
3. Canvas API ๋ฐ LearningX API (`xn_api_token`) ํ†ตํ•ฉ ์š”์ฒญ
4. OCS XML ํŒŒ์‹ฑ์„ ํ†ตํ•œ VOD ์ŠคํŠธ๋ฆฌ๋ฐ ์ฃผ์†Œ ์ถ”์ถœ

### ์ธ์ฆ ํ๋ฆ„

```
ํ•™๋ฒˆ/๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ โ†’ SSO ๋กœ๊ทธ์ธ โ†’ RSA ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™” โ†’ Canvas ์„ธ์…˜
                โ†’ API ํ™œ์„ฑ ์ฟ ํ‚ค ํš๋“ โ†’ CAU-ON API ์š”์ฒญ
```

- ์„œ๋ฒ„๊ฐ€ ์ œ๊ณตํ•˜๋Š” RSA ๊ฐœ์ธํ‚ค๋กœ ํด๋ผ์ด์–ธํŠธ ์ธก ์•”ํ˜ธํ™” (ํŠน์ดํ•œ ๊ตฌ์กฐ!)
- PKCS1v15 ํŒจ๋”ฉ
- HTTP/2 ํ•„์ˆ˜
- `Referer` ํ—ค๋”๊ฐ€ ์„ธ์…˜ ์—…๊ทธ๋ ˆ์ด๋“œ์— ํ•„์ˆ˜
- ์„ธ์…˜ ์ฟ ํ‚ค: 208์ž (๊ธฐ๋ณธ) โ†’ 421์ž (API ํ™œ์„ฑ)

---

## โ“ ๋ฌธ์ œ ํ•ด๊ฒฐ

### "Failed to authenticate with CAU SSO"

- ํ•™๋ฒˆ/๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋งž๋Š”์ง€ ํ™•์ธ
- Web UI์—์„œ ๋‹ค์‹œ ์„ค์ •: http://localhost:8000 (SSE ๋ชจ๋“œ)
- ๋˜๋Š” ๊ธฐ์กด ์ธ์ฆ ์ •๋ณด ์‚ญ์ œ ํ›„ ์žฌ๋“ฑ๋ก:
  ```bash
  python -c "from cau_eclass_mcp.utils.credentials import CredentialManager; m = CredentialManager(); m.delete_credentials()"
  ```

### "Keyring not available"

ํ‚ค๋ง์ด ์•ˆ ๋˜๋ฉด ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”:
```bash
$env:CAU_USERNAME="ํ•™๋ฒˆ"
$env:CAU_PASSWORD="๋น„๋ฐ€๋ฒˆํ˜ธ"
```

### MCP ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•˜์ง€ ์•Š์„ ๋•Œ

1. ์ง์ ‘ ์‹คํ–‰ํ•ด์„œ ์—๋Ÿฌ ํ™•์ธ:
   ```bash
   python -m cau_eclass_mcp          # stdio ๋ชจ๋“œ
   python -m cau_eclass_mcp --sse    # SSE ๋ชจ๋“œ
   ```
2. Claude Code ๋กœ๊ทธ ํ™•์ธ
3. `.mcp.json` ๋˜๋Š” `claude.json` ์„ค์ • ํ™•์ธ

### ์„ธ์…˜ ๋งŒ๋ฃŒ ์—๋Ÿฌ

์„ธ์…˜์€ 30๋ถ„ ๋™์•ˆ ์บ์‹œ๋˜๋ฉฐ, ๋งŒ๋ฃŒ ์‹œ ์ž๋™์œผ๋กœ ์žฌ๋กœ๊ทธ์ธ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋ฉด Claude Code๋ฅผ ์žฌ์‹œ์ž‘ํ•˜์„ธ์š”.

---

## ๐Ÿ› ๏ธ ๊ฐœ๋ฐœ ์ฐธ์—ฌ

### ํ…Œ์ŠคํŠธ ์‹คํ–‰

```bash
pip install -e .[dev]
pytest tests/ -v
```

### ์ฝ”๋“œ ํฌ๋งทํŒ…

```bash
black src/ tests/
ruff check src/ tests/
```

### ๊ธฐ์—ฌํ•˜๊ธฐ

1. ์ด repository๋ฅผ Fork
2. ๊ธฐ๋Šฅ ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ (`git checkout -b feature/๋ฉ‹์ง„๊ธฐ๋Šฅ`)
3. ์ปค๋ฐ‹ (`git commit -m '๋ฉ‹์ง„ ๊ธฐ๋Šฅ ์ถ”๊ฐ€'`)
4. ํ‘ธ์‹œ (`git push origin feature/๋ฉ‹์ง„๊ธฐ๋Šฅ`)
5. Pull Request ์ƒ์„ฑ

---

## ๐Ÿ”’ ๋ณด์•ˆ

- ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” OS ํ‚ค๋ง์— ์•”ํ˜ธํ™” ์ €์žฅ
- ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ ˆ๋Œ€ Git์— ์ปค๋ฐ‹ํ•˜์ง€ ๋งˆ์„ธ์š”
- ๋ณด์•ˆ ์ด์Šˆ ๋ฐœ๊ฒฌ ์‹œ [GitHub Issues](https://github.com/legendwon/cau-eclass-mcp/issues)๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”

## ๐Ÿ“„ ๋ผ์ด์„ ์Šค

MIT License โ€” [LICENSE](LICENSE) ํŒŒ์ผ ์ฐธ๊ณ 

## ๐Ÿ™ ๊ฐ์‚ฌ

- [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
- [Claude Code](https://claude.com/code)
- 13์‹œ๊ฐ„์˜ CAU-ON API ๋””๋ฒ„๊น…์—์„œ ํƒ„์ƒ ๐Ÿ›

---

**๊ถ๊ธˆํ•œ ์ ์ด๋‚˜ ๋ฒ„๊ทธ๋Š”?** โ†’ [GitHub Issues](https://github.com/legendwon/cau-eclass-mcp/issues)์— ๋‚จ๊ฒจ์ฃผ์„ธ์š”!