A2A Protocol
A2A MCP 통합

Git 저장소:A2A MCP

이 저장소는 a2a-python SDK를 설정하고 사용하여 간단한 서버와 클라이언트를 만들어 a2a 프로토콜을 구현하는 방법을 보여주며, 에이전트 서버는 mcp로 구현됩니다.

개요

  • A2A (Agent-to-Agent): 상호 운용 가능한 AI 에이전트를 구축하기 위한 프로토콜 및 SDK입니다.
  • 이 예제: 기본 A2A 서버와 클라이언트를 실행하고, 메시지를 교환하며, 응답을 확인하는 방법을 보여줍니다.

전제 조건

  • Python 3.13+
  • uv (빠른 종속성 관리 및 실행용)
  • OpenRouter API 키 (OPENROUTER_API_KEY로 설정)

설치

  1. 저장소 복제:

    git clone https://github.com/sing1ee/a2a-mcp-openrouter
    cd https://github.com/sing1ee/a2a-mcp-openrouter
    
  2. 종속성 설치:

    uv venv
    source .venv/bin/activate
    
  3. 환경 변수 설정:

    export OPENROUTER_API_KEY=your-openrouter-api-key
    

    또는 다음 내용으로 .env 파일을 생성하세요:

    OPENROUTER_API_KEY=your-openrouter-api-key
    

    참고: OpenRouter API 키는 https://openrouter.ai/에서 얻을 수 있습니다.

예제 실행

1. 서버 시작

uv run --env-file .env a2a-server
  • 서버는 포트 9999에서 시작됩니다.

에이전트 카드 검증:

2. 클라이언트 실행

새 터미널에서:

uv venv
source .venv/bin/activate
uv run --env-file .env a2a-client --question "A2A 프로토콜이 무엇인가요?"
  • 클라이언트가 서버에 연결하여 요청을 보냅니다.

3. 응답 확인

  • 클라이언트의 응답은 response.xml에 저장됩니다.

구성

시스템은 다음 구성을 사용합니다:

  • 모델: OpenRouter를 통한 google/gemini-flash-1.5
  • 기본 URL: https://openrouter.ai/api/v1

파일 구조

  • src/a2a_mcp_openrouter/server/: 서버 구현.
  • src/a2a_mcp_openrouter/client/: 클라이언트 구현.
  • response.xml: 클라이언트의 예제 응답.

문제 해결

  • 종속성 누락: uv가 설치되어 있는지 확인하세요.
  • API 키 오류: OPENROUTER_API_KEY가 올바르게 설정되어 있는지 확인하세요.
  • 포트 충돌: 포트 9999가 사용 가능한지 확인하세요.

A2A vs MCP: 프로토콜 유사성과 통합 접근법

이 구현을 통해 **A2A (Agent-to-Agent)**와 **MCP (Model Context Protocol)**가 놀라운 아키텍처 유사성을 공유한다는 것을 발견했습니다. 두 프로토콜 모두 발견, 기능 교환 및 실행에 대해 유사한 패턴을 따릅니다.

통합 구현 패턴

핵심 발견: A2A와 MCP 모두 동일한 기본 구현 패턴을 따릅니다:

  • HTTP 기반 통신: 둘 다 통신에 HTTP를 사용합니다 (A2A는 REST API, MCP는 Server-Sent Events 사용)
  • 프롬프트 기반 설계: 둘 다 무엇을 호출할지와 어떻게 호출할지 결정하기 위해 LLM 프롬프트에 의존합니다
  • 발견 메커니즘: 둘 다 사용 가능한 기능을 발견하는 방법을 제공합니다
  • 구조화된 응답: 둘 다 프로그래밍 방식으로 처리할 수 있는 구조화된 데이터를 반환합니다

mcp.py 구현을 보면 다음과 같습니다:

# HTTP를 통한 MCP 도구 발견
async with sse_client(url) as (read, write):
    resources = await session.list_tools()
    
# LLM 의사 결정을 위한 프롬프트 생성
return template.render(tools=resources.tools)

# HTTP를 통한 도구 호출 실행
return await session.call_tool(tool_name, arguments=arguments)

이는 A2A 에이전트 호출 패턴과 개념적으로 동일합니다 - 기능을 발견하고, LLM을 사용하여 무엇을 호출할지 결정한 다음, 호출을 실행합니다.

범용 인터페이스로서의 A2A

핵심 통찰: A2A는 호출 패턴이 본질적으로 동일하기 때문에 에이전트 간 통신과 도구 호출 모두에 대한 통합 인터페이스 역할을 할 수 있습니다:

  1. A2A → 에이전트: 클라이언트 → HTTP → 에이전트 → LLM 응답
  2. A2A → 도구: 클라이언트 → HTTP → 도구 래퍼 → MCP 도구 응답

두 패턴 모두 다음을 사용합니다:

  • HTTP 통신
  • 기능 발견
  • LLM 기반 의사 결정
  • 구조화된 요청/응답 형식

이 통합 접근법의 이점

  • 단일 인터페이스: 클라이언트는 하나의 호출 패턴만 이해하면 됩니다
  • 상호 운용성: 동일한 워크플로에서 에이전트와 도구를 원활하게 혼합할 수 있습니다
  • 일관된 아키텍처: 다양한 기능 유형에 걸쳐 동일한 구현 패턴을 사용합니다
  • LLM 네이티브 설계: 둘 다 지능적인 기능 선택을 위해 LLM 추론을 활용합니다

이는 A2A와 MCP가 경쟁하는 프로토콜이 아니라 단일 인터페이스 패러다임 하에서 통합될 수 있는 상호 보완적인 패턴임을 보여줍니다.

시스템 아키텍처 및 플로우

다음은 클라이언트 입력에서 최종 응답까지 A2A 프로토콜의 완전한 플로우를 보여주는 상세한 시퀀스 다이어그램입니다:

sequenceDiagram
    participant User
    participant Client as A2A Client
    participant LLM_Client as OpenRouter LLM (Client)
    participant Server as A2A Server
    participant AgentExecutor as Agent Executor
    participant Agent as Server Agent
    participant LLM_Server as OpenRouter LLM (Server)
    participant MCP as MCP Tool

    User->>Client: 질문 입력: "A2A 프로토콜이 무엇인가요?"
    
    Note over Client: agent_urls로 에이전트 초기화
    Client->>Server: GET /agent-card - 사용 가능한 에이전트 발견
    Server-->>Client: 기능이 포함된 AgentCard 반환
    
    Note over Client: 에이전트 프롬프트 템플릿 렌더링
    Client->>LLM_Client: 질문과 사용 가능한 에이전트가 포함된 결정 프롬프트 전송
    LLM_Client-->>Client: 선택된 에이전트가 포함된 JSON 반환
    
    loop 선택된 각 에이전트에 대해
        Client->>Server: POST /send-message-streaming
        
        Server->>AgentExecutor: execute(context, event_queue)
        AgentExecutor->>Agent: stream(query)
        
        Agent->>MCP: 사용 가능한 도구 가져오기
        MCP-->>Agent: 도구 정의 반환
        
        Note over Agent: 도구 프롬프트 템플릿 렌더링
        Agent->>LLM_Server: 질문과 도구가 포함된 결정 프롬프트 전송
        LLM_Server-->>Agent: 선택된 도구가 포함된 JSON 반환
        
        loop 선택된 각 도구에 대해 (최대 반복)
            Agent->>MCP: 인수와 함께 도구 호출
            MCP-->>Agent: 도구 결과 반환
            
            Note over Agent: called_tools 히스토리 업데이트
            Agent->>LLM_Server: 도구 결과가 포함된 업데이트된 프롬프트 전송
            LLM_Server-->>Agent: 다음 도구 또는 최종 답변 반환
            
            alt 더 많은 도구가 필요한 경우
                Note over Agent: 다음 반복으로 계속
            else 작업 완료
                Note over Agent: 작업 완료됨
            end
        end
        
        Agent-->>AgentExecutor: 스트리밍 이벤트 생성
        AgentExecutor-->>Server: 이벤트를 event_queue로 전달
        Server-->>Client: HTTP를 통해 응답 청크 스트리밍
        
        Client->>Client: 응답 태그에서 답변 추출
        Note over Client: agent_answers 목록에 추가
    end
    
    alt 최종 합성이 필요한 경우
        Client->>LLM_Client: 모든 답변이 포함된 합성 프롬프트 전송
        LLM_Client-->>Client: 최종 합성된 답변 반환
    else 합성이 필요하지 않은 경우
        Note over Client: 기존 답변 사용
    end
    
    Client-->>User: 에이전트 출력과 함께 최종 응답 스트리밍

주요 기능

  • 에이전트 발견: A2A 프로토콜을 통한 사용 가능한 에이전트의 자동 발견
  • LLM 기반 선택: LLM 추론을 사용한 지능적인 에이전트 및 도구 선택
  • MCP 통합: 지식 검색을 위한 MCP 도구와의 원활한 통합
  • 스트리밍 파이프라인: 전체 파이프라인에 걸친 실시간 스트리밍 응답
  • 반복 처리: 컨텍스트가 유지되는 다중 반복 도구 호출

플로우 설명

시스템은 다음과 같은 주요 단계를 따릅니다:

클라이언트 단계: 사용자 질문 입력 → 클라이언트가 에이전트 발견 → LLM이 관련 에이전트 선택

서버 단계: 서버가 요청 수신 → 에이전트가 도구 발견 → LLM이 도구 선택 → 도구가 반복적으로 실행

응답 단계: 결과가 파이프라인을 통해 스트리밍됨 → 클라이언트가 최종 답변 합성 → 사용자가 응답 수신

이 아키텍처는 서로를 발견하고 협력할 수 있는 상호 운용 가능한 AI 에이전트를 만드는 A2A 프로토콜의 힘을 보여주며, 외부 지식 소스에 액세스하기 위해 MCP 도구를 활용합니다.