icloud-mcp

icloud-mcp

Enables Claude to interact with iCloud Calendar through CalDAV, allowing users to list, search, create, update, and delete calendar events using natural language.

Category
Visit Server

README

icloud-mcp

iCloud Calendar와 Claude를 연결하는 MCP(Model Context Protocol) 서버.

Claude(Claude Code / Claude Desktop)에서 자연어로 iCloud 캘린더를 조회·생성·수정·삭제할 수 있게 한다.


아키텍처

Claude (Claude Code / Desktop)
        │  MCP (stdio)
        ▼
  icloud-mcp 서버 (TypeScript, @modelcontextprotocol/sdk)
        │  CalDAV (HTTPS)
        ▼
  iCloud CalDAV 서버 (caldav.icloud.com)
  • 연결 방식: CalDAV + Apple 앱 암호(app-specific password) 인증
    • macOS EventKit 방식 대비 플랫폼 독립적이고, 권한 팝업 없이 동작
    • Apple ID 2FA 환경에서도 앱 암호로 접근 가능
  • 언어/런타임: TypeScript + Node.js 18+, ESM ("type": "module", tsconfig NodeNext)
  • 주요 라이브러리:
    • @modelcontextprotocol/sdk — MCP 서버 프레임워크 (stdio transport)
    • tsdav — CalDAV 클라이언트
    • ical.js — iCalendar(VEVENT) 파싱 생성
    • zod — tool 입력 스키마 검증
  • 인증 정보 관리: 환경변수(APPLE_ID, APPLE_APP_PASSWORD) — 코드/저장소에 절대 커밋 금지

확정된 기술 결정

결정 이유
iCalendar 라이브러리를 ical.js 하나로 통일 update_event는 기존 VEVENT를 파싱 → 수정 → 재직렬화하는 왕복이 필수다. 생성 전용 라이브러리(ical-generator)를 함께 쓰면 왕복 과정에서 필드 유실·포맷 불일치가 발생한다.
ESM + NodeNext MCP SDK가 ESM 우선이다.
반복 일정은 ICAL.RecurExpansion으로 클라이언트 측 전개 CalDAV 서버측 <C:expand> REPORT는 iCloud 지원이 불균일하다. 조회 구간 내 개별 발생을 라이브러리로 전개하는 편이 안정적이다.
이벤트 식별자는 uid + calendarUrl CalDAV 리소스 URL은 서버가 바꿀 수 있어 대화 중 재사용에 부적합하다.
모든 로그는 stderr 로만 출력 stdio transport에서 stdout은 JSON-RPC 전용 채널이다. stdout에 한 줄이라도 찍으면 프로토콜이 깨진다.
종일 일정의 end.date포함적(마지막 날) RFC 5545의 DTEND는 배타적이지만("8/1 하루" → DTEND:20260802), LLM이 매번 +1일을 정확히 계산하기를 기대하는 건 위험하다. "8월 1~3일" → start=08-01, end=08-03으로 직관적으로 매핑되게 하고, ±1일 변환은 ical.ts 한 곳에서만 처리한다.

모듈 구조 및 소유권

src/
├── types.ts          # 공용 계약: CalendarEvent, EventDraft, ICloudCalendarClient …
├── errors.ts         # ICloudError + 에러 코드
├── config.ts         # 환경변수 로딩/검증
├── caldav/
│   ├── client.ts     # createICloudClient() — ICloudCalendarClient 구현체
│   └── ical.ts       # VEVENT ↔ CalendarEvent 변환, RRULE 전개
├── tools/            # MCP tool 등록 (7종)
├── schemas.ts        # zod 입력 스키마
└── index.ts          # 서버 엔트리포인트 (stdio)

src/types.ts가 CalDAV 레이어와 MCP 레이어 사이의 고정된 계약이다. 양쪽은 이 파일을 통해서만 통신하며, 계약 변경은 양쪽 동시 수정을 뜻하므로 함부로 바꾸지 않는다.

제공할 MCP Tools

Tool 설명
list_calendars 사용 가능한 캘린더 목록 조회
list_events 기간(시작~종료)으로 이벤트 조회
search_events 키워드로 이벤트 검색
create_event 이벤트 생성 (제목, 시작/종료, 종일 여부, 위치, 메모, 알림, 반복)
update_event 이벤트 수정
delete_event 이벤트 삭제
get_event 단일 이벤트 상세 조회

작업 보드

이 섹션을 Jira처럼 사용한다. 상태: [ ] TODO / [~] IN PROGRESS / [x] DONE 작업 착수 시 [~]로, 완료 시 [x]로 갱신하고 커밋한다.

Phase 1 — 프로젝트 셋업

  • [x] ICMCP-20: 공용 계약 정의 (src/types.ts, src/errors.ts) — Phase 2/3 병렬 구현의 전제
  • [x] ICMCP-1: Node.js + TypeScript 프로젝트 초기화 (package.json, tsconfig.json, .gitignore)
  • [x] ICMCP-2: 의존성 설치 (@modelcontextprotocol/sdk, tsdav, ical.js, zod)
  • [x] ICMCP-3: 빌드/실행 스크립트 구성 (build, dev, start) + src/config.ts

Phase 2 — iCloud CalDAV 연동

  • [x] ICMCP-5: CalDAV 클라이언트 모듈 작성 — 로그인, principal/calendar-home 디스커버리
  • [x] ICMCP-6: 캘린더 목록 조회 구현 (current-user-privilege-set으로 readOnly 판별)
  • [x] ICMCP-7: 이벤트 조회(기간 필터) 구현 — VEVENT 파싱, 타임존 처리
  • [x] ICMCP-8: 이벤트 생성 구현 — VEVENT 생성, UID 관리
  • [x] ICMCP-9: 이벤트 수정/삭제 구현 — etag If-Match 기반 충돌 처리
  • [x] ICMCP-13: 반복 이벤트(RRULE) 지원 — ICAL.RecurExpansion 전개, EXDATE/RECURRENCE-ID 반영, 500회 상한

Phase 3 — MCP 서버

  • [x] ICMCP-10: MCP 서버 뼈대 작성 (stdio transport, 서버 메타데이터)
  • [x] ICMCP-11: Tool 스키마 정의 (zod v4) 및 7개 tool 등록
  • [x] ICMCP-12: 에러 처리 — 인증 실패, 네트워크 오류, 잘못된 입력을 사용자 친화적 메시지로 변환

Phase 4 — 통합 및 검증

  • [x] ICMCP-21: 통합 — 전체 타입체크/빌드 통과, stdout 누수 감사, 자격증명 없는 기동 동작 확인
  • [ ] ICMCP-4: 앱 암호 발급 절차 문서화 (appleid.apple.com → 앱 암호)
  • [ ] ICMCP-14: Claude Code에 MCP 서버 등록 (claude mcp add) 및 실제 캘린더로 E2E 테스트
  • [ ] ICMCP-15: Claude Desktop 설정 방법 문서화 (claude_desktop_config.json)
  • [ ] ICMCP-16: README 사용법 최종 정리 (설치, 설정, tool 사용 예시)

Backlog (추후)

  • [ ] ICMCP-22: getEvent/updateEvent/deleteEvent의 UID 조회가 캘린더 전체 스캔이다. EventRef에 리소스 URL이 없어 O(n)이며, 이력이 긴 캘린더에서 느리다. UID prop-filter REPORT 또는 uid→url 캐시로 개선.
  • [ ] ICMCP-23: 쓰기 시 VTIMEZONE을 고정 오프셋 단일 observance로 합성한다(tzdata 미번들). DST가 있는 지역에서 전환을 걸치는 반복 일정은 전환 이후 발생의 오프셋이 틀어질 수 있다. 기본값 Asia/Seoul은 DST가 없어 영향 없음.
  • [ ] ICMCP-24: tsdav의 디스커버리/조회 계열은 상태 코드 없는 평범한 Error를 던져서, 에러 분류가 메시지 정규식 추정에 의존한다. CRUD 계열만 상태 코드 기반으로 정확히 분류됨.
  • [ ] ICMCP-17: iCloud Reminders(미리알림) 지원
  • [ ] ICMCP-18: 초대/참석자(ATTENDEE) 지원
  • [ ] ICMCP-19: 캐싱으로 조회 속도 개선

실제 계정으로 확인이 필요한 미결 사항

구현은 끝났지만 실 iCloud 계정 없이는 검증할 수 없어 가정으로 남아 있는 것들이다. ICMCP-14에서 반드시 확인한다.

  1. 조회 구간 end의 배타성list_events/search_eventsend를 배타적 경계(RFC 4791 time-range 관례)로 문서화하고 tool 설명에도 그렇게 적었다. Apple 서버가 포함적으로 동작한다면 하루치가 어긋난다.
  2. readOnly 판별current-user-privilege-set PROPFIND 응답을 덕타이핑으로 해석한다. 실제 iCloud 응답 형태로 검증 필요.
  3. 생성 직후 재조회createEvent는 PUT 후 서버에서 다시 읽어 etag를 채운다. iCloud의 반영 지연이 있다면 재시도가 필요할 수 있다.

개발 환경 설정

npm install
npm run build       # dist/ 생성
npm run typecheck   # 타입만 검사
npm run dev         # watch 모드

앱 암호는 appleid.apple.com > 로그인 및 보안 > 앱 암호에서 발급한다. Apple ID 본 비밀번호로는 CalDAV 로그인이 되지 않는다.

Claude Code 등록:

claude mcp add icloud \
  --env APPLE_ID=you@icloud.com \
  --env APPLE_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
  -- node /path/to/icloud-mcp/dist/index.js

.env 파일은 읽지 않는다. 자격증명은 MCP 호스트가 환경변수로 주입한다.

선택 환경변수: ICLOUD_DEFAULT_CALENDAR_URL(생성 시 기본 캘린더), ICLOUD_DEFAULT_TIMEZONE(기본 Asia/Seoul).

현재 상태

Phase 1~3 구현 완료. 타입체크·빌드 통과, 전 소스에 stdout 출력 없음(프로토콜 안전), 자격증명 누락 시 stderr로 안내 후 exit 1 확인. 아직 실제 iCloud 계정으로 E2E 검증은 하지 않았다 (ICMCP-14).

보안 원칙

  • Apple ID 본 비밀번호는 절대 사용하지 않는다. 앱 암호만 사용한다.
  • .env.gitignore에 포함하며, 자격증명은 어떤 파일로도 커밋하지 않는다.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured