반응형

잡담.

MCP 서버를 내가 외부에 제공한다고 했을 때, 여러 방법이 있을 것 같다.

가장 먼저 생각나는 건 서버 코드를 공유하고 stdio 실행 방식으로 제공하는 방식, 그리고 또 다른 방법은 웹서버를 띄워 StreamableHTTP 방식으로 제공하는 것이다.

MCP 서버를 직접 운영하면서 오픈한다는 의미는 인증과 인가를 붙이겠다는 의미일 것 같다.

AWS Lambda 환경에서 MCP 서버를 배포할 경우 아래의 장점이 있다.
- 인프라 관리가 불필요하여, 서버 운영 부담이 없다.
- 사용한 만큼 비용이 지불되기 때문에 비용 효율성이 높다.
- 자동으로 스케일링이 되기 때문에 트래픽에 따라 h/w 자원을 동적으로 변경할 수 있다.
- 보안 및 권한 관리가 쉽고, 도메인 주소관리, SSL 관리 등의 네트워크 리소스 운영 작업이 편하다.

단점도 있다.
- 최대 실행시간과 메모리 제한이 있고, 로깅과 제어가 제한적이다.

이 포스팅의 목적은 비교적 최근에 나온 MCP 서버를 AWS Lambda 환경에서 MCP 배포가 가능할지 확인해보기 위함이다.


그럼 시작해보자.

 

 


AWS Lambda 에서 MCP 서버 구축 해보기

A) 사전 준비

  • fastMCP 로 구현한 mcp server 코드
  • 컨테이너 이미지 로 생성할 Dockerfile 코드
  • requirements.txt 패키지 설치 파일

B) 시나리오 

1. teams webhook 을 이용해 message 를 발송하는 MCP 서버 구축
2. mcp 서버를 컨테이너 이미지로 생성하고, ECR 레포지토리에 업로드
3. aws lambda 를 생성하고 ecr 에 업로드 된 이미지를 이용하여 배포 
4. 아래 두 가지 방식으로 MCP Server 테스트를 한다.

  a. Lambda 의 FunctionURL 을 이용해 MCP Client 로 연결하여 Teams 채널로 메세지를 전송해본다.
(LLM 모델은 로컬에서 테스트를 위해 Ollama 모델을 활용)
  b. cursor 의 MCP tool 로 등록해서 Teams 채널로 메세지를 전송해본다.

 

C) Step by Step

MCP 서버 코드 

from fastmcp import FastMCP
import os
import requests
import json
from typing import Optional, Dict, Any
WEBHOOK_URL = "웹훅 주소"
mcp = FastMCP("MCP-TEST-SERVER")

@mcp.tool()
async def get_my_info() -> str:
    """ 안녕하세요. 저는 러닝을 좋아하는 jssvs 입니다."""
    return f""

@mcp.tool()
async def get_weather() -> str:
    """현재 날씨를 조회합니다"""
    return f"오늘 날씨는 맑습니다."


@mcp.tool()
def send_teams_message(
    message: str,
    title: str = None,
) -> bool:
    """
    Microsoft Teams 채널에 webhook을 통해 메시지를 전송합니다.
    
    Args:
        message (str): 전송할 메시지 내용
        title (str, optional): 메시지 제목
    Returns:
        bool: 전송 성공 여부
    Example:
        send_teams_message(message="안녕하세요!", title="알림")
    """
    color = "00FF00"
    # MessageCard 형식으로 페이로드 구성
    payload = {
        "@type": "MessageCard",
        "@context": "https://schema.org/extensions",
        "summary": title or "알림",
        "sections": [{
            "activityTitle": title,
            "text": message
        }]
    }
    
    # 색상이 지정된 경우 추가
    if color:
        payload["themeColor"] = color
    
    # 제목이 없는 경우 섹션에서 제거
    if not title:
        del payload["sections"][0]["activityTitle"]
    
    try:
        response = requests.post(
            WEBHOOK_URL,
            headers={"Content-Type": "application/json"},
            data=json.dumps(payload)
        )
        
        # 성공 여부 확인
        if response.status_code == 200:
            print(f"✓ 메시지 전송 성공")
            return True
        else:
            print(f"✗ 메시지 전송 실패: {response.status_code}")
            print(f"응답: {response.text}")
            return False
            
    except Exception as e:
        print(f"✗ 오류 발생: {str(e)}")
        return False

def main():
    host = os.environ.get("HOST","0.0.0.0")
    port = int(os.environ.get("PORT",8080))
    print(f"Starting FastMCP HTTP Server on {host}:{port}")
    print("Available tools:")
    print("- get_bdp_team_info: Returns BDP team information")
    print("- get_weather: Returns weather information")
    print(f"Server accessible at: http://{host}:{port}")
    mcp.run(transport="http",host=host, port=port, stateless_http=True)

if __name__ == "__main__":
    main()

requirements.txt

fastmcp>=0.1.0
requests

 

Dockerfile

FROM python:3.12-slim
WORKDIR /app

# ### Environment Variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1


# Install the specified packages
COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt

# MCP 서버 코드 복사
COPY mcp_server.py .

# 환경 변수 설정
ENV PORT=8080
ENV AWS_LWA_INVOKE_MODE=response_stream
ENV AWS_LWA_READINESS_CHECK_PORT=8080
ENV AWS_LWA_READINESS_CHECK_PATH=/health

# === Lambda Web Adapter ===
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.7.0 /lambda-adapter /opt/extensions/lambda-adapter

# 서버 시작 명령어
CMD ["python", "mcp_server.py"]

 

D) 참고해야 할 부분 !

1) Lambda 설정 시 참고 
-> 환경변수에 2개의 값 추가 (Dockerfile 에 ENV 에 추가해줬다면 생략해도 된다.)

2) 기본 TImeout 값으로는 MCP tool 호출이 되기 전에 호출이 종료되기 때문에 값을 조정한다.

 

 

 

E) 테스트 해보기

 

 

A) Strands Agent 코드를 작성하여 테스트 발송

from strands import Agent
from strands.models.ollama import OllamaModel
from strands.tools.mcp.mcp_client import MCPClient
from mcp.client.streamable_http import streamablehttp_client


client = MCPClient(
    lambda: streamablehttp_client(
        # url = "http://127.0.0.1:8080/mcp"
        url = "https://LambdaFunctinURL 주소.lambda-url.ap-northeast-2.on.aws/mcp"
    )
)
with client:
    tools = client.list_tools_sync()
    
    base_model = OllamaModel(
        host = "http://localhost:11434",
        model_id = "llama3.1:8b",
        temperature = 0.1
        )
    agent = Agent(tools = tools, model = base_model)
    # print(agent.tool.get_weather())
    result = agent("teams 채널에 아래 메세지를 전송해줘 \n message : Lambda 에서 구축한 MCP 서버 테스트 \n title : MCP 서버 테스트")
    print(result)

 

 

 

B) Cursor MCP 툴 연동하여 테스트 발송

 

 

결론

  • lambda 의 장점은 서버리스, 즉 물리 서버를 운용하지 않으면서 서비스를 배포하는데 있다. 그렇다면 MCP 서버 역시 이런 장점을 누릴 수 있다.
  • 내가 테스트한 부분은 운영 버전용으로 활용할 수 는 없다. 운영 버전까지 고려할 때는 보안을 위해 VPC 안에서 배포를 한다던지, 앞단에 Gateway 의 셋팅, 동시성 테스트 등 다양한 준비가 필요하다.
  • 그리고 Dockerfile 을 보면 알겠지만, lambda web adapter 를 멀티스테이지 빌드를 사용하여 로드한 부분이 있는데, lambda 의 extension 기능으로 붙인 것이다. 즉 기능 추가, 의존성 등의 확장에 있어 제한이 있을 수 있음을 의미한다.

참고

[1] Welcome to FastMCP 2.0 - https://gofastmcp.com/getting-started/welcome 
[2] GitHub - awslabs/aws-lambda-web-adapter - https://github.com/awslabs/aws-lambda-web-adapter 
[3] Deploy MCP Server on AWS Lambda | Step-by-Step Guide - https://www.youtube.com/watch?v=JncV8hXuyRg&t=341s 
[4] 컨테이너 이미지로 Python Lambda 함수 배포 - Python용 AWS 기본 이미지 사용 - https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-image.html#python-image-instructions

반응형
반응형

 

최근 Cursor 업데이트로 PLAN 모드가 쓸만 한 것 같아, 소개하면서 룰과 메모리 뱅크에 대해서 비교한 내용을 포스팅 한다

 

커서의 룰과 메모리뱅크는 왜쓸까?

 

바로 일관된 규칙과 지시사항을 준수하게 하기 위해 사용한다.

 

cursor 에도 기본적으로 제공하는 .rule이라는 이름의 기능이 있지만, 별도의 써드파티 설치로 memory bank 를 활용하기도 하는데, 이 둘의 용도가 약간 햇갈린다.

1-1.Plan 모드 (신규 기능)

  • 코딩 작업 실행 전 사용자 요구사항을 확장하여 전략적 사고와 계획을 수립한다.
  • 큰 목적에 따라 작업을 분해하고, 계획을 세우며, 순차적 실행을 하기 위한 총 전략 파일을 markdown 포맷으로 생성한다.
  • 중간에 사용자와 interactive 하게 세부 계획에 대한 질문을 던져 수정하기도 한다.

1-2.Memroy bank 기능

  • 프로젝트 전반에 걸쳐 지속적으로 사용할 컨텍스트와 지식을 파일에 저장하여 관리한다.
  • cursor 에 내장된 기능인 rule 과 유사하지만, 룰은 단순 텍스트기반이지만 , memory bank 는 조금 더 구조화된 데이터를 갖는다
  • CLI 도구를 통해 컨텍스트와 프로그램 정보를 현행화한다.
  • 차이 점 비교 

구분기본 RulesMemory Bank

구분 Cursor Rules Memroy BAnk
관리 방식 수동 편집 CLI 도구
구조 단순 텍스트 구조화된 데이터
업데이트 파일 직접 수정 명령어로 관리
조직화 개발자가 직접 자동 카테고리화
학습 정적 AI 기반 학습 가능
검색 직접 찾기 검색 기능 제공

2. 2개의 기능 요약

기능주요 목적작동 방식 및 특징

Plan Mode (계획 모드) 코딩 작업 실행 전에 깊이 있는 전략적 사고와 계획 수립을 지원 - AI가 코드베이스를 분석하고, 관련 파일, 종속성, 문서를 연구하여 컨텍스트를 빠르게 파악
    - 실행 전에 명확한 질문을 던져 요구 사항을 정교화
    - 수립된 계획은 Markdown 파일로 저장되며, 파일 경로 및 코드 참조가 포함되어 수정 및 공유가 용이
    - 대규모 작업 시 코딩 전에 계획을 수립하도록 유도하여 버그를 줄이고 구조를 개선
Memory Bank
(npx cursor-bank)
AI가 세션 간에 프로젝트 컨텍스트를 유지하고 지속적인 기억을 갖도록 함. (Cursor의 기본 AI는 매 세션 컨텍스트가 초기화됨) - 구조화된 문서 파일 (예: [projectbrief.md](http://projectbrief.md), [activeContext.md](http://activeContext.md), [systemPatterns.md](http://systemPatterns.md) 등)을 생성하고 유지하여 장기 기억 역할 수행
    - AI는 새로운 세션이 시작될 때 이 문서들을 참조하여 프로젝트 이해도를 재구축
    - 커뮤니티에서 개발된 프로젝트이며, npx cursor-bank init과 같은 명령어로 설정
    - PLAN, ACT, update memory bank와 같은 커맨드를 통해 구조화된 워크플로우를 촉진

3. 결론

  • memory bank 는 숙지 하고 잘 쓰면, 서로의 컨텍스트를 공유하며 일관된 바이브 코딩의 결과를 기대할 수 있을 것 같지만, 사용하기 전에 CLI 를 숙지해야 하고 학습이 필요하고 , 프로젝트의 규모가 클 경우에 유리해 보인다.

끝.

반응형

+ Recent posts