Skip to main content
Glama
README.md
# ๐Ÿฏ HoneyMCP โ€” ์–ผ๋ถˆ์ถค(ADOFAI) ๊ณ ํ€„๋ฆฌํ‹ฐ ๋งต ์ž๋™์ƒ์„ฑ MCP

> **"๋งต ๋งŒ๋“ค์–ด์ค˜" ํ•œ๋งˆ๋””๋ฉด ์œ ํŠœ๋ธŒ๊ธ‰ ์ปค์Šคํ…€ ๋งต์ด ๋‚˜์˜ต๋‹ˆ๋‹ค.**
> A Model Context Protocol server that generates human-quality
> *A Dance of Fire and Ice* custom levels from any song.
> ๋…ธ๋ž˜๋ฅผ ์ฃผ๋ฉด ์‹ค์ œ ์Œํ‘œ์— ๋งž์ถ˜ ํƒ€์ผ๊ธธ + ๋งค์ง์„œํด + ์นด๋ฉ”๋ผ/์กฐ๋ช… ์ดํŽ™ํŠธ๊นŒ์ง€ ์ž๋™์œผ๋กœ ๋ฝ‘์•„์ค๋‹ˆ๋‹ค.

![python](https://img.shields.io/badge/python-3.10%2B-blue) ![mcp](https://img.shields.io/badge/MCP-stdio-green) ![tests](https://img.shields.io/badge/tests-11_passing-brightgreen)

## โœจ ํ•ต์‹ฌ ๊ธฐ์ˆ  (์™œ ๋…ธ์žผ์ด ์•„๋‹Œ๊ฐ€)

| ๊ธฐ์ˆ  | ์„ค๋ช… |
|---|---|
| ๐ŸŽน **์‹ค์ œ ์Œํ‘œ ์‹ฑํฌ** | ffmpeg + spectral flux๋กœ ๋…ธ๋ž˜์˜ ์˜จ์…‹(์Œํ‘œ) ์ˆ˜๋ฐฑ ๊ฐœ๋ฅผ 2์ดˆ ๋งŒ์— ์ถ”์ถœ. ํƒ€์ผ์„ ์ง„์งœ ์Œํ‘œ ์œ„์— ๋ฐฐ์น˜ (์‹ฑํฌ์œจ ~90%) |
| ๐Ÿงฒ **SetSpeed ๋ฐ•์ž ๊ณ ์ •** | ๊ณต์‹ ์—๋””ํ„ฐ ๊ฐ€์ด๋“œ์˜ ๋งค์ง์‰์ดํ”„ ์ •์„. ๋„ํ˜•์€ ์ž์œ ๋กญ๊ฒŒ, ๋ฐ•์ž๋Š” ํƒ€์ผ๋งˆ๋‹ค BPM ๋ณด์ •์œผ๋กœ ๊ณ ์ • |
| ๐Ÿ—บ๏ธ **๊ฒน์นจ ์ œ๋กœ ๋ฐฐ์น˜** | ์ „ ํƒ€์ผ ์ขŒํ‘œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ + DFS ๋ฐฑํŠธ๋ž˜ํ‚น. ๋ญ‰๊ฐœ์ง„ ๋ฉ์–ด๋ฆฌ ์›์ฒœ ์ฐจ๋‹จ |
| ๐Ÿ‡๐Ÿข **์†๋„๋น„์œจ ์ œํ•œ** | ํƒ€์ผ ์†๋„๋น„๋ฅผ ๊ธฐ์ค€์˜ 0.45~2.6๋ฐฐ๋กœ ๊ฐ•์ œ. ๋น ๋ฆ„/๋А๋ฆผ ํ‘œ์‹(ํ† ๋ผ/๊ฑฐ๋ถ์ด) ๋„๋ฐฐ + ๋ถˆ๊ฐ€๋Šฅ ๊ตฌ๊ฐ„ ์›์ฒœ ์ฐจ๋‹จ. ๋น ๋ฅธ ์Œํ‘œ=์ง์„  ์ŠคํŠธ๋ฆผ, ๋А๋ฆฐ ์Œํ‘œ=ํฐ ๋„ํ˜• (๊ณ ์ˆ˜ ์›์น™) |
| ๐ŸŒ€ **ํ”„๋ ˆ์ด์ฆˆ ๋ชจํ‹ฐํ”„** | 8ํƒ€์ผ๋งˆ๋‹ค ๋ฌผ๊ฒฐโ†’์ง€๊ทธ์žฌ๊ทธโ†’์•„ํฌโ†’๋‚˜์„  ์ˆœํ™˜ + ๊ตฌ๊ฐ„๋งˆ๋‹ค ๋ฐฉํ–ฅ ์ „ํ™˜. ํ‰ํ–‰ ๊ณ ์†๋„๋กœ ๋ฐฉ์ง€ |
| ๐Ÿ›ก๏ธ **ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ** | ์ ์ˆ˜์ œ ๊ฒ€์ฆ(errors/warnings). ๋ถˆํ•ฉ๊ฒฉ์ด๋ฉด ์‹œ๋“œ ๋ฐ”๊ฟ” ์ตœ๋Œ€ 6ํšŒ ์ž๋™ ์žฌ์ƒ์„ฑ ํ›„ ์ตœ๊ณ ๋ณธ๋งŒ ์ €์žฅ |
| ๐Ÿ‘† **2/3/4ํ‚ค ๋™์‹œ์น˜๊ธฐ** | ๊ณต์‹ ๊ฐ€์ด๋“œ multi-press ์ •์„(0.01ยฐ ํžˆ๋“  ๋ฏธ๋“œ์Šคํ•€). โ˜…5๋ถ€ํ„ฐ ์ฝ”๋Ÿฌ์Šค์— 2ํ‚ค ์ž๋™, ์ˆ˜๋™ ์ถ”๊ฐ€๋„ ๊ฐ€๋Šฅ |

## ๐Ÿ“‹ ์š”๊ตฌ์‚ฌํ•ญ

- Python 3.10+
- **ffmpeg** (์Œํ‘œ ์ถ”์ถœ์šฉ. ์—†์œผ๋ฉด ๊ธฐ๊ณ„ ๊ทธ๋ฆฌ๋“œ ํด๋ฐฑ์œผ๋กœ ๋™์ž‘)
  - Windows: `winget install ffmpeg` (๋˜๋Š” [ffmpeg.org](https://ffmpeg.org/download.html))
- ์–ผ๋ถˆ์ถค ๋ณธํŽธ (๊ฒฐ๊ณผ๋ฌผ ํ™•์ธ์šฉ. ์ƒ์„ฑ ์ž์ฒด๋Š” ๊ฒŒ์ž„ ์—†์ด ๋จ)

## ๐Ÿš€ ์„ค์น˜

```powershell
git clone https://github.com/dohunkr/HoneyMCP.git
cd HoneyMCP
pip install -e ".[dev]"
```

## ๐Ÿ”Œ MCP ์—ฐ๊ฒฐ๋ฒ• (ํด๋ผ์ด์–ธํŠธ๋ณ„)

์„œ๋ฒ„ ์‹คํ–‰ ๋ช…๋ น(๊ณตํ†ต): `python -m honey_mcp.server` (stdio ๋ฐฉ์‹)

> โš ๏ธ ์„ค์ • ํ›„ **ํด๋ผ์ด์–ธํŠธ๋ฅผ ์™„์ „ํžˆ ์ข…๋ฃŒโ†’์žฌ์‹œ์ž‘**ํ•ด์•ผ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.

### opencode (`opencode.json` โ€” ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ)

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "honey-adofai": {
      "type": "local",
      "command": ["C:/Python310/python.exe", "-m", "honey_mcp.server"],
      "enabled": true
    }
  }
}
```
`command`์˜ python ๊ฒฝ๋กœ๋Š” ๋ณธ์ธ ํ™˜๊ฒฝ์— ๋งž๊ฒŒ ์ˆ˜์ •. `.venv` ์‚ฌ์šฉ ์‹œ `.venv/Scripts/python.exe` ์ ˆ๋Œ€๊ฒฝ๋กœ ๊ถŒ์žฅ.
`opencode.json.example` ์ฐธ๊ณ . ์—ฐ๊ฒฐ ํ™•์ธ: ํˆด ๋ชฉ๋ก์— `honey-adofai`๊ฐ€ ๋ณด์ด๋ฉด OK.

### Claude Code (`.mcp.json` โ€” ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ)

```json
{
  "mcpServers": {
    "honey-adofai": {
      "command": "python",
      "args": ["-m", "honey_mcp.server"],
      "cwd": "D:/Github/ADOFAI/HoneyMCP"
    }
  }
}
```

### Cursor (`~/.cursor/mcp.json`)

```json
{
  "mcpServers": {
    "honey-adofai": {
      "command": "python",
      "args": ["-m", "honey_mcp.server"],
      "cwd": "D:/Github/ADOFAI/HoneyMCP"
    }
  }
}
```

### Antigravity / Codex

MCP ์„ค์ •์— stdio ์„œ๋ฒ„๋กœ ๋“ฑ๋ก (์œ„์™€ ๋™์ผ):
command `python`, args `["-m", "honey_mcp.server"]`, cwd = ์ด ํด๋”.

## ๐ŸŽฎ ์‚ฌ์šฉ๋ฒ•

์ฑ„ํŒ…์— ๋…ธ๋ž˜ ํŒŒ์ผ ๊ฒฝ๋กœ๋งŒ ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค:

```
D:\Music\track.ogg ๋กœ ๋งต ๋งŒ๋“ค์–ด์ค˜ (โ˜…5, ํ™”๋ คํ•˜๊ฒŒ)
```

AI๋Š” ์ž๋™์œผ๋กœ `analyze_song โ†’ generate_full_map โ†’ ํ’ˆ์งˆ๊ฒŒ์ดํŠธ`๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
์ถœ๋ ฅ: `D:/Github/ADOFAI/HoneyMap_<๊ณก๋ช…>/` ์•ˆ์— `.adofai` + ๋…ธ๋ž˜ ๋ณต์‚ฌ๋ณธ โ†’
**์–ผ๋ถˆ์ถค ๋ ˆ๋ฒจ ์—๋””ํ„ฐ๋กœ ํด๋”๋ฅผ ์—ด์–ด์„œ F5 ํ…Œ์ŠคํŠธํ”Œ๋ ˆ์ด.**

MCP ์—†์ด ์ง์ ‘ ์ƒ์„ฑ๋„ ๊ฐ€๋Šฅ:

```powershell
python tools/make_map.py --audio "C:/Music/song.ogg" --outdir "D:/Github/ADOFAI/HoneyMap_song" `
    --title "Song" --artist "Artist" --difficulty 5 --style showcase --seed 7
```

- `difficulty`: 1~10 (โ˜…5-6 ๊ถŒ์žฅ. โ˜…5๋ถ€ํ„ฐ 2ํ‚ค ๋™์‹œ์น˜๊ธฐ, โ˜…7๋ถ€ํ„ฐ 6๊ฐœ, โ˜…9๋ถ€ํ„ฐ 3ํ‚ค)
- `style`: `showcase`(ํ™”๋ ค) / `clean`(๊น”๋”) / `party`

## ๐Ÿงฐ MCP ๋„๊ตฌ

| ๋„๊ตฌ | ์„ค๋ช… |
|---|---|
| `analyze_song(audio_path)` | BPM/์˜คํ”„์…‹/์Œํ‘œ/๊ตฌ๊ฐ„ ๋ถ„์„ (~2์ดˆ) |
| `generate_full_map(audio_path, output_dir, title, artist, difficulty, style, seed)` | ์›์ƒท ํ’€๋งต ์ƒ์„ฑ + ํ’ˆ์งˆ๊ฒŒ์ดํŠธ + ์ž๋™์žฌ์‹œ๋„ |
| `validate_level_tool(level_path)` | ์ ์ˆ˜/์—๋Ÿฌ/๊ฒฝ๊ณ  ๋ฆฌํฌํŠธ |
| `adjust_effects(level_path, style, zoom, enable_flash)` | ํƒ€์ผ ์œ ์ง€ + ์ดํŽ™ํŠธ๋งŒ ๊ต์ฒด |
| `add_multipress(level_path, floor, keys)` | 2/3/4ํ‚ค ๋™์‹œ์น˜๊ธฐ ์ˆ˜๋™ ์ถ”๊ฐ€ |
| `list_patterns()` | ํŒจํ„ด ์‚ฌ์ „ |
| ํ”„๋กฌํ”„ํŠธ `make_map` / ๋ฆฌ์†Œ์Šค `adofai://spec` | AI ์ž‘์—…ๆ‰‹้ † + ์ŠคํŽ™ ์š”์•ฝ |

## ๐Ÿ›ก๏ธ ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ (์žฌ๋ฐœ๋ฐฉ์ง€)

`errors` (ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด ์ž๋™ ์žฌ์ƒ์„ฑ):
- ๊ฒŒ์ž„ enum ์œ„๋ฐ˜ (`Forward` ๋“ฑ โ€” ๊ณผ๊ฑฐ ๋กœ๋”ฉ ํฌ๋ž˜์‹œ ์›์ธ)
- SetSpeed๊ฐ€ ๊ธฐ์ค€์˜ 0.35~3๋ฐฐ ์ดˆ๊ณผ (๋ถˆ๊ฐ€๋Šฅ ๊ตฌ๊ฐ„)
- floor ๋ฒ”์œ„ ์ดˆ๊ณผ / ํƒ€์ผ ๋ถ€์กฑ / BPM ๋ฒ”์œ„ ์ดํƒˆ

`warnings` (์ ์ˆ˜ ๊ฐ์ ):
- ์ง์„  7์—ฐ์† ๊ณ ์†๋„๋กœ / ์ขŒ์šฐํšŒ์ „ ํŽธ์ค‘ / ํƒ€์ผ ๊ฒน์นจ / ์Œํ‘œ ์‹ฑํฌ์œจ 60% ๋ฏธ๋งŒ

## ๐Ÿ—บ๏ธ ๋งต ์ถœ๋ ฅ ๊ทœ์น™

- ๋ชจ๋“  ๋งต์€ `D:/Github/ADOFAI/HoneyMap_<๊ณก๋ช…>/` ์— ์ƒ์„ฑ (ํ”„๋กœ์ ํŠธ ํด๋”์™€ ๋ถ„๋ฆฌ)
- ์˜ˆ์‹œ: ๋„๋ผ์—๋ชฝ ํ”ผ์•„๋…ธ ์ปค๋ฒ„ โ†’ ํƒ€์ผ 210๊ฐœ, score 100, ์‹ฑํฌ์œจ 90%, 2ํ‚คร—3

## ๐Ÿงช ๊ฐœ๋ฐœ

```powershell
pytest -q
```

๊ตฌ์กฐ: `src/honey_mcp/` โ€” `server.py`(MCP) / `audio.py` / `onsets.py`(์Œํ‘œ์ถ”์ถœ) /
`chart.py`(์ฑ„๋ณด+๋ฐฐ์น˜) / `effects.py`(์ดํŽ™ํŠธ) / `adofai.py`(ํŒŒ์ผIO+๊ฒ€์ฆ+๋ฉ€ํ‹ฐํ”„๋ ˆ์Šค)

## โ“ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

| ์ฆ์ƒ | ์›์ธ/ํ•ด๊ฒฐ |
|---|---|
| `Requested value 'Forward' was not found` | ๊ตฌ๋ฒ„์ „ ์‚ฐ์ถœ๋ฌผ. ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ์žฌ์ƒ์„ฑ (๊ฒŒ์ดํŠธ์—์„œ ์›์ฒœ ์ฐจ๋‹จ๋จ) |
| ํƒ€์ผ์— ํ† ๋ผ/๊ฑฐ๋ถ์ด ๋„๋ฐฐ | ๊ตฌ๋ฒ„์ „ ์†๋„ ํญ์ฃผ. v6+ ์†๋„๋น„์œจ ์ œํ•œ์œผ๋กœ ํ•ด๊ฒฐ |
| MCP๊ฐ€ ๋…ธ๋ž˜ ๋ถ„์„์—์„œ ๋ฉˆ์ถค | ๊ตฌ librosa ๊ฒฝ๋กœ ๋ฌธ์ œ. ํ˜„์žฌ ffmpeg ๊ธฐ๋ฐ˜์œผ๋กœ 2์ดˆ ๋‚ด์™ธ (ffmpeg ์„ค์น˜ ํ™•์ธ) |
| ํ•œ๊ธ€ ์ถœ๋ ฅ ๊นจ์ง (cp949) | `$env:PYTHONUTF8="1"` ์„ค์ • |
| MCP๊ฐ€ ์•ˆ ๋ณด์ž„ | ํด๋ผ์ด์–ธํŠธ ์žฌ์‹œ์ž‘ ํ™•์ธ + python ์ ˆ๋Œ€๊ฒฝ๋กœ ํ™•์ธ |

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

MIT โ€” ์ž์œ ๋กญ๊ฒŒ ์“ฐ๊ณ  ๊ณ ์น˜๊ณ  ๊ณต์œ ํ•˜์„ธ์š”. ๋งต์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•œ ๋…ธ๋ž˜์˜ ์ €์ž‘๊ถŒ์€ ๊ฐ ๊ถŒ๋ฆฌ์ž์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค.

TDQS

A3.5/5.0

Scored across 6 tools

Disambiguation4/5

Tools target distinct stages: audio analysis, pattern listing, full generation, validation, multipress editing, and effects adjustment. The only mild overlap is that generate_full_map is a one-shot pipeline that may implicitly subsume analysis and pattern selection, but the dedicated tools still have clear separate purposes.

Naming Consistency4/5

Most names follow a consistent snake_case verb_noun pattern: analyze_song, list_patterns, add_multipress, generate_full_map, adjust_effects. The only deviation is validate_level_tool, where the redundant _tool suffix breaks the otherwise clean convention.

Tool Count5/5

Six tools is well-scoped for a specialized ADOFAI map-generation server. Each tool covers a distinct operation in the create-validate-adjust workflow without obvious redundancy or bloat.

Completeness4/5

The surface covers the core lifecycle: analyze a song, generate a full map, validate it, adjust effects, and add multipress patterns. Minor gaps remain, such as removing multipress, editing individual tiles or rhythms directly, or previewing maps without full regeneration.

Maintenance

ActivityMaintained
ResponsivenessNo issues