메인 콘텐츠로 건너뛰기

MCP 서버에서 MCP Auth 구성하기

최신 MCP 명세 (2025-06-18)에 따르면, MCP 서버는 외부 인가 (Authorization) 서버에서 발급한 액세스 토큰 (Access token)을 검증하는 리소스 서버 (Resource Server) 역할을 합니다.

MCP Auth를 구성하려면 두 가지 주요 단계를 거쳐야 합니다:

  1. 인가 (Authorization) 서버 메타데이터 구성 - 어떤 인가 (Authorization) 서버가 MCP 서버에 대해 유효한 토큰을 발급할 수 있는지 정의하고, MCP 클라이언트가 액세스 토큰 (Access token)을 어디서 받아야 하는지 안내합니다.
  2. 보호된 리소스 메타데이터 구성 - 지원하는 스코프 (Scope)와 함께 MCP 서버를 보호된 리소스로 정의합니다.

1단계: 인가 (Authorization) 서버 메타데이터 구성하기

메타데이터 자동 가져오기

인가 (Authorization) 서버 메타데이터를 구성하는 가장 쉬운 방법은 well-known URL에서 메타데이터를 가져오는 내장 함수를 사용하는 것입니다. 만약 사용 중인 공급자가 다음 표준 중 하나를 준수한다면:

fetchServerConfig를 사용하여 issuer URL만 제공하면 메타데이터를 자동으로 가져올 수 있습니다:

import { fetchServerConfig } from 'mcp-auth';

// 인가 (Authorization) 서버 메타데이터 가져오기
const authServerConfig = await fetchServerConfig('https://auth.logto.io/oidc', { type: 'oidc' }); // 또는 'oauth'

issuer에 경로가 포함된 경우, OAuth 2.0과 OpenID Connect에서 동작이 약간 다릅니다:

  • OAuth 2.0: well-known URL이 issuer의 도메인에 추가됩니다. 예를 들어, issuer가 https://my-project.logto.app/oauth라면, well-known URL은 https://auth.logto.io/.well-known/oauth-authorization-server/oauth가 됩니다.
  • OpenID Connect: well-known URL이 issuer에 직접 추가됩니다. 예를 들어, issuer가 https://my-project.logto.app/oidc라면, well-known URL은 https://auth.logto.io/oidc/.well-known/openid-configuration이 됩니다.

필요 시 디스커버리(On demand discovery)

Cloudflare Workers와 같이 최상위 async fetch가 허용되지 않는 엣지 런타임을 사용하는 경우, 필요 시 디스커버리를 사용할 수 있습니다. issuertype만 제공하면, 최초로 필요할 때 메타데이터가 자동으로 fetch됩니다:

const authServerConfig = { issuer: '<issuer-url>', type: 'oidc' }; // 또는 'oauth'

인가 (Authorization) 서버 메타데이터를 구성하는 다른 방법

커스텀 데이터 변환(Custom data transpilation)

경우에 따라 공급자가 반환하는 메타데이터가 예상 형식과 다를 수 있습니다. 공급자가 표준을 준수한다고 확신한다면, transpileData 옵션을 사용하여 메타데이터를 사용하기 전에 수정할 수 있습니다:

import { fetchServerConfig } from 'mcp-auth';

const authServerConfig = await fetchServerConfig('<auth-server-issuer>', {
  type: 'oidc',
  transpileData: (data) => ({ ...data, response_types_supported: ['code'] }), 
});

이렇게 하면 MCP Auth에서 메타데이터 객체를 사용하기 전에 필드를 추가/삭제하거나 값을 변경하거나 다른 형식으로 변환할 수 있습니다.

특정 URL에서 메타데이터 가져오기

공급자가 표준이 아닌 특정 메타데이터 URL을 제공하는 경우, 다음과 같이 사용할 수 있습니다:

import { fetchServerConfigByWellKnownUrl } from 'mcp-auth';

const authServerConfig = await fetchServerConfigByWellKnownUrl('<metadata-url>', { type: 'oidc' }); // 또는 'oauth'

특정 URL에서 커스텀 데이터 변환과 함께 메타데이터 가져오기

공급자 응답이 잘못되었거나 예상 메타데이터 형식과 다를 수 있습니다. 공급자가 표준을 준수한다고 확신한다면, config 옵션을 통해 메타데이터를 변환할 수 있습니다:

const authServerConfig = await fetchServerConfigByWellKnownUrl('<metadata-url>', {
  type: 'oidc',
  transpileData: (data) => ({ ...data, response_types_supported: ['code'] }), 
});

메타데이터를 수동으로 제공하기

공급자가 메타데이터 fetch를 지원하지 않는 경우, 메타데이터 객체를 직접 제공할 수 있습니다:

const authServerConfig = {
  metadata: {
    issuer: '<issuer-url>',
    // 메타데이터 필드는 camelCase로 작성해야 합니다
    authorizationEndpoint: '<authorization-endpoint-url>',
    // ... 기타 메타데이터 필드
  },
  type: 'oidc', // 또는 'oauth'
};

2단계: 보호된 리소스 메타데이터 구성하기

인가 (Authorization) 서버 메타데이터를 구성한 후, 보호된 리소스 메타데이터를 정의하여 MCPAuth를 리소스 서버로 초기화해야 합니다.

이 단계는 RFC 9728 (OAuth 2.0 Protected Resource Metadata) 명세를 따라 MCP 서버를 보호된 리소스로 설명합니다:

import { MCPAuth } from 'mcp-auth';

// 리소스 식별자 정의
const resourceIdentifier = 'https://api.example.com/notes';

// 리소스 서버 모드로 MCPAuth 초기화
const mcpAuth = new MCPAuth({
  protectedResources: {
    metadata: {
      resource: resourceIdentifier,
      authorizationServers: [authServerConfig], // 1단계에서 구성한 config 사용
      scopesSupported: ['read:notes', 'write:notes'],
    },
  },
});

여러 리소스가 있다면, 각각의 메타데이터 구성을 가진 보호된 리소스 config 배열을 제공할 수 있습니다.

위의 구성은 기본 설정을 다룹니다. 더 고급 메타데이터 파라미터는 RFC 9728을 참고하세요.

3단계: 보호된 리소스 메타데이터 엔드포인트 마운트하기

라우터를 마운트하여 보호된 리소스 메타데이터 엔드포인트를 제공합니다. 엔드포인트 경로는 리소스 식별자의 path 컴포넌트에 따라 자동으로 결정됩니다:

  • 경로 없음: https://api.example.com/.well-known/oauth-protected-resource
  • 경로 있음: https://api.example.com/notes/.well-known/oauth-protected-resource/notes
import express from 'express';

const app = express();

const mcpAuth = new MCPAuth({/* ... */});

app.use(mcpAuth.protectedResourceMetadataRouter());