MCP Oauth2
1. 소개
mcp-oauth2는 OAuth2/OIDC(주로 Keycloak 사용)를 활용하여 MCP HTTP endpoints를 보호하는 Kong plugin/policy입니다. mcp-oauth2는 다음과 같은 기능을 제공합니다.
- Client discovery: /.well-known/oauth-protected-resource (RFC 9728)를 통해 MCP 클라이언트가 Authorization Server와 지원되는 범위를 확인할 수 있습니다.
- JWT access-token validation: iss(issuer), aud(audience), 그리고 JWKS를 사용한 서명을 검증합니다.
- (선택 사항) authorization by scope/role: mcp_scopes와 같은 클레임을 활용하여 범위 MCP JSON-RPC 메서드에 매핑해 접근 권한을 제어할 수 있습니다.
2. APIM 콘솔 설정
단계 1: 백엔드를 MCP 서버로 설정하여 신규 API를 생성합니다.
MCP 서버: http://wikipedia-mcp.기본값.svc.cluster.local:8080/mcp
VS Code에서 이 API를 통해 MCP 서버에 접근해야 하므로, VS Code는 추가 경로 세그먼트가 있는 URL을 지원하지 않기 때문에 Base Path를 “/” (경로 없음)으로 설정합니다.

단계 2: mcp-oauth2 정책을 해 API에 적용합니다.

단계 3: mcp-oauth2 정책 버튼을 클릭하여 아래의 구성 세부정보를 표시합니다.
Section 1: PROTECTED RESOURCE METADATA (RFC 9728)
| 필드 | 유형 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
| Protected Resource Metadata Path | string | Yes | /.well-known/oauth-protected-resource | • 플러그인이 RFC 9728 보호된 리소스 메타데이터 문서를 제공하는 URL 경로입니다. • MCP 클라이언트는 이를 사용하여 인증 서버와 지원되는 범위를 발견합니다. • 거의 변경할 필요가 없습니다. |
- 신뢰할 수 있는 인증 서버의 배열입니다. 이 MCP 엔드포인트에 대한 토큰을 발급하는 각 Keycloak 영역(또는 다른 OAuth2 공급자)마다 하나의 항목을 추가합니다.
- 더 많은 항목을 추가하려면 +를 클릭합니다.
| 필드 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
| Url | string | Yes | • 인증 서버의 공개 URL (클라이언트가 인증 및 토큰 발급을 위해 접근하는 주소)입니다. • jwks_uri가 상대 경로일 경우, JWKS URL을 구성하기 위한 기본 URL로도 사용됩니다.. 예시: https://keycloak-demo.apimags.skcloud.io/realms/master |
| Issuer | string | Yes | • JWT의 iss (발급자) 클레임과 일치합니다. • 토큰의 발급자가 일치하지 않으면 거부됩니다. • 정확히 string이 일치해 하며, 프로토콜, 호스트, 포트 및 경로(끝에 슬래시 없음)를 포함해야 합니다. • 확인 위치: {realm-url}/.well-known/openid-configuration → issuer 필드. |
| Audience | string | Yes | • JWT의 aud (audience) 클레임과 일치합니다. • 다른 서비스용으로 설정된 토큰이 수락되지 않도록 방지합니다. • Keycloak Audience Mapper에 설정된 값과 정확히 일치해야 합니다. |
| JWKS URI | string | Yes | • 플러그인이 JWT 서명을 검증하기 위해 인증 서버의 공개 서명 키(JWKS)를 가져오는 엔드포인트입니다. • Relative path (Url에 추가됨): /.well-known/jwks.json 일 수도 있고 Absolute URL (그대로 사용됨): https://keycloak-demo.ags.cloudzcp.net/realms/master/protocol/openid-connect/certs일 수도 있습니다. Kong이 클라이언트와 동일한 호스트명을 통해 인증 서버에 접근할 수 없는 경우(예: Docker/Kubernetes 네트워킹 환경), Absolute URL 사용을 권장합니다. (예: Docker/k8s 네트워킹). 기본값: /.well-known/jwks.json |

| 필드 | 유형 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
| Scopes Supported | string | Yes | 비어 있음 | 보호된 리소스 메타데이터 문서에 나열되어 클라이언트가 어떤 범위를 요청해야 하는지 안내합니다. 이는 정보 제공용일 뿐이며, 클라이언트 디스커버리를 돕지만 실제로 접근을 강제하지는 않습니다. 각 범위를 입력하고 Enter를 눌러 추가할 수 있습니다. 예시: mcp:tools |

| 필드 | 유형 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
| Authorization Header Name | string | Yes | Authorization | • Authorization Header Name = 서버/플러그인이 토큰 검증을 위해 액세스 토큰을 찾기 위해 읽을 HTTP 헤더 이름입니다. • 일반적으로 Authorization으로 유지합니다. • 클라이언트는 다음과 같이 토큰을 전송합니다: Authorization: Bearer <access_token>• API가 다른 헤더에서 토큰을 기대하는 경우에만 변경합니다. • (예: X-Authorization). |
Section 4: UPSTREAM TOKEN FORWARDING

| 필드 | 유형 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
| Forward Authorization Header | boolean | No | false | • false - MCP 서버로 전달하기 전에 Authorization 헤더를 제거합니다 (더 안전한 기본값). • true - Bearer <token> 헤더를 업스트림 MCP 서버로 전달합니다. • MCP 서버가 토큰을 읽어야 하는 경우 활성화합니다 (예: 사용자 신원 또는 클레임을 추출하기 위해). |

| Field | Type | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
| Enable ACL | boolean | No | false | • false - 유효한 토큰은 모든 MCP 메서드에 대한 접근을 허용합니다 (토큰 검증은 여전히 발생합니다). • true - 토큰을 검증한 후, 플러그인은 특정 JSON-RPC 메서드가 허용되는지 결정하기 위해 토큰의 범위/역할을 Scope Method Mapping와 비교합니다. |
| ACL Claim | string | No | scope | • 사용자의 권한을 포함하는 JWT 클레임의 이름입니다. 플러그인은 이 클레임을 읽고 ACL 검사를 위해 그 값을 사용합니다. • 일반적인 값: → mcp_scopes - Keycloak Protocol Mapper의 커스 클레임 ⚠️ Keycloak Protocol Mapper에서 토큰 클레임 이름을 정확히 일치해야 합니다. |
각 범위/역할을 해당 범위가 호출할 수 있는 MCP JSON-RPC 메서드 목록에 매핑합니다. Enable ACL가 true일 때만 유효합니다.

| 필드 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
| Scope | string | Yes (per entry) | 범위/역할 이름입니다. ACL Claim에서 JWT 클레임에 지정된 값과 일치해야 합니다. 예시: mcp:tools |
| Methods | array of strings | Yes (per entry) | 이 범위에서 호출할 수 있는 MCP JSON-RPC 메서드 이름입니다. 각 메서드 이름을 입력하고 Enter를 눌러 추가합니다. 예시: tools/list, tools/call |
⚠️ ACL이 활성화되어 있지만 Scope Method Mapping이 비어 있는 경우: 모든 요청이 거부됩니다. 최소한 하나의 매핑을 구성해야 합니다.
💡 권한은 누적된 경우: 사용자는 메서드를 허용하는 하나의 범위만 필요합니다. 토큰의 어떤 범위라도 메서드를 허용하면 접근이 허용됩니다.
Section 7: TIMEOUTS & CACHING| 필드 | 유형 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
| Token Cache TTL (s) | number | No | 300 | 검증된 토큰이 Kong의 공유 메모리에 캐시되는 시간(초)입니다. 이 기간 동안 동일한 토큰으로 반복 요청을 하면 JWT 디코딩 및 서명 검증을 건너뜁니다. 캐시된 경우에도 플러그인은 매 요청마다 JWT exp 클레임을 재확인하고 만료된 토큰을 무효화합니다. |
| HTTP Timeout (ms) | number | No | 10000 | 인증 서버에서 JWKS(공개 서명 키)를 가져오기 위한 HTTP 요청의 타임아웃(밀리초)입니다. 인증 서버가 이 시간 내에 응답하지 않으면 토큰 검증이 실패합니다. • 인증 서버가 느린 네트워크에 있거나 콜드 스타트 중인 경우 증가시킵니다. • 인증 서버에 접근할 수 없을 때 더 빠른 실패를 위해 감소시킵니다. |
3. Keycloak 설정
3.1. Keycloak OAuth2 Foundation
이 단계는 MCP 클라이언트가 인증 서버를 발견하고 올바른 audience으로 토큰을 얻을 수 있도록 Keycloak을 구성합니다.
3.1.1 클라이언트 범위 생성
작동 방식: 클라이언트가 요청할 수 있는 이름이 지정된 스코프(named scope)를 생성합니다. 클라이언트가 해당 스코프를 요청하면, Keycloak은 이를 토큰에 포함시키며, 해당 스코프에 연결된 mapper들도 함께 실행됩니다.
단계 1: Keycloak Admin → Client scopes → Create client scope로 이동

| 필드 | 값 | 설명 |
|---|---|---|
| Name | mcp:tools | 귀하의 MCP 클라이언트가 요청할 범위 이름 |
| Protocol | OpenID Connect | 표준 OAuth2/OIDC 프로토콜 |
| Display on consent screen | ON | 클라이언트가 로그인 중 요청하는 내용 표시 |
| Consent screen text | Access MCP tools | 사용자에게 읽기 쉬운 설명 |
| Include in token scope | ON | 범위 값이 JWT 범위 클레임에 나타나도록 보장 |
3.1.2 Audience Mapper 추가
동작 방식: 액세스 토큰에 aud(audience) 클레임을 추가합니다. 플러그인은 토큰의 audience이 구성된 값과 일치하는지 검증합니다 - 이는 다른 서비스에 대해 발급된 토큰이 귀하의 MCP 엔드포인트에서 수락되는 것을 방지합니다.
단계 1: 방금 생성한 mcp:tools scope로 이동 → Mappers 탭 → Configure a new mapper → Audience 선택

| 필드 | 값 | 설명 |
|---|---|---|
| Name | audience-config | 이 Mapper에 대한 설명 이름 |
| Included Custom Audience | audience-name | Kong 플러그인 구성의 audience 필드와 일치해야 합니다 |
| Add to access token | ON | 플러그인은 ID 토큰이 아닌 액세스 토큰을 읽습니다. |
| Add to ID token | OFF | ID 토큰은 클라이언트 앱을 위한 것이며, 리소스 서버를 위한 것이 아닙니다. |

3.1.3. 새 클라이언트 만들기
동작 방식: MCP 클라이언트가 Keycloak에 연결할 수 있도록 클라이언트를 만듭니다.
단계 1: Clients → Create client로 이

| 필 | 값 | 설명 |
|---|---|---|
| Client ID | Mcp-client | 클라이언트 ID |


3.2. Keycloak: 그룹 기반 ACL 설정
이 섹션에서는 사용자별로 서로 다른 MCP 권한을 부여하기 위한 세분화된 접근 제어(fine-grained access control)를 설정합니다. 전체 아키텍처는 다음과 같습니다.
Groups → Realm Roles → Protocol Mapper → "mcp_scopes" JWT claim → ACL
3.2.1. Realm Roles 만들기
동작 방식: 명명된 권한 계층입니다. 각 역할은 사용자가 호출할 수 있는 MCP 메서드 집합을 나타냅니다. 역할 이름은 JWT mcp_scopes 클레임에 나타납니다.
단계 1: Realm roles → Create role (repeat for each)로 이동
| Role Name | 용도 | 예시 MCP Methods |
|---|---|---|
| mcp:tools | 도구 접근을 위함 | tools/list |
| mcp:resources | 리소스 접근을 위함 | resources/read |

3.2.2. 그룹 만들기
동작 방식: 사용자에 대한 조직적 컨테이너입니다. 사용자별로 역할을 할당하는 대신, 그룹에 역할을 할당하고 그 후 사용자를 그룹에 추가합니다.
단계 1: Groups → Create group로 이동

| Group Name | Description |
|---|---|
| mcp-member | 기본 회원 접근 |
| mcp-admin | 모든 MCP 도구 및 리소스에 대한 전체 접근 |

3.2.3. 그룹에 역할 할당하기
단계 1: Groups으로 이동 → 하나의 group 클릭 → Role mapping 탭 클 → Assign role 선택| Group | Roles to Assign |
|---|---|
| Mcp-admin | mcp:tools, mcp:resources |
| Mcp-member | mcp:tools |

Assign 클

3.2.4. Protocol Mapper 만들기 (mcp_scopes 클레임)
동작 방식: Keycloak에 사용자의 영역 역할(필터링된 mcp: 접두사 포함)을 액세스 토큰의 mcp_scopes라는 사용자 정의 클레임으로 포함하도록 지시합니다. 이는 Kong 플러그인이 ACL 결정을 내리기 위해 읽는 클레임입니다. 단계 4: Client scopes → mcp:tools → Mappers → Add mapper 클 → By configuration 선택 → User Realm Role 선택



| 필드 | 값 | 설명 |
|---|---|---|
| Name | mcp-scopes-mapper | 설명 이름 |
| Mapper Type | User Realm Role | 사용자의 영역 역할을 토큰 클레임에 매핑 |
| Token Claim Name | mcp_scopes | Kong 플러그인 구성의 acl_claim과 일치해야 함 |
| Multi값d | ON | 사용자는 여러 역할을 가질 수 있음 |
| Add to access token | ON | 플러그인이 액세스 토큰을 읽음 |
| Add to ID token | OFF | 리소스 서버 검증에 필요하지 않음 |
| Add to userinfo | OFF | 필요하지 않음 |
Critical: Token Claim Name (mcp_scopes)는 Kong 플러그인 구성의 acl_claim 필드와 일치해야 합니다. 불일치가 발생하면 플러그인이 토큰에서 권한을 찾을 수 없습니다.
3.2.5. 사용자 그룹에 추가
단계 1: Users로 이동 → 하나의 user 클릭 → Groups 탭으로 이동 → Join group 클릭 → 적절한 그룹을 선택
| User | Group | Resulting JWT mcp_scopes |
|---|---|---|
| canhng1 | Mcp-member | Mcp:tools, Mcp:resources |
| admin | mcp-admin | Mcp:resources |

4. Visual Studio Code를 사용한 테스트
4.1. Kong 프록시를 로컬로 포워딩

4.2. 새로운 MCP 서버 만들기
VS Code를 실행한 후, Ctrl + Shift + P를 누르고 MCP: Add server…를 선택합니다.그 다음 HTTP를 선택하고 http://localhost:8100을 입력합니다.Visual Studio Code 내에서 사용할 고유한 서버 이름을 지정합니다.이제 mcp.json 파일에서 아래와 같은 항목을 확인할 수 있습니다:


4.3. 서버 시작 및 Keyloak 인증으로 모의 MCP 서버에 연결하기





로그인 성공하고 22개의 도구로 Mock MCP 서버에 연결되었습니다.