한국어
Week 3: 멀티 에이전트
02. MCP & A2A

04. Model Context Protocol (MCP) & A2A

개요

이번 세션에서는 LLM을 외부 데이터 소스 및 도구에 연결하는 범용 표준인 **MCP (Model Context Protocol)**와 A2A (Agent-to-Agent) 통신 패턴을 살펴봅니다.

문제: 도구 통합의 파편화

MCP 이전에는 모든 AI 애플리케이션이 커스텀 통합을 직접 구축해야 했습니다:

문제점:

  • 모든 LLM마다 별도의 통합 코드 필요
  • N개 LLM × M개 도구 = N×M개의 통합
  • 일관성 없는 구현
  • 유지보수 악몽

MCP란?

**Model Context Protocol (MCP)**은 Anthropic이 개발한 오픈 표준으로, LLM이 외부 시스템과 연결하는 범용적인 방법을 제공합니다.

장점:

  • 한 번 작성하면 어디서나 사용
  • 표준화된 인터페이스
  • 사전 구축된 커넥터 생태계
  • 보안 및 접근 제어 내장

MCP 핵심 프리미티브

프리미티브설명예시
Resources서버가 노출하는 데이터파일, 데이터베이스 레코드, 로그
Prompts사전 정의된 템플릿"이 문서를 요약해줘"
Tools실행 가능한 함수get_user(), send_message()

MCP 아키텍처

Mock MCP 서버 구축하기

class MockMCPServer:
    def __init__(self, name: str):
        self.name = name
        self.users = {
            "user_1": {"name": "Alice", "email": "alice@example.com"},
            "user_2": {"name": "Bob", "email": "bob@example.com"}
        }
 
    def list_tools(self) -> List[Dict]:
        """탐색: 이 서버가 무엇을 할 수 있는가?"""
        return [
            {
                "name": "get_user_info",
                "description": "ID로 사용자 정보 조회",
                "input_schema": {
                    "type": "object",
                    "properties": {"user_id": {"type": "string"}},
                    "required": ["user_id"]
                }
            }
        ]
 
    def call_tool(self, tool_name: str, arguments: Dict) -> str:
        """도구 실행 및 결과 반환"""
        if tool_name == "get_user_info":
            user = self.users.get(arguments["user_id"])
            return json.dumps(user) if user else "User not found"

MCP 클라이언트 (에이전트) 구축하기

class MCPClient:
    def __init__(self, server: MockMCPServer):
        self.server = server
 
    def run(self, query: str):
        # 1. 탐색 단계
        tools = self.server.list_tools()
 
        # 2. OpenAI 형식으로 변환
        openai_tools = [{
            "type": "function",
            "function": {
                "name": t["name"],
                "description": t["description"],
                "parameters": t["input_schema"]
            }
        } for t in tools]
 
        # 3. LLM이 결정하고 실행
        # ... (도구 호출 에이전트 루프)

A2A: 에이전트 간 통신

클라이언트가 서버와 통신하는 것처럼, 에이전트도 서로 통신할 수 있습니다. Agent A가 ask_me 도구를 노출하면, Agent B가 이를 사용할 수 있습니다.

A2A 구현 패턴

class ResearchAgent:
    """자신을 도구로 노출하는 에이전트"""
 
    def as_tool(self) -> Dict:
        return {
            "name": "ask_researcher",
            "description": "리서치 에이전트에게 정보 검색 요청",
            "input_schema": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"}
                }
            }
        }
 
    def invoke(self, query: str) -> str:
        # 이 에이전트가 자체 리서치 수행
        return self._search_and_summarize(query)
 
# 매니저가 이제 ResearchAgent를 도구로 사용 가능!
manager_tools = [research_agent.as_tool()]

실제 MCP 서버들

예시: Claude Desktop에서 MCP 사용하기

// claude_desktop_config.json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"
      }
    }
  }
}

실습 내용

노트북에서 다음을 수행합니다:

Mock MCP 서버 구축

사용자 데이터를 도구로 노출하는 서버 생성

탐색 구현

클라이언트가 사용 가능한 도구를 동적으로 탐색

에이전트 루프 구축

OpenAI 함수 호출을 사용해 LLM을 서버에 연결

A2A 실험

다른 에이전트를 도구로 사용하는 에이전트 생성

MCP vs 직접 도구 통합

측면직접 통합MCP
재사용성앱별범용
탐색하드코딩동적
보안임시방편내장 스코프
생태계DIY성장하는 라이브러리
유지보수앱마다 개별중앙 집중

MCP 사용 시점

MCP를 사용해야 할 때:

  • 여러 LLM 제공자에서 도구가 작동해야 할 때
  • 표준 인터페이스가 필요한 프로덕션 시스템 구축 시
  • MCP 생태계를 활용하고 싶을 때
⚠️

다른 방법을 고려할 때:

  • 단순한 일회성 통합
  • 프로토타이핑 (직접 함수 호출이 더 빠름)
  • 고도로 특수화된 독점 도구

참고 자료 & 추가 학습

관련 개념

학술 논문

다음 단계

MCP와 A2A를 이해했으니, CrewAI로 이동하여 프레임워크가 이러한 패턴을 어떻게 추상화하여 빠른 멀티 에이전트 개발을 가능하게 하는지 확인하세요!