whenwecan
by yudh0802
README.md
# 다같이 가능한 시간 (When We Can)
단톡방에서 모두 가능한 약속 시간을 빠르게 잡아주는 일정 조율 MCP.
- **MCP 이름**: 다같이 가능한 시간
- **식별자**: `whenwecan`
- **사용**: 카카오 [PlayMCP](https://playmcp.kakao.com) 카탈로그에서 활성화
- **인증**: 없음 (poll_id 8자 base62 토큰으로 접근 제어)
- **사양**: Streamable HTTP · Stateless · Remote MCP (PlayMCP 가이드 준수)
## 90초 사용 시나리오
1. 카카오톡 AI 채팅창: "다음 주 평일 저녁 7-10시 중에 60분 약속 잡아줘"
2. AI가 `createPoll` 호출 → 폴 URL + 단톡방 공유용 카드 반환
3. 단톡방에 링크 공유 → 멤버들이 클릭, 닉네임 입력, 가능한 시간 ✓
4. "결과 확인해줘" → `getPollResults`로 가장 많이 가능한 시간 TOP 3
5. "화요일 8시로 확정" → `closePoll` → ISO 8601 시간 반환 → 톡캘린더 MCP에 그대로 전달
## 툴 (4개)
| 툴 | 역할 |
|----|------|
| `createPoll` | 새 폴 생성 (명시 슬롯 또는 날짜범위+시간창 자동 생성) |
| `getPollResults` | 응답 집계, 베스트 슬롯 TOP 3 |
| `addCandidateSlots` | 폴에 후보 슬롯 추가 |
| `closePoll` | 폴 마감, 확정 슬롯의 ISO 8601 출력 |
## 로컬 개발
### 1. 의존성
```bash
npm install
```
### 2. 환경변수
`.env.local`:
```bash
UPSTASH_REDIS_REST_URL=... # Upstash Redis (Vercel Marketplace에서 자동 주입)
UPSTASH_REDIS_REST_TOKEN=...
WHENWECAN_PUBLIC_URL=http://localhost:3000
```
### 3. 실행
```bash
npm run dev
```
### 4. MCP Inspector로 검증
```bash
npm run inspector
# 또는 직접
npx @modelcontextprotocol/inspector http://localhost:3000/api/mcp
```
- 모든 툴이 보이는지
- 각 툴이 `name + description + inputSchema + annotations(5필드)` 모두 갖추는지
- `createPoll → getPollResults → closePoll` 한 사이클 동작하는지
### 5. 단위 테스트
```bash
npm test
```
순수 함수(`lib/slots.ts`)에 대한 vitest 단위 테스트만 포함. Redis 의존 모듈은 통합 환경에서 검증.
## Vercel 배포
1. Vercel에 프로젝트 import
2. Vercel Marketplace에서 **Upstash Redis** 통합 추가 → `UPSTASH_REDIS_REST_URL/TOKEN` 자동 주입
3. 환경변수 `WHENWECAN_PUBLIC_URL` 추가 (예: `https://whenwecan.vercel.app`)
4. 첫 배포 후 `https://<domain>/api/mcp`에 MCP Inspector를 붙여 동작 확인
## PlayMCP 등록 절차
[`docs/superpowers/specs/2026-06-24-whenwecan-design.md`](./docs/superpowers/specs/2026-06-24-whenwecan-design.md) §9 등록 정보 참조.
PlayMCP 개발자 콘솔 → "새로운 MCP 서버 등록":
| 항목 | 값 |
|------|----|
| MCP 이름 | 다같이 가능한 시간 |
| MCP 식별자 | `whenwecan` |
| 대표 이미지 | `public/icon.png` |
| 인증 방식 | 인증 사용하지 않음 |
| MCP Endpoint | `https://<domain>/api/mcp` |
| 대화 예시 | README 본문 90초 시나리오에 기재된 3가지 |
## 디렉터리 구조
```
app/
api/mcp/route.ts # MCP Streamable HTTP 엔드포인트
p/[pollId]/ # 폴 페이지 (Server Component + 클라이언트 폼)
page.tsx
PollForm.tsx
respond/route.ts # 응답 제출 액션
not-found.tsx
layout.tsx, page.tsx, globals.css
lib/
slots.ts # 슬롯 생성/교집합/추천 (순수 함수)
slots.test.ts
poll.ts # Redis 어댑터
format.ts # 한국어 시간 포맷, 마크다운 카드
mcp.ts # MCP 서버 + 툴 4개 정의
public/icon.png # 대표 이미지 (1024x1024 PNG)
docs/superpowers/specs/ # 설계 스펙
```
## PlayMCP 가이드 준수 체크리스트
- [x] Streamable HTTP only / Remote / Stateless
- [x] MCP 스펙 2025-03-26 ~ 2025-11-25 (공식 SDK v1.x)
- [x] "kakao" 단어 미사용
- [x] 툴 4개 (권장 3~10 범위)
- [x] 모든 툴: name + description(영문 + 서비스명 영국문) + inputSchema + annotations 5필드
- [x] description 1024자 이내
- [x] Tool name에 서비스명 미포함 (prefix 자동 부착)
- [x] result는 정제된 마크다운
- [x] 응답속도 — 모든 핸들러가 단일 Redis read/write + 순수 계산
- [x] 광고 0
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues