kakao-moment-mcp
# Kakao Moment Ads MCP
카카오모먼트 광고 데이터를 **조회·분석·리포트** 위주로 다루는 읽기 전용 MCP 서버. 회사 구성원 여러 명이
하나의 호스팅 서버(GCP Cloud Run)로 연동해 쓰는 것을 목표로 한다. 전체 설계는 [DESIGN.md](DESIGN.md),
배포는 [DEPLOY.md](DEPLOY.md), 향후 과제는 [ROADMAP.md](ROADMAP.md) 참고. 자매 프로젝트
`NaverSearchAds_MCP` / `kakao-keywordad-mcp`(키워드광고)와 아키텍처를 공유한다.
## 현재 상태
읽기 툴 24종 + 리소스 2종. **Cloud Run 배포 + 라이브 검증 완료** (계정/캠페인/광고그룹/소재/리포트
4레벨·다차원 분해까지 실데이터 확인). 읽기 전용(mutating 툴 없음).
## 인증 모델 — 사용자별 비즈니스 토큰 (중요)
카카오모먼트는 **비즈니스 토큰**으로 인증하며, 이 토큰은 **사용자(로그인한 카카오계정)별**이다.
- 전용 플로우 `GET /oauth/business/authorize` → `POST /oauth/business/token`. 응답에 `refresh_token`
없음 → 재발급 없이 재사용하는 장수명 토큰(장기 미사용 시만 만료). 불필요한 재발급은 발급 개수 한도
(KOE236)를 유발하므로 **재사용**이 원칙.
- 토큰은 `token_user_id`(사용자)에 귀속되고, 접근 가능한 광고계정은 `tokeninfo.ad_account_ids`가 결정한다.
`resource_ids=moment:*` 동의 시 사용자 보유 **전체 계정** 접근.
- **따라서 비즈니스 토큰·광고계정 ID는 `.env`에 저장하지 않는다.** 둘 다 사용자마다 바뀌는 런타임 값.
- `.env`에는 **앱 수준 발급 자격증명만** 둔다(아래).
### 두 가지 인증 모드
| 모드 | 용도 | 동작 |
|---|---|---|
| **OAuth 로그인-온-커넥트** (호스팅 권장) | Cloud Run 다중 사용자 | `KAKAO_AUTH_MODE=oauth`. 서버가 OAuth 보호 리소스가 되고 IdP는 카카오 비즈니스 인증 — 클라이언트 연결 시 **카카오 로그인**이 뜨고, 각 요청이 카카오 토큰을 실어 온다(구글/네이버 MCP와 동일한 "로그인 베이스"). 별도 로그인 툴 불필요. |
| **세션 로그인** (로컬/stdio) | 개인 로컬 사용 | `login(business_token)`으로 토큰을 서버 세션에 저장 → `use_account(ad_account_id)` → 이후 인자 없이 조회. |
두 모드 모두 각 툴에 `business_token`/`ad_account_id`를 직접 넘겨 override 가능.
### OAuth 상태 영속화 (Firestore) — KOE236 방지
호스팅(OAuth) 모드에서 OAuth 상태(클라이언트 등록·발급 토큰)를 **Firestore에 영속화**한다
(`GCP_PROJECT_ID`+`KAKAO_OAUTH_FIRESTORE_DATABASE` 설정 시). 이로써 **재배포해도 기존 비즈니스 토큰을
재사용**(재발급 안 함)해 카카오 토큰 발급 개수 한도(KOE236)에 걸리지 않는다. 토큰 정리 시 카카오에도
폐기 요청(`/v1/business/revoke`)이 나간다. 설정 없으면 파일 저장소로 폴백(로컬 개발용).
## 설정 (.env — 앱 발급 자격증명만, gitignore됨)
`.env.example` 복사 후 채운다. **토큰/계정 ID는 여기 넣지 않는다.**
```
KAKAO_REST_API_KEY=... # OAuth client_id (발급용)
KAKAO_BUSINESS_CLIENT_SECRET=... # 비즈니스 인증 Client Secret (발급용)
KAKAO_REDIRECT_URI=... # 앱에 등록한 Redirect URI (발급용)
```
### 비즈니스 토큰 발급 (세션 모드용, scripts/get_business_token.py)
```bash
.venv/bin/python scripts/get_business_token.py url --scope moment_management
# → 브라우저에서 카카오 로그인·동의 → 리다이렉트 주소의 code= 복사
.venv/bin/python scripts/get_business_token.py exchange --code <AUTH_CODE>
# → 출력된 비즈니스 토큰을 툴 호출 시 business_token 인자로 사용 (.env에 저장하지 않음)
```
> OAuth 로그인-온-커넥트 모드에서는 이 스크립트가 불필요 — 클라이언트 연결 시 카카오 로그인으로 자동 처리.
## 개발 / 실행
```bash
uv venv --python 3.13 && uv pip install -e ".[dev]"
.venv/bin/pytest # auth / client / tool / route 테스트
.venv/bin/kakao-moment-mcp # stdio 서버 (.env의 발급 자격증명만 로드)
```
## 툴 (읽기 24종)
**디스커버리**: `get_token_info`, `get_user_info`, `list_ad_accounts`(페이지네이션 전체), `session_status`, `login`/`logout`/`use_account`
**계정**: `get_ad_account`, `get_account_balance`, `list_trackers`, `list_channel_profiles`
**엔티티**: `list_campaigns`·`get_campaign`, `list_adgroups`·`get_adgroup`, `list_creatives`·`get_creative`
**성과/리포트**: `get_account_performance`, `get_campaign_performance`, `get_adgroup_performance`, `get_creative_performance`, `get_performance_report(level=AD_ACCOUNT|CAMPAIGN|AD_GROUP|CREATIVE)`
**타겟/오디언스**: `list_audiences`, `list_cohorts` · **리소스**: `kakao://metric-glossary`, `kakao://report-dimensions`
### 리포트 스펙 (라이브 확정)
- 파라미터명 **`metricsGroup`(단수)**. 그룹: `BASIC`/`ADDITION`/`MESSAGE`/`VIDEO`/`PIXEL_SDK_CONVERSION`(쉼표로 복수).
- 최대 조회 창 **31일**(초과 시 400 detailCode 60008), 보관 ~2년. 툴은 `KAKAO_REPORT_MAX_DAYS`로 자동 청킹.
- 하위 레벨(campaign/adGroup/creative)은 대상 ID를 **반복 파라미터**로 전달하며 **개수 한도가 낮다(≈5)** →
툴이 `KAKAO_REPORT_MAX_IDS`(기본 5)로 ID를 배치 청킹(초과 시 detailCode 78003 방지).
- `dimension`: `AGE_BAND`/`GENDER`/`DEVICE_TYPE`/`PLACEMENT`/`CREATIVE_FORMAT`/`LOCATION`/`HOUR`.
- 비용 필드는 **`cost`**(키워드광고는 `spending`). **메시지 광고는 발송당 과금** → 노출 0인데 비용만 잡히므로
디스플레이 성과와 분리 해석 필요.
## 호스트 맵
| 용도 | Host |
|------|------|
| 토큰 발급 | `kauth.kakao.com/oauth/business/{authorize,token}` |
| 토큰/사용자 정보·폐기 | `kapi.kakao.com/v1/business/{tokeninfo,userinfo,revoke}` |
| 광고 API | `apis.moment.kakao.com/openapi/v4` |
> **선행조건**: 비즈니스 앱 전환 + 실명확인 + 카카오모먼트 권한(`moment_management`) 승인 + Redirect URI 등록.
## 라이선스
MIT — [LICENSE](LICENSE).
TDQS
Scored across 24 tools
Most tools are distinct, but the performance report family overlaps: get_account_performance, get_campaign_performance, get_adgroup_performance, get_creative_performance can all be subsumed by get_performance_report, which also auto-enumerates entities. Additionally, session_status and get_token_info both expose token_user_id, creating some ambiguity.
The naming is largely consistent with verb_noun (list_*, get_*, use_account). Notable deviations include get_performance_report (which inverts the entity-first pattern) and login/logout/use_account as standalone verbs, but these are natural exceptions and do not cause confusion.
At 24 tools, this is slightly above the typical well-scoped range, but the coverage is broad across authentication, account management, campaign/adgroup/creative reads, and performance reports. The redundancy of get_performance_report with the level-specific performance tools slightly inflates the count but overall each tool has a legitimate use.
The tool set covers the full read/query lifecycle for campaigns, adgroups, creatives, and accounts, plus performance reporting at multiple levels. Missing are create/update/delete operations and get-single for audiences/cohorts/trackers, but the server appears designed as an insights/reporting tool, so these are acceptable minor gaps.