Hugging Face MCP 서버 스터디

Hugging Face MCP 서버 스터디

이 글은 Hugging Face 블로그의 Building the Hugging Face MCP Server를 읽고 공부한 내용을 바탕으로 정리했습니다.


주요 개념

원문 용어 (English) 번역 용어 (Korean)
Model Context Protocol (MCP) 모델 컨텍스트 프로토콜(MCP)
STDIO STDIO
HTTP with SSE HTTP with SSE
Server Sent Events (SSE) 서버 전송 이벤트
Streamable HTTP Streamable HTTP
Direct Response 직접 응답
Request Scoped Streams 요청 범위 스트림
Server Push Streams 서버 푸시 스트림
Stateless 무상태
Stateful 상태 유지
Session Affinity 세션 어피니티
Sampling 샘플링
Elicitation 추가 정보 요청

MCP 서버 설계 의사결정 흐름 (블로그 글 기준)

  1. 어떤 전송 방식을 쓸지 (Transport, 전송 방식)
    • STDIO: 로컬 실행, 개발/테스트 환경에 적합
    • HTTP with SSE: 과거 원격 표준, 현재는 Streamable HTTP로 대체됨
    • Streamable HTTP: 최신 원격 전송 방식. 요청/응답 + 스트리밍 모두 가능
  2. 어떤 데이터 흐름 패턴을 선택할지 (Communication Pattern, 통신 방식)
    • Direct Response: 단순 요청-응답. 가볍고 빠름
    • Request Scoped Streams: 요청 단위 스트리밍. 진행 상황·추가 요청(Elicitation) 가능
    • Server Push Streams: 장기 연결. 서버가 능동적으로 알림·변경사항 푸시
  3. 상태를 유지할지 여부 (State Management, 상태 관리)
    • Stateless: 각 요청 독립 처리. 확장성 높음, 관리 단순
    • Stateful: 서버가 세션 유지. 세션 ID·세션 어피니티 필요, 재개(Resumption) 지원 가능
  4. 상호작용 기능을 지원할지 (Interactive Features)
    • Sampling: 서버가 선택지를 제공, 클라이언트가 선택
    • Elicitation: 서버가 클라이언트에 추가 정보 요청
    • Progress Notification: 요청 범위 스트림에서 진행 상황을 알림

1. 전송(Transport) 방식

  • STDIO 로컬 환경에서 MCP 서버와 클라이언트가 같은 컴퓨터에서 실행될 때, 표준 입출력으로 통신하는 방식. → 로컬 개발/테스트용
    클라이언트 프로세스                          서버 프로세스
      |                                       |
      |-- STDIN: initialize ----------------->|
      |<-- STDOUT: initialized ---------------|
      |-- STDIN: tools/call ----------------->|
      |<-- STDOUT: result --------------------|
      |-- STDIN: tools/call ----------------->|
      |<-- STDOUT: result --------------------|
    
  • HTTP with SSE (서버 전송 이벤트) 서버가 열린 HTTP 연결을 유지하며 클라이언트로 이벤트를 지속 전송하는 방식. → 과거 원격 표준, 현재는 사용 중단 추세
    클라이언트                                   서버
     |                                         |
     |-- POST /initialize -------------------->|
     |<-- 200 OK (세션/설정) -------------------|
     |-- GET /events (Accept: text/event-stream)|
     |<== SSE: ready/heartbeat/updates =======|
     |                                         |
     |-- POST /tools/call -------------------->|
     |<== SSE: progress/output/done ==========|
    
  • Streamable HTTP 최신 원격 통신 방식. 요청/응답뿐 아니라 스트리밍도 가능해 유연성이 높음. SSE의 진화된 형태. → 현재 MCP 프로덕션 환경에서 권장

2. 통신 방식(Communication Patterns) - Streamable HTTP*

  • Direct Response (직접 응답)
    클라이언트                                  서버
     |                                    |
     |-- POST /initialize --------------->|   (옵션: Stateless면 세션ID 없음)
     |<-- 200 OK -------------------------|
     |                                    |
     |-- POST /tools/call --------------->|   (질문1/툴 호출)
     |<-- 200 OK (결과1 본문) -------------|
     |                                    |
     |-- POST /tools/call --------------->|   (질문2/툴 호출)
     |<-- 200 OK (결과2 본문) -------------|
    
  • Request Scoped Streams (요청 범위 스트림) 특정 요청에 한정된 임시 스트리밍. 작업 중간에 진행 상황 알림, 추가 정보 요청 가능.
    클라이언트                                  서버
     |                                    |
     |-- POST /initialize --------------->|   (Stateful일 경우 세션ID 발급)
     |<-- 200 OK (mcp-session-id=abc123)--|
     |                                    |
     |-- POST /tools/call (abc123) ------>|   (질문1)
     |<-- 202 Accepted (request_id=r1) ---|
     |                                    |
     |-- GET  /streams/r1 --------------->|   (SSE 구독, Accept: text/event-stream)
     |<== SSE: progress 10% ==============|
     |<== SSE: progress 80% ==============|
     |<== SSE: output(답변1) =============|
     |<== SSE: done ======================|
     |                                    |
     |-- POST /tools/call (abc123) ------>|   (질문2)
     |<-- 202 Accepted (request_id=r2) ---|
     |-- GET  /streams/r2 --------------->|
     |<== SSE: progress ... ==============|
     |<== SSE: output(답변2) =============|
     |<== SSE: done ======================|
    
  • Server Push Streams (서버 푸시 스트림) 장기 연결을 유지하며 서버가 능동적으로 알림/메시지를 보냄 → 도구 목록 변경 알림, 구독 이벤트 등에 활용. 관리가 복잡함
    클라이언트                                  서버
     |                                    |
     |-- POST /initialize --------------->|   (Stateful 권장)
     |<-- 200 OK (mcp-session-id=abc123)--|
     |                                    |
     |-- GET  /events?session=abc123 ---->|   (장기 SSE 연결)
     |<== SSE: tool_list_changed =========|
     |<== SSE: resource/update ===========|
     |                                    |
     |-- POST /tools/call (abc123) ------>|   (질문1)
     |<-- 202 Accepted (request_id=r1) ---|
     |<== SSE: progress ... ==============|   (같은 장기 스트림으로 푸시)
     |<== SSE: output(답변1) =============|
     |                                    |
     |-- POST /tools/call (abc123) ------>|   (질문2)
     |<-- 202 Accepted (request_id=r2) ---|
     |<== SSE: output(답변2) =============|
     |<== SSE: ping/keep-alive ===========|
    

3. 상태 관리(State Management)

  • Stateless (무상태) 요청 간 연결된 상태를 유지하지 않음. 확장성이 뛰어나지만 맥락은 클라이언트가 직접 전달해야 함

  • Stateful (상태 유지) 서버가 클라이언트의 세션을 기억. 세션 ID(mcp-session-id)를 발급하여 맥락을 이어갈 수 있음

  • Session Affinity (세션 어피니티) Stateful 구조에서 특정 클라이언트 요청을 항상 같은 서버 인스턴스로 보장하는 방식
    • 로드밸런서가 세션 쿠키, 세션 ID, 혹은 IP 기반으로 동일 서버에 붙여줌
  • Resumption (재개) 연결이 끊겼다가 다시 이어질 때, 이전 세션 상태를 복원하는 기능
    • keep-alive 실패 → 연결 끊김 → 재개(resumption) 메커니즘이 동작

4. 상호작용/확장 기능

  • Sampling (샘플링) 서버가 클라이언트에 선택지를 주고, 그 중 하나를 고르도록 요청
    • 예: “이 제목 후보 중 하나 고르기”, “짧은 요약 문구 만들기”
    • 자동화된 결정이 필요할 때 사용
  • Elicitation (추가 정보 요청) 서버가 클라이언트에게 누락된 입력이나 추가 옵션을 요구
    • 예: “동영상 길이를 입력해주세요”, “정말 삭제하시겠습니까?”
    • 사람이 직접 확인·선택해야 하는 상황에 사용

시연

로컬

  1. HuggingFace MCP 서버 기동
    $ docker build --no-cache -t hf-mcp-server:latest .
    $ docker run --rm -p 3000:3000 hf-mcp-server:latest
    Starting MCP server with transport type: streamablehttpjson on port 3000
    Using standard HF_TOKEN authentication.
    Using streamableHttpJson transport type (JSON response mode enabled)
    {"level":30,"time":"2025-09-28T02:49:19.177Z","pid":11,"hostname":"179a01035eed","msg":"Starting Streamable HTTP server..."}
    {"level":30,"time":"2025-09-28T02:49:19.177Z","pid":11,"hostname":"179a01035eed","msg":"JSON response mode enabled"}
    {"level":30,"time":"2025-09-28T02:49:19.178Z","pid":11,"hostname":"179a01035eed","msg":"Using internal API client with user config API: http://localhost:3000}"}
    {"level":30,"time":"2025-09-28T02:49:19.181Z","pid":11,"hostname":"179a01035eed","msg":"Server running at http://localhost:3000"}
    {"level":30,"time":"2025-09-28T02:49:19.181Z","pid":11,"hostname":"179a01035eed","transportType":"streamableHttpJson","mode":"production","msg":"Server configuration"}   
    {"level":30,"time":"2025-09-28T02:49:19.181Z","pid":11,"hostname":"179a01035eed","msg":"HTTP JSON transport initialized (stateless mode)"}
    {"level":30,"time":"2025-09-28T02:49:19.182Z","pid":11,"hostname":"179a01035eed","msg":"Starting API polling with interval 5000ms"}
    

hf-mcp-dashborad

  1. HuggingFace MCP 명령어 테스트
    $ npx mcp-remote http://localhost:3000/mcp --interactive
    
  • 도구 목록 호출
    $ npx mcp-remote http://localhost:3000/mcp --interactive
    [34228] Using automatically selected callback port: 4208
    [34228] [34228] Connecting to remote server: http://localhost:3000/mcp
    [34228] Using transport strategy: http-first
    [34228] Connected to remote server using StreamableHTTPClientTransport
    [34228] Local STDIO server running
    [34228] Proxy established successfully between local STDIO and remote StreamableHTTPClientTransport
    [34228] Press Ctrl+C to exit
    {"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}
    [34228] [Local→Remote] tools/list
    [34228] [Remote→Local] 1
    {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"hf_whoami","description":"Hugging Face tools are being used anonymously and may be rate limited. Call this tool for instructions on joining and authenticating.","inputSchema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"title":"Hugging Face User Info"}} ...
    
  • 이미지 생성 모델 호출
    {  "jsonrpc": "2.0",  "id": 2,  "method": "tools/call",  "params": {    "name": "gr1_flux1_schnell_infer",    "arguments": {      "prompt": "고양이가 책상 위에 앉아있는  일러스트"    }  }}
    [34228] [Local→Remote] tools/call
    [34228] [Remote→Local] 2
    {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"image","data":"...","mimeType":"image/webp"},{"type":"text","text":"Image URL: https://evalstate-flux1-schnell.hf.space/gradio_api/file=/tmp/gradio/644adb3a95a6d8a02ed911a004ef00544749d5dc899e36679fd1266dad7ce4f0/image.webp"},{"type":"text","text":"1134957760"}],"isError":false}}
    

hf-mcp-transport-statistics

Claude Desktop

  1. Claude Desktop 내 MCP 서버 설정 추가 claude_desktop_config.json
     "huggingface": {
       "command": "npx",
       "args": [
         "mcp-remote",
         "http://localhost:3000/mcp"
       ],
       "env": {
         "HF_TOKEN": "hf_~"
       }
     }
    
  2. HuggingFace MCP 테스트
  • 도구 목록 호출

hf-mcp-claude-test1

  • 데이터셋, 모델, 스페이스 검색

hf-mcp-claude-test2

  • 이미지 생성 모델 호출

hf-mcp-claude-test3

hf-mcp-transport-metrics hf-mcp-transport-statistics2

hyeonseo
hyeonseo Hello, I’m Hyeonseo! 🤗