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 생태계를 활용하고 싶을 때
⚠️
다른 방법을 고려할 때:
- 단순한 일회성 통합
- 프로토타이핑 (직접 함수 호출이 더 빠름)
- 고도로 특수화된 독점 도구
참고 자료 & 추가 학습
관련 개념
- Google A2A 프로토콜: Agent-to-Agent Communication (opens in a new tab)
- LangChain Tool Calling: LangChain 문서 (opens in a new tab)
- OpenAI Function Calling: OpenAI 문서 (opens in a new tab)
학술 논문
-
"Toolformer: Language Models Can Teach Themselves to Use Tools" - Schick et al., 2023
- arXiv:2302.04761 (opens in a new tab)
- 도구 사용 LLM의 기초
-
"Gorilla: Large Language Model Connected with Massive APIs" - Patil et al., 2023
- arXiv:2305.15334 (opens in a new tab)
- API 인식 LLM 학습
다음 단계
MCP와 A2A를 이해했으니, CrewAI로 이동하여 프레임워크가 이러한 패턴을 어떻게 추상화하여 빠른 멀티 에이전트 개발을 가능하게 하는지 확인하세요!