feat(mcp): Dabit.Mcp 초기 공개 (리네임 + colors 수정 + scroll 검증)

- refactor: DabitChe.Mcp → Dabit.Mcp (namespace, csproj, exe 모두)
- fix: display_message colors를 쉼표 구분 문자열로 변경 (ModelContextProtocol 1.3.0 배열 바인딩 버그 우회)
- docs: scroll 4방향(left/right/up/down) 실기 검증 완료 (DIBD600T V3.6.1)

20 도구 (읽기 4 + 콘텐츠 2 + 설정 14), stdio 전송, Windows exe.
실기 검증: scroll/fill_screen 8색/display_message 글자별색 모두 정상.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
insulee
2026-06-02 11:20:49 +09:00
parent 94dd74bd5c
commit 640c9a3380
109 changed files with 7146 additions and 0 deletions

130
Dabit.Mcp/README.md Normal file
View File

@@ -0,0 +1,130 @@
# Dabit.Mcp — AI로 LED 전광판을 제어하는 MCP 서버
Claude Desktop 같은 AI 클라이언트가 자연어로 LED 전광판을 **읽고(상태 조회) + 표시하고(텍스트/색) + 설정하는(화면·밝기·시간·보드)** MCP(Model Context Protocol) 서버다.
> 예) "정문 전광판 밝기 50%로", "화면 빨강으로 채워", "시간 맞춰", "가나다라를 4색으로 왼쪽으로 흘려" → AI가 해당 도구를 호출 → 이 서버가 기존 검증된 `DibdProtocol` 코드로 바이트를 조립해 컨트롤러에 전송.
## 동작 구조
```
[사람] → [Claude Desktop (AI)] ──MCP(stdio, JSON-RPC)──> [Dabit.Mcp.exe] ──> [전광판 컨트롤러]
(이 프로젝트) (COM/TCP)
```
- 새로 만든 건 이 서버(어댑터)뿐. 바이트 조립·통신은 `DibdProtocol.Core`(프로토콜) + `DibdProtocol.Transport`(시리얼/TCP)를 그대로 재사용한다.
- 각 도구의 조립은 정본 `DabitChe.Desktop/ViewModels/SettingsViewModel.cs`를 본떠 **byte-identical**.
- `LedControlService``DabitChe.AutoSend`의 전송 패턴을 축약한 것(WPF 의존성 제거). **Phase 2에서 `DibdProtocol.Transport.Rpc.DibdRpcClient`(신 프로토콜 96 method)로 교체 예정인 폐기성 코드.**
## 도구 (20개)
### 읽기 / 상태
| 도구 | 설명 |
|------|------|
| `get_firmware_info` | 펌웨어 모델/버전/화면 크기 (HEX 0x6F) |
| `get_screen_size` | 화면 가로×세로 (펌웨어 응답에서 추출) |
| `get_time` | 컨트롤러 RTC 시각 (HEX 0x66, BCD 파싱) |
| `get_connection_status` | 설정된 연결 정보 — 통신 안 함(스모크용) |
### 콘텐츠 표시 ⚠️ 쓰기
| 도구 | 설명 |
|------|------|
| `display_text` | 단색 텍스트 한 줄 즉시 표시 (실시간 메시지) |
| `display_message` | 글자별 색 + 입장/퇴장 이동효과 + 속도/유지 |
### 화면 · 밝기 · 전원 ⚠️ 쓰기
| 도구 | 설명 |
|------|------|
| `set_screen_size` | 화면 크기(단/열) 설정 (HEX 0x40) |
| `fill_screen` | 전체 단색 채우기, 8색 (HEX 0x42) |
| `load_background_image` | 저장된 배경이미지 로드 (HEX 0x4F) |
| `set_brightness` | 밝기 0~4단계 (100/75/50/25/5%) (HEX 0x44) |
| `led_power_on` / `led_power_off` | LED 전원 (HEX 0x41) |
### 페이지 메시지 ⚠️ 쓰기
| 도구 | 설명 |
|------|------|
| `set_page_count` | 페이지 개수 1~10 (ASCII "60") |
| `reset_page_message` | 페이지 초기화 (전체/개별) (ASCII "61") |
| `set_section_effect` | 섹션 동시/개별 표출 (ASCII "62") |
### 표출신호 (HUB75) ⚠️ 쓰기
| 도구 | 설명 |
|------|------|
| `set_display_signal` | 대표 신호 7종 이름으로 설정 (HEX 0x49) |
| `send_custom_signal` | 사용자 신호 코드 직접 전송 (ASCII "44") |
### 시간 · 보드 설정 (고급)
| 도구 | 종류 | 설명 |
|------|------|------|
| `sync_controller_time` | ⚠️ 쓰기 | PC 시간으로 RTC 동기화 (HEX 0x47, 7B BCD) |
| `read_board_settings` | 읽기 | 디버그/포트기능/통신속도 (ASCII "B3") |
| `save_board_settings` | ⚠️ 쓰기 | 보드기능 저장 (ASCII "B2") |
> **제외(블록 전송)**: 폰트(0x98)·펌웨어(0x9F)·이미지(DAT/BGP/PLA)·스케줄. 대용량 다블록 전송이라 PoC 범위 밖.
## 빌드 · 실행
```powershell
dotnet build Dabit.Mcp/Dabit.Mcp.csproj
dotnet run --project Dabit.Mcp
```
## Claude Desktop 연결
`claude_desktop_config.json``mcpServers`에 등록한다(아래는 실증된 Serial COM2 설정):
```json
{
"mcpServers": {
"dabit-led": {
"command": "D:\\Gitea\\dabitche-mcp\\Dabit.Mcp\\bin\\Debug\\net9.0-windows\\Dabit.Mcp.exe",
"env": {
"DABIT_TRANSPORT": "Serial",
"DABIT_COM": "COM2",
"DABIT_BAUD": "115200"
}
}
}
}
```
(개발 중엔 `command``dotnet` + `args:["run","--project","...Dabit.Mcp"]`로 둘 수도 있으나, exe 직접 실행이 빠르고 안정적.)
### 환경변수 (연결 설정)
| 변수 | 의미 | 기본값 |
|------|------|--------|
| `DABIT_TRANSPORT` | `TcpClient` 또는 `Serial` | `TcpClient` |
| `DABIT_HOST` / `DABIT_PORT` | TCP 호스트 / 포트 | `192.168.0.201` / `5000` |
| `DABIT_COM` / `DABIT_BAUD` | 시리얼 포트 / 속도 | `COM1` / `9600` |
| `DABIT_RESPONSE_LATENCY` | 응답 타임아웃(ms) | `1000` |
## 제약 · 주의
- ⚠️ **COM 포트 동시 점유 불가** — WPF 앱(DabitChe.Desktop/AutoSend)과 같은 COM 포트를 동시에 못 연다. 시리얼 사용 시 **WPF 앱을 끄고** MCP 서버를 실행한다.
- ⚠️ **로그는 반드시 stderr** — stdio는 stdout을 JSON-RPC에 쓴다. `Program.cs`에서 `ClearProviders()` + 콘솔 로그를 stderr로 보낸다(Windows EventLog 로거 제거 포함).
- ⚠️ **요청 순서 비보장** — MCP 서버가 여러 요청을 병렬 처리한다. `LedControlService._gate`가 전송은 한 번에 하나로 직렬화하지만 **진입 순서는 보장 안 함**. 한 번에 여러 명령을 몰아 보내면(예: sync 직후 get_time) 실행 순서가 뒤바뀔 수 있다. 순서 의존 작업은 응답을 받고 다음을 보낸다.
- **FlashWrite 명령**(시간·보드·화면크기·페이지·밝기·표출신호·fill·배경)은 응답이 느려 `timeoutMsOverride: 5000` 적용.
-**scroll 4방향(left/right/up/down) 실기 검증 완료**(2026-06-02, DIBD600T V3.6.1). 🟡 미검증: `bpp` 색심도 의미, 밝기 index1 ASCII(75)≠HEX(0x48) 레거시값.
## 로드맵
| Phase | 내용 |
|-------|------|
| **0 (완료)** | 읽기 4 + 콘텐츠 2 + 설정 14 = 20 도구. stdio. 얇은 LedControlService |
| 1 | 밝기 고급(13B 시간대별/CDS)·컨트롤러 재시작/초기화·기타 고급(스케줄속도/깜빡임/잔상/릴레이) |
| 2 | 백엔드를 `DibdRpcClient`(JSON-RPC 96 method)로 승격 — 신 프로토콜 실기 검증 후 |
| 3 | HTTP/SSE transport + HMAC 인증 → 원격/B2B |
## 검증 상태 (2026-06-01)
- ✅ 빌드(경고 0/오류 0), stdio 스모크(20개 도구 노출, tools/call 왕복, 환경변수 로딩, stdout 청결성)
- ✅ 이중 코드 리뷰 반영 — Anthropic `code-reviewer`(byte 조립 정합·죽은코드·timeout) + OpenAI `codex`(HEX status 체크: 거부 응답을 성공으로 오보하던 것 수정)
-**실기 검증** (DIBD500S 펌웨어 V3.4.8, COM2 @ 115200):
- 읽기: `get_firmware_info`, `get_time`(BCD), `read_board_settings`(7필드)
- 표시: `display_text`(환영합니다 빨강), `display_message`(가나다라 4색 좌이동)
- 설정: `set_brightness`(50%), `fill_screen`(빨강), `sync_controller_time`(2026 적용 확인) — 모두 status 0x00
-**실기 검증 추가** (2026-06-02, DIBD600T 펌웨어 V3.6.1, COM2 @ 115200):
- scroll 4방향 전부 정상: `scroll_left`(우→좌) · `scroll_right`(좌→우) · `scroll_up`(아래→위) · `scroll_down`(위→아래) — 육안 확인
- `display_message` 글자별 색(`colors`) 정상 — colors를 쉼표 구분 문자열로 변경해 배열 바인딩 버그 수정
- 🟡 미검증: bpp 색심도, save_board_settings 실기 반영