Clip 2: 오픈소스 AI AGENT의 mcp 활용 코드 까보기
📋 학습 개요
🎯 학습 목표
- MCP 클라이언트의 3단계 처리 프로세스를 이해하고 설명할 수 있다 
- 도구 정규화와 스키마 변환 메커니즘을 파악할 수 있다 
- LLM 주도 실행 루프의 동작 원리를 분석할 수 있다 
🔍 STEP 1: MCP 클라이언트 3단계 프로세스
MCP 클라이언트는 연결 → 도구 발견 → LLM 실행의 3단계로 동작합니다.
① 연결
MCPClient
서버 설정 로드, Connector 생성, Session 초기화
② 도구 발견
MCPSession
서버의 tools/resources/prompts 목록 요청
③ LLM 실행
MCPAgent
LLM에게 도구 전달, 실행 결과 처리
mcp-use 예시 코드
# 1단계: 연결
client = MCPClient.from_config_file("config.json")
await client.create_all_sessions()  # 모든 서버 연결
# 2단계: 도구 발견 (자동 수행)
session = client.get_session("linear")
tools = session.list_tools()  # MCP tools 목록
# 3단계: LLM 실행
agent = MCPAgent(llm=ChatOpenAI(model="gpt-5"), client=client)
response = await agent.run("linear에서 이슈 생성해줘")🛠️ STEP 2: 도구 정규화와 스키마 변환
도구 이름 정규화
MCP 서버의 도구를 LLM이 사용할 때 충돌을 방지하기 위해 서버명 접두사를 추가합니다.
create_issue
linear__create_issue
mcp-use: server__tool
create_issue
linear/create_issue
Codex: server/tool
스키마 변환 테이블
type: "integer"
type: "number"
integer는 number로 정규화
type 미지정
type: "string"
기본값 string 할당
properties 없음
properties: {}
빈 객체 삽입
중첩 스키마
재귀적 sanitize
sanitize_json_schema() 호출
Codex의 스키마 변환 코드 (Rust)
// codex-rs/core/src/tools/spec.rs
pub(crate) fn mcp_tool_to_openai_tool(
    fully_qualified_name: String,
    tool: mcp_types::Tool,
) -> Result<ResponsesApiTool, serde_json::Error> {
    let mut input_schema = tool.input_schema;
    // OpenAI 필수 필드 처리
    if input_schema.properties.is_none() {
        input_schema.properties = Some(serde_json::Value::Object(Map::new()));
    }
    let mut serialized = serde_json::to_value(input_schema)?;
    sanitize_json_schema(&mut serialized);  // 재귀적 정규화
    Ok(ResponsesApiTool {
        name: fully_qualified_name,
        parameters: serde_json::from_value(serialized)?,
        strict: false,
    })
}🤖 STEP 3: LLM 주도 실행 루프
실행 흐름
사용자 입력 → LLM 판단 → 도구 호출 → 결과 반환 → LLM 판단 (반복)
                ↑                                       ↓
                └────────── 최대 max_steps까지 반복 ──────┘mcp-use의 LangChain 어댑터 구조
# mcp_use/adapters/langchain_adapter.py
class LangChainAdapter:
    async def _arun(self, **kwargs):
        # ① 도구 실행
        result = await self.tool_connector.call_tool(self.name, kwargs)
        # ② 결과를 문자열로 변환 (LLM이 읽을 수 있게)
        return str(result.content)Codex의 병렬 도구 실행
// codex-rs/core/src/tools/registry.rs
pub async fn dispatch(&self, invocation: ToolInvocation)
    -> Result<ResponseInputItem, FunctionCallError> {
    let handler = self.handler(tool_name)?;
    // 병렬 실행 지원 도구는 동시 처리
    if handler.supports_parallel() {
        tokio::spawn(handler.handle(invocation)).await
    } else {
        handler.handle(invocation).await
    }
}💻 STEP 4: 바이브코딩으로 분석하기
프롬프트 1: mcp-use 구조 파악
mcp-use 저장소의 MCPClient, MCPSession, LangChainAdapter 클래스 관계를
클래스 다이어그램으로 보여줘. 주요 메서드만 포함.프롬프트 2: Codex 도구 변환 로직
codex/codex-rs/core/src/tools/spec.rs 파일에서
mcp_tool_to_openai_tool 함수와 sanitize_json_schema 함수의
변환 로직을 테이블로 요약해줘.프롬프트 3: 에러 처리 비교
mcp-use와 Codex의 도구 실행 실패 시 에러 처리 방식을
비교 분석해줘. 코드 예시 포함.✅ 핵심 정리
- 3단계 프로세스: 연결(Client) → 발견(Session) → 실행(Agent) 
- 도구 정규화: - server__tool(mcp-use) 또는- server/tool(Codex) 포맷으로 충돌 방지
- 스키마 변환: MCP 스키마를 OpenAI Function Calling 포맷으로 정규화 (integer→number, 빈 properties 삽입) 
- 실행 루프: LLM이 도구 선택 → 실행 → 결과 평가를 max_steps까지 반복 
- 병렬 처리: Codex는 - supports_parallel_tool_calls플래그로 동시 실행 지원
📖 참고 자료
- mcp-use GitHub: https://github.com/mcp-use/mcp-use 
- Codex GitHub: https://github.com/openai/codex 
강사 정보
- 작성자: 정구봉 
- LinkedIn: https://www.linkedin.com/in/gb-jeong/ 
- 이메일: bong@dio.so 
강의 자료
- 강의 자료: https://goobong.gitbook.io/fastcampus 
- Github: https://github.com/Koomook/fastcampus-ai-agent-vibecoding 
- FastCampus 강의 주소: https://fastcampus.co.kr/biz_online_vibeagent 
Last updated