🔐 Keycloak 사일런트 SSO
Keycloak에 로그인되어 있으면 mmcp는 화면 없이 바로 로그인됩니다(prompt=none). 첫 로그인 때 계정이 자동 생성되고 mcp-* 역할이 동기화됩니다.
v1.0.1 오프라인 사내망용 MCP 게이트웨이
Keycloak으로 로그인한 그 사람의 Mattermost 권한 그대로 Claude Code·Codex·Cursor·사내 AI 포털이 채널을 검색하고, 스레드를 요약하고, 승인 후 DM을 보냅니다. 환경변수 4개, 이미지 하나.
mmcp는 Keycloak 사용자를 Mattermost 계정에 안전하게 고정 매핑하고, 그 사용자의 권한으로만 Mattermost를 호출하는 MCP 서버입니다. Keycloak 액세스 토큰은 Mattermost API에 그대로 쓸 수 없고, 공용 서비스 계정으로 조회하면 AI가 사용자가 볼 수 없는 비공개 채널까지 보게 됩니다. mmcp가 그 간극을 메웁니다.
| 항목 | 공용 서비스 계정 | mmcp |
|---|---|---|
| 조회 권한 | 서비스 계정 권한 (과다 노출) | 사용자 본인 권한 |
| 사용자 식별 | 없음 또는 문자열 매칭 | Keycloak sub ↔ Mattermost user_id 고정 |
| 계정 재생성 공격 | 무방비 | IDENTITY_CONFLICT로 자동 차단 |
| 메시지 발송 | 무조건 실행 | 미리보기 → 동의 → confirm_token |
| 비밀번호 수집 | 경우에 따라 필요 | 절대 받지 않음 (PAT 자동 발급/봇) |
| 감사 | 서비스 계정 이름만 | 요청자·도구·채널·결과·지연 전부 |
Keycloak에 로그인되어 있으면 mmcp는 화면 없이 바로 로그인됩니다(prompt=none). 첫 로그인 때 계정이 자동 생성되고 mcp-* 역할이 동기화됩니다.
동적 클라이언트 등록, PKCE S256, 회전형 리프레시 토큰과 재사용 감지. Claude Code에서 "허용" 한 번이면 연결됩니다. Keycloak 토큰 직접 인증과 개인 API 키도 지원합니다.
preferred_username으로 최초 탐색한 뒤 sub ↔ user_id를 영구 식별자로 고정합니다. 삭제·재생성·이름 가로채기는 충돌로 차단하고 관리자 재매핑을 요구합니다.
김철수처럼 이름으로 받는 사람을 찾고 동명이인이면 후보를 돌려줍니다. 발신은 본인/봇("○○님의 요청")/자동 중에서 고르고 props.requested_by를 남깁니다.
쓰기 도구는 미리보기와 confirm_token을 먼저 돌려줍니다. 사용자가 동의해야 실행되고, 인자 변경·재사용·만료는 거부됩니다. 개인 공간에서 미리 승인/거절할 수 있습니다.
마스터 키 → 사용자별 데이터 키(AES-256-GCM, AAD 바인딩). 개인 키 회전, 마스터 키 무중단 회전(재래핑), API 키 유예 회전, Mattermost 토큰 자동 발급·일괄 회전.
공개/비공개/DM/그룹 채널별 허용, DM 검색·파일 다운로드 기본 차단, 사용자별 호출 한도, IP 허용목록, 프롬프트 인젝션 대비 신뢰불가 콘텐츠 래핑.
대시보드, 실시간 서버 로그(SSE), 감사 로그 CSV, 도구 실행기, 백업·복원, Ctrl+K 초성 검색 팔레트, 다크 모드, 모바일 화면.
distroless 단일 이미지(약 36MB), 읽기 전용 루트 FS, 외부 CDN 호출 없음. 환경변수 POSTGRES_DSN 외 3개가 전부입니다.


























mmcp-v1.0.1.tar.gz를 사내망으로 옮기고 검증합니다.docker load로 mmcp:v1.0.1을 올립니다.compose.offline.yml로 띄우고 8080 포트에 접속합니다.# 1) 검증 후 로드
sha256sum mmcp-v1.0.1.tar.gz # 릴리스 노트의 SHA-256 값과 비교
docker load -i mmcp-v1.0.1.tar.gz
# 2) 환경변수는 이 4개가 전부
cat > .env <<EOF
POSTGRES_DSN=postgres://mmcp:secret@db:5432/mmcp
BOOTSTRAP_ADMIN=admin
BOOTSTRAP_ADMIN_PASSWORD=Change-Me-Now-2026!
ENCRYPTION_KEY=$(docker run --rm mmcp:v1.0.1 gen-key)
EOF
# 3) 실행
docker compose -f compose.offline.yml up -d
# 4) AI 클라이언트 연결
claude mcp add --transport http mmcp \
https://mcp.company.co.kr/mcp
mattermost_me mattermost_teams mattermost_channels mattermost_channel mattermost_search_posts mattermost_get_post mattermost_get_thread mattermost_recent_posts mattermost_users mattermost_unread mattermost_pinned_posts mattermost_get_file
mattermost_post_message mattermost_reply mattermost_update_post mattermost_add_reaction mattermost_upload_file mattermost_create_channel mattermost_add_member mattermost_delete_post* mattermost_archive_channel*
mattermost_send_dm mattermost_send_group_dm mattermost_reply_dm mattermost_upload_dm_file mattermost_read_dm mattermost_recent_dms mattermost_search_dm
* 기본 비활성 위험 도구. 공식 Mattermost MCP 호환 별칭 dm group_message create_post search_users를 켤 수 있습니다. 리소스 mattermost://me, mattermost://channels/{id} 등과 프롬프트(채널 요약, 결정 사항 찾기, 오늘의 다이제스트, DM 초안)도 제공합니다.
MCP 클라이언트(Claude Code, Codex, Cursor, 사내 AI 포털)가 Mattermost를 쓰게 해 주는 게이트웨이입니다. 사용자는 Keycloak으로 인증하고, mmcp는 그 사용자에게 매핑된 Mattermost 계정의 권한으로만 REST API를 호출합니다.
아니요. Mattermost REST API는 자체 세션이나 개인 액세스 토큰(PAT)을 요구합니다. mmcp는 Keycloak 토큰으로 사용자를 식별하고, preferred_username으로 Mattermost 계정을 찾아 sub ↔ user_id를 고정한 뒤 그 사용자의 PAT로 호출합니다.
서비스 계정으로 조회하면 사용자가 볼 수 없는 비공개 채널까지 AI가 볼 수 있습니다. mmcp는 조회를 항상 사용자 본인 자격증명으로 실행하고, 서비스 토큰은 사용자 찾기와 PAT 자동 발급에만 씁니다.
필요 없습니다. 시스템 관리자 토큰이 설정되어 있으면 사용자 명의 PAT를 자동 발급하고, 아니면 사용자가 PAT를 직접 등록합니다. 봇 발신 모드에서는 사용자 자격증명 없이도 "○○님의 요청"으로 DM을 보낼 수 있습니다.
쓰기 도구는 기본적으로 2단계 승인입니다. 첫 호출은 미리보기와 confirm_token만 돌려주고, 사용자가 동의해야 같은 인자로 다시 호출해 실행됩니다. 인자가 바뀌거나 만료·거절·재사용된 토큰으로는 실행되지 않습니다.
mmcp는 username이 아닌 user_id를 신뢰합니다. 같은 username이 다른 계정을 가리키면 IDENTITY_CONFLICT로 자동 차단하고, 관리자가 확인 후 재검증해야만 새 계정과 다시 연결됩니다(이전 자격증명은 폐기).
네. mmcp-v1.0.1.tar.gz를 반입해 docker load하고 환경변수 4개만 지정하면 됩니다. UI·폰트까지 이미지에 포함되어 외부 CDN을 호출하지 않습니다.
로그인 화면이 prompt=none으로 Keycloak에 다녀옵니다. Keycloak 세션이 있으면 화면 없이 로그인되고, 계정이 없으면 자동 생성되며 mcp-* 역할이 동기화됩니다. 세션이 없으면 로그인 화면이 그대로 보입니다. 최상위 리다이렉트 방식이라 서드파티 쿠키 차단의 영향을 받지 않습니다.
사용자별 데이터 키는 개인 화면이나 관리 콘솔에서 즉시 회전합니다. 마스터 키는 ENCRYPTION_KEY="새키,이전키"로 재시작 → 콘솔의 "재래핑" → 이전 키 제거 순서로 무중단 회전합니다.