# @odyssey365/mcp-server

[Odyssey](https://odyssey-app.com) — 일상의 OS — 의 할일/메모/타임라인을 MCP 호환 AI 클라이언트에서 관리할 수 있게 해주는 MCP 서버입니다.

## 지원 클라이언트

| 클라이언트 | 설정 파일 | 최상위 키 | SKILL.md |
|---|---|---|---|
| Claude Code (글로벌) | `~/.claude/settings.json` | `mcpServers` | ✅ `~/.claude/skills/` |
| Claude Code (프로젝트) | `.claude/settings.json` | `mcpServers` | ✅ `.claude/skills/` |
| Claude Desktop | 플랫폼별 config | `mcpServers` | ✅ `~/.claude/skills/` |
| Cursor | `~/.cursor/mcp.json` 또는 `.cursor/mcp.json` | `mcpServers` | ✅ `~/.cursor/skills/` |
| VS Code | `~/Library/Application Support/Code/User/mcp.json` (darwin) 등 | **`servers`** | ❌ (MCP prompts만) |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `mcpServers` | ✅ `~/.codeium/windsurf/skills/` |
| Antigravity | `~/.gemini/antigravity/mcp_config.json` | `mcpServers` | ❌ |

VS Code와 Antigravity는 SKILL.md 슬래시 명령 시스템이 없어 MCP 도구만 노출됩니다.
`odyssey-mcp install`은 각 대상에 맞는 JSON 구조로 자동 기록합니다.

### 웹 AI (Claude.ai / ChatGPT / Notion 등)

이 npm 패키지는 **내 컴퓨터에서 실행하는 stdio 클라이언트**용입니다. 설치 없이 웹 AI에서 바로
쓰려면 **호스티드 리모트 커넥터**를 사용하세요 — 동일한 도구를 OAuth로 노출합니다.

- 엔드포인트: `https://mcp-odyssey30-60.odyssey365.app`
- OAuth 2.1 + DCR 지원 (Claude.ai 커스텀 커넥터 등은 이 URL만 추가하면 로그인 창으로 연결).
- API Key 헤더를 지원하는 클라이언트는 앱에서 **외부 AI(remote)** 키를 발급받아
  `Authorization: Bearer <키>` 로 설정.

앱 → **설정 → MCP 연동**에서 용도에 맞는 키(내 디바이스 / 외부 AI)를 발급합니다.

## 빠른 시작

### 1. Odyssey 앱에서 API Key 생성

Odyssey 앱 → **설정 → MCP 연동 → API Key 관리** → `+` 버튼으로 새 키 발급.

발급된 키는 `odk_` 로 시작하는 20자 문자열입니다. **이 순간에만 확인 가능**하므로 안전한 곳에 저장하세요.

### 2. 대화형 설치 (추천)

```bash
npx -y @odyssey365/mcp-server@latest install
```

API Key 입력 → 글로벌 설치 → 설정 파일 자동 등록 → 스킬 설치까지 한 번에 완료됩니다.

제거하려면:

```bash
npx -y @odyssey365/mcp-server@latest uninstall
```

설정 파일에서 `odyssey` 항목과 설치된 슬래시 스킬을 제거하고, 원하면 글로벌 npm
패키지도 함께 삭제합니다 (설정 파일은 `.bak` 백업이 남습니다).

### 3. 수동 등록 (직접 설정)

먼저 글로벌 설치:
```bash
npm i -g @odyssey365/mcp-server
```

그 후 설정 파일에 등록:

**Claude Code** — `~/.claude/settings.json` 또는 프로젝트의 `.claude/settings.json`:

```json
{
  "mcpServers": {
    "odyssey": {
      "command": "odyssey-mcp",
      "args": [],
      "env": {
        "ODYSSEY_API_KEY": "odk_여기에_발급받은_키"
      }
    }
  }
}
```

**Claude Desktop** — `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):

```json
{
  "mcpServers": {
    "odyssey": {
      "command": "odyssey-mcp",
      "args": [],
      "env": {
        "ODYSSEY_API_KEY": "odk_여기에_발급받은_키"
      }
    }
  }
}
```

**Cursor** — `~/.cursor/mcp.json` (글로벌) 또는 프로젝트의 `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "odyssey": {
      "command": "odyssey-mcp",
      "args": [],
      "env": {
        "ODYSSEY_API_KEY": "odk_여기에_발급받은_키",
        "ODYSSEY_AUTO_UPDATE": "1"
      }
    }
  }
}
```

**VS Code** — `~/Library/Application Support/Code/User/mcp.json` (macOS 글로벌) 또는 프로젝트의 `.vscode/mcp.json`. ⚠️ VS Code는 최상위 키가 `servers`입니다 (다른 클라이언트의 `mcpServers`와 다름):

```json
{
  "servers": {
    "odyssey": {
      "command": "odyssey-mcp",
      "args": [],
      "env": {
        "ODYSSEY_API_KEY": "odk_여기에_발급받은_키",
        "ODYSSEY_AUTO_UPDATE": "1"
      }
    }
  }
}
```

**Windsurf** — `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "odyssey": {
      "command": "odyssey-mcp",
      "args": [],
      "env": {
        "ODYSSEY_API_KEY": "odk_여기에_발급받은_키",
        "ODYSSEY_AUTO_UPDATE": "1"
      }
    }
  }
}
```

**Antigravity** — `~/.gemini/antigravity/mcp_config.json`: Windsurf와 동일한 `mcpServers` 구조.

### 4. 클라이언트 재시작

재시작하면 `odyssey` MCP 서버가 자동 연결됩니다. 자연어로 요청해 보세요:

> "OdysseyProduct 카테고리 할일 목록 보여줘"
>
> "오늘 한 작업을 메모로 저장해줘"
>
> "내 프로젝트 중에서 경제학 관련된 거 상세 보여줘"

## 제공하는 Tool (26개)

### 카테고리
- **`list_categories`** — 카테고리 목록 조회 (이름 필터)
- **`create_category`** — 카테고리 + 홈 필터 페이지 카드 동시 생성 (앱 정합)

### 할일
- **`list_todos`** — 카테고리·상태·오늘/전체·태그 필터 조회 (정렬·페이지네이션)
- **`get_todo`** — 상세 조회 (체크리스트/달성조건 포함)
- **`create_todo`** — 할일 생성 (done 상태·사후기록·deadline 지원)
- **`update_todo`** — 할일 수정 (deadline 교체/해제)
- **`delete_todo`** — 할일 삭제
- **`complete_todo`** — 완료 처리 (타임라인 이벤트 자동 생성)

### 메모 / 일기
- **`list_memos`** — 메모 목록 (본문 미리보기, 임베드 assetCount)
- **`get_memo`** — 메모 상세 (plain text 변환 + 임베드 이미지/비디오 URL을 `assets[]`로 노출)
- **`read_memo_image`** — 메모 임베드 이미지를 다운스케일해 image content로 반환 (비전 입력용)
- **`create_memo`** — 메모 생성 (plain text → Quill Delta 자동 변환, 타임라인 이벤트 자동 생성)
- **`delete_memo`** — 메모 삭제

### 캘린더
- **`list_events`** — 기간 내 캘린더 이벤트 조회
- **`get_event`** — 단일 이벤트 상세
- **`create_event`** — 캘린더 이벤트 생성

### 타임라인 (수행·회고 기록)
- **`create_timeline_event`** — 타임라인 이벤트 생성 (대화를 수행/회고로 묶기, reflectionElements 지원)
- **`add_item_to_timeline_event`** — 기존 타임라인 이벤트에 아이템 첨부

### 프로젝트
- **`list_projects`** — 프로젝트 목록 (정렬·페이지네이션)
- **`get_project`** — 상세 + 포함 아이템(`items[]`) 평탄화 (`includeComponents`로 보드 원본 포함)
- **`get_project_components`** — 원본 components/links까지 포함한 상세
- **`create_project`** — 새 프로젝트(빈 보드) 생성. title 필수, categoryName/tags/emoji/memo 선택
- **`add_project_component`** — 컴포넌트 추가 (order 자동할당 or 끼워넣기 shift)
- **`update_project_component`** — 컴포넌트 수정. `containItems`는 `mode: 'append' | 'replace' | 'remove'`
- **`delete_project_component`** — 컴포넌트 제거 (참조 links 함께 정리)

### 설정
- **`get_setup_template`** — CLAUDE.md 섹션 템플릿 반환 (프로젝트별 맞춤 연동 가이드 생성)

> 도구는 백엔드 SSOT(`functions_v2/src/mcp/tools/*.ts`) 한 곳에서 관리되며, 이 npm 패키지는
> stdio→리모트 프록시입니다. 도구 추가/변경은 백엔드 배포만으로 반영되고 npm 재배포는 불필요합니다.

## 주요 워크플로우

### 할일 기반 작업 루프
```
list_todos(categoryName: "OdysseyProduct", status: "notStarted")
  → 각 할일 작업 수행
  → complete_todo(todoId, completionNote)
```

### 작업 요약 → 메모
각 작업 완료 후 document/update 등에 히스토리 작성 → 요약을 메모로:
```
create_memo(
  title: "작업 제목",
  text: "핵심 요약...",
  categoryName: "OdysseyProduct",
  generateTimelineEvent: true
)
```

### 프로젝트 논의
```
list_projects()
get_project(projectId) → items[]
각 아이템은 get_todo(id) / get_memo(id)로 상세 조회
```

### 일기 / 저널
철학적 대화, 생각 정리 등을 일기 카테고리 메모로:
```
create_memo(
  title: "주제",
  text: "대화 요약",
  categoryName: "일기",
  generateTimelineEvent: true
)
```

## 아키텍처

```
MCP 클라이언트 (Claude Code/Desktop/Cursor)
    │ stdio (JSON-RPC)
    ▼
odyssey-mcp (이 패키지)
    │ HTTPS + Bearer API Key
    ▼
Firebase Functions (asia-northeast3)
    │
    ▼
Firestore (할일/메모/프로젝트/타임라인)
```

## 보안

- API Key는 sha256 해시로만 Firestore에 저장됨 (원본은 발급 시 1회만 노출)
- 모든 요청에 API Key 인증 필수
- 본인 데이터만 접근 가능
- 만료된 키는 서버에서 즉시 거부 (`revokedAt` 검증)
- Odyssey 앱에서 언제든 키 폐기 가능

## 문제 해결

### 첫 호출이 느리거나 응답 없음

Firebase Functions의 **cold start** 때문입니다. 첫 요청은 최대 10초 정도 걸릴 수 있고, 이후 호출은 즉시 응답합니다. 클라이언트 내부에서 자동 재시도(최대 3회, 누적 ~25초)가 적용되므로 그냥 기다리시면 됩니다.

### "도구를 찾을 수 없음" 에러

글로벌 설치(`npm i -g @odyssey365/mcp-server`) 후 설정의 command를 `odyssey-mcp`으로 변경하세요. `npx`를 사용하면 npm registry 조회 시간 때문에 세션 시작 시 도구가 누락될 수 있습니다.

### "API Key가 만료되었습니다"

Odyssey 앱 → 설정 → MCP 연동에서 새 키를 발급하고 `odyssey-mcp install`로 다시 설치하세요.

### 업데이트

서버가 시작될 때마다 자동으로 최신 버전을 확인하고 업데이트합니다 (다음 세션부터 적용). 자동 업데이트를 끄려면 설정 파일의 env에 `"ODYSSEY_AUTO_UPDATE": "0"`을 추가하거나, 설치 시 "자동 업데이트 사용?"에 N으로 답하세요. 수동 업데이트는 언제나:

```bash
odyssey-mcp update
```

## 요구사항

- Node.js 20 이상
- Odyssey 앱 계정 + API Key

## 라이선스

MIT
