본문으로 건너뛰기

Logto로 MCP 기반 앱에 인증 (Authentication) 활성화

:

Logto의 AI 솔루션 을 살펴보세요: MCP 서버, AI 에이전트, 앱을 위한 인증 (Authentication) 및 인가 (Authorization).

이 가이드는 mcp-authMCP 공식 SDK v2를 사용하여 Logto를 MCP 서버와 통합하는 방법을 안내합니다. 이를 통해 사용자를 인증하고 액세스 토큰에서 검증된 아이덴티티를 안전하게 읽을 수 있습니다.

이 가이드에서 배우게 될 내용:

  • MCP 서버의 인가 (Authorization) 서버로 Logto를 구성하는 방법
  • MCP 서버에 “whoami” 도구를 설정하여 현재 사용자의 클레임 (Claim)을 반환하는 방법
  • VS Code (MCP 클라이언트)로 플로우를 테스트하는 방법

이 튜토리얼을 마치면 MCP 서버는 다음과 같은 기능을 갖추게 됩니다:

  • Logto 테넌트에서 사용자를 인증 (Authentication)
  • Logto에서 발급한 JWT 액세스 토큰 (서명, 발급자, 대상, 만료 등)을 검증
  • "whoami" 도구 호출 시 검증된 아이덴티티 클레임 (sub, iss, aud 등) 반환

통합이 완료되면, VS Code 대신 웹 앱 등 자체 MCP 클라이언트로 MCP 서버가 노출하는 도구와 리소스에 접근할 수 있습니다.

샘플 코드:

이 가이드의 완전하고 실행 가능한 샘플 코드는 mcp-auth/js 저장소에서 확인할 수 있습니다:

  • whoami-express: 이 가이드에서 사용하는 "whoami" 서버로, Node.js와 Express 기반입니다.
  • whoami: fetch-native(웹 표준 Request / ResponseHono)로 구축된 동일한 서버로, Cloudflare Workers에 배포할 수 있습니다.

사전 준비 사항

  • Logto Cloud (또는 자체 호스팅) 테넌트
  • Node.js >= 20 환경

아키텍처 이해하기

  • MCP 서버: MCP 클라이언트에게 도구와 리소스를 제공하는 서버입니다. 최신 MCP 명세에 따라, Logto에서 발급한 액세스 토큰 (Access token)을 검증하는 OAuth 2.0 리소스 서버 역할을 합니다.
  • MCP 클라이언트: 인증 (Authentication) 플로우를 시작하고 통합을 테스트하는 데 사용되는 클라이언트입니다. 이 가이드에서는 VS Code (내장 MCP 지원)를 클라이언트로 사용합니다.
  • Logto: OpenID Connect 제공자 (인가 (Authorization) 서버)로서, 사용자 아이덴티티를 관리하고 MCP 서버를 위한 대상 (Audience) 바인딩된 JWT 액세스 토큰 (Access token)을 발급합니다.

비공식 시퀀스 다이어그램은 전체 프로세스의 흐름을 보여줍니다:

노트:

MCP가 빠르게 발전하고 있기 때문에, 위 다이어그램이 완전히 최신이 아닐 수 있습니다. 최신 정보는 mcp-auth 문서를 참고하세요.

Logto에서 앱 설정하기

MCP 클라이언트가 인가 플로우를 시작하려면 Logto에 애플리케이션으로 등록되어야 합니다. 이 가이드에서는 VS Code를 클라이언트로 등록합니다:

  1. Logto 콘솔에 로그인하세요.

  2. 애플리케이션애플리케이션 생성프레임워크 없이 앱 생성으로 이동하세요.

  3. 유형 선택: 네이티브 앱.

  4. 앱 이름(예: "VS Code") 및 기타 필수 항목을 입력한 후 애플리케이션 생성을 클릭하세요.

  5. 설정 / 리디렉션 URI 섹션에서 VS Code용으로 아래 리디렉션 URI를 추가한 뒤 변경 사항을 저장하세요:

    http://127.0.0.1
    https://vscode.dev/redirect
  6. 앱 ID발급자 (Issuer) 엔드포인트를 저장하고 복사하세요.

MCP 서버 설정하기

MCP 공식 SDK v2와 mcp-auth를 사용하여, 현재 사용자의 아이덴티티 클레임을 반환하는 "whoami" 도구가 포함된 MCP 서버를 만들어보겠습니다.

프로젝트 생성 및 의존성 설치

mkdir mcp-server
cd mcp-server
npm init -y
npm pkg set type="module"
npm pkg set main="whoami.js"
npm pkg set scripts.start="node whoami.js"
npm install @modelcontextprotocol/server @modelcontextprotocol/express @modelcontextprotocol/node express mcp-auth
  • @modelcontextprotocol/server는 웹 표준 Request / Response를 사용하는 MCP SDK v2의 핵심입니다.
  • @modelcontextprotocol/express@modelcontextprotocol/node는 이를 Node.js의 Express에 맞게 변환해줍니다.
  • mcp-auth는 MCP SDK를 위한 토큰 검증기와 OAuth 디스커버리 메타데이터를 제공합니다.
노트:

MCP SDK v2와 mcp-auth는 ESM 전용이며 Node.js >= 20이 필요합니다.

MCP 서버를 API 리소스로 등록하기

최신 MCP 명세는 액세스 토큰이 발급된 리소스에 바인딩되어야 함을 요구합니다 (RFC 8707), 그리고 mcp-auth는 이를 강제합니다: 토큰의 aud 클레임이 MCP 서버의 리소스 식별자와 일치해야 합니다. Logto에서는 MCP 서버의 URL과 일치하는 리소스 지표를 가진 API 리소스를 생성하여 이를 수행합니다:

  1. Logto 콘솔에 로그인하세요.
  2. API 리소스API 리소스 생성으로 이동하세요.
  3. 세부 정보를 입력한 후 API 리소스 생성을 클릭하세요:
    • API 이름: 예시로 "Who am I"와 같이 입력하세요.
    • API 식별자: http://localhost:3001/을 입력하세요. 이는 MCP 서버에서 설정할 리소스 식별자와 일치해야 합니다.
리소스 지표의 슬래시:

항상 리소스 지표 끝에 슬래시(/)를 포함하세요. MCP 공식 SDK의 현재 버그로 인해, SDK를 사용하는 클라이언트는 인증 요청을 시작할 때 리소스 식별자에 자동으로 슬래시를 추가합니다. 리소스 지표에 슬래시가 없으면 해당 클라이언트에서 리소스 검증이 실패합니다.

Logto와 함께 MCP Auth 구성하기

MCP 서버를 보호된 리소스로 선언하세요: 리소스 식별자와 신뢰하는 인가 서버를 지정합니다. <your-logto-issuer-endpoint>는 이전에 복사한 발급자 엔드포인트(애플리케이션 상세 페이지의 엔드포인트 & 자격 증명에서 확인, 예: https://my-project.logto.app/oidc)로 교체하세요.

whoami.js에서:

import { MCPAuth } from 'mcp-auth';

const authIssuer = '<your-logto-issuer-endpoint>';

const mcpAuth = new MCPAuth({
protectedResourceMetadata: {
// 리소스 식별자; Logto에 등록한 API 리소스 지표와 일치해야 함
resource: 'http://localhost:3001/',
// 이 MCP 서버가 신뢰하는 인가 서버
authorizationServer: { issuer: authIssuer, type: 'oidc' },
},
});

인가 서버 메타데이터는 처음 필요할 때 지연 로딩되어 이후 캐시됩니다. MCPAuth 인스턴스는 Logto의 JWKS를 통해 JWT 액세스 토큰을 검증합니다 — 서명, 발급자, 대상, 만료 모두 강제됩니다. 별도의 토큰 검증 코드를 작성할 필요가 없습니다.

"whoami" 도구 구현하기

이제, 검증된 액세스 토큰에서 현재 사용자의 아이덴티티 클레임을 반환하는 "whoami" 도구를 구현해봅시다. mcp-auth가 검증한 인증 정보를 툴의 콜백 컨텍스트에서 getAuthInfo로 읽어옵니다.

import { McpServer } from '@modelcontextprotocol/server';
import { getAuthInfo } from 'mcp-auth';

// MCP 서버 인스턴스를 생성하는 팩토리 함수
// 각 요청마다 별도의 서버 인스턴스를 생성하여 요청을 격리함
const createMcpServer = () => {
const mcpServer = new McpServer({
name: 'WhoAmI',
version: '0.0.0',
});

// 현재 사용자 정보를 반환하는 도구를 서버에 추가
mcpServer.registerTool(
'whoami',
{
description: '현재 사용자 정보 가져오기',
},
(context) => {
const { claims } = getAuthInfo(context);
return {
content: [{ type: 'text', text: JSON.stringify(claims) }],
};
}
);

return mcpServer;
};

서버 연결하기

마지막으로, MCP 클라이언트가 인가 서버를 찾을 수 있도록 OAuth 디스커버리 문서(RFC 9728 / RFC 8414)를 제공하고, SDK의 Bearer 인증 미들웨어로 MCP 엔드포인트를 보호하세요.

import {
createMcpExpressApp,
mcpAuthMetadataRouter,
requireBearerAuth,
} from '@modelcontextprotocol/express';
import { toNodeHandler } from '@modelcontextprotocol/node';
import { createMcpHandler } from '@modelcontextprotocol/server';

const PORT = 3001;

// MCP 핸들러는 웹 표준 Request / Response를 사용하며, `toNodeHandler`가 이를 Express에 맞게 변환합니다
const mcpNodeHandler = toNodeHandler(createMcpHandler(createMcpServer));

const app = createMcpExpressApp();

// OAuth 디스커버리 문서(`/.well-known/...`)를 제공하며, 기본적으로 공개되어 있습니다
app.use(mcpAuthMetadataRouter(await mcpAuth.getAuthMetadataOptions()));

app.all(
'/',
// 유효한 Bearer 토큰이 필요합니다; 검증된 인증 정보는 `req.auth`를 통해 핸들러로 전달됩니다
requireBearerAuth(mcpAuth.getBearerAuthOptions()),
// `createMcpExpressApp`은 `express.json()`을 적용하여 요청 스트림을 소진하므로,
// 파싱된 body를 명시적으로 전달합니다
async (request, response) => mcpNodeHandler(request, response, request.body)
);

app.listen(PORT);

서버를 실행하려면:

npm start

통합 테스트하기

  1. MCP 서버를 시작하세요:

    npm start
  2. VS Code를 MCP 서버에 연결하세요:

    1. Command + Shift + P (macOS) 또는 Ctrl + Shift + P (Windows / Linux)를 눌러 커맨드 팔레트를 엽니다.
    2. MCP: Add Server...를 입력하고 선택하세요.
    3. 서버 유형으로 HTTP를 선택하세요.
    4. MCP 서버 URL을 입력하세요: http://localhost:3001/
    5. OAuth 플로우가 시작되면, VS Code에서 Client ID를 입력하라는 메시지가 표시됩니다. 앞서 복사한 앱 ID를 붙여넣으세요.
    6. 앱 시크릿이 없는 공개 클라이언트이므로, 엔터를 눌러 시크릿 입력을 건너뜁니다.
    7. 브라우저에서 로그인 플로우를 완료하세요.
  3. 로그인 후, VS Code에서 whoami 도구를 실행하세요.

액세스 토큰에서 검증된 클레임 (Claim)이 아래와 같이 표시되어야 합니다:

{
"iss": "https://my-project.logto.app/oidc",
"sub": "user_XXXX",
"aud": "http://localhost:3001/",
"client_id": "<your-app-id>"
}

추가 참고 자료

이제 MCP 서버가 인바운드 액세스 토큰을 검증합니다. 다음 단계로, 토큰 패스스루 없이 사용자 컨텍스트를 유지하며 사용자를 대신해 다운스트림 비즈니스 API를 안전하게 호출하는 방법을 알아보세요:

MCP 서버가 사용자를 대신해 API를 호출하는 방법: 프로덕션 토큰 전략