관리자 가이드
bbmcp 운영에 필요한 전부를 다룹니다. 환경변수는 네 개뿐이고, 나머지 설정은 모두 이 문서가 설명하는 관리 콘솔에서 입력합니다.
1. 설치
1.1 환경변수 4개
| 변수 | 필수 | 설명 |
|---|---|---|
DATABASE_URL | 예 | PostgreSQL DSN. POSTGRES_DSN 도 인식합니다. |
BOOTSTRAP_ADMIN | 예 | 최초 관리자 아이디. 기동할 때마다 이 계정의 관리자 권한과 비밀번호를 보정합니다. |
BOOTSTRAP_ADMIN_PASSWORD | 예 | 최초 관리자 비밀번호. |
ENCRYPTION_KEY | 예 | 저장 비밀값 암호화 키. 32바이트(hex 64자, base64 44자, 평문 32자). |
BBMCP_ADDR | 아니오 | 수신 주소. 기본 :8080. |
ENCRYPTION_KEY 를 분실하면 저장된 Client Secret·서비스 PAT·사용자 PAT 을 복호화할 수
없습니다. 데이터베이스 백업과 반드시 함께 보관하십시오. 키를 바꾸려면 모든 비밀값을 다시
입력해야 합니다.
1.2 compose 기동
# 1) 릴리스 이미지 적재 (오프라인망에서는 반입한 파일 사용)
docker load -i bbmcp-v0.2.1.tar.gz
# 2) 환경변수 준비
cp deploy/.env.example deploy/.env
$EDITOR deploy/.env # ENCRYPTION_KEY=$(openssl rand -base64 32)
# 3) 기동
docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d
# 4) 확인
curl -fsS http://localhost:8080/healthz
curl -fsS http://localhost:8080/readyz # 구성 전에는 503 이 정상입니다
스키마 마이그레이션은 기동 시 자동으로 적용됩니다. PostgreSQL 이 늦게 올라와도 bbmcp 가 최대 1분간 재시도합니다.
1.3 첫 로그인
브라우저에서 서비스 주소를 열고 BOOTSTRAP_ADMIN 계정으로 로그인합니다. 이후 설정 순서는
Keycloak → Bitbucket → 권한 해석기 → 정책 → 도구 를 권장합니다.
2. 관리 대시보드
구성 요소 상태(데이터베이스, Keycloak, Bitbucket REST, 서비스 계정 PAT, 권한 해석기, AI)와 주요 수치, 최근 활동을 보여 줍니다. 상태 배지에 마우스를 올리면 실패 사유가 나옵니다.
3. Keycloak 연동
3.1 클라이언트 생성
Keycloak 관리 콘솔에서 아래와 같이 클라이언트를 만듭니다.
| 항목 | 값 |
|---|---|
| Client type | OpenID Connect |
| Client ID | bbmcp |
| Client authentication | On (confidential) |
| Standard flow | Enabled |
| Valid redirect URIs | https://<bbmcp 주소>/auth/oidc/callback |
| Web origins | https://<bbmcp 주소> |
| Valid post logout redirect URIs | https://<bbmcp 주소>/* |
bbmcp 관리 콘솔 → 인증 (Keycloak) 에서 Issuer URL(realm 포함), Client ID, Client Secret 을 입력하고 저장한 뒤 연결 점검 을 누르십시오. 엔드포인트는 디스커버리 문서에서 자동으로 읽습니다.
3.2 역할
| Realm 역할 | 권한 |
|---|---|
bitbucket-mcp-user | 조회 도구 |
bitbucket-mcp-writer | 조회 + PR 작성·댓글 |
bitbucket-mcp-executor | + 머지·승인·거절·브랜치 생성 |
bitbucket-mcp-admin | + bbmcp 관리 콘솔 |
서비스 관리자 역할 항목에 지정한 역할(기본 bitbucket-mcp-admin)을 가진
사용자는 로그인 시 자동으로 관리자 권한을 받습니다. 로그인 필수 역할 을 지정하면 그
역할이 없는 사용자는 로그인 자체가 차단됩니다.
3.3 사일런트 SSO
켜 두면 로그인 화면이 숨은 프레임으로 prompt=none 인가 요청을 보내, 이미 Keycloak 세션이
있는 사용자는 클릭 없이 들어옵니다. 세션이 없으면 Keycloak 이 login_required 로 답하고
로그인 폼이 그대로 남습니다(오류로 표시되지 않습니다). 로그아웃한 사용자가 즉시 다시 자동
로그인되지 않도록, 로그아웃 후에는 같은 탭에서 사일런트 시도를 하지 않습니다.
3.4 MCP OAuth
MCP 클라이언트는 사람이 아니라 프로그램이고, 비밀값을 안전하게 보관할 수 없는 공개 클라이언트입니다. 그래서 웹 콘솔과 같은 Keycloak 클라이언트를 쓰지 않습니다. Keycloak 에 공개 클라이언트를 하나 더 만드십시오.
| 항목 | 웹 콘솔용 | MCP 클라이언트용 |
|---|---|---|
| Client ID 예시 | bbmcp | bbmcp-mcp |
| Client authentication | On (기밀) | Off (공개) |
| PKCE | 선택 | S256 필수 |
| Valid redirect URIs | https://<bbmcp>/auth/oidc/callback |
http://127.0.0.1:*, http://localhost:* |
| Web origins | https://<bbmcp> | + 또는 비움 |
MCP 클라이언트는 루프백 포트로 콜백을 받기 때문에 리다이렉트 URI 에 와일드카드 포트가 필요합니다. 그다음 bbmcp 관리 콘솔 → 인증 → MCP OAuth 에서 클라이언트 ID 를 입력하고 MCP OAuth 점검 을 누르십시오.
클라이언트가 거치는 경로
| 단계 | 요청 | bbmcp 응답 |
|---|---|---|
| 1 | POST /mcp (자격증명 없음) |
401 + WWW-Authenticate: Bearer resource_metadata="…" |
| 2 | GET /.well-known/oauth-protected-resource |
인가 서버(Keycloak issuer)와 스코프 |
| 3 | GET <issuer>/.well-known/openid-configuration |
Keycloak 의 authorize · token · JWKS |
| 4 | POST /oauth/register (선택) |
사전 등록된 공개 클라이언트 ID |
| 5 | PKCE 인가 코드 교환 | 클라이언트 ↔ Keycloak 직접 |
| 6 | POST /mcp + Bearer | 서명·발급자·대상·스코프 검증 후 처리 |
동적 등록(DCR)이 막혀 있다면. Keycloak 이 동적 등록을 허용하지 않는 조직이 많습니다.
게이트웨이 동적 등록 대행을 켜 두면 bbmcp 가 /oauth/register 로 위에서
만든 공개 클라이언트 ID 를 대신 돌려줍니다. bbmcp 가 Keycloak 클라이언트를 새로 만들지는 않으므로,
클라이언트가 요청하는 리다이렉트 URI 가 Keycloak 쪽에 미리 허용되어 있어야 합니다.
대상(audience) 검증. bbmcp 는 서명과 만료만 보지 않고 토큰의 aud 또는
azp 가 허용 클라이언트인지도 확인합니다. 같은 realm 의 다른 애플리케이션(예:
모니터링 도구)이 받은 토큰으로는 들어올 수 없습니다. 허용 목록을 비우면 MCP 클라이언트 ID 와
웹 콘솔 Client ID 가 자동으로 사용됩니다.
더 좁히려면 필수 스코프(예: mcp)를 지정하고, Keycloak 에 같은 이름의
client scope 를 만들어 MCP 클라이언트에만 기본 스코프로 추가하십시오.
사용자 쪽 설정 — URL 하나면 됩니다.
{
"mcpServers": {
"bbmcp": { "type": "http", "url": "https://bbmcp.company.local/mcp" }
}
}
3.5 Invalid redirect URI 해결
Keycloak 은 리다이렉트 URI 를 문자열 그대로 비교합니다. 한 글자라도 다르면
Invalid parameter: redirect_uri 로 거부합니다. bbmcp 는 보내는 값을 항상 정규화하고,
연결 점검 결과에 그대로 등록할 문자열을 복사 버튼과 함께
보여 줍니다. 그 값을 Keycloak 에 붙여 넣으십시오.
| 증상 | 원인 | 조치 |
|---|---|---|
로그인 시 Invalid parameter: redirect_uri |
등록값과 bbmcp 가 보내는 값이 다름. 흔한 차이: 후행 슬래시, 대소문자, :443·:80 명시, http/https |
연결 점검의 Valid redirect URIs 값을 복사해 Keycloak 에 등록 |
| 리버스 프록시 뒤에서만 실패 | 프록시가 알려 주는 호스트와 실제 공개 주소가 달라 유도값이 어긋남 | Redirect URI 에 공개 주소를 명시하고, 보안 설정의 프록시 헤더 신뢰를 켜십시오 |
로그아웃 시 Invalid parameter |
등록되지 않은 post_logout_redirect_uri 전송 |
bbmcp 는 설정했을 때만 보냅니다. 값을 넣었다면 Keycloak 의 Valid post logout redirect URIs 에도 등록하십시오 |
| MCP 클라이언트 로그인 창에서 실패 | 공개 클라이언트에 루프백 와일드카드 포트가 없음 | http://127.0.0.1:* 와 http://localhost:* 를 등록하십시오 |
저장 시 INVALID_URL |
스킴 누락, 질의 문자열·공백 포함 등 | 메시지가 가리키는 항목을 고치십시오. 잘못된 값은 저장되지 않습니다 |
bbmcp 는 저장할 때 URL 의 공백·후행 슬래시·대소문자·기본 포트를 정리합니다. 따라서
https://BBMCP.local:443/ 를 입력해도 실제로는 https://bbmcp.local 로
저장되고 전송됩니다. 질의 문자열이나 프래그먼트처럼 의도를 바꿀 수 있는 입력은 조용히
지우지 않고 저장을 거부합니다.
4. Bitbucket 연결
4.1 서비스 계정
- Bitbucket 에 전용 계정(예:
mcp-bitbucket-service)을 만듭니다. - 그 계정으로 로그인해 개인 액세스 토큰(PAT)을 발급합니다.
- bbmcp → Bitbucket 연결 에 기본 URL, 서비스 계정 사용자명, PAT 을 입력합니다.
- 연결 점검 으로 응답과 샘플 프로젝트를 확인합니다.
서비스 계정을 SYS_ADMIN 으로 두지 마십시오. bbmcp 는 서비스 계정 권한을 사용자 권한으로
간주하지 않지만, 토큰이 유출됐을 때의 피해 범위는 계정 권한에 비례합니다. 필요한 프로젝트에만
권한을 부여하는 편이 안전합니다.
단, REST 폴백 권한 해석 모드는 전역·그룹 권한 조회를 위해 관리자 권한을 요구할 수 있습니다. 이 요구를 없애려면 권한 플러그인을 설치하십시오.
4.2 인증 모드
| 모드 | REST 자격증명 | Bitbucket 작성자 | 용도 |
|---|---|---|---|
| 서비스 계정 (기본) | 중앙 서비스 PAT | 서비스 계정 (본문에 요청자 표기) | 표준 |
| 사용자 PAT | 사용자 개인 PAT | 요청자 본인 | 작성자를 본인으로 남겨야 할 때 |
요청자 표기 추가 를 켜면 서비스 계정으로 작성한 PR·댓글 본문 머리에
[MCP 요청자: hkjang] 가 붙습니다. 감사 로그에는 두 주체가 항상 따로 기록됩니다.
5. 권한 해석기
이 설정이 bbmcp 의 핵심입니다. 모든 도구 호출은 여기서 나온 판정을 기준으로 허용·거부됩니다.
| 모드 | 동작 | 장단점 |
|---|---|---|
| REST 폴백 (기본) | 전역·프로젝트·저장소·그룹 권한을 REST 로 조회해 조합 | 플러그인 불필요. 서비스 계정에 관리자 권한이 필요할 수 있음 |
| 권한 플러그인 (권장) | Bitbucket 자체 PermissionService 판정을 그대로 사용 |
상속·그룹·공개 저장소까지 정확히 일치 |
판정 실패 시 차단(fail-closed) 은 켜 두십시오. 권한을 확인할 수 없을 때 통과시키면 게이트웨이의 의미가 사라집니다.
5.1 권한 플러그인
- 저장소의
plugin/을 Atlassian SDK 가 있는 환경에서 빌드합니다:atlas-package - Bitbucket 관리 → 애플리케이션 관리 → 앱 업로드로 jar 를 설치합니다.
bitbucket.properties에 공유 비밀값을 넣고 Bitbucket 을 재시작합니다.bbmcp.permission.secret=<충분히 긴 임의 문자열>- bbmcp → 권한 해석기에서 모드를 권한 플러그인 으로 바꾸고 같은 비밀값을 입력합니다.
- 판정 시험 으로 확인합니다.
플러그인 API 는 조회 전용이며, 공유 비밀값과 HMAC 서명(±5분)을 검증합니다. 비밀값이 설정되지 않으면 모든 요청을 거부합니다. 네트워크 계층에서 bbmcp 서버 IP 만 허용하면 더 좋습니다.
6. 식별 매핑
Keycloak 주체(sub)와 Bitbucket 사용자 ID 를 연결한 영구 매핑입니다. 사용자가 처음 접속할
때 preferred_username 으로 정확히 일치하는 Bitbucket 계정을 찾아 자동
등록하고, 이후에는 ID 기준으로 판정합니다.
- 수동 매핑: Keycloak
hong↔ Bitbuckethong01처럼 이름이 다른 경우. - 재검증: 저장된 Bitbucket 사용자 ID 가 그대로인지 다시 확인합니다.
- 비활성: 매핑을 일시 중지합니다. 해당 사용자는 권한 도구를 쓸 수 없습니다.
- 매핑 실패 목록: 자동 매핑이 실패한 주체와 사유가 횟수와 함께 쌓입니다.
하나의 Bitbucket 계정은 하나의 Keycloak 주체에만 매핑됩니다. 중복 매핑 시도는 거부됩니다.
7. MCP 도구
도구별로 활성화, 승인 필요 여부, 최소 역할을 조정합니다.
| 등급 | 예시 | 기본값 |
|---|---|---|
| 조회 (1차) | projects, repositories, get_file, pr_review_context | 활성 · 승인 불필요 |
| 작성 (2차) | create_pull_request, comment_pull_request, create_branch | 활성 · 승인 필요 |
| 실행 (3차) | merge_pull_request, approve/decline_pull_request | 비활성 · 승인 필수 |
삭제·권한 변경·사용자 관리 도구는 의도적으로 제공하지 않습니다. MCP 에 노출할 이유가 없기 때문입니다.
8. 접근 정책
Bitbucket 권한 위에 MCP 사용 범위를 더 좁힙니다. 권한을 넓히는 용도로는 쓸 수 없습니다.
판정 규칙
- 같은 종류(프로젝트/저장소/브랜치)에 차단 규칙이 하나라도 일치하면 즉시 차단합니다.
- 허용 규칙이 하나 이상 있으면, 허용 목록에 포함된 대상만 통과합니다.
- 규칙이 전혀 없으면 Bitbucket 권한만으로 판정합니다.
- 허용 규칙의 위험도 상한은 해당 리소스에서 쓸 수 있는 도구 등급을 제한합니다.
권장 출발점
차단 프로젝트 HR (우선순위 1)
차단 브랜치 production/*
허용 프로젝트 AI
허용 프로젝트 ALM 위험도 상한: READ
허용 프로젝트 DEVOPS
9. 승인 운영
쓰기 등급은 요청자 본인이 승인할 수 있고, 실행 등급(머지·승인·거절)은 서비스 관리자가 승인해야 합니다. 승인은 호출 인자 해시와 PR version 에 묶입니다.
- 승인 유효 시간은 보안 설정의 승인 유효 시간 으로 조정합니다(기본 15분).
- 승인 후 인자가 바뀌면
APPROVAL_STALE, PR 에 새 커밋이 올라오면 역시 무효입니다. - 승인은 1회용입니다. 같은 승인으로 두 번 실행할 수 없습니다.
10. 키 권한 체계
개인 API 키가 가질 수 있는 스코프 묶음을 역할로 정의합니다. 기본 제공 역할 (reader·writer·executor·admin)의 스코프도 수정할 수 있습니다.
| 설정 | 의미 |
|---|---|
| 기본 역할 | 사용자가 역할을 고르지 않았을 때 적용 |
| 회전 주기 | 이 기간이 지나면 키 상태가 "회전 필요" 로 바뀝니다 |
| 키 유효 기간 | 자동 만료 기간. 0 이면 만료 없음 |
| 사용자당 최대 활성 키 | 초과 발급을 막습니다 |
| 회전 유예 시간 | 회전 후 기존 키가 함께 동작하는 시간(무중단 교체) |
| 사용자 직접 발급 허용 | 끄면 관리자만 키를 만들 수 있습니다 |
11. 사용자
Keycloak 로그인 사용자는 첫 로그인 시 자동 등록되고, 역할은 매 로그인마다 토큰 값으로 갱신됩니다. 로컬 계정은 SSO 장애 시 접속용으로만 쓰십시오. 마지막 서비스 관리자는 삭제·강등할 수 없습니다.
12. AI 설정
Anthropic Messages 형식과 OpenAI 호환 형식을 지원하며, 호출은 항상 스트리밍으로 중계합니다. 최대 출력 토큰 상한은 256k 입니다. 오프라인망에서는 사내 추론 게이트웨이를 OpenAI 호환 모드로 연결하십시오.
13. 보안
| 항목 | 권장 |
|---|---|
| IP 허용 목록 | MCP 클라이언트가 있는 대역만 허용(CIDR 가능) |
| 분당 요청 허용량 / 버스트 | 기본 120 / 40. 대량 수집 작업이 있으면 올리십시오 |
| 웹 세션 유지 시간 | 업무 시간에 맞춰 480분 전후 |
| 승인 유효 시간 | 15분. 길수록 승인 시점과 실행 시점의 차이가 커집니다 |
| 감사 로그 보존 | 사내 규정에 맞게. 기본 365일 |
| 프록시 헤더 신뢰 | 리버스 프록시 뒤에서만 켜십시오 |
14. 감사와 관측
모든 도구 호출과 관리 변경이 기록됩니다. 기록에는 Keycloak 요청자, 매핑된 Bitbucket 사용자, 대리 수행한 서비스 계정, 도구, 대상, 승인 ID, 결과, 지연이 포함됩니다. 토큰·Authorization 헤더·소스 전문·diff 전문·프롬프트 전문은 기록하지 않습니다.
관측 엔드포인트
| 엔드포인트 | 용도 |
|---|---|
/healthz | 생존 확인(항상 200) |
/readyz | 의존 구성 요소 점검. 하나라도 비정상이면 503 |
/metrics | Prometheus 텍스트 지표 |
bbmcp_tool_requests_total
bbmcp_tool_errors_total
bbmcp_permission_denied_total
bbmcp_identity_mapping_errors_total
bbmcp_approval_requests_total
bbmcp_approval_pending
bbmcp_api_keys_active
bbmcp_mcp_sessions_active
15. 백업과 업그레이드
# 백업 (두 가지를 함께 보관)
pg_dump "$DATABASE_URL" --format=custom --file=bbmcp-$(date +%Y%m%d).dump
# + ENCRYPTION_KEY
# 업그레이드
docker load -i bbmcp-v0.2.1.tar.gz
# deploy/.env 의 BBMCP_VERSION 을 올린 뒤
docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d
# 마이그레이션은 기동 시 자동 적용됩니다
Bitbucket 자체를 업그레이드하는 경우, bbmcp 는 BitbucketAdapter 뒤에서만 Bitbucket 을
호출하므로 어댑터와 권한 플러그인만 교체하면 됩니다. MCP 도구·Keycloak 연동·관리 콘솔은 그대로
유지됩니다.