icloud-mcp
Provides tools for managing iCloud Calendar events, including listing calendars, searching and retrieving events, and creating, updating, and deleting events with support for all-day events, reminders, and recurrence.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@icloud-mcpWhat events do I have scheduled tomorrow?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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", tsconfigNodeNext)주요 라이브러리:
@modelcontextprotocol/sdk— MCP 서버 프레임워크 (stdio transport)tsdav— CalDAV 클라이언트ical.js— iCalendar(VEVENT) 파싱 및 생성zod— tool 입력 스키마 검증
인증 정보 관리: 환경변수(
APPLE_ID,APPLE_APP_PASSWORD) — 코드/저장소에 절대 커밋 금지. 앱 암호는 macOS 키체인에 두고 실행 래퍼(bin/icloud-mcp.sh)가 주입하는 것을 권장한다(ICMCP-25).
확정된 기술 결정
결정 | 이유 |
iCalendar 라이브러리를 |
|
ESM + | MCP SDK가 ESM 우선이다. |
반복 일정은 | CalDAV 서버측 |
이벤트 식별자는 | CalDAV 리소스 URL은 서버가 바꿀 수 있어 대화 중 재사용에 부적합하다. |
모든 로그는 stderr 로만 출력 | stdio transport에서 stdout은 JSON-RPC 전용 채널이다. stdout에 한 줄이라도 찍으면 프로토콜이 깨진다. |
종일 일정의 | RFC 5545의 |
모듈 구조 및 소유권
bin/
└── icloud-mcp.sh # 실행 래퍼: 키체인에서 앱 암호를 꺼내 주입 후 서버 exec
scripts/
└── setup.sh # 새 Mac 셋업: 빌드 + 키체인 + 호스트 등록 + 기동 검증
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 레이어 사이의 고정된 계약이다. 양쪽은 이 파일을 통해서만 통신하며, 계약 변경은 양쪽 동시 수정을 뜻하므로 함부로 바꾸지 않는다.
Related MCP server: Daylite Claude Connector
제공할 MCP Tools
Tool | 설명 |
| 사용 가능한 캘린더 목록 조회 |
| 기간(시작~종료)으로 이벤트 조회 |
| 키워드로 이벤트 검색 |
| 이벤트 생성 (제목, 시작/종료, 종일 여부, 위치, 메모, 알림, 반복) |
| 이벤트 수정 |
| 이벤트 삭제 |
| 단일 이벤트 상세 조회 |
작업 보드
이 섹션을 Jira처럼 사용한다. 상태:
[ ]TODO /[~]IN PROGRESS /[x]DONE 작업 착수 시[~]로, 완료 시[x]로 갱신하고 커밋한다.
Phase 1 — 프로젝트 셋업
ICMCP-20: 공용 계약 정의 (
src/types.ts,src/errors.ts) — Phase 2/3 병렬 구현의 전제ICMCP-1: Node.js + TypeScript 프로젝트 초기화 (
package.json,tsconfig.json,.gitignore)ICMCP-2: 의존성 설치 (
@modelcontextprotocol/sdk,tsdav,ical.js,zod)ICMCP-3: 빌드/실행 스크립트 구성 (
build,dev,start) +src/config.ts
Phase 2 — iCloud CalDAV 연동
ICMCP-5: CalDAV 클라이언트 모듈 작성 — 로그인, principal/calendar-home 디스커버리
ICMCP-6: 캘린더 목록 조회 구현 (
current-user-privilege-set으로 readOnly 판별)ICMCP-7: 이벤트 조회(기간 필터) 구현 — VEVENT 파싱, 타임존 처리
ICMCP-8: 이벤트 생성 구현 — VEVENT 생성, UID 관리
ICMCP-9: 이벤트 수정/삭제 구현 — etag
If-Match기반 충돌 처리ICMCP-13: 반복 이벤트(RRULE) 지원 —
ICAL.RecurExpansion전개, EXDATE/RECURRENCE-ID 반영, 500회 상한
Phase 3 — MCP 서버
ICMCP-10: MCP 서버 뼈대 작성 (stdio transport, 서버 메타데이터)
ICMCP-11: Tool 스키마 정의 (zod v4) 및 7개 tool 등록
ICMCP-12: 에러 처리 — 인증 실패, 네트워크 오류, 잘못된 입력을 사용자 친화적 메시지로 변환
Phase 4 — 통합 및 검증
ICMCP-21: 통합 — 전체 타입체크/빌드 통과, stdout 누수 감사, 자격증명 없는 기동 동작 확인
ICMCP-4: 앱 암호 발급 절차 문서화 (appleid.apple.com → 앱 암호)
[~] ICMCP-14: Claude Code에 MCP 서버 등록 (
claude mcp add) 및 실제 캘린더로 E2E 테스트 — 등록·연결·tools/list(7개)·list_calendars(실 캘린더 8개 조회)까지 확인. 아래 미결 사항 1·3은 미검증ICMCP-15: Claude Desktop 설정 방법 문서화 (
claude_desktop_config.json) — GUI 최소 PATH 환경에서 래퍼가/usr/local/bin/node로 폴백해 기동하는 것까지 검증ICMCP-26: 프로젝트를 TCC 보호 폴더 밖(
~/dev/icloud-mcp)으로 이전 — Claude Desktop이 GUI 프로세스라~/Documents내 파일을 실행조차 못 하고Operation not permitted로 죽었다. 앱에 문서 폴더 접근 권한을 주는 대신 경로를 옮겨 해결. 기존 위치엔 심볼릭 링크를 남겨 폴더 구성을 유지했고, Claude Code/Desktop 양쪽 등록 경로를 갱신했다.ICMCP-27: 다른 Mac에서 한 번에 설치·등록하는 셋업 스크립트 (
scripts/setup.sh) — 빌드, 키체인 저장, Claude Code/Desktop 등록, TCC 보호 폴더 검사, GUI 최소 PATH 기동 검증까지ICMCP-16: README 사용법 최종 정리 (설치, 설정, tool 사용 예시)
ICMCP-25: 앱 암호를 MCP 호스트 설정(
~/.claude.json)에 평문으로 두지 않도록 macOS 키체인 연동 — 실행 래퍼bin/icloud-mcp.sh가 기동 시 키체인에서 꺼내 환경변수로 주입
Backlog (추후)
ICMCP-22:
getEvent/updateEvent/deleteEvent의 UID 조회가 캘린더 전체 스캔이다.EventRef에 리소스 URL이 없어 O(n)이며, 이력이 긴 캘린더에서 느리다. UIDprop-filterREPORT 또는 uid→url 캐시로 개선.ICMCP-23: 쓰기 시 VTIMEZONE을 고정 오프셋 단일 observance로 합성한다(tzdata 미번들). DST가 있는 지역에서 전환을 걸치는 반복 일정은 전환 이후 발생의 오프셋이 틀어질 수 있다. 기본값
Asia/Seoul은 DST가 없어 영향 없음.ICMCP-24: tsdav의 디스커버리/조회 계열은 상태 코드 없는 평범한
Error를 던져서, 에러 분류가 메시지 정규식 추정에 의존한다. CRUD 계열만 상태 코드 기반으로 정확히 분류됨.ICMCP-28: 기동 시 디스커버리가 간헐적으로 실패한다. 실제로 Claude Desktop에서 principal 조회는 성공하고
calendar-home-set조회만cannot find homeUrl로 실패한 뒤, 재시작하니 정상 동작한 사례가 있다. home url은p60-caldav.icloud.com같은 별도 샤드 호스트로 리디렉트되는데 이쪽이 일시적으로 실패하는 것으로 보인다. 디스커버리 단계에 짧은 백오프 재시도를 넣어야 한다. 지금은 실패하면 서버가 그대로 죽어서 호스트에는Server disconnected로만 보인다.ICMCP-17: iCloud Reminders(미리알림) 지원
ICMCP-18: 초대/참석자(ATTENDEE) 지원
ICMCP-19: 캐싱으로 조회 속도 개선
실제 계정으로 확인이 필요한 미결 사항
구현은 끝났지만 실 iCloud 계정 없이는 검증할 수 없어 가정으로 남아 있는 것들이다. ICMCP-14에서 반드시 확인한다.
조회 구간
end의 배타성 —list_events/search_events의end를 배타적 경계(RFC 4791 time-range 관례)로 문서화하고 tool 설명에도 그렇게 적었다. Apple 서버가 포함적으로 동작한다면 하루치가 어긋난다.readOnly판별 —current-user-privilege-setPROPFIND 응답을 덕타이핑으로 해석한다. 실 계정에서list_calendars가 8개 캘린더를 모두 "쓰기 가능"으로 반환했으나, 테스트 계정에 읽기 전용 캘린더(구독 캘린더 등)가 없어서 "판별이 동작한다"와 "항상 쓰기 가능을 반환한다"를 구분하지 못했다. 구독 캘린더를 하나 추가해 재확인 필요.생성 직후 재조회 —
createEvent는 PUT 후 서버에서 다시 읽어 etag를 채운다. iCloud의 반영 지연이 있다면 재시도가 필요할 수 있다.
빠른 설치 — 다른 Mac에서 (ICMCP-27)
새 Mac에서는 셋업 스크립트 하나로 끝난다. ~/Documents·~/Desktop·~/Downloads 밖에 clone해야 한다 (이유는 Claude Desktop 등록 참고).
git clone https://github.com/jinho-waah/icloud-mcp.git ~/dev/icloud-mcp
cd ~/dev/icloud-mcp
./scripts/setup.sh # Apple ID를 대화형으로 물어본다
./scripts/setup.sh you@icloud.com # 인자로 넘겨도 된다스크립트가 하는 일:
프로젝트가 TCC 보호 폴더 안에 있으면 중단하고 옮기는 방법을 안내한다
Node.js 18 이상 확인 →
npm install→npm run buildApple ID의 Latin1 범위 검사 (한글이 섞이면 기동 시점에
btoa()에서 죽으므로 미리 막는다)앱 암호를 키체인에 저장 (이미 있으면 유지할지 묻는다). 화면·셸 히스토리 어디에도 남지 않는다
Claude Code 등록 (
claudeCLI가 있으면)Claude Desktop 설정 병합 (
jq없이 node로 처리, 기존 키 보존,.bak생성)GUI 최소 PATH 환경을 재현해 실제로 iCloud 로그인까지 되는지 검증
끝나면 Claude Code는 재시작, Claude Desktop은 ⌘Q 후 재실행하면 된다.
앱 암호는 기기마다 따로 발급하는 편이 낫다. 한 대를 분실하거나 정리할 때 그 기기 것만 폐기하면 되고, 다른 기기는 영향을 받지 않는다. (Apple 계정당 앱 암호는 여러 개 만들 수 있다.)
개발 환경 설정
npm install
npm run build # dist/ 생성
npm run typecheck # 타입만 검사
npm run dev # watch 모드수동으로 설정하려면 아래 절들을 따른다.
앱 암호 발급
로그인 및 보안 > 앱 전용 암호 > + 로 새 암호 생성 (이름은
icloud-mcp등 아무거나)xxxx-xxxx-xxxx-xxxx형태의 16자 암호가 한 번만 표시된다. 창을 닫으면 다시 볼 수 없으니 바로 복사한다.
Apple ID 본 비밀번호로는 CalDAV 로그인이 되지 않는다. 2단계 인증이 켜져 있어야 앱 암호 메뉴가 나타난다.
Claude Code 등록 — 권장: 키체인 방식 (ICMCP-25)
MCP 호스트 설정 파일(~/.claude.json)에 앱 암호를 평문으로 적지 않는 방식이다. 암호는 macOS 키체인에 두고, 실행 래퍼 bin/icloud-mcp.sh가 기동 시점에 꺼내 환경변수로 주입한다.
# 1) 앱 암호를 키체인에 저장 (한 번만)
# '-w' 뒤에 값을 쓰지 않으면 대화형으로 입력받는다 → 셸 히스토리에 남지 않는다
security add-generic-password -s icloud-mcp -a "you@icloud.com" -T /usr/bin/security -w
# 2) 래퍼를 command로 등록. env에는 APPLE_ID만 들어간다
claude mcp add icloud --scope user \
-e APPLE_ID=you@icloud.com \
-- /절대/경로/icloud-mcp/bin/icloud-mcp.sh-T /usr/bin/security는 키체인 항목의 ACL에security명령을 신뢰 앱으로 등록한다. 이게 없으면 서버가 뜰 때마다 키체인 접근 허용 팝업이 뜬다.키체인 항목의 account는
APPLE_ID값과 같아야 한다. 래퍼가-a "$APPLE_ID"로 조회한다.서비스 이름을 바꾸려면
ICLOUD_MCP_KEYCHAIN_SERVICE환경변수로 덮어쓴다 (기본icloud-mcp).APPLE_APP_PASSWORD가 환경변수로 이미 들어와 있으면 래퍼는 키체인을 건너뛴다 (CI·수동 테스트용).GUI 앱(Claude Desktop)은 PATH가 최소한이라 nvm/homebrew의
node를 못 찾을 수 있다. 그런 경우NODE_BIN에node절대경로를 지정한다.
이 방식이 막아주는 것과 못 막는 것: 평문 유출 경로(설정 파일 백업·클라우드 동기화·스크린샷·실수 커밋)를 막고, 폐기/교체 지점을 한 곳으로 모은다. 반면 키체인은 로그인 시 잠금이 풀려 있으므로 이미 내 계정 권한을 획득한 악성 프로세스는 여전히 꺼낼 수 있다. 로컬 침해에 대한 방어가 아니다.
Claude Code 등록 — 간단(비권장): 환경변수 직접 주입
claude mcp add icloud --scope user \
-e APPLE_ID=you@icloud.com \
-e APPLE_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
-- node /절대/경로/icloud-mcp/dist/index.js앱 암호가 ~/.claude.json에 평문으로 남는다(파일 권한은 600). 편의상 쓸 수는 있지만 위 키체인 방식을 권한다.
Claude Desktop 등록 (ICMCP-15)
설정 파일: ~/Library/Application Support/Claude/claude_desktop_config.json
Claude Desktop에는 claude mcp add 같은 CLI가 없으므로 이 파일을 직접 편집한다. 기존 키(preferences 등)를 지우지 않도록 병합해서 쓴다.
{
"mcpServers": {
"icloud": {
"command": "/절대/경로/icloud-mcp/bin/icloud-mcp.sh",
"env": { "APPLE_ID": "you@icloud.com" }
}
}
}명령줄로 안전하게 병합하려면:
CFG=~/Library/Application\ Support/Claude/claude_desktop_config.json
cp "$CFG" "$CFG.bak"
jq '.mcpServers.icloud = {
"command": "/절대/경로/icloud-mcp/bin/icloud-mcp.sh",
"env": { "APPLE_ID": "you@icloud.com" }
}' "$CFG" > "$CFG.tmp" && mv "$CFG.tmp" "$CFG"Claude Code 설정과 완전히 독립이다. 두 앱은 서로 다른 파일을 보므로 양쪽 다 쓰려면 양쪽에 등록해야 한다. 키체인 항목은 하나를 공유한다.
주의할 점:
프로젝트를
~/Documents·~/Desktop·~/Downloads안에 두면 안 된다 (ICMCP-26). 이 세 폴더는 macOS TCC 보호 대상이다. Claude Desktop은 GUI 앱이라 기본적으로 접근 권한이 없어서, 그 안의 스크립트를 실행조차 못 하고 이렇게 죽는다:/bin/sh: /Users/이름/Documents/.../bin/icloud-mcp.sh: Operation not permitted [icloud] Server transport closed unexpectedly파일 권한(
chmod +x)이나 quarantine 문제가 아니다. 터미널에서 실행되는 Claude Code는 이미 권한이 있으므로 같은 설정이 Claude Code에선 되고 Desktop에서만 실패한다. 앱에 문서 폴더 접근 권한을 줘도 해결되지만(시스템 설정 > 개인정보 보호 및 보안 > 파일 및 폴더), 서버 하나 돌리려고 GUI 앱에 문서 폴더 전체를 여는 건 과하다. 보호 폴더 밖(~/dev등)에 두는 편이 낫다.기존 폴더 구성을 유지하고 싶으면 원래 위치에 심볼릭 링크를 남긴다. 링크는 사람이 탐색할 때만 쓰이고 MCP 설정에는 실제 경로를 적으므로 TCC에 걸리지 않는다:
mv ~/Documents/어딘가/icloud-mcp ~/dev/icloud-mcp ln -s ~/dev/icloud-mcp ~/Documents/어딘가/icloud-mcpdist/index.js를 읽는 node도 같은 TCC 컨텍스트에서 돌기 때문에, 래퍼만 밖으로 빼는 것으로는 부족하고 프로젝트 전체가 밖에 있어야 한다.command는 반드시 절대경로로 쓴다. 상대경로는 앱의 작업 디렉터리 기준이라 맞지 않는다.GUI 앱은 PATH가 최소한(
/usr/bin:/bin:/usr/sbin:/sbin)이다. 로그인 셸이 아니라 launchd가 띄우기 때문에~/.zshrc가 로드되지 않고, nvm이나 homebrew로 설치한node는 PATH에 없다. 그래서node dist/index.js를 직접command로 지정하면 데스크톱 앱에서만spawn node ENOENT로 실패한다. 래퍼는 이 상황에서/usr/local/bin/node→/opt/homebrew/bin/node순으로 폴백한다. 둘 다 없으면env에NODE_BIN으로 절대경로를 지정한다:"env": { "APPLE_ID": "you@icloud.com", "NODE_BIN": "/Users/이름/.nvm/versions/node/v22.14.0/bin/node" }앱을 완전히 종료(⌘Q)한 뒤 다시 실행해야 설정이 반영된다. 창만 닫는 것으로는 부족하다.
로그:
~/Library/Logs/Claude/mcp-server-icloud.log(서버 stderr),~/Library/Logs/Claude/mcp.log(호스트 측 연결 로그). 연결이 안 되면 여기부터 본다.키체인 항목을 만들 때
-T /usr/bin/security를 빠뜨리면, 데스크톱 앱이 서버를 띄울 때마다 키체인 접근 허용 팝업이 뜬다.
공통 주의사항
--scope project를 쓰지 말 것. 저장소 루트에.mcp.json을 만들고 거기에 앱 암호를 평문으로 적는다. 이 저장소는 GitHub에 푸시되므로 그대로 유출된다. (.gitignore에 방어선을 넣어 두긴 했다.)--scope user는~/.claude.json에 저장되어 어느 디렉터리에서든 쓸 수 있다.등록 명령은 셸 히스토리에 남는다. 신경 쓰인다면 실행 후
history -d로 지우거나, 앞에 공백을 한 칸 넣어 히스토리에 남지 않게 한다.APPLE_ID에 한글 등 Latin1 범위 밖 문자가 들어가면 안 된다. CalDAV Basic 인증 헤더를 만드는btoa()단계에서The string to be encoded contains characters outside of the Latin1 range.로 죽고, 호스트에는Connection closed로만 보인다.
.env 파일은 읽지 않는다. 자격증명은 MCP 호스트가 환경변수로 주입한다.
암호 교체 / 폐기
앱 암호가 새어 나갔다고 판단되면 appleid.apple.com에서 해당 암호만 취소하면 된다. Apple ID 본 비밀번호나 다른 기기 로그인에는 영향이 없다.
키체인 방식이면 교체는 항목 갱신 한 번으로 끝난다:
security delete-generic-password -s icloud-mcp -a "you@icloud.com"
security add-generic-password -s icloud-mcp -a "you@icloud.com" -T /usr/bin/security -w선택 환경변수: ICLOUD_DEFAULT_CALENDAR_URL(생성 시 기본 캘린더), ICLOUD_DEFAULT_TIMEZONE(기본 Asia/Seoul).
현재 상태
Phase 1~3 구현 완료. 타입체크·빌드 통과, 전 소스에 stdout 출력 없음(프로토콜 안전), 자격증명 누락 시 stderr로 안내 후 exit 1 확인.
실 계정 연동 확인됨 — Claude Code에 키체인 래퍼 방식으로 등록(ICMCP-25), CalDAV 로그인·principal 디스커버리 성공, initialize + tools/list(7개) 정상, list_calendars로 실제 캘린더 8개 조회 성공. 이벤트 CRUD와 조회 구간 경계 동작은 아직 미검증이다(ICMCP-14).
보안 원칙
Apple ID 본 비밀번호는 절대 사용하지 않는다. 앱 암호만 사용한다.
.env는.gitignore에 포함하며, 자격증명은 어떤 파일로도 커밋하지 않는다.앱 암호는 MCP 호스트 설정 파일에 평문으로 두지 않는다. macOS 키체인 +
bin/icloud-mcp.sh조합을 쓴다(ICMCP-25).로그는 전부 stderr로 나가며,
src/errors.ts의redact()가 진단 메시지에서 Apple ID·앱 암호를 마스킹한다. 래퍼 스크립트도 stdout에 아무것도 쓰지 않는다.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityDmaintenanceEnables users to view and create events in their iCloud Calendar using natural language through supported LLMs. It integrates with Apple's infrastructure via app-specific passwords to provide secure calendar management.Last updated1
- FlicenseAqualityDmaintenanceConnects Daylite CRM to Claude Code via the CalDAV interface to manage tasks and appointments. It enables users to list, create, update, and delete calendar events and to-dos directly through natural language.Last updated111
- Flicense-qualityBmaintenanceEnables LLM clients to interact with Apple Calendar (iCloud) via CalDAV, supporting listing calendars, retrieving, creating, updating, and moving events.Last updated
- AlicenseAqualityCmaintenanceEnables Claude to read, create, update, and delete Google Calendar events directly through natural language.Last updated6153MIT
Related MCP Connectors
Calendar API for AI agents: events, availability, Google/Microsoft setup, scheduling, and iCal.
Connects ChatGPT to your Apple Calendar via a local Mac agent + Vercel relay
Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jinho-waah/icloud-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server