레이블이 MCP인 게시물을 표시합니다. 모든 게시물 표시
레이블이 MCP인 게시물을 표시합니다. 모든 게시물 표시

2026/07/07

MCP 대 API: 기존 API가 AI 에이전트 구축에 한계를 보이는 이유

MCP 대 API: 기존 API가 AI 에이전트 구축에 한계를 보이는 이유

Google Cloud Tech의 영상을 기반으로, 왜 전통적인 API로는 AI 에이전트를 제대로 구축할 수 없는지, 그리고 MCP(Model Context Protocol)가 그 해답이 되는지를 정리해 봅니다.


"API면 충분하지 않나요?" — 가장 자연스러운 질문

AI 개발을 해오던 분이라면 MCP(Model Context Protocol)라는 새로운 표준이 등장했을 때 이런 생각을 해보셨을 겁니다.

"관심은 가는데, 왜 기존에 쓰던 API로는 안 되는 거지?"

표면적으로 보면 합리적인 질문입니다. LLM에 OpenAPI 스펙을 주고 적절한 요청을 하도록 하면 되지 않나요?

문제는 이 접근 방식이 현실에서 심각한 장애물에 부딪힌다는 점입니다. 인간 개발자를 위해 설계된 인터페이스AI 에이전트가 추론에 필요한 프로토콜은 근본적으로 다릅니다.

핵심은 이겁니다: 전통적인 API는 개발자를 위한 명령서입니다. MCP는 AI 에이전트를 위한 언어입니다.


기존 API가 AI 에이전트에 부족한 3가지 이유

1. "선택의 역설"이 성능을 망친다

에이전트에 더 많은 도구를 주면 더 똑똑해질 것이라고 생각하기 쉽습니다. 하지만 정반대입니다. 도구만 많아질 뿐, 에이전트는 더 혼란스러워집니다.

엔터프라이즈 API는 쉽게 75~100개 엔드포인트를 가집니다. LLM은 긴 목록에서 올바른 옵션을 고르는 데 놀랍도록 약합니다. 선택지가 너무 많으면:

  • 응답 속도가 느려짐
  • 유사한 도구 간 구별에 실패
  • 잘못된 도구를 선택하거나 아예 동작하지 않음

결국 개발자가 수동으로 작은 도구 목록만 골라줘야 하는데, 이는 풍부한 API를 가진다는 의미를 무색하게 만듭니다.

2. 수동 번역의 부담

API 문서는 인간 개발자를 위해 작성됩니다. 맥락을 추론하고 구글에서 찾아보는 것이 가능합니다. AI 에이전트는 그런 일을 할 수 없습니다.

결과적으로 개발자는 풀타임 번역가가 됩니다:

  • 각 도구마다 래퍼를 작성
  • 목적, 파라미터, 출력을 상세히 기술
  • API가 바뀔 때마다 깨지는 fragile한 시스템

3. 에이전트는 맹목적으로 비행한다

에이전트가 API에게 "새로운 기능이 뭐가 있어요?" 또는 "제게 뭘 해줄 수 있나요?"라고 물을 수 없습니다. 하드코딩된 도구만 알 뿐입니다. 새로운 기능을 활용하거나 적응할 수 없으므로, 에이전트의 자율성과 유용성이 근본적으로 제한됩니다.


MCP는 어떻게 이 문제들을 해결하는가

MCP는 단순히 다른 API가 아닙니다. 에이전트가 "생각"하는 방식에 맞춰 설계된 완전히 다른 접근법입니다.

1. 복잡성을 추상화해 더 나은 추론을 가능하게 함

MCP의 가장 큰 강점입니다. 100개의 저수준 도구를 LLM에 과부하로 주기 대신, 소수의 고수준 기능을 제공합니다.

예를 들어 createUser, updateUserAddress, resetUserPassword 같은 개별 도구를 주기 대신, 하나의 manageUserProfile 기능을 제공합니다. 에이전트는 이 하나를 호출하면 되고, MCP 서버가 내부 로직을 처리합니다.

또 다른 예: LLM은 복잡한 SQL 작성이 약점입니다. 단일 run_sql 도구를 주기 대신, MCP는 여러 단계의 database_migration 기능을 제공할 수 있습니다 — 먼저 테스트 브랜치에 SQL을 스테이징하고, LLM이 검증하도록 요청한 후 최종 커밋합니다. 에이전트의 추론 수준에 맞춰 성공으로 이끄는 것입니다.

2. 동적 발견을 가능하게 함

에이전트가 실행 시점에 MCP 서버에 연결하여 "무엇을 할 수 있나요?"라고 물을 수 있습니다. 즉석에서 사용 가능한 기능을 학습합니다. 에이전트 코드를 재배포하지 않고도 새로운 도구를 추가할 수 있으므로, 전체 시스템이 훨씬 더 적응 가능해집니다.

3. 통신을 표준화함

"AI용 USB-C 포트" 비유처럼, MCP는 에이전트-도구 간 통신의 보편적 프로토콜을 만듭니다. 각 서비스마다 커스텀 래퍼를 작성할 필요가 줄어더므로, 더 견고하고 확장 가능한 생태계가 형성됩니다.


보안 질문: 이 에이전트는 대체 누구인가?

이 새로운 아키텍처는 새로운 보안 질문을 부각시킵니다. 에이전트가 스스로 도구를 발견하고 사용할 수 있게 되면 다음과 같은 질문에 답할 수 있어야 합니다:

  • 에이전트가 특정 사용자를 위해 진정한 권한으로 행동하는지 어떻게 보장할까?
  • 에이전트가 허용된 도구만, 서비스하는 사용자를 위해 사용할 수 있도록 세분화된 권한을 어떻게 강제할까?

이는 이론적 질문이 아닙니다. AI 보안의 다음 현실적 과제입니다. 해결을 위해서는 OAuth 2.0과 같은 검증된 패턴으로 토크 위임을 통해 에이전트에 구체적이고 제한된 권한을 부여하고, 사용자의 신원을 대화의 전체 라이프사이클에 안전하게 묶어야 합니다.


MCP는 AI 에이전트를 위한 올바른 인터페이스

궁극적으로 MCP는 기존 API를 대체하는 것이 아닙니다. 새로운 소비자 — AI 에이전트 — 를 위해 설계된 필수적인 추상화 레이어입니다.

효과적인 MCP 서버 구축은 OpenAPI 스펙을 한 번 클릭으로 변환하는 것 이상이 필요합니다. 등장 중인 모범 사례는 하이브리드 접근법입니다:

  1. 기존 스펙에서 시작
  2. LLM을 압도하지 않도록 도구셋을 적극적으로 정리
  3. 저수준 엔드포인트를 고수준 작업 지향 기능으로 추상화
  4. 에이전트가 신뢰성 있게 작동하도록 지속적인 평가

이러한 신중한 설계가 자율적 AI 애플리케이션의 진정한 잠재력을 해방하는 열쇠입니다.


요약

MCP는 AI 에이전트 시대의 새로운 인터페이스 표준입니다. 기존 API를 버리는 게 아니라, AI가 이해할 수 있는 언어로 번역하는 층을 추가하는 것입니다.


출처: Google Cloud Tech — "MCP 대 API: 기존 API가 AI 에이전트 구축에 한계를 보이는 이유" (영상 링크) / Auth0 Blog — "Why Can't I Just Use an API? Because Your AI Agent Needs MCP" (링크) / MCP 공식 문서

2026/06/13

LLM 에 MCP 를 연동하는 방법 — 날짜 서버로 배우는 Model Context Protocol

LLM(대형 언어 모델) 은 기본적으로 텍스트를 받아 텍스트를 내뱉는 시스템입니다. 하지만 외부 데이터에 접근하거나, 실시간 정보를 얻거나, 파일 시스템을 조작하려면 도구(Tool)가 필요합니다. MCP(Model Context Protocol) 는 LLM 이 외부 도구와 안전하게 통신할 수 있게 하는 표준 프로토콜입니다.

이 글에서는 "오늘 날짜를 알려주는 MCP 서버"를 예로 들어, MCP 서버를 직접 코딩하고, 설정하고, LLM 이 이를 호출하는 전체 과정을 단계별로 설명합니다.


1. MCP(Model Context Protocol) 란?

MCP 는 Anthropic 이 제안한 개방형 프로토콜로, LLM 애플리케이션과 외부 데이터 소스·도구들을 연결하는 표준 인터페이스입니다. USB 포트가 다양한 주변기기를 연결하듯, MCP 는 어떤 LLM 이든 어떤 MCP 서버든 연결할 수 있게 합니다.

MCP 가 없으면 각 LLM 플랫폼마다 전용 플러그인을 만들어야 합니다. MCP 가 있으면 한 번 만든 서버가 Claude, Cursor, Hermes Agent 등 모든 LLM 플랫폼에서 바로 동작합니다.

MCP 의 핵심 구성 요소

  • MCP Host: LLM 을 실행하는 애플리케이션 (예: Hermes Agent, Claude Desktop, Cursor)
  • MCP Server: 외부 도구나 데이터를 제공하는 서버 (예: 오늘 날짜를 반환하는 서버)
  • Transport: 호스트와 서버 간 통신 방식 (stdio, HTTP/SSE)
  • Tools: 서버가 호스트에 제공하는 기능 목록 (예: get_today)

MCP 가 해결하는 문제

  • 재사용: 한 번 작성한 MCP 서버가 모든 LLM 플랫폼에서 동작
  • 보안: LLM 은 MCP 서버를 통해만 외부에 접근 — 직접 네트워크/파일시스템 접근 불가
  • 표준화: JSON-RPC 기반의 통일된 프로토콜 — 각 플랫폼별 커스텀 플러그인 불필요

2. MCP 서버 코드 작성하기 — 날짜 서버 만들기

먼저 Python 으로 "오늘 날짜를 알려주는" MCP 서버를 직접 만들어보겠습니다. mcp Python 패키지를 사용하면 몇 줄로도 서버를 만들 수 있습니다.

2-1. 환경 준비

먼저 MCP SDK 를 설치합니다.

pip install mcp

2-2. 날짜 서버 전체 코드

#!/usr/bin/env python3
"""
today_mcp_server.py — 오늘 날짜를 알려주는 MCP 서버

사용법:
  python today_mcp_server.py        # stdio 모드로 실행
  python today_mcp_server.py --http  # HTTP 모드로 실행 (포트 8090)
"""

import argparse
from datetime import datetime
from zoneinfo import ZoneInfo
from mcp.server import Server

app = Server("today-server")

# ── 비즈니스 로직 ──────────────────────────────────────────
def get_today(timezone: str = "Asia/Seoul") -> dict:
    """지정된 시간대의 현재 날짜와 시간을 반환합니다."""
    try:
        tz = ZoneInfo(timezone)
        now = datetime.now(tz)
        weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday",
                    "Friday", "Saturday", "Sunday"]
        return {
            "datetime": now.strftime("%Y-%m-%d %H:%M:%S"),
            "timezone": timezone,
            "weekday": weekdays[now.weekday()],
            "date_only": now.strftime("%Y-%m-%d"),
            "time_only": now.strftime("%H:%M:%S")
        }
    except Exception as e:
        return {"error": str(e)}

def get_formatted_date(format_str: str, timezone: str = "Asia/Seoul") -> str:
    """strftime 포맷으로 날짜를 반환합니다."""
    try:
        tz = ZoneInfo(timezone)
        now = datetime.now(tz)
        return now.strftime(format_str)
    except Exception as e:
        return f"Error: {e}"

# ── MCP 서버 ───────────────────────────────────────────────
@app.tool()
def get_today_tool(timezone: str = "Asia/Seoul") -> dict:
    """현재 날짜와 시간을 반환합니다.

    Args:
        timezone: 시간대 (기본값: Asia/Seoul)
                 예: America/New_York, Europe/London, UTC

    Returns:
        날짜, 시간, 요일, 시간대 정보
    """
    return get_today(timezone)

@app.tool()
def get_formatted_date_tool(format_str: str, timezone: str = "Asia/Seoul") -> str:
    """지정된 포맷으로 날짜를 반환합니다.

    Args:
        format_str: strftime 포맷 (예: "%Y년 %m월 %d일")
        timezone: 시간대 (기본값: Asia/Seoul)

    Returns:
        포맷팅된 날짜 문자열
    """
    return get_formatted_date(format_str, timezone)

# ── 실행 ───────────────────────────────────────────────────
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Today MCP Server")
    parser.add_argument("--http", action="store_true", help="Run in HTTP mode")
    args = parser.parse_args()

    if args.http:
        from mcp.server.http import run_server_as_async_http_app
        import http.server
        import threading

        # Simple HTTP server for testing
        from wsgiref.simple_server import make_server
        from mcp.server.http import run_server_as_async_http_app

        async def main():
            app_instance = run_server_as_async_http_app(app)
            httpd = make_server("localhost", 8090, app_instance)
            print("MCP HTTP Server running on http://localhost:8090")
            httpd.serve_forever()

        import asyncio
        asyncio.run(main())
    else:
        from mcp.server.stdio import stdio_server
        import asyncio

        async def main():
            async with stdio_server() as (read, write):
                await app.run(read, write)

        asyncio.run(main())

코드 설명

이 코드는 크게 두 부분으로 나뉩니다.

1) 비즈니스 로직 (상단)

  • get_today(): 지정된 시간대의 현재 날짜/시간을 반환
  • get_formatted_date(): strftime 포맷으로 사용자 정의 날짜 형식 반환
  • 에러 처리: 잘못된 시간대 이름도 try/except 로 안전하게 처리

2) MCP 서버 (하단)

  • @app.tool(): 함수를 MCP 도구로 등록 — LLM 이 호출할 수 있음
  • stdio 모드: 기본 방식. 호스트가 서버를 자 프로세스로 실행하고 stdin/stdout 으로 통신
  • HTTP 모드: 서버를 별도 HTTP 엔드포인트로 실행 — 원격 호스트에서 연결 가능

테스트 해보기

이렇게 하면 서버를 거치지 않고 함수가 정상 동작하는지 확인할 수 있습니다.

# 서버를 거치지 않고 직접 테스트
from today_mcp_server import get_today, get_formatted_date

print(get_today())
# {"datetime": "2025-06-13 14:30:00", "timezone": "Asia/Seoul", ...}

print(get_formatted_date("%Y년 %m월 %d일 (%A)"))
# 2025년 06월 13일 (Friday)

3. MCP 서버 설정하기

서버 코드를 만들었다면, 이제 LLM 애플리케이션에 연결해야 합니다. Hermes Agent 를 예로 들어 설명합니다.

3-1. config.yaml 에 등록

~/.hermes/config.yaml 파일에 mcp_servers 섹션을 추가합니다.

mcp_servers:
  today:
    command: python
    args:
      - ~/Developer/scripts/today_mcp_server.py

여기서 today 는 서버 이름입니다. 이 이름이 도구 이름 앞에 붙습니다:

  • 서버의 get_today 도구 → today.get_today(로 인식됨)
  • 서버의 get_formatted_date 도구 → today.get_formatted_date(로 인식됨)

3-2. 설정 옵션 전체

mcp_servers:
  today:
    command: python                    # 실행할 명령어
    args:                              # 명령어 인수
      - ~/Developer/scripts/today_mcp_server.py
    env:                               # 환경 변수 (선택)
      API_KEY: "sk-xxx"
    timeout: 30                        # 연결 타임아웃 (초)
    disabled: false                    # 서버 비활성화

3-3. HTTP 방식 서버도 지원

stdio 대신 HTTP 로 통신하는 원격 MCP 서버도 연결할 수 있습니다.

mcp_servers:
  remote-server:
    url: http://your-server.com/mcp    # HTTP 엔드포인트

3-4. Hermes Agent 재시작

설정을 추가한 후 Hermes Agent 를 재시작하면:

  • 자동 감지: config.yaml 의 mcp_servers 를 읽어 MCP 서버 프로세스를 시작
  • 도구 등록: 서버가 제공하는 도구 목록(LLM 이 볼 수 있는 설명 포함)을 가져옴
  • 즉시 사용: 사용자가 대화를 시작하면 LLM 이 MCP 도구들을 사용할 수 있음
  • 에러 피드백: 서버가 시작 실패하면 Hermes Agent 가 콘솔에 에러를 출력
  • 핫 리로드: 서버 코드를 수정하면 다음 Agent 세션에서 자동으로 반영

4. LLM 이 MCP 를 호출하는 전 과정

이제 가장 중요한 부분입니다. 사용자가 "오늘 날짜 알려줘"라고 입력했을 때, 내부에서 어떤 일이 일어나는지 단계별로 추적해보겠습니다.

단계 1: 사용자 입력

메시지가 LLM 애플리케이션(Hermes Agent) 에 전달됩니다.

"오늘 날짜 알려줘"

단계 2: LLM 이 도구 사용 여부를 판단

LLM 은 다음 정보를 함께 받습니다:

  • 사용자의 질문
  • 등록된 MCP 도구 목록 (이름 + 설명 + 파라미터)
  • 시스템 프롬프트 (도구 사용 가이드라인)

단계 3: LLM 이 도구 호출을 결정

LLM 은 "오늘 날짜"라는 키워드를 보고 get_today 도구를 사용해야 한다고 판단합니다.

Tool: today.get_today
Description: 현재 날짜와 시간을 반환합니다.
Parameters:
  - timezone: 시간대 (기본값: Asia/Seoul)

단계 4: Hermes Agent 가 MCP 서버에 요청 전달

LLM 이 도구 호출을 결정하면, Hermes Agent 가 실제 MCP 서버에 요청을 보냅니다. JSON-RPC 2.0 프로토콜을 사용합니다.

Tool Call:
  tool_name: today.get_today
  arguments: {"timezone": "Asia/Seoul"}

이 요청은 MCP 서버 프로세스의 stdin 으로 전달됩니다.

실제 JSON-RPC 메시지는 다음과 같습니다:

// Hermes Agent → MCP Server
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_today",
    "arguments": {"timezone": "Asia/Seoul"}
  }
}

// MCP Server → Hermes Agent
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [{
      "type": "text",
      "text": "{"datetime": "2025-06-13 14:30:00", "timezone": "Asia/Seoul", "weekday": "Friday", ...}"
    }],
    "isError": false
  }
}

단계 5: 결과 LLM 에 전달

MCP 서버의 응답을 LLM 에 다시 전달합니다.

Tool Result (today.get_today):
현재 시간: 2025-06-13 14:30:00
시간대: Asia/Seoul
요일: Friday

단계 6: LLM 이 최종 답변 생성

LLM 은 도구 결과를 바탕으로 자연스러운 답변을 생성합니다.

"지금 한국 시간으로 2025년 6월 13일 금요일 오후 2시 30분입니다."

전체 흐름 다이어그램

┌─────────────┐     ┌──────────────────┐     ┌──────────────────┐
│   사용자    │────▶│  Hermes Agent     │────▶│  LLM (qwen3.6)   │
│             │     │                  │     │                  │
│ "오늘 날짜   │     │  MCP 서버 관리    │     │  1. 질문 분석     │
│  알려줘"    │◀────│  프로세스 실행    │◀────│  2. 도구 호출     │
│             │     │                  │     │     결정          │
└─────────────┘     └────────┬─────────┘     └──────────────────┘
                             │
                    ┌────────▼─────────┐
                    │  MCP Server      │
                    │  (today)         │
                    │                  │
                    │  get_today()     │
                    │  실행            │
                    └────────┬─────────┘
                             │
                    ┌────────▼─────────┐
                    │  JSON-RPC 응답   │
                    │                  │
                    │  {"datetime":    │
                    │   "2025-06-13    │
                    │   14:30:00", ...}│
                    └────────┬─────────┘
                             │
                    ┌────────▼─────────┐
                    │  Hermes Agent    │
                    │                  │
                    │  결과를 LLM 에   │
                    │  다시 전달       │
                    └────────┬─────────┘
                             │
                    ┌────────▼─────────┐     ┌─────────────┐
                    │  LLM             │────▶│   사용자    │
                    │                  │     │             │
                    │  최종 답변 생성   │     │ "지금 한국  │
                    │                  │     │  시간으로    │
                    └──────────────────┘     │  2025년 6월 │
                                            │  13일 금요일 │
                                            │  오후 2시    │
                                            │  30분입니다" │
                                            └─────────────┘

5. MCP 서버 작성 시 주의사항

5-1. docstring 은 LLM 이 보는 설명서

MCP 서버에서 docstring은 단순 주석이 아닙니다. LLM 이 도구 사용 여부를 결정하는 유일한 정보원입니다.

@app.tool()
def get_today(timezone: str = "Asia/Seoul") -> str:
    """현재 날짜와 시간을 반환합니다.

    Args:
        timezone: 시간대 (기본값: Asia/Seoul)
                 예: America/New_York, Europe/London, UTC

    Returns:
        현재 날짜와 시간 문자열
    """

docstring 이 명확해야 LLM 이 언제 이 도구를 호출해야 하는지 정확히 알 수 있습니다. 모호한 설명은 LLM 이 도구를 사용하지 않거나 잘못된 파라미터로 호출하는 원인이 됩니다.

5-2. 입력 파라미터 정의하기

@app.tool()
def search_files(directory: str, pattern: str) -> list:
    """지정된 디렉토리에서 패턴에 맞는 파일 목록을 반환합니다.

    Args:
        directory: 검색할 디렉토리 경로
        pattern: 파일 이름 패턴 (예: "*.py", "test_*")

    Returns:
        일치하는 파일 경로 목록
    """
  • 타입 힌트 필수: str, int, bool 등 명확한 타입 지정
  • 기본값 설정: 가능한 한 파라미터에 기본값 제공
  • Args 설명: 각 파라미터의 용도와 예시를 docstring 에 포함

5-3. 에러 처리는 반드시

@app.tool()
def get_weather(city: str) -> str:
    """도시의 현재 날씨를 반환합니다."""
    try:
        response = requests.get(f"https://api.weather.com/{city}")
        response.raise_for_status()
        return json.dumps(response.json(), ensure_ascii=False)
    except Exception as e:
        return f"날씨 조회 실패: {e}"

에러가 발생해도 서버가 크래시되지 않도록 try/except로 감싸야 합니다. 에러 메시지도 LLM 에 전달되므로, 의미 있는 에러 메시지를 반환하세요.

5-4. 보안 — 환경 변수는 명시적으로 전달

mcp_servers:
  weather:
    command: python
    args: [~/scripts/weather_server.py]
    env:
      WEATHER_API_KEY: "***"  # API 키는 여기에서 전달

API 키나 비밀번호는 코드에 하드코딩하지 말고 env 옵션으로 전달하세요. config.yaml 은 버전 컨트롤에 포함되지 않도록 .gitignore 에 추가하세요.


6. 실전 — 다른 MCP 서버 예시

파일 시스템 서버

mcp_servers:
  filesystem:
    command: npx
    args:
      - "-y"
      - "@modelcontextprotocol/server-filesystem"
      - "/Users/mulpats/Developer"  # 접근 허용 디렉토리

지정된 디렉토리 내의 파일을 읽고, 검색하고, 목록을 확인할 수 있습니다. 접근 허용 디렉토리만 지정해야 보안상 안전합니다.

GitHub 서버

mcp_servers:
  github:
    command: npx
    args:
      - "-y"
      - "@modelcontextprotocol/server-github"
    env:
      GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxx"

GitHub 리포지토리의 코드를 읽고, 이슈를 확인하고, PR 을 검토할 수 있습니다.

시간대 서버 (uvx)

mcp_servers:
  timezone:
    command: uvx
    args:
      - "mcp-server-timezone"

uvx 로 설치 없이 바로 실행할 수 있는 MCP 서버도 많습니다. uvx는 Python 패키지를 가상 환경에서 즉시 실행하는 도구입니다.


7. 문제 해결 가이드

MCP 도구가 인식되지 않음

# config.yaml 의 mcp_servers 섹션 확인
cat ~/.hermes/config.yaml | grep -A 5 mcp_servers

# Hermes Agent 재시작 후 로그 확인
hermes start  # 또는 재시작
  • config.yaml 의 YAML 들여쓰기가 정확한지 확인 (스페이스 2개 사용)
  • 서버 경로를 절대 경로로 변경해보기
  • Hermes Agent 를 재시작했는지 확인

"MCP SDK not available" 오류

# Python 환경 확인
which python
python --version

# MCP SDK 설치 확인
pip show mcp
  • pip install mcp 로 최신 버전 설치
  • 가상 환경이 활성화되어 있는지 확인
  • Python 버전이 3.9 이상인지 확인

서버 연결 실패

# 서버 직접 실행 (디버깅)
python ~/Developer/scripts/today_mcp_server.py

# HTTP 모드로 실행 테스트
python ~/Developer/scripts/today_mcp_server.py --http
# 브라우저에서 http://localhost:8090 접속
  • 서버를 직접 실행해서 에러 메시지 확인
  • 포트가 이미 사용 중인지 확인 (lsof -i :8090)
  • 방화벽 설정 확인 (macOS: 시스템 설정 → 네트워크 → 방화벽)

요약

  • MCP 는 LLM 과 외부 도구를 연결하는 표준 프로토콜
  • Python mcp 패키지로 몇 줄로도 MCP 서버 작성 가능
  • config.yaml 에 등록하면 Hermes Agent 가 자동으로 관리
  • LLM 은 도구 설명(docstring) 을 보고 언제 호출할지 결정
  • JSON-RPC 2.0 으로 호스트와 서버 간 통신
  • 에러 처리와 보안(API 키 관리) 을 반드시 고려

2026/06/03

headroom — AI 에이전트 토큰을 90% 줄여주는 컨텍스트 압축 레이어

AI 에이전트를 실제로 써본 사람이라면 한 번쯤 이런 경험을 했을 거다. Claude Code나 Codex로 코드베이스 분석을 시키는데, 툴 출력 결과 하나에만 토큰이 수천 개 쏟아지고 — 조금 지나면 컨텍스트가 꽉 차서 에이전트가 이상한 소리를 하기 시작한다. 결국 세션을 다시 시작하거나, 직접 프롬프트를 잘라내거나. 왜 이렇게 됐냐고 물어보면 대부분 "컨텍스트 윈도우가 작아서"라고 하는데, 진짜 문제는 따로 있다. LLM한테 필요도 없는 정보를 너무 많이 먹이고 있다는 거다.

headroom은 이 문제에 정면으로 달려드는 프로젝트다. GitHub 스타 6,300개, 포크 445개. 몇 주 전에 알게 됐는데 생각보다 훨씬 잘 만들어져 있어서 정리해봤다.


headroom이 하는 일

한 줄 요약하면 — 에이전트가 LLM한테 보내는 걸 압축해주는 미들웨어다. 툴 출력, 로그, RAG 청크, 파일 내용, 대화 히스토리 전부.

실제 벤치마크 수치를 보면 이게 마케팅이 아니라는 걸 알 수 있다:

코드 검색 결과 100개: 17,765 → 1,408 토큰 (92% 절감)

SRE 인시던트 디버깅: 65,694 → 5,118 토큰 (92% 절감)

GitHub 이슈 트리아지: 54,174 → 14,761 토큰 (73% 절감)

정확도도 같이 확인했다. GSM8K(수학) 기준 압축 전후 정확도 차이가 ±0.000이고, BFCL(툴 콜링) 기준 32% 압축에서 97% 정확도. 이게 가능한 이유가 있다. 단순히 토큰을 자르는 게 아니라, 실제로 LLM이 필요한 정보를 식별해서 나머지를 버리는 방식이기 때문이다.

내부 구조가 꽤 흥미롭다

headroom이 단순 텍스트 트리밍 도구가 아닌 이유는 컨텐츠 타입을 구분해서 각각 다른 압축기를 쓴다는 데 있다.

ContentRouter — 들어오는 내용이 JSON인지, 코드인지, 일반 텍스트인지 판단하고 적절한 압축기로 라우팅한다.

SmartCrusher — JSON과 구조화된 데이터 전용. 중첩 객체, 배열, 혼합 타입을 다 처리한다.

CodeCompressor — AST(추상 구문 트리) 기반. Python, JS, Go, Rust, Java, C++ 지원. 코드의 의미 구조를 이해하고 압축하기 때문에 단순 텍스트 압축보다 훨씬 안전하다.

Kompress-base — 일반 텍스트용 커스텀 HuggingFace 모델. 에이전트 트레이스 데이터로 학습됐다. LLMLingua처럼 별도의 로컬 LLM이 필요하지 않다.

CacheAligner — 프롬프트 프리픽스를 안정화해서 LLM 프로바이더의 KV 캐시 히트율을 높인다. 같은 컨텍스트를 반복 사용하는 에이전트 루프에서 실질적인 비용 절감이 된다.

CCR (Compressed-Context Retrieval) — 원본을 로컬에 저장해두고, LLM이 필요하면 headroom_retrieve 툴로 다시 가져올 수 있다. 압축이 되돌릴 수 없는 정보 손실이 아니라는 게 핵심이다.

설치와 사용 — 진입 장벽이 낮다

여러 배포 방식을 지원하는데, 가장 빠른 건 에이전트 래핑이다:

pip install "headroom-ai[all]"

headroom wrap claude  # Claude Code 바로 연결

headroom wrap codex  # Codex도 동일

기존 코드를 건드리기 싫으면 프록시 모드가 있다:

headroom proxy --port 8787  # OpenAI 호환 프록시, 코드 변경 없음

Python 코드에 직접 붙이는 것도 간단하다:

from headroom import compress

compress(messages, model=...)

LangChain, LiteLLM, Vercel AI SDK, Agno 등 주요 프레임워크 통합도 다 있다. Python 3.10+, 라이선스는 Apache 2.0.

MCP 서버로도 쓸 수 있다

headroom은 MCP 서버 모드를 지원한다. headroom_compress, headroom_retrieve, headroom_stats 세 가지 툴을 제공해서, Claude나 Cursor 같은 MCP 클라이언트가 직접 호출할 수 있다.

headroom mcp install  # 끝

MCP 생태계에서 메모리/컨텍스트 관련 서버들을 비교해보면:

공식 MCP Memory Server (Anthropic) — 엔티티-릴레이션 기반 지식 그래프 메모리. 정보를 '저장하고 검색'하는 구조라서 headroom의 '압축'과는 다른 문제를 푼다. modelcontextprotocol/servers 레포(⭐86.6k)에 포함.

mem0 MCP Server — 대화에서 사실을 추출해 벡터/그래프 DB에 저장, 세션 간 메모리 유지. headroom과 상호 보완적으로 같이 쓸 수 있다.

압축을 해주는 MCP 서버는 현재 headroom이 유일하다고 봐도 된다.

비슷한 도구들이랑 뭐가 다른가

가장 자주 비교되는 건 Microsoft의 LLMLingua다. 둘 다 토큰 압축을 목표로 하지만 접근이 다르다. LLMLingua는 소형 LLM(Llama-2-7B)을 써서 토큰 퍼플렉시티를 계산하고 중요도 낮은 토큰을 제거한다. 학술 논문 기반(EMNLP 2023, ACL 2024)으로 잘 연구된 방식인데, 압축기 자체가 로컬 LLM을 필요로 한다는 게 실용적인 허들이다. 에이전트 래핑이나 프록시 모드, MCP 서버도 없다.

Letta(구 MemGPT)나 LangChain Memory 같은 메모리 프레임워크들은 사실 다른 문제를 푼다. 이쪽은 '세션 간 기억을 어떻게 유지할 것인가'가 핵심인데, headroom은 '지금 이 턴에 LLM한테 보내는 내용을 어떻게 줄일 것인가'에 집중한다. 상충하는 게 아니라 보완적이다.

headroom의 실질적인 차별점은 세 가지다. 첫째, 컨텐츠 타입별 압축기 — JSON을 텍스트처럼, 코드를 텍스트처럼 압축하지 않는다. 둘째, CCR 가역 압축 — 원본이 로컬에 살아있어서 필요하면 되찾을 수 있다. 셋째, 크로스 에이전트 공유 메모리 — Claude, Codex, Gemini가 같은 메모리 스토어를 쓸 수 있다.

headroom learn — 실패에서 배우는 기능

개인적으로 재밌다고 생각한 기능이 headroom learn이다. 에이전트 세션에서 실패한 케이스들을 자동으로 마이닝해서 CLAUDE.md, AGENTS.md, GEMINI.md 같은 지침 파일에 수정사항을 기록해준다. 다음 세션에서 같은 실수를 반복하지 않도록 에이전트 자체를 점진적으로 개선하는 구조다. 아직 실험적인 기능이겠지만 방향성이 맞다.

써볼 만한가

현재 버전 0.22.3, 커밋 1,389개, 브랜치 163개. 리포 상태를 보면 상당히 활발하게 개발되고 있다. 오픈 이슈 75개, PR 55개는 사용자가 많다는 신호이기도 하다.

Claude Code나 Codex로 큰 코드베이스 작업을 자주 하는 사람이라면 headroom wrap으로 감싸는 것만으로 토큰 비용이 꽤 줄어들 수 있다. 라이브 데모에서 10,144 → 1,260 토큰으로 줄어든 채로 동일한 버그를 찾아냈다는 수치가 허황된 느낌이 아니다.

단, Kompress-base ML 모델 없이 쓰려면 headroom-ai[proxy] 같은 세부 패키지를 쓰면 된다. 모든 기능이 다 필요한 게 아니라면 [all] 대신 필요한 것만 설치하는 게 낫다.

📎 참고 링크: headroom GitHub | headroom 문서 | LLMLingua (Microsoft) | Letta (MemGPT) | 공식 MCP Memory Server | mem0

SK하이닉스 ADR 상장 이후 한국 증시 급락의 원인 분석

분류: 증시분석 SK하이닉스 ADR 상장 이후 한국 증시 급락의 원인 분석 지난 7월 10일, SK하이닉스가 미국 나스닥에 미국주식예탁증서(ADR)를 상장했다. 공모가 149달러로 상장한 하이닉스 ADR은 첫 거래일인 13일 기준 약 168달...