AWS 기술 블로그

Amazon Bedrock Agents와 MCP(Model Context Protocol) 통합하기

Amazon Bedrock 등장

Amazon Bedrock은 업계를 선도하는 다양한 파운데이션 모델을 선택할 수 있는 완전 관리형 서비스입니다. Bedrock은 생성형 AI 기반의 애플리케이션을 구축하는 데 필요한 광범위한 기능을 제공하여 보안, 개인 정보 보호 및 책임감 있는 AI를 통해 생성형 AI 기반 애플리케이션을 개발하는데 필요한 시간을 단축시켜 줍니다.

Bedrock의 포괄적인 기능을 통해 다양한 최고 수준의 파운데이션 모델을 실험하고, 미세 조정 및 검색 증강 생성(RAG)과 같은 기술을 사용하여 비공개로 모델을 사용자 정의할 수 있습니다. 또한 복잡한 비즈니스 작업을 실행하는 관리형 에이전트를 생성할 수 있으며, 이러한 모든 기능을 코드 작성 없이 사용 가능합니다.

더불어 Bedrock은 서버리스이므로 인프라를 관리할 필요가 없으며, 이미 익숙한 AWS 서비스를 사용하여 애플리케이션에 생성형 AI 기능을 안전하게 통합하고 배포할 수 있습니다.

Amazon Bedrock Agents 역할 주요 특징

Amazon Bedrock Agents는 기업의 생성형 AI 애플리케이션 개발을 가속화하는 서비스입니다. 파운데이션 모델의 추론 능력을 활용하여 사용자 요청을 분석하고, 회사의 시스템, API 및 데이터 소스와 원활하게 연동하여 복잡한 다단계 작업을 자동화합니다.

Bedrock Agents를 이용하면 여러 전문 에이전트의 협업을 통해 복잡한 비즈니스 워크플로우를 처리할 수 있으며, 검색 증강 생성(RAG)을 활용하여 더 정확한 정보를 제공하는것도 가능해 지며, 상호작용 과정에서 메모리를 유지하여 사용자에게 더욱 개인화된 경험을 제공해 줄 수 있습니다.

이런 기능들을 Bedrock Agents에서는 간단한 설정만으로 구축이 가능하며, 내장된 보안 및 신뢰성을 위한 Guardrails를 제공하여 안전하고 효율적인 AI 애플리케이션 개발을 지원합니다.

Model Context Protocol 소개

생성형 AI에 사전훈련되어 있는 정보는 방대합니다. 하지만 사전훈련되어 있지 않은 정보에 대해서는 매우 간단한 질문도 답변할 수 없으며, 특히 현재 시간과 같이 질문 시점에 따라 달라지는 정보가 필요한 경우에는 정확한 답변이 불가능합니다. 이러한 문제는 생성형 AI에게 답변에 필요한 컨텍스트를 제공하는 방식으로 해결할 수 있습니다. 지금까지는 각각의 애플리케이션별로 각기 다른 방식으로 컨텍스트를 수집하고 생성하여 생성형 AI에게 제공해 왔습니다. 이러한 방법을 표준화한 프로토콜이 바로 Model Context Protocol(MCP)입니다.

MCP는 애플리케이션이 생성형 AI에 컨텍스트를 제공하는 방법을 표준화하는 개방형 프로토콜입니다.

MCP를 사용하는 개체는 클라이언트와 서버로 나누어집니다. 클라이언트는 MCP를 이용하여 서버로부터 리소스, 도구, 프롬프트의 형태로 컨텍스트를 제공받을 수 있습니다. 더 나아가, MCP는 생성형 AI에게 다양한 도구를 노출시켜 MCP 서버를 통해 여러 작업을 수행할 수 있게 합니다. 이는 마치 모델이라는 틀 속에 갇힌 생성형 AI에게 눈과 귀, 그리고 손발을 제공하는 것과 같습니다.

MCP는 개방형 프로토콜인 만큼, 한번 개발한 MCP 클라이언트는 다양한 MCP 서버로부터 컨텍스트를 제공받을 수 있고, MCP 서버 또한 다양한 MCP 클라이언트와 연계하여 작동할 수 있습니다.

Bedrock Agents MCP 통합의 한계와 극복 방안

현재 Bedrock Agents는 여러가지 강력한 기능을 제공하며, 거기에는 Action Groups라는 기능을 통해 Bedrock Agents외부의 도구를 활용하는 기능도 있습니다. 하지만 MCP서버를 도구로 바로 활용하기는 어려운데, Bedrock Agents가 MCP와 같은 특정 프로토콜을 지원하고 있지는 않기 때문입니다.

이러한 한계를 극복하기 위해, 본 포스트에서는 서버리스 아키텍처를 활용하여 Bedrock Agents와 MCP를 효과적으로 통합하는 방안을 소개하고자 합니다. AWS CDK(Cloud Development Kit)AWS Lambda의 함수를 활용한 이 접근 방식은 코드 수준의 통합을 통해 Bedrock Agents가 MCP 서버와 원활하게 통신할 수 있도록 합니다.

이어지는 섹션에서는 이 통합을 위한 아키텍처 설계부터 실제 구현 방법, 그리고 배포 및 테스트 방법까지 상세히 살펴보겠습니다. 이 방법을 통해 개발자는 완전관리형 서비스인 Bedrock Agents의 체계적인 API 관리 기능과 연동된 생성형 AI의 추론능력, 그리고 MCP의 유연한 데이터 접근 기능을 결합하여 더욱 풍부한 AI 애플리케이션을 구축할 수 있을 것입니다.

서버리스 기반의 Bedrock Agents-MCP 통합 아키텍처

아키텍처 개요

Bedrock Agents와 MCP을 통합하기 위한 서버리스 아키텍처는 AWS의 주요 관리형 서비스들을 활용하여 확장성과 관리 용이성을 극대화합니다. 이 아키텍처의 핵심은 Bedrock Agents에서 정의한 Action Group의 Lambda 함수를 통해 MCP 서버와 연결하는 것입니다.

전체 시스템은 크게 세 가지 주요 구성 요소로 이루어집니다:

  1. Bedrock Agents: 사용자와의 대화를 처리하고 필요한 도구를 호출합니다.
  2. Lambda 함수: STDIO(Standard Input/Output)기반의 MCP 서버를 구동하고, Bedrock Agents와 MCP 서버 사이의 중개자 역할을 합니다.
  3. 외부 MCP 서버: Lambda 함수 내에서 구동되는 MCP 서버는 그 자체로 도구의 역할을 하기도 하지만 외부 MCP 서버와 다시 중계 역할을 하기도 합니다.

위 구성에서 외부 MCP 서버와의 통신을 위해 NAT 게이트웨이 까지는 모두 Amazon VPC를 기반으로 구성되어 사설 네트워크 수준에서 연결됩니다. 만약 Lambda 함수 내에서 구동되는 MCP 서버가 그 자체만으로 도구 역할을 한다면, 외부 네트워크 접근 없이 VPC 내에서 사설 네트워크 수준에서 모든 동작이 이루어집니다.

이러한 서버리스 접근 방식의 주요 이점은 다음과 같습니다:

  • 인프라 관리 부담 최소화
  • 필요에 따른 자동 확장
  • 서비스 간 안전한 통신
  • 실제 사용한 만큼만 비용 발생

CDK기반 Bedrock Agents 구성

AWS Cloud Development Kit(CDK)를 활용하면 이러한 복잡한 인프라를 코드로 정의하고 배포할 수 있습니다. CDK는 TypeScript, Python 등의 프로그래밍 언어를 사용하여 AWS CloudFormation 템플릿을 생성합니다.

이 프로젝트에서는 CloudFormation과 CDK를 통해 다음과 같은 인프라 구성 요소를 정의합니다:

1.VPC 네트워킹 구성요소(선택사항, 기존 VPC활용 가능):

  • 퍼블릭 서브넷 2개
  • 프라이빗 서브넷 2개
  • 인터넷 게이트웨이, NAT 게이트웨이, 라우팅 테이블
  • S3 VPC 엔드포인트

2. 보안 그룹 및 IAM 역할:

  • Lambda 보안 그룹: Lambda 함수의 네트워크 액세스 제어
  • Bedrock Agents 역할: 필요한 권한을 가진 IAM 역할

3. Bedrock Agents 구성:

  • Action Group 정의: OpenAPI 스키마를 기반으로 생성
  • 에이전트 전체 설정 및 구성

CDK 스택은 필요한 모든 리소스를 자동으로 생성하고 구성하므로, 개발자는 인프라 구성에 대한 걱정 없이 애플리케이션의 기능에 집중할 수 있습니다.

Lambda 함수를 통한 MCP 연동

Lambda 함수는 Bedrock Agents와 MCP 서버 사이의 핵심 연결 지점으로, 다음과 같은 방식으로 동작합니다:

요청 처리 흐름:

  • Bedrock Agents의 LLM은 Action Group을 통해 사용 가능한 도구의 목록과 용도를 파악합니다.
  • 사용자 질의에 따라 LLM이 특정 도구를 호출해야 한다고 판단하면, 이를 OpenAPI 스키마에 정의된 방식으로 Lambda 함수에 요청합니다.
  • Lambda 함수는 이 요청을 MCP 서버가 이해할 수 있는 형식으로 변환하여 처리합니다.
  • Lambda함수에서 구동중인 MCP 서버는 요청된 도구를 실행하고 결과를 반환합니다. 이때, 해당 MCP 서버는 필요하다면 다시 외부 MCP 서버나 다른 애플리케이션과 연계하여 동작합니다. 이 경우에는 Lambda 함수에서 인터넷 등의 외부 네트워크에 접근이 필요할 수 있습니다.
  • Lambda함수는 이 결과를 다시 Bedrock Agents가 이해할 수 있는 형식으로 변환하여 응답합니다.

매개변수 변환 및 도구 호출:

Lambda 핸들러는 Bedrock Agents로부터 받은 매개변수를 MCP 도구가 이해할 수 있는 형식으로 변환합니다:

function convertPropertiesToArgs(properties) {
    return properties.reduce((args, prop) => {
    let convertedValue;
    try {
        switch(prop.type) {
            case 'string':
                convertedValue = String(prop.value);
                break;
            case 'boolean':
...
    }
    
    args[prop.name] = convertedValue;
    return args;
    }, {});
}
...
const toolArg = {
    name: toolName,
    arguments: convertPropertiesToArgs(properties)
}
...
try {
    const result = await client.callTool(toolArg);
    // 결과 처리 및 반환
}
...
JavaScript

이러한 접근 방식의 장점은 MCP 서버가 제공하는 도구들을 동적으로 Bedrock Agents에서 사용할 수 있다는 점입니다. MCP 서버의 도구가 변경되면, OpenAPI 스키마를 새로 생성하여 Agents의 Action Group을 업데이트하기만 하면 됩니다.

또한, MCP 서버가 인터넷이나 다른 네트워크 리소스에 접근해야 하는 경우에도 Lambda 함수를 통해 이러한 요청을 처리할 수 있습니다. Lambda 함수는 VPC 내에서 실행되므로 필요한 네트워크 연결을 안전하게 구성할 수 있습니다.

이 아키텍처의 서버리스 특성으로 인해, MCP 서버와 통합된 Bedrock Agents는 사용량에 따라 자동으로 확장되며 유휴 시간 동안에는 비용이 발생하지 않습니다. 이는 비용 효율적이면서도 확장성 있는 솔루션을 제공합니다.

구현 – 퀵스타트

이 섹션에서는 Bedrock Agents와 MCP 서버를 통합하기 위한 실제 구현 방법을 단계별로 살펴보겠습니다. 먼저 퀵스타트를 통해 아마존 리눅스를 기반으로 구현을 위해 필요한 사전 요구사항을 구성부터 배포 및 테스트까지 빠르게 실행 해 본 뒤 핵심 소스 코드의 분석까지 상세히 알아보겠습니다.

AWS CloudShell 준비

본 퀵스타트의 모든 배포과정은 AWS 웹 콘솔에서 리눅스 쉘을 사용할 수 있도록 해 주는 CloudShell을 기반으로 수행합니다. 다만, 이는 설명상 편의를 위한것일 뿐 적절한 버전의 도구들을 설치하고 권한을 부여한다면 맥이나 윈도우 등의 OS에서도 정상적인 배포가 가능합니다.

CloudShell은 AWS 웹 콘솔에서 “CloudShell”을 검색하거나 다음의 링크를 통해서도 접속하실 수 있습니다.

사전 요구사항 설치

시작하기 전에 다음 구성 요소들이 준비되어 있어야 합니다:

  • Node.js v20.x 이상 – CDK 코드 Lambda function 핸들러 빌드
  • npm 10.x 이상 – CDK 코드 및 Lambda function 핸들러 빌드
  • AWS CLI v2.x 이상 – CDK 코드 및 CloudFormation배포
  • AWS CDK v2.x 이상 – CDK 코드 빌드 및 배포
  • git v2.x 이상 – 소스코드 다운로드
  • VPC, EC2, Bedrock Agent, Bedrock, Lambda 등 리소스 생성, 사용 권한 – 퀵스타트는 오레곤 리전을 대상으로 이루어집니다. 그 외 리전에서 구성할 경우 일부 코드의 수정이 필요할 수 있습니다.

이때 우리가 사용할 CloudShell 환경에는 기본적으로 위 도구들이 모두 설치 돼 있습니다.

다음 명령을 통해 설치 돼 있는 도구들의 버전을 확인할 수 있습니다.

node --version
npm --version
aws --version
cdk --version
git --version

예상 출력:
~ $ node --version
v20.18.3
~ $ npm --version
10.8.2
~ $ aws --version
aws-cli/2.27.14 Python/3.13.3 Linux/6.1.134-150.224.amzn2023.x86_64 exec-env/CloudShell exe/x86_64.amzn.2023
~ $ cdk --version
2.1006.0 (build a3b9762)
~ $ git --version
git version 2.47.1
Bash

초기 설정

1. CDK 부트스트래핑

Bedrock Agents와 MCP 통합 코드는 AWS CDK를 기반으로 구현하고 배포합니다. CDK를 사용하기 위해서는 CDK를 사용하려는 계정의 대상 리전에 최초 1회 CDK 부트스트래핑 과정이 필요합니다. CDK 부트스트래핑은 다음과 같이 수행할 수 있습니다.

# 퀵스타트는 오레곤 리전을 대상으로 이루어지므로, 오레곤 리전에 CDK 부트스트래핑을 수행합니다.
cdk bootstrap aws://$(aws sts get-caller-identity --query 'Account' --output text)/us-west-2
Bash

2. 저장소를 클론합니다:

git clone https://github.com/aws-samples/kr-tech-blog-sample-code.git
cd kr-tech-blog-sample-code/
# CloudShell의 제한된 용량을 활용하기 위해 bedrock-mcp-agent-cdk 외 디렉토리는 모두 삭제 후 bedrock-mcp-agent-cdk 하위 디렉토리로 워킹디렉토리를 변경합니다.
find . -maxdepth 1 -type d ! -name '.' ! -name 'bedrock-mcp-agent-cdk' -exec rm -rf {} +
cd bedrock-mcp-agent-cdk/
Bash

3. VPC 구성(선택사항):

base-infra-example/base-vpc.yaml 파일을 CloudFormation을 이용해서 배포합니다. 이는 Bedrock Agents의 Action Group용 Lambda function을 배포할 VPC를 구성하는것으로 이미 존재하는 VPC 및 Subnet을 사용할 수 있으므로, 반드시 배포 해야하는것은 아닙니다. 본 퀵스타트에서는 새로운 VPC를 CloudFormation을 이용하여 배포하고, 배포 output으로 얻을 수 있는 VPC ID와 Subnet ID를 conf/vpc-info에 기록하여 다음 과정에서 활용합니다. 만약 이미 존재하는 VPC에 배포한 경우에는 conf/vpc-info 파일을 적절히 수정해야 합니다.

VPC 배포 및 vpc-info 생성:

cd base-infra-example/
# 해당 스크립트를 통해 base-vpc.yaml 을 CloudFormation으로 배포하고, 배포의 output에서 VPC ID와 Subnet ID를 추출하여 conf/vpc-info에 기록합니다. 해당 스크립트는 base-infra-example 디렉토리를 워킹디렉토리로 변경해야 정상 작동합니다.
./deploy.sh
Bash

MCP 서버 구성

Bedrock Agents에서 사용할 MCP 서버는 conf/mcp.json 파일에 구성합니다. 이 파일에는 여러 MCP 서버를 정의할 수 있으며, 각 서버는 명령어와 인자로 지정됩니다.

다음은 두 가지 MCP 서버를 구성하는 예시인 mcp.json.example 파일의 내용입니다:

{
  "mcpServers": {
    "time-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@smithery/cli@latest",
        "run",
        "@yokingma/time-mcp",
        "--key",
        "<your-smithery-key>"
      ],
      "bundling": {
        "nodeModules": ["npm", "@smithery/cli"]
      }
    },
    "duckduckgo-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "@smithery/cli@latest",
        "run",
        "@nickclyde/duckduckgo-mcp-server",
        "--key",
        "<your-smithery-key>"
      ],
      "bundling": {
        "nodeModules": ["npm", "@smithery/cli"]
      }
    }
  }
}
JSON

위 구성에서는 Smithery에서 제공하는 두 가지 MCP 서버를 정의하는 예시를 보여줍니다:

  • time-mcp: 현재 시간 정보를 제공하는 MCP 서버
  • duckduckgo-mcp-server: DuckDuckGo 검색 기능을 제공하는 MCP 서버

이때 두 MCP Server는 모두 Smithery에서 제공받을 수 있는 MCP 서버들 입니다. Smithery는 MCP Server를 제공하고 제공받을 수 있는 플랫폼으로, 예제에서 설정한 MCP 서버들이 정상 작동하기 위해서는 Smithery에서 각자 API Key를 확인하고 설정에 반영해야 합니다.

우선 Smithery에 가입하고(2025년 5월 현재 github 인증을 통해 가입이 가능합니다.), time server를 검색하여 Time MCP Server를 찾습니다. 또는 링크를 통해 바로 Time MCP Server 페이지를 열 수 있습니다.

이 후 해당 페이지의 우측 Install 탭에서 JSON을 클릭하면 Time MCP Server의 설정을 json 형태로 확인할 수 있습니다.

해당 키에는 위 그림과 같이 Smithery의 API Key가 포함 돼 있습니다. 해당 키를 복사하여, mcp.json 파일에 적용해야 MCP Server들이 정상적으로 응답할 수 있습니다.

우선 아래와 같은 명령으로 예제 설정파일을 mcp.json 으로 따로 저장합니다.

cd ..
cp conf/mcp.json.example conf/mcp.json
Bash

이후 CloudShell 환경에서 nano나 vi 에디터로 mcp.json 파일을 수정합니다.

nano conf/mcp.json
Bash

또는

vi conf/mcp.json
Bash

파일을 열어서 Time MCP Server와 DuckDuckGo MCP Server 두 설정의 <your-smithery-key> 부분을Smithery 웹 페이지에서 확인한 API Key로 교체하고 저장합니다.

빌드 및 배포

1. 프로젝트 빌드

npm run build
Bash

이때 npm run build를 수행하면 실제로는 CDK 코드와 Lambda function의 핸들러 코드에 대해 각각 npm install을 통해 모듈 설치를 수행한 뒤 typescript 코드를 컴파일 한 뒤에 함께 제공되는 schema conversion tool을 이용해서 설정된 MCP 서버에 접근하여 도구 정보를 가져와 OpenAPI schema를 생성하여 Lambda function의 핸들러에서 이용하도록 구성합니다. 자세한 스크립트는 프로젝트 루트의 package.json에서 확인 가능합니다.

2. CDK 스택 배포

./deploy.sh
Bash

여기서 deploy.sh 스크립트는 cdk deploy 명령을 실행 해 주는 스크립트이지만 앞서 conf/vpc-info 파일에 저장 해 두었던 VPC관련 변수들을 활용해 cdk deploy 명령의 파라미터로 전달해 주는 역할을 합니다. 배포 중 AWS 인프라 변경에 대한 승인으로 변경내용을 확인한 뒤에 ‘y’를 입력합니다.

배포 과정에서는 다음과 같은 작업이 수행됩니다:

  • Lambda 함수 생성 및 배포
  • Bedrock Agents 생성 및 구성
  • IAM 역할 및 보안 그룹 설정

배포과정에는 변경된 MCP 서버에 대한 설정이 반영되지 않습니다npm run build:schema 명령을 통해 MCP 서버의 도구를 OpenAPI schema 변경해야 합니다. 해당 과정은 npm run build 과정의 일부로 한차례 실행을 한 상태입니다. 하지만 MCP 서버의 설정을 변경했다면 npm run build 또는 npm run build:schema 명령을 통해 MCP 서버 도구에 대한 OpenAPI schema를 다시 빌드해야합니다.

스택을 배포하면 배포된 Bedrock Agents의 AgentId를 출력합니다. 해당 AgentID는 예제 클라이언트를 통해 테스트할 때 필요하므로, 따로 메모 해 둡니다.

출력예시:
✨  Deployment time: 218.14s

Outputs:

BedrockAgentStack.BedrockAgentId = BN3XXXXX

Stack ARN:

arn:aws:cloudformation:us-west-2:000000000000:stack/BedrockAgentStack/00000000-0000-0000-0000-000000000000

✨  Total time: 252.45s

테스트 및 검증

배포가 완료된 후에는 제공된 Jupyter Notebook을 사용하여 배포를 테스트할 수 있습니다. 퀵스타트에서는 해당 Jypyter notebook을 Amazon Sagemaker AI의 Jupyter notebook 인스턴스로 배포하여 별도 서버 구성없이 테스트 해 봅니다.

cd client-example/
# 우선 Sagemaker AI의 Jupyter notebook을 배포할 CloudFormation template을 생성합니다.
./generate_template.sh
Bash

다음으로 생성된 CloudFormation template을 배포합니다.

./deploy.sh
Bash

Sagemaker AI의 Jupyter notebook 인스턴스 배포가 완료되면 CloudShell 터미널에 Jupyter notebook 인스턴스에 접근할 수 있는 URL이 다음과 같이 출력됩니다.

Notebook URL: https://us-west-2.console.aws.amazon.com/sagemaker/home?region=us-west-2#/notebook-instances/openNotebook/NotebookInstance-XXXXXXXXXXX?view=classic

해당 URL을 웹브라우저로 열면 코드와 함께 제공되는 예제 클라이언트인 bedrock-agent-test.ipynb 를 Jupyter notebook에서 열어볼 수 있습니다. 이때 예제 코드에서 가장 상단의 Cell에서 agent_id 부분을 앞서 메모했던 BedrockAgentId로 교체해야 정상작동 합니다.

코드의 가장 마지막에는 아래와 같은 예시 질문 두가지가 있습니다.

# example questions

questions = [

"AWS와 관련된 뉴스 3개를 알려주세요.",

#"Tell me three AWS related news stories.",

"현재 서울의 시간을 HH:mm:ss 형식으로 알려주세요.",

#"Tell me the current time in Seoul using the format HH:mm:ss."

]

그리고 이 질문들에 대한 예상 결과는 다음과 같습니다:

Q: AWS와 관련된 뉴스 3개를 알려주세요.

A: 다음은 AWS와 관련된 최신 뉴스 3개입니다:

1. **What's New at AWS - Cloud Innovation & News**

- URL: [https://aws.amazon.com/new/](https://aws.amazon.com/new/)

- 요약: AWS는 지속적으로 새로운 기능을 추가하여 최신 기술을 활용하여 더 빠르게 실험하고 혁신할 수 있도록 합니다. What's New 게시물은 우리가 바로 그렇게 하고 있음을 보여주며, 모든 AWS 서비스, 기능 및 지역 확장 발표가 출시될 때마다 간략한 개요를 제공합니다.

2. **Latest news about Amazon and AWS**

- URL: [https://www.aboutamazon.com/amazon-aws-news](https://www.aboutamazon.com/amazon-aws-news)

- 요약: Amazon Web Services(AWS)에 대한 최신 뉴스 및 업데이트를 읽으세요. Bedrock, Q 및 기타 도구의 최신 개발 사항, 기술 교육, 커뮤니티 이니셔티브 등에 대해 알아보세요. ... Amazon Web Services(AWS)는 200개 이상의 완전한 기능을 갖춘 서비스를 데이터에서 사용할 수 있는 세계에서 가장 포괄적이고 널리 채택된 클라우드입니다.

3. **The 10 Biggest AWS News Stories Of 2024: CEO Exit, AI And Partners - CRN**

- URL: [https://www.crn.com/news/cloud/2024/top-10-biggest-aws-news-stories-of-2024-ceo-exit-ai-and-partners](https://www.crn.com/news/cloud/2024/top-10-biggest-aws-news-stories-of-2024-ceo-exit-ai-and-partners)

- 요약: CRN은 2024년 AWS의 가장 중요한 사건을 검토합니다. 새로운 CEO Matt Garman, AI 혁신, 칩 제조 및 클라우드 시장 지배력을 포함합니다. AWS가 AI 스타트업에 수십억 달러를 투자하고, 직원들에게 사무실 복귀를 의무화하고, VMware 파트너와의 관계를 단절한 방법을 알아보세요.

Q: 현재 서울의 시간을 HH:mm:ss 형식으로 알려주세요.

A: 현재 서울의 시간은 11:47:21입니다.

여기서 주목할 점은 모델이 현재 시간과 같은 실시간 정보를 정확히 제공할 수 있다는 것입니다. 일반적으로 LLM은 학습 데이터에만 의존하기 때문에 현재 시간과 같은 최신 정보를 정확히 알 수 없지만, MCP 도구 통합을 통해 이러한 실시간 정보를 제공할 수 있게 됩니다.

소스 코드 분석

이제 주요 소스 코드를 분석하여 Bedrock Agents와 MCP 서버의 통합이 어떻게 구현되었는지 살펴보겠습니다.

Bedrock Agent 스택 (bedrock-agent-stack.ts)

Bedrock Agent 스택은 CDK를 사용하여 AWS 리소스를 정의하고 배포하는 코드입니다. 주요 구성 요소는 다음과 같습니다:

1. Lambda 함수 생성:

각 MCP 서버에 대해 별도의 Lambda 함수를 생성합니다.

      const lambdaFunction = new NodejsFunction(this, `McpHandler-${mcpServerName}`, {
        runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
        handler: 'index.handler',
        entry: path.join(__dirname, '../lambda/mcp_action_group_handler/index.mjs'),
        timeout: cdk.Duration.seconds(180),
        memorySize: 512,
        environment: {
          MCP_SERVER_NAME: mcpServerName,
          MCP_SERVER_CONFIG: Buffer.from(JSON.stringify(mcpServerConfig)).toString('base64')
        },
        vpc,
        vpcSubnets: {
          subnets: subnets
        },
        securityGroups: [lambdaSg],
        bundling: bundling
      });
JavaScript

이 코드는 각 MCP 서버에 대한 Lambda 함수를 생성하며, MCP 서버 구성은 환경 변수를 통해 전달됩니다. 특히 MCP_SERVER_CONFIG는 base64로 인코딩되어 전달됩니다.

2. Action Group 구성:

각 MCP 서버에 대해 Bedrock Agent의 Action Group을 정의합니다.

actionGroups.push({
// '-' is not allowed for action group name
ActionGroupName: `${mcpServerName.replace(/-/g, '_')}`,
ActionGroupExecutor: {
    Lambda: lambdaFunction.functionArn
},
ApiSchema: {
    Payload: JSON.stringify(props.openApiSchema[mcpServerName], null, 2)
}
})
JavaScript

이 코드는 각 MCP 서버의 도구들을 Bedrock Agent의 Action Group으로 등록합니다. 여기서 openApiSchema는 MCP 서버의 도구를 OpenAPI 스키마 형식으로 변환한 결과입니다.

3. Bedrock Agent 생성:

최종적으로 Bedrock Agent를 생성하고 구성합니다.

const bedrockAgent = new cdk.CfnResource(this, 'BedrockAgent', {
type: 'AWS::Bedrock::Agent',
properties: {
    AgentName: 'BedrockMcpDemoAgent',
    AgentResourceRoleArn: bedrockAgentRole.roleArn,
    FoundationModel: novaInferenceProfileArn,
    AutoPrepare: true,
    Description: 'An agent that provides MCP capability',
    IdleSessionTTLInSeconds: 1800,
    Instruction: `You are an intelligent and resourceful assistant...`,
    ActionGroups: actionGroups
}
});
JavaScript

이 코드는 Bedrock Agent를 생성하고, 이전에 정의한 Action Group들을 연결합니다. Instruction을 통해 Agent의 기본 동작 방식을 정의하며, FoundationModel을 통해 사용할 기초 모델을 지정합니다.

4. MCP 도구를 OpenAPI 스키마로 변환 (schema-conversion-tool.ts)

MCP 서버의 도구들을 Bedrock Agent의 Action Group으로 사용하기 위해서는 OpenAPI 스키마 형식으로 변환해야 합니다. 이 과정은 schema-conversion-tool.ts에서 수행됩니다.

MCP 클라이언트 생성 및 도구 목록 가져오기:
const transport = new StdioClientTransport({
command: command,
args: args
});

const client = new Client(
{
    name: "bedrock-agent-client",
    version: "0.0.1"
},
{
    capabilities: {
    tools: {}
    }
}
);

await client.connect(transport);
const serverCapabilities = client.getServerCapabilities()

if(serverCapabilities && 'tools' in serverCapabilities){
const tools = await client.listTools();
openApiSchema[mcpServerName] = convertToOpenAPI(mcpServerName, tools as ToolsResponse)
}
JavaScript

이 코드는 MCP 서버에 연결하여 사용 가능한 도구 목록을 가져오고, 이를 OpenAPI schema로 변환 해 줍니다.

5. 도구를 OpenAPI 스키마로 변환:

export function convertToOpenAPI(mcpName: String, toolsJson: ToolsResponse): any {
const openapi: OpenAPISpec = {
    openapi: '3.0.0',
    info: {
    title: mcpName + ' API',
    version: '1.0.0'
    },
    paths: {},
};

toolsJson.tools.forEach(tool => {
    try {
    const pathName = `/${tool.name}`;
    
    // 요청 스키마 생성
    const requestSchema = deepCloneSchema(cleanObject(tool.inputSchema));

    // 경로 항목 생성
    openapi.paths[pathName] = {
        post: {
        tags: ['tools'],
        summary: tool.description,
        description: tool.description,
        operationId: tool.name,
        requestBody: {
            required: true,
            content: {
            'application/json': {
                schema: requestSchema
            }
            }
        },
        responses: {
            '200': {
            description: 'Successful operation',
            // ...응답 스키마...
            },
            '400': {
            description: 'Bad request',
            // ...에러 응답 스키마...
            }
        }
        }
    };
    } catch (error) {
    console.error(`Error processing tool ${tool.name}:`, error);
    }
});

return openapi;
}
JavaScript

이 함수는 MCP 서버의 각 도구를 OpenAPI 경로로 변환합니다. 각 도구는 /도구이름 형태의 경로로 매핑되며, POST 메서드를 통해 호출됩니다. 도구의 입력 스키마는 요청 본문의 스키마로 사용됩니다.

Lambda 함수 구현 (index.mjs)

Lambda 함수는 Bedrock Agent와 MCP 서버 사이의 중개자 역할을 합니다. 주요 기능은 다음과 같습니다:

1. MCP 클라이언트 생성:

MCP 서버 설정을 기반으로 MCP 클라이언트를 생성합니다.

async function createClientFn() {
  const command = mcpServerConfig.command;
  const args = mcpServerConfig.args ?? [];
  const env = mcpServerConfig.env ?? {};
  const transport = new StdioClientTransport({
    command: command,
    args: args,
    env: { ...process.env, ...env }
  });
  
  const client = new Client(
    {
      name: "bedrock-agent-client",
      version: "0.0.1"
    },
    {
      capabilities: {
        tools: {}
      }
    }
  );

  await client.connect(transport);
  return client;
}
JavaScript

2. 요청 처리:

Bedrock Agent로부터 받은 요청을 MCP 도구 호출로 변환합니다.

export const handler = async (event, context) => {
  safeLogger.log('start');
  const httpMethod = event.httpMethod;
  const actionGroup = event.actionGroup;
  const apiPath = event.apiPath;
  const parameters = event.parameters;
  const toolName = apiPath.replace(/^\//, '');
  const properties = event.requestBody.content["application/json"].properties

  safeLogger.log(JSON.stringify(event), null, 2)
  safeLogger.log(httpMethod);
  safeLogger.log(actionGroup);
  safeLogger.log(apiPath);
  safeLogger.log(parameters);
  
  const toolArg = {
    name: toolName,
    arguments: convertPropertiesToArgs(properties)
  }
  safeLogger.log(JSON.stringify(toolArg));

  const client = await createClientFn();
  try {
    const result = await client.callTool(toolArg);
    const ret = {
      "messageVersion": "1.0",
      "response": {
        "actionGroup": actionGroup,
        "apiPath": apiPath,
        "httpMethod": httpMethod,
        "httpStatusCode": 200,
        "responseBody": {
          "application/json": {
            "body": JSON.stringify(result)
          }
        }
      }
    }
    safeLogger.log(JSON.stringify(ret));
    client.close();
    return ret;
  } catch (error) {
    throw error;
  }
};
JavaScript

이 코드는 Bedrock Agent로부터 받은 요청을 MCP 도구 호출로 변환하고, 결과를 다시 Bedrock Agent가 이해할 수 있는 형식으로 반환합니다.

문제 해결

자주 발생하는 문제들과 해결 방법은 다음과 같습니다:

VPC 구성 문제

    • 문제: CDK 배포가 VPC 유효성 검사 오류로 실패
    • 해결: vpc-info 파일에서 VPC ID와 서브넷 ID 확인

cat conf/vpc-info
# 다음과 같이 포함되어야 함:
# export AWS_REGION=us-west-2
# export VPC_ID=vpc-xxxxxx
# export SUBNET_IDS=subnet-xxx,subnet-yyy

MCP 서버 연결 문제

  • 문제: MCP 서버 시작 실패
  • 해결: MCP 서버 구성 및 자격 증명 확인

# MCP 서버 구성 확인
cat conf/mcp.json
# 형식과 자격 증명 확인

할당량 제한

Bedrock Agents에는 다음과 같은 기본 할당량 제한이 있습니다:

  • 에이전트당 최대 5개의 액션 그룹 함수
  • 액션 그룹당 최대 5개의 파라미터

이러한 제한을 초과해야 하는 경우, AWS 콘솔의 Service Quotas를 통해 한도 증가를 요청할 수 있습니다.

이렇게 Bedrock Agents와 MCP 서버의 통합을 위한 환경 구성부터 배포, 테스트, 그리고 소스 코드 분석까지 살펴보았습니다. 이 구현을 통해 Bedrock Agents는 MCP 서버가 제공하는 다양한 도구를 활용하여 더 풍부한 기능을 제공할 수 있게 됩니다.

결론 향후 과제

통합의 의미와 가치

이 블로그에서 살펴본 Amazon Bedrock Agents와 MCP의 서버리스 통합은 완전관리형 서비스인 Bedrock Agents가 제공하는 강력한 자연어 처리 및 추론 능력과 MCP를 통해 접근할 수 있는 다양한 외부 도구들을 결합함으로써, 더욱 실용적이고 확장 가능한 AI 솔루션을 구축할 수 있다는 가능성을 보여줍니다.

서버리스 아키텍처의 장점

AWS CDK와 Lambda 함수를 활용한 서버리스 아키텍처는 여러 가지 중요한 이점을 제공합니다:

  1. 관리 오버헤드 감소: 인프라 관리에 대한 부담 없이 핵심 비즈니스 로직에 집중할 수 있습니다.
  2. 비용 효율성: 사용한 만큼만 비용을 지불하므로, 특히 불규칙한 사용 패턴을 가진 애플리케이션에 경제적입니다.
  3. 자동 확장성: 트래픽 증가에 따라 자동으로 확장되므로 수동 조정이 필요 없습니다.
  4. 빠른 배포와 업데이트: CDK를 통한 인프라 코드는 빠른 배포와 업데이트를 가능하게 합니다.

이러한 특성은 실험적인 프로젝트부터 엔터프라이즈급 애플리케이션까지 다양한 규모의 AI 솔루션 개발을 용이하게 합니다.

한계와 제약사항

현재 구현에는 몇 가지 한계와 제약사항이 있습니다:

  1. 간접 연결 방식: Lambda 함수를 통한 간접 연결 방식은 MCP 서버의 cold start와 같은 추가적인 지연 시간을 발생시킬 수 있으며, 복잡한 상호 작용이 필요한 경우에는 효율이 떨어질 수 있습니다.
  2. 동적 도구 업데이트: MCP 서버의 도구가 변경될 경우, OpenAPI 스키마를 재생성하고 Bedrock Agents를 업데이트해야 하는 수동 과정이 필요합니다.
  3. Lambda Node runtime기반 구동: 현재 Action Group은 Lambda 함수의 Node runtime으로만 구동되어, Node.js 기반의 MCP 서버로 사용이 제한됩니다. 또한 Lambda 실행환경의 특성상 특정 모듈 사용에 제약이 있을 수 있으나, 이는 컨테이너 기반 Lambda 함수를 통해 일부 해결할 수 있습니다.

마치며

이 블로그에서 소개한 Amazon Bedrock Agents와 MCP의 서버리스 통합 방안은 현재 존재하는 제약을 우회하여 두 기술의 장점을 결합한 솔루션을 제시합니다. AWS의 서버리스 기술과 결합된 이 접근 방식은 관리 오버헤드를 최소화하면서도 강력한 AI 애플리케이션을 구축할 수 있는 기반을 제공합니다.

Amazon Bedrock을 포함한 AWS의 다양한 AI/ML 제품은 계속 발전하고 있습니다. 따라서, 이러한 통합 방식도 더욱 세련되고 효율적으로 발전할 것으로 기대됩니다. 개발자와 기업들은 이러한 접근 방식을 통해 더욱 지능적이고 상호작용이 풍부한 사용자 경험을 제공하는 애플리케이션을 만들 수 있을 것입니다.

마지막으로 본 포스트의 모든 소스코드는 https://github.com/aws-samples/kr-tech-blog-sample-code 에서 MIT-0 license하에 제공되며, 해당 프로젝트는 MCP와 Bedrock Agents의 통합을 위한 개념증명(PoC)이므로, 프로덕션 환경에서 활용하기 전에는 개선이 필요합니다.

Junhwan An

Junhwan An

안준환 솔루션즈 아키텍트는 다양한 분야의 애플리케이션 개발과 클라우드 인프라 구축 및 운영 경험을 바탕으로 고객이 AWS의 여러 서비스들을 효율적으로 이용할 수 있도록 도와드리고 있습니다.