naverworks-channel-mcp
v0.2.5
Published
NaverWorks Channel MCP Server for Claude Code
Readme
naverworks-channel-mcp
NAVER WORKS 메신저와 Claude Code를 릴레이 서버 + per-session MCP 서버 구조로 연결한다.
현재 저장소에는 실행 대상이 2개 있다.
- Relay Server: NAVER WORKS callback 수신, WebSocket relay, API proxy, RBAC, permission check 제공
- MCP package: 사용자 PC에서
npx naverworks-channel-mcp로 실행되는 per-session MCP 서버
현재 구현 범위
- NAVER WORKS 텍스트/파일/이미지 메시지를 Claude Code 세션으로 전달
reply도구로 NAVER WORKS에 응답 전송view_image도구로 다운로드된 이미지 미리보기- Rich message 전송 지원
textbutton_templatelinkimagelist_templatecarouselimage_carouselflex- optional
quick_reply
- Relay API proxy를 통한 NAVER WORKS 자격증명 중앙화
- 선택적 RBAC managed session
- role별 허용 도구 제한
- 민감 경로 차단
- 감사 로그 기록
- 전송 계층 보안 강화
- HTTP 보안 헤더
- rate limiting
- reverse proxy 뒤
REQUIRE_TLS강제 - internal permission token rotation
구성 요소
| 경로 | 역할 |
|------|------|
| src/index.ts | Relay Server 엔트리포인트 |
| src/relay/relay-server.ts | HTTP callback, WS relay, API proxy, RBAC 구성 |
| src/session/per-session-server.ts | 배포용 MCP 서버 엔트리포인트 |
| scripts/build-mcp.sh | dist/mcp-server.js 번들 생성 |
| scripts/build-mcpb.sh | Claude Desktop용 dist/naverworks-channel.mcpb 번들 생성 |
| mcpb/manifest.json | MCPB 메타데이터와 설치 시 입력받을 user_config 정의 |
| .env.example | Relay/배포 환경변수 예시 |
| .mcp.json.example | 사용자 PC용 MCP 설정 예시 |
아키텍처
NAVER WORKS
└─ POST /callback
↓
Relay Server (HTTP + WS + API proxy + RBAC)
↑ ↓
│ POST /api/send-message
│ POST /api/download-media
│
WebSocket /ws
↑
MCP package (npx naverworks-channel-mcp)
↑
Claude Codesrc/session/per-session-server.ts는 Relay에 WebSocket으로 연결하고, 응답 전송이나 미디어 다운로드가 필요할 때 Relay HTTP API를 사용한다.
빠른 시작
1. Relay Server 준비
bun install
cp .env.example .env최소 필수값:
NW_BOT_SECRET=<Bot Secret>
USER_TOKENS=userId1:token1,userId2:token2Relay가 NAVER WORKS API까지 대신 호출하게 하려면 아래도 채운다.
NW_CLIENT_ID=<Client ID>
NW_CLIENT_SECRET=<Client Secret>
NW_SERVICE_ACCOUNT_ID=<Service Account ID>
NW_PRIVATE_KEY=<inline PEM>
# 또는 NW_PRIVATE_KEY_PATH=./private-key.pem
NW_BOT_ID=<Bot ID>
NW_DOMAIN_ID=<Domain ID>RBAC managed session을 켜려면 아래도 필요하다.
USER_ROLES=userId1:admin,userId2:developer,userId3:viewer
TENANT_ID=my-workspace2. Relay Server 실행
# 로컬 개발
bun start
# Docker
docker compose up -d relaydocker-compose.yml은 기본적으로 3000만 publish하고 8080은 expose만 한다. 외부 사용자를 붙이려면 reverse proxy 또는 원격 배포가 필요하다.
현재 docker-compose.yml은 기본 환경변수만 전달한다. 추가 환경변수 설정이 필요하면 WebSocket Relay 배포 메모를 참고한다.
3. 사용자 PC에서 MCP 설정 (Claude Desktop)
GitHub Releases에서 naverworks-channel.mcpb 파일을 다운로드한 뒤 더블클릭하면 Claude Desktop에 자동 설치된다. 설치 시 Relay URL, 인증 토큰, Bot ID를 입력하는 폼이 표시된다.
로컬에서 직접 번들을 만들려면 bun run build:mcpb를 사용한다.
3-1. 사용자 PC에서 MCP 설정 (대화형 위저드)
npx naverworks-channel-mcp init관리자로부터 받은 Relay URL, 토큰, Bot ID를 입력하면 연결 테스트 후 Claude Code에 자동 등록된다.
비대화형 모드:
npx naverworks-channel-mcp init \
--relay-url wss://relay.example.com/ws \
--token your-token \
--bot-id your-bot-id| 옵션 | 설명 |
|------|------|
| --relay-url | Relay WebSocket URL |
| --token | 인증 토큰 |
| --bot-id | NAVER WORKS Bot ID |
| --api-url | API Base URL (선택, 미지정 시 자동 유도) |
| --skip-test | 연결 테스트 건너뛰기 |
| --server-name | MCP 서버 등록 이름 (기본: naverworks) |
3-2. 수동 MCP 설정
위저드 대신 직접 설정하려면 아래 JSON을 .mcp.json에 추가한다.
기본 공개 경로가 /ws, /api/*인 경우:
{
"mcpServers": {
"naverworks": {
"command": "npx",
"args": ["-y", "naverworks-channel-mcp"],
"env": {
"RELAY_WS_URL": "wss://relay.example.com/ws",
"RELAY_TOKEN": "<서버에서 발급한 토큰>",
"NW_BOT_ID": "<Bot ID>"
}
}
}
}공개 경로에 prefix가 있거나 HTTP API base가 WebSocket URL에서 자동 추론되지 않으면 RELAY_API_URL을 명시한다.
{
"mcpServers": {
"naverworks": {
"command": "npx",
"args": ["-y", "naverworks-channel-mcp"],
"env": {
"RELAY_WS_URL": "wss://relay.example.com/socket/ws",
"RELAY_TOKEN": "<서버에서 발급한 토큰>",
"RELAY_API_URL": "https://relay.example.com/relay",
"NW_BOT_ID": "<Bot ID>"
}
}
}
}주의:
RELAY_API_URL은 base URL이다- 클라이언트가 여기에
/api/send-message,/api/download-media를 이어 붙인다 - 따라서 보통
https://host/relay처럼 넣고,https://host/relay/api처럼/api까지 포함하지 않는다
사용자 초대 (Provision URL)
Relay 서버에 RBAC(USER_ROLES, TENANT_ID)과 NW_BOT_ID가 설정되어 있으면, admin 역할의 사용자가 초대 URL을 생성하여 새 사용자를 온보딩할 수 있다.
curl -X POST https://relay.example.com/api/provision/invite \
-H "Authorization: Bearer <관리자-토큰>" \
-H "Content-Type: application/json" \
-d '{"targetUserId": "nw-user-id"}'응답으로 받은 inviteUrl을 사용자에게 전달하면, 사용자는 브라우저에서 열어 표시된 명령어를 터미널에 붙여넣기만 하면 설정이 완료된다.
공개 URL이 실제 요청 host/path와 다르면 아래 환경변수로 초대 링크와 init 명령어를 분리해서 제어할 수 있다.
PROVISION_PUBLIC_BASE_URL: 브라우저에 반환할inviteUrl의 기준 HTTP base URL. 보통https://host/relay처럼 설정하고/api는 붙이지 않는다.PROVISION_WS_URL:init --relay-url에 강제로 넣을 WebSocket URLPROVISION_API_URL:init --api-url에 강제로 넣을 HTTP API base URL
| 파라미터 | 설명 |
|----------|------|
| targetUserId | NAVER WORKS 사용자 ID |
| expiresInMinutes | 초대 만료 시간 (기본: 60분) |
초대 URL은 1회용이며, 사용 후 또는 만료 후 재사용할 수 없다. 동적으로 발급된 토큰은 Relay 재시작 시 소실되므로, USER_TOKENS에도 등록하는 것을 권장한다.
공개 엔드포인트와 prefix
기본값:
| 종류 | 공개 경로 |
|------|-----------|
| Callback | /callback |
| HTTP API | /api/send-message, /api/download-media, /api/provision/invite, /api/provision/setup/:inviteToken |
| WebSocket | /ws |
| Health | /health |
예를 들어 아래처럼 설정하면:
HTTP_PATH_PREFIX=/relay
WS_PATH_PREFIX=/socket공개 경로는 다음처럼 바뀐다.
| 종류 | 공개 경로 |
|------|-----------|
| Callback | /relay/callback |
| HTTP API | /relay/api/send-message, /relay/api/download-media, /relay/api/provision/invite, /relay/api/provision/setup/:inviteToken |
| WebSocket | /socket/ws |
| Health | /relay/health, /socket/health |
상세 프록시 예시는 docs/operations/websocket-relay-proxy.md를 따른다.
RBAC 현재 상태
RBAC는 USER_ROLES와 TENANT_ID가 모두 설정될 때만 활성화된다.
현재 구현에서 role별 허용 도구는 다음과 같다.
| role | 허용 도구 |
|------|-----------|
| admin | Read, Edit, Write, Grep, Glob, Bash, Skill, reply |
| developer | Read, Edit, Write, Grep, Glob, reply |
| viewer | Read, reply |
추가 제약:
- non-admin은
.env,.pem,secret,credentials,private_key패턴 경로 접근이 차단된다 - permission check는
scripts/pre-tool-use-hook.sh가 Relay의/api/check-permission을 호출해 수행한다 - 감사 로그는 JSON Lines로 기록되고 크기 기준 rotation이 적용된다
환경 변수
Relay Server
| 변수 | 설명 | 기본값 |
|------|------|--------|
| NW_BOT_SECRET | NAVER WORKS callback 서명 검증 | 필수 |
| USER_TOKENS | 사용자별 Relay 토큰 매핑 (userId:token,...) | 필수 |
| HTTP_PORT | HTTP 포트 | 3000 |
| WS_PORT | WebSocket 포트 | 8080 |
| NW_CLIENT_ID | 설정 시 API proxy 활성화 | - |
| NW_CLIENT_SECRET | NAVER WORKS client secret | - |
| NW_SERVICE_ACCOUNT_ID | service account ID | - |
| NW_PRIVATE_KEY | inline PEM private key | - |
| NW_PRIVATE_KEY_PATH | private key 파일 경로 | - |
| NW_BOT_ID | Bot ID | - |
| NW_DOMAIN_ID | NAVER WORKS domain ID | - |
| QUEUE_MAX_SIZE | 사용자별 대기 메시지 최대 개수 | 100 |
| QUEUE_TTL_HOURS | 대기 메시지 TTL | 24 |
| HTTP_PATH_PREFIX | HTTP prefix | 빈 문자열 |
| WS_PATH_PREFIX | WebSocket prefix | 빈 문자열 |
| USER_ROLES | RBAC role 매핑 | - |
| TENANT_ID | RBAC tenant ID | - |
| SESSION_TTL_HOURS | issued session TTL | 1 |
| MAX_SESSIONS | 최대 동시 managed session 수 | 10 |
| IDLE_TIMEOUT_MINUTES | 세션 유휴 종료 시간 | 30 |
| AUDIT_LOG_PATH | 감사 로그 파일 경로 | /var/log/relay/audit.jsonl |
| MAX_AUDIT_LOG_BYTES | 감사 로그 rotation 기준 크기 | 10485760 |
| MAX_AUDIT_LOG_FILES | 보관할 rotated audit log 수 | 5 |
| PROVISION_WS_URL | Provision이 init --relay-url에 넣을 WebSocket URL override | 자동 유도 |
| PROVISION_API_URL | Provision이 init --api-url에 넣을 HTTP API base URL override | 자동 유도 |
| PROVISION_PUBLIC_BASE_URL | Provision inviteUrl 생성에 사용할 공개 HTTP base URL | 요청 URL + HTTP_PATH_PREFIX |
| TRUST_PROXY | X-Forwarded-* 신뢰 여부 | false |
| REQUIRE_TLS | reverse proxy 뒤 HTTPS 강제 여부 | false |
| MAX_CONNECTIONS_PER_IP | IP당 동시 WS 연결 수 | 5 |
| MAX_MESSAGES_PER_MINUTE | WS 메시지 rate limit | 60 |
| MAX_WS_UPGRADES_PER_MINUTE | WS upgrade rate limit | 30 |
| MAX_REQUESTS_PER_MINUTE | HTTP request rate limit | 120 |
| MAX_FILE_SIZE_MB | 다운로드 가능한 첨부 최대 크기 | 50 |
참고: 현재 docker-compose.yml은 이 표의 모든 값을 자동 전달하지 않는다. 상세 내용은 배포 메모를 참고한다.
MCP package
| 변수 | 설명 | 기본값 |
|------|------|--------|
| RELAY_WS_URL | Relay WebSocket URL | 필수 |
| RELAY_TOKEN | 사용자별 Relay 토큰 | 필수 |
| NW_BOT_ID | reply 대상 Bot ID | 필수 |
| RELAY_API_URL | Relay HTTP API base URL | 자동 추론 |
| MAX_IMAGE_VIEW_SIZE_MB | view_image 최대 허용 크기 | 10 |
로컬 스킬
이 저장소에는 현재 3개의 로컬 스킬이 있다.
| 스킬 | 파일 | 용도 |
|------|------|------|
| build | .agents/skills/build/SKILL.md | MCP 번들 또는 Relay Docker 이미지 빌드 |
| test | .agents/skills/test/SKILL.md | unit/integration/E2E 테스트 실행 |
| deploy | .agents/skills/deploy/SKILL.md | npm publish 또는 원격 Relay 배포 |
핵심 명령:
build:bun run build:mcp,bun run build:mcpb,bun run build:relaytest:bun run testdeploy:bun run deploy:relay,bun run publish:package
개발
bun install
bun run check # lint + typecheck + test
bun run test # 테스트만
bun run typecheck # 타입 체크만
bun run lint # lint만
bun run format # 코드 포맷팅
bun run build:mcp # MCP 번들 빌드
bun run build:mcpb # MCPB 번들 빌드
bun run build:relay # Relay Docker 이미지 빌드운영 문서:
docs/operations/websocket-relay.mddocs/operations/websocket-relay-proxy.md
라이선스
MIT
Privacy Policy
Data Collection
This MCP server processes the following data:
- Message content: Text, images, and files sent through NAVER WORKS
- User identifiers: NAVER WORKS user IDs and channel IDs
- Metadata: Timestamps, message types, file names
Data Storage
- Message queue: In-memory only, TTL 24 hours (configurable), not persisted to disk
- Media files: Temporarily stored in
/tmp/naverworks-media/ - Audit logs: Stored locally at configured path, rotated at 10MB, max 5 files retained
- Authentication tokens: In-memory only, rotated every 30 minutes
Third-Party Sharing
- NAVER WORKS API: Messages are relayed to/from NAVER WORKS via their official API
- Anthropic: When used via Claude Code, Anthropic collects tool call parameters and responses as telemetry. Consumer plan data may be used for model training with explicit opt-in. Team/Enterprise plans are excluded.
Data Retention
| Data Type | Retention | |-----------|-----------| | Message queue | 24 hours (configurable via QUEUE_TTL_HOURS) | | Media temp files | Until manual cleanup | | Audit logs | Size-based rotation (10MB x 5 files) | | Session tokens | Until server restart or 1-hour TTL |
Your Rights
Users may exercise data protection rights (GDPR, CCPA, LGPD) by contacting the server operator. MCP servers handle compliance independently from Claude.
Contact
For privacy inquiries: [email protected]
