본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 15. 23:43

IdP와 MCP 세계 사이의 간극 메우기

요약

본 글은 기업용 IdP와 MCP 서버 간의 인증 과정에서 발생하는 기술적 불일치 문제를 다룹니다. 기존 IdP는 OAuth 동작 방식, Scope 관리, Discovery 메타데이터 등 여러 면에서 MCP 클라이언트가 기대하는 표준과 차이가 있습니다. 이를 해결하기 위해 'mcp-auth-adapter'라는 경량 Node.js 프록시를 제안합니다. 이 어댑터는 실제 인증은 IdP에 맡기면서도, OAuth 과정을 MCP와 호환되도록 필터링된 Discovery, 안전한 기본값 주입, 그리고 Open DCR 엔드포인트 등을 제공하여 간극을 메워줍니다.

핵심 포인트

  • mcp-auth-adapter는 기존 IdP와 MCP 클라이언트 사이에 위치하는 상태 비저장(stateless) Node.js 프록시입니다.
  • 이 어댑터는 필터링된 Discovery를 제공하여 MCP가 필요로 하는 최소한의 메타데이터만 노출합니다.
  • Scope 필터링 기능을 통해 불필요하거나 위험할 수 있는 내부 Scope나 `offline_access` 같은 스코프 사용을 제어할 수 있습니다.
  • Open DCR 엔드포인트를 구현하여 IdP 측의 복잡한 Dynamic Client Registration 없이도 MCP 클라이언트가 스스로 등록(self-register)할 수 있게 합니다.
  • CIMD 지원 기능을 통해 IETF 초안 단계의 새로운 표준에 대한 호환성을 선제적으로 확보합니다.

기업용 IdP(Keycloak, Auth0, Okta, Azure AD 등 무엇이든)를 갖추고 있고, 이제 MCP 서버가 인증을 위해 이를 사용하기를 원한다고 가정해 봅시다. Claude Code나 Cursor를 그곳으로 지정하면... 문제가 발생합니다. 동의 화면에서의 Scope 폭발, 누락된 PKCE 기본값, MCP가 기대하는 방식으로 제공되지 않는 Dynamic Client Registration을 요구하는 클라이언트들. 익숙한 상황인가요?

문제점
MCP Authorization 명세는 대부분의 엔터프라이즈 IdP가 기본적으로 제공하지 않는 특정 OAuth 동작을 기대합니다:

  • MCP 클라이언트는 개방된 Dynamic Client Registration을 기대합니다. 대부분의 IdP는 이를 노출하지 않거나 관리자 자격 증명 뒤에 잠가 둡니다.
  • MCP 클라이언트는 발표된 모든 Scope를 요청하는 경향이 있습니다. 이는 명세에서 요구하는 사항은 아닙니다. 단지 대부분의 클라이언트(Claude Code, Cursor 등)가 실제로 동작하는 방식일 뿐입니다. 이들은 discovery에서 scopes_supported를 읽고 그 중 모든 것을 요청합니다. 당신의 Keycloak이 15개의 내부 Scope를 발표하나요? 축하합니다, 이제 사용자는 지옥 같은 동의 화면을 보게 될 것입니다. 또는 클라이언트가 발표된 특정 Scope에 대해 사전 승인되지 않았다면 요청이 즉시 거부될 수도 있습니다.
  • 많은 클라이언트가 조건 없이 offline_access를 추가합니다. 이 역시 명세 요구 사항은 아니며, Refresh Token을 확보하기 위한 일반적인 클라이언트 동작입니다. 이는 IdP가 수명이 긴 Refresh Token을 제한하거나 해당 Scope에 대해 클라이언트 사전 승인을 요구할 때 문제가 됩니다.
  • Discovery 메타데이터 필터링이 필요합니다. IdP는 MCP에는 무관한 소음이며 클라이언트를 혼란스럽게 할 수 있는 수십 개의 OIDC 필드(CIBA, device flow, logout endpoints...)를 노출합니다.

IdP를 직접 커스텀할 수도 있지만, 이는 유지보수의 늪에 빠지는 일입니다. 특히 MCP가 아닌 다른 앱이나 레거시 앱을 위해 동일한 IdP를 사용해야 하는 경우 더욱 그렇습니다.

mcp-auth-adapter 등장

mcp-auth-adapter는 MCP 클라이언트와 기존 IdP 사이에 위치하는 가볍고 상태가 없는(stateless) Node.js 프록시입니다. 이 도구는 토큰을 발행하거나 인증을 처리하지 않습니다. 모든 실제 작업은 IdP에서 수행됩니다. 단지 OAuth 과정을 MCP와 호환되도록 만들어 줄 뿐입니다.

기능

  • 필터링된 Discovery -- MCP 클라이언트가 실제로 필요로 하는 필드만 포함하여 /.well-known/ IdP 메타데이터를 제공합니다.

안전한 기본값 주입 (PKCE S256, authorization_code grant) -- IdP의 메타데이터가 불완전할 경우 안전한 기본값을 주입하며, 필요한 경우 자체적인 기능을 수행합니다.

Open DCR 엔드포인트 -- POST /register를 통해 고정된 사전 구성 client_id를 발급하므로, MCP 클라이언트가 스스로 등록(self-register)할 수 있습니다. IdP 측의 DCR(Dynamic Client Registration)은 필요하지 않습니다.

Scope 필터링 -- IdP에 전달되는 스코프(Scope)를 제어합니다. offline_access를 제거하거나, 내부 스코프를 삭제하거나, 허용 목록(allowlist)을 사용할 수 있습니다:
# 오직 이 스코프들만이 상위 IdP에 도달합니다.
MCP_PROXY_AUTH_SCOPES_PRESERVED = openid,api.read,api.write

CIMD 지원 (실험적 기능) -- MCP 스펙은 클라이언트 식별을 위해 Client ID Metadata Documents (CIMD)를 기본값으로 사용하지만, 이는 아직 초기 단계의 IETF 초안(RFC 아님)이며 현재 어떤 주요 IdP도 이를 네이티브로 지원하지 않습니다. 이 어댑터는 그 간극을 메워줍니다. MCP 클라이언트로부터 CIMD 스타일의 client_id URL을 받아 메타데이터 문서를 검증하고, 이를 IdP가 이해할 수 있는 실제 상위 client_id로 매핑합니다. 따라서 IdP 벤더가 이를 구현할 때까지 기다리지 않고도 CIMD 호환성을 확보할 수 있습니다.

내장된 관측성 (Observability) -- /metrics에서의 Prometheus 메트릭, 구조화된 로깅(structured logging), k8s를 위한 상태 확인(health probes)을 제공합니다.

30초 만에 배포하기
컨테이너 이미지를 가져와 바로 실행하세요:
docker run -d --name mcp-auth-adapter \ -p 3000:3000 \ -e MCP_BASE_URL = https://mcp-auth.example.com \ -e MCP_UPSTREAM_SSO_URL = https://sso.example.com/auth/realms/external \ -e MCP_PROXY_DCR_CLIENT_ID = mcp-client \ ghcr.io/velias/mcp-auth-adapter:latest

끝입니다. 기본 설정을 위한 세 가지 환경 변수(env vars)는 다음과 같습니다:

  • MCP_BASE_URL: 이 어댑터가 실행되는 공개 URL
  • MCP_UPSTREAM_SSO_URL: IdP의 발행자(issuer) URL
  • MCP_PROXY_DCR_CLIENT_ID: IdP에 미리 등록된 공개 클라이언트(public client)

그 다음, MCP 서버의 authorization_serversMCP_BASE_URL로 지정하면 클라이언트가 .well-known을 통해 모든 것을 발견(discover)할 수 있습니다.

전형적인 프로덕션 설정 (Typical production config)
실제 배포를 위해서는 스코프(scope) 제어도 필요할 것입니다:

MCP_BASE_URL = https://mcp-auth.example.com
MCP_UPSTREAM_SSO_URL = https://sso.example.com/auth/realms/external
MCP_PROXY_DCR_CLIENT_ID = mcp-client
MCP_WELL_KNOWN_SCOPES_SUPPORTED = openid,api.read,api.write
MCP_PROXY_AUTH_SCOPES_REMOVED = offline_access

이는 양쪽 모두를 제어합니다: 클라이언트가 발견(discovery) 과정에서 보는 내용과 실제로 귀하의 IdP에 도달하는 내용 모두를 제어합니다.

제공하지 않는 기능 (What it doesn't do)
이 어댑터는 의도적으로 최소한의 기능만 제공합니다:

  • 토큰 발행 없음 -- 토큰은 항상 귀하의 IdP에서 발급됩니다.
  • 사용자 데이터베이스 없음 -- 상태가 저장되지 않는(stateless) 방식이며, 백업할 데이터도 없습니다.
  • 속도 제한(rate limiting) 없음 -- 기존의 리버스 프록시(reverse proxy) 또는 WAF 뒤에 배치하십시오.
  • CORS 없음 -- 브라우저의 fetch 호출이 아닌, 리다이렉트 기반 흐름(redirect-based flows)을 위해 설계되었습니다.

누구를 위한 것인가요? (Who is this for?)
만약 MCP 서버를 운영 중이거나 운영할 계획이 있고, 기존의 OAuth/OIDC 제공자가 있다면, 이 도구는 MCP 클라이언트의 특이한 요구사항을 맞추기 위해 IdP 설정을 억지로 수정해야 하는 수고를 덜어줍니다.

Keycloak, Auth0, Okta, Azure AD/Entra, Google Identity 등 표준 OIDC 발견(discovery)을 지원하는 모든 서비스와 함께 작동합니다.
Claude Code, Claude Desktop, Cursor IDE, Cursor Agent, Gemini CLI, VS Code 등에서 테스트되었습니다.

마무리하며 (Wrapping up)
MCP는 빠르게 발전하고 있으며, 인증(auth)은 당연히 잘 작동해야 하지만 실제 환경의 IdP를 실제 환경의 MCP 클라이언트에 연결하려고 할 때 종종 제대로 작동하지 않는 문제 중 하나입니다.
IdP 설정을 붙잡고 씨름하거나 벤더들이 CIMD와 같은 신흥 표준을 따라잡기를 기다리는 대신, 가벼운 어댑터를 중간에 배치하고 사용자들이 진정으로 원하는 실제 MCP 도구를 만드는 데 집중하십시오.

문제가 발생하거나 아이디어가 있다면 이슈(issue)를 생성해 주세요. 이 프로젝트는 초기 단계이며 피드백이 로드맵을 형성합니다.
Apache 2.0 라이선스. PR(Pull Request)을 환영합니다.
GitHub: github.com/velias/mcp-auth-adapter

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0