메인 콘텐츠로 건너뛰기

튜토리얼: 나는 누구인가? (Who am I?)

이 튜토리얼에서는 MCP Auth를 설정하여 사용자를 인증 (Authentication)하고 인가 (Authorization) 서버에서 아이덴티티 정보를 가져오는 과정을 안내합니다.

이 튜토리얼을 완료하면 다음을 얻게 됩니다:

  • ✅ MCP Auth를 사용하여 사용자를 인증 (Authentication)하는 방법에 대한 기본적인 이해
  • ✅ 사용자 아이덴티티 정보를 조회할 수 있는 MCP 서버

개요 (Overview)

이 튜토리얼에는 다음과 같은 구성 요소가 포함됩니다:

  • MCP 서버: MCP 공식 SDK를 사용하여 요청을 처리하는 간단한 MCP 서버
  • MCP 인스펙터: MCP 서버를 위한 시각적 테스트 도구. OAuth / OIDC 클라이언트 역할도 하여 인가 (Authorization) 플로우를 시작하고 액세스 토큰 (Access token)을 가져옵니다.
  • 인가 (Authorization) 서버: 사용자 아이덴티티를 관리하고 액세스 토큰 (Access token)을 발급하는 OAuth 2.1 또는 OpenID Connect 제공자

아래는 이 구성 요소들 간의 상호작용을 나타낸 고수준 다이어그램입니다:

인가 (Authorization) 서버 이해하기

사용자 아이덴티티 정보 조회하기

이 튜토리얼을 완료하려면, 인가 (Authorization) 서버가 사용자 아이덴티티 정보를 조회할 수 있는 API를 제공해야 합니다:

Logto는 표준 userinfo 엔드포인트를 지원하는 OpenID Connect 제공자입니다.

userinfo 엔드포인트에 접근할 수 있는 액세스 토큰 (Access token)을 얻으려면 최소 두 개의 스코프 (Scope), 즉 openidprofile이 필요합니다. 스코프 설정은 아래에서 다루니 계속 읽어주세요.

동적 클라이언트 등록 (Dynamic Client Registration)

이 튜토리얼에서는 동적 클라이언트 등록이 필수는 아니지만, MCP 클라이언트 등록 과정을 자동화하고 싶다면 유용할 수 있습니다. 자세한 내용은 동적 클라이언트 등록이 필요한가요? 를 참고하세요.

MCP 서버 설정하기

MCP 공식 SDK를 사용하여 인가 (Authorization) 서버에서 사용자 아이덴티티 정보를 조회하는 whoami 도구가 포함된 MCP 서버를 만듭니다.

새 프로젝트 생성하기

mkdir mcp-server
cd mcp-server
uv init # 또는 `pipenv`나 `poetry`로 새 가상환경 생성

MCP SDK 및 의존성 설치하기

pip install "mcp[cli]" starlette uvicorn

또는 uv, poetry 등 원하는 패키지 매니저를 사용하세요.

MCP 서버 만들기

먼저, whoami 도구를 구현하는 MCP 서버를 만듭니다.

whoami.py라는 파일을 만들고 다음 코드를 추가하세요:

from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
from typing import Any

mcp = FastMCP("WhoAmI")

@mcp.tool()
def whoami() -> dict[str, Any]:
    """현재 사용자의 정보를 반환하는 도구입니다."""
    return {"error": "Not authenticated"}

app = Starlette(
    routes=[Mount('/', app=mcp.sse_app())]
)

서버 실행:

uvicorn whoami:app --host 0.0.0.0 --port 3001

MCP 서버 점검하기

MCP 인스펙터 클론 및 실행

이제 MCP 서버가 실행 중이므로, MCP 인스펙터를 사용해 whoami 도구가 사용 가능한지 확인할 수 있습니다.

현재 구현의 한계로 인해, MCP 인스펙터를 포크하여 인증 (Authentication) 및 인가 (Authorization)에 더 유연하고 확장 가능하도록 개선했습니다. 변경 사항을 원본 저장소에 PR로 제출했습니다.

MCP 인스펙터를 실행하려면 (Node.js 필요):

git clone https://github.com/mcp-auth/inspector.git
cd inspector
npm install
npm run dev

그런 다음 브라우저에서 http://localhost:6274/ (또는 터미널에 표시된 URL)로 접속하여 MCP 인스펙터에 접근하세요.

MCP 인스펙터를 MCP 서버에 연결하기

진행하기 전에 MCP 인스펙터에서 다음 설정을 확인하세요:

  • Transport Type: SSE로 설정
  • URL: MCP 서버의 URL로 설정 (예: http://localhost:3001/sse)

이제 "Connect" 버튼을 클릭하여 MCP 인스펙터가 MCP 서버에 연결되는지 확인하세요. 정상적으로 연결되면 MCP 인스펙터에서 "Connected" 상태를 볼 수 있습니다.

체크포인트: whoami 도구 실행하기

  1. MCP 인스펙터 상단 메뉴에서 "Tools" 탭 클릭
  2. "List Tools" 버튼 클릭
  3. 페이지에 whoami 도구가 표시되어야 합니다. 클릭하여 도구 상세 보기
  4. 우측에 "Run Tool" 버튼이 보입니다. 클릭하여 도구 실행
  5. JSON 응답 {"error": "Not authenticated"}가 결과로 표시되어야 합니다.

MCP 인스펙터 첫 실행

인가 (Authorization) 서버와 통합하기

이 섹션을 완료하려면 다음 사항들을 고려해야 합니다:

인가 (Authorization) 서버의 발급자 (Issuer) URL

일반적으로 인가 (Authorization) 서버의 기본 URL입니다. 예: https://auth.example.com. 일부 제공자는 https://example.logto.app/oidc와 같이 경로가 포함될 수 있으니, 제공자 문서를 꼭 확인하세요.

인가 (Authorization) 서버 메타데이터 조회 방법
  • 인가 (Authorization) 서버가 OAuth 2.0 Authorization Server Metadata 또는 OpenID Connect Discovery를 준수한다면, MCP Auth 내장 유틸리티로 메타데이터를 자동으로 가져올 수 있습니다.
  • 준수하지 않는 경우, MCP 서버 설정에서 메타데이터 URL 또는 엔드포인트를 수동으로 지정해야 합니다. 제공자 문서에서 엔드포인트를 확인하세요.
MCP 인스펙터를 인가 (Authorization) 서버에 클라이언트로 등록하는 방법
  • 인가 (Authorization) 서버가 동적 클라이언트 등록을 지원한다면, MCP 인스펙터가 자동으로 클라이언트로 등록되므로 이 단계를 건너뛸 수 있습니다.
  • 지원하지 않는 경우, MCP 인스펙터를 인가 (Authorization) 서버에 수동으로 클라이언트로 등록해야 합니다.
사용자 아이덴티티 정보 조회 및 인가 (Authorization) 요청 파라미터 설정 방법
  • OpenID Connect 제공자의 경우: 인가 (Authorization) 플로우 시작 시 최소 openidprofile 스코프 (Scope)를 요청해야 합니다. 이렇게 하면 인가 (Authorization) 서버가 반환하는 액세스 토큰 (Access token)에 userinfo 엔드포인트에 접근할 수 있는 권한이 포함됩니다.

    참고: 일부 제공자는 userinfo 엔드포인트를 지원하지 않을 수 있습니다.

  • OAuth 2.0 / OAuth 2.1 제공자의 경우: 액세스 토큰 (Access token)으로 사용자 아이덴티티 정보를 어떻게 조회하는지, 어떤 파라미터가 필요한지 제공자 문서를 확인하세요.

각 제공자마다 세부 요구사항이 다를 수 있지만, 아래 단계에 따라 MCP 인스펙터와 MCP 서버를 제공자별 설정으로 통합할 수 있습니다.

MCP 인스펙터를 클라이언트로 등록하기

Logto는 표준 userinfo 엔드포인트를 지원하는 OpenID Connect 제공자이므로 통합이 간단합니다.

Logto는 아직 동적 클라이언트 등록을 지원하지 않으므로, MCP 인스펙터를 Logto 테넌트에 수동으로 클라이언트로 등록해야 합니다:

  1. MCP 인스펙터에서 "OAuth Configuration" 버튼을 클릭하고 Redirect URL (자동 입력) 값을 복사하세요. 예: http://localhost:6274/oauth/callback
  2. Logto Console (또는 자체 호스팅 Logto Console)에 로그인하세요.
  3. "Applications" 탭에서 "Create application" 클릭. 페이지 하단에서 "Create app without framework" 클릭.
  4. 애플리케이션 정보를 입력하고 "Create application" 클릭:
    • Select an application type: "Single-page application" 선택
    • Application name: 예: "MCP Inspector"
  5. "Settings / Redirect URIs" 섹션에 복사한 Redirect URL (자동 입력) 값을 붙여넣고, 하단 바에서 "Save changes" 클릭
  6. 상단 카드에서 "App ID" 값을 복사하세요.
  7. MCP 인스펙터로 돌아가 "OAuth Configuration"의 "Client ID"에 "App ID" 값을 붙여넣으세요.
  8. "Auth Params" 필드에 {"scope": "openid profile email"} 값을 입력하세요. 이렇게 하면 Logto가 반환하는 액세스 토큰 (Access token)에 userinfo 엔드포인트 접근에 필요한 스코프가 포함됩니다.

MCP Auth 설정하기

MCP 서버 프로젝트에서 MCP Auth SDK를 설치하고 인가 (Authorization) 서버 메타데이터를 사용하도록 설정해야 합니다.

먼저 mcpauth 패키지를 설치하세요:

pip install mcpauth

또는 uv, poetry 등 원하는 패키지 매니저를 사용하세요.

MCP Auth는 인가 (Authorization) 서버 메타데이터가 필요합니다. 제공자에 따라 아래를 참고하세요:

발급자 (Issuer) URL은 Logto Console의 애플리케이션 상세 페이지 "Endpoints & Credentials / Issuer endpoint" 섹션에서 확인할 수 있습니다. 예: https://my-project.logto.app/oidc

whoami.py 파일을 업데이트하여 MCP Auth 구성을 포함하세요:

from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config

auth_issuer = '<issuer-endpoint>'  # 발급자 엔드포인트로 교체하세요
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)

이제 MCP 인스펙터에서 제공한 액세스 토큰 (Access token)을 사용하여 인가 서버에서 사용자 아이덴티티 정보를 가져오는 커스텀 액세스 토큰 (Access token) 검증기를 만들어야 합니다.

import pydantic
import requests
from mcpauth.exceptions import (
    MCPAuthTokenVerificationException,
    MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo

def verify_access_token(token: str) -> AuthInfo:
    """
    제공된 Bearer 토큰을 인가 서버에서 사용자 정보를 가져와 검증합니다.
    토큰이 유효하면 사용자의 정보가 담긴 `AuthInfo` 객체를 반환합니다.

    :param token: MCP 인스펙터에서 받은 Bearer 토큰.
    """

    issuer = auth_server_config.metadata.issuer
    endpoint = auth_server_config.metadata.userinfo_endpoint # 공급자가 userinfo 엔드포인트를 지원해야 합니다
    if not endpoint:
        raise ValueError(
            "Userinfo 엔드포인트가 인증 서버 메타데이터에 구성되어 있지 않습니다."
        )

    try:
        response = requests.get(
            endpoint,
            headers={"Authorization": f"Bearer {token}"}, # 표준 Bearer 토큰 헤더
        )
        response.raise_for_status() # HTTP 오류 발생 시 예외 발생
        json = response.json() # JSON 응답 파싱
        return AuthInfo(
            token=token,
            subject=json.get("sub"), # 'sub'는 주체(사용자 ID)에 대한 표준 클레임 (Claim)입니다
            issuer=issuer, # 메타데이터의 발급자 (Issuer) 사용
            claims=json, # userinfo 엔드포인트에서 반환된 모든 클레임 (Claim) (JSON 필드) 포함
        )
    # `AuthInfo`는 Pydantic 모델이므로, 검증 오류는 보통 응답이 예상 구조와 일치하지 않을 때 발생합니다
    except pydantic.ValidationError as e:
        raise MCPAuthTokenVerificationException(
            MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
            cause=e,
        )
    # 요청 중 발생할 수 있는 기타 예외 처리
    except Exception as e:
        raise MCPAuthTokenVerificationException(
            MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
            cause=e,
        )

MCP 서버 업데이트하기

거의 다 왔습니다! 이제 MCP Auth 라우트와 미들웨어를 적용하고, whoami 도구가 실제 사용자 아이덴티티 정보를 반환하도록 MCP 서버를 업데이트합니다.

@mcp.tool()
def whoami() -> dict[str, Any]:
    """현재 사용자의 정보를 반환하는 도구입니다."""
    return (
        mcp_auth.auth_info.claims
        if mcp_auth.auth_info # Bearer 인증 (Authentication) 미들웨어에서 채워집니다
        else {"error": "Not authenticated"}
    )

# ...

bearer_auth = Middleware(mcp_auth.bearer_auth_middleware(verify_access_token))
app = Starlette(
    routes=[
        # 메타데이터 라우트 추가 (`/.well-known/oauth-authorization-server`)
        mcp_auth.metadata_route(),
        # Bearer 인증 (Authentication) 미들웨어로 MCP 서버 보호
        Mount('/', app=mcp.sse_app(), middleware=[bearer_auth]),
    ],
)

체크포인트: 인증 (Authentication)과 함께 whoami 도구 실행하기

MCP 서버를 재시작하고 MCP 인스펙터를 브라우저에서 엽니다. "Connect" 버튼을 클릭하면 인가 (Authorization) 서버의 로그인 페이지로 리디렉션됩니다.

로그인 후 MCP 인스펙터로 돌아오면, 이전 체크포인트에서 했던 것처럼 whoami 도구를 실행하세요. 이번에는 인가 (Authorization) 서버가 반환하는 사용자 아이덴티티 정보가 표시됩니다.

MCP 인스펙터 whoami 도구 결과

정보

MCP Auth Python SDK 저장소에서 MCP 서버(OIDC 버전)의 전체 코드를 확인할 수 있습니다.

마무리 (Closing notes)

🎊 축하합니다! 튜토리얼을 성공적으로 완료하셨습니다. 지금까지 한 내용을 요약하면:

  • whoami 도구가 포함된 기본 MCP 서버 설정
  • MCP Auth를 사용하여 MCP 서버를 인가 (Authorization) 서버와 통합
  • MCP 인스펙터를 설정하여 사용자 인증 (Authentication) 및 아이덴티티 정보 조회

추가로 다음과 같은 고급 주제도 탐구해보세요:

MCP Auth를 최대한 활용하려면 다른 튜토리얼과 문서도 꼭 확인해보세요.