cs 맥북에어 M4 RAM 16GB에서 Hermes Agent 로컬로 사용해보기 (2) : MCP 연동 테스트
본문 바로가기
  • 매일 한걸음씩
  • 매일 한걸음씩
카테고리 없음

맥북에어 M4 RAM 16GB에서 Hermes Agent 로컬로 사용해보기 (2) : MCP 연동 테스트

by 시몬쯔 2026. 7. 24.
728x90
반응형

1탄에서 로컬 구동까지 성공했으니, 이번엔 MCP(Model Context Protocol) 로 외부 툴을 붙여봄.
결론: MCP 연동은 잘 됨. 근데 화이트리스트 필터링의 효과가 예상과 완전히 달랐음.


0. 1탄 요약

1탄에서 한 것:

  • Hermes는 두 가지 — Hermes 모델(LLM)과 Hermes Agent(에이전트 프레임워크). 검토 대상은 후자. 스킬을 스스로 만들고 개선하는 학습 루프가 핵심.
  • 맥북에어 M칩 16GB에 완전 로컬로 세팅 성공. 외부 API 호출 0. Ollama + qwen3:4b 조합.
  • 3대 관문을 다 밟음 — ① 툴콜 파서(vLLM은 --tool-call-parser hermes 플래그 필요, Ollama는 자동) ② 64K 컨텍스트 강제(ollama_num_ctx: 65536) ③ thinking 지원 모델 선택(Llama 3.1은 미지원 → Qwen3로).
  • 결론: 16GB 에어는 "기능 확인 장비"지 "성능 판단 장비"가 아님. 응답 하나에 3분 넘게 걸림.

이번 편은 그 위에 MCP를 연동해보고 기록하는 내용이다.


1. 왜 MCP인가 — native 툴 vs MCP

에이전트가 뭔가를 하려면 그 기능이 툴(tool) 로 등록돼 있어야 함. 사내 시스템(티켓팅 API, 사내 DB, Kubeflow)은 기본 툴에 없으니 붙이는 방법이 두 가지.

  • native 툴 — Hermes 소스에 툴을 코드로 직접 짜 넣음. 함수 정의·인증·스키마·에러 처리를 프레임워크에 박아야 함. 버전 오르면 다시 맞춰야 할 수 있음.
  • MCP 서버 — 표준 프로토콜. 사내 시스템을 MCP 서버로 감싸서 연결만 하면 그 기능들이 자동으로 툴 목록에 뜸. Hermes 코드는 안 건드림.

비유하면 native 툴은 직접 납땜, MCP는 콘센트에 꽂기. 제품이 바뀌어도 다시 꽂으면 됨. 재사용성(다른 에이전트에도 그대로 붙음)·유지보수·버전 안정성에서 MCP가 유리함.

단, MCP 서버는 권한 이슈가 있을 수 있음. 권한 스코프를 좁게 잡아야 함(이번 실험에서 실제로 검증함, 아래 4-3).


2. 세팅 — filesystem MCP 붙이기

첫 테스트로 파일시스템 MCP를 골랐음. 외부 인증이 없고, 경로를 지정해서 그 폴더 밖은 못 건드리게 막을 수 있어서 안전함.

준비

stdio 방식 MCP 서버는 대부분 Node.js 기반이라 npx가 필요함.

npx --version        # 없으면 brew install node

mkdir -p ~/mcp-test
echo "hello mcp" > ~/mcp-test/sample.txt

config 설정

~/.hermes/config.yamlmcp_servers 키를 추가함. 기본으로 없는 키라 직접 써넣어야 하고, model:과 같은 최상위 레벨이어야 함.

model:
  default: qwen3:4b
  provider: custom
  base_url: http://127.0.0.1:11434/v1
  context_length: 65536
  ollama_num_ctx: 65536

mcp_servers:
  filesystem:
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/<사용자명>/mcp-test"]
    timeout: 120
    connect_timeout: 60

⚠️ 경로는 절대경로로.
YAML 들여쓰기가 싫으면 CLI로도 됨: hermes mcp add filesystem --command "npx -y @modelcontextprotocol/server-filesystem /절대경로"

Hermes는 시작할 때 config를 한 번 읽고 MCP 서버를 자식 프로세스로 띄운 뒤 툴 목록을 받아옴. 그래서 설정을 바꾸면 Hermes를 껐다 켜야 반영됨(Ollama는 안 건드려도 됨).

재실행하니 시작 로그에 filesystem이 떴음. 연결 성공.

3. 실험 설계

기왕 붙인 김에 측정을 해보기로 함. 확인하고 싶었던 것:

  1. MCP 툴이 실제로 실행되는가 (native 툴 없이 붙는다는 세일즈 포인트 검증)
  2. 툴 개수가 소형 모델(4B)의 신뢰도에 주는 영향 — 화이트리스트 필터링의 효과
  3. MCP 자체의 속도 오버헤드가 얼마인가

화이트리스트가 뭔가

MCP 서버를 붙이면 그 서버의 툴이 전부 등록됨. filesystem만 해도 읽기·쓰기·이동·삭제·목록·검색 등 10개 넘게 딸려옴. 그리고 그 목록 전체가 매 턴 모델에게 전달됨 — 모델이 툴을 고르려면 이름·설명·입력 스키마를 다 알아야 하니까.

화이트리스트는 그중 지정한 것만 남기고 나머지를 숨기는 설정임.

mcp_server_filter:
  filesystem:
    mode: whitelist
    tools:
      - read_text_file
      - list_directory
      - write_file
      - create_directory

식당 메뉴판 비유가 맞음. 주방에 재료가 100개여도 메뉴판에 4개만 적으면 손님은 그 4개 중에서 고름. 주문이 빨라지고 실수도 줄어듦.

툴 이름은 로그에 찍히는 mcp__filesystem__read_text_file에서 서버 접두사(mcp__filesystem__)를 뺀 것.


4. 결과

4-1. 측정값

구성 툴 호출 컨텍스트 소요 시간
8B, MCP 없음 16.6K 3m 27s
4B, MCP 필터 없음 (읽기) 1회 18.3K 3m 24s
4B, MCP 필터 없음 (쓰기) 3회 18.7K 3m 56s
4B, MCP 화이트리스트 4개 (쓰기) 1회 18.4K 1m 10s

4-2. 발견 1 — 화이트리스트의 효과는 "토큰 절약"이 아니었음

기대는 컨텍스트가 확 줄어드는 거였음. 실제로는 18.7K → 18.4K, 겨우 0.3K(2%) 밖에 안 줄었음. 툴 스키마가 컨텍스트에서 차지하는 비중이 생각보다 작았음. 나머지는 시스템 프롬프트·스킬·메모리가 먹고 있었음.

대신 시간이 3m 56s → 1m 10s로 70% 줄었음. 원인은 토큰이 아니라 툴 선택 정확도였음.

필터 전 로그 — 모델이 헤맴:

⚡ write_file       → 실패 (Parent directory does not exist)
⚡ create_directory → 폴더 생성
⚡ write_file       → 성공          ... 3스텝

필터 후 로그 — 한 번에 맞춤:

⚡ write_file       → 성공          ... 1스텝

선택지를 12개에서 4개로 줄이니 4B가 첫 시도에 맞췄음.

결론: 소형 모델에게 화이트리스트는 토큰 절약 도구가 아니라 정확도 보정 장치임.

4-3. 발견 2 — 경로 스코프가 실제로 작동함

필터 전 테스트에서 "mcp-test 폴더에 파일 만들어줘"라고 했더니 mcp-test/mcp-test/test2.txt중첩 생성됐음. MCP 서버 입장에선 config에 지정한 경로가 최상위 루트라, 상대경로를 그 기준으로 해석한 것.

처음엔 버그인 줄 알았는데 오히려 좋은 신호였음. 서버가 지정된 루트 밖으로 절대 못 나간다는 증거이기 때문. 사내 시스템에 붙일 때 권한 통제가 이 방식으로 걸린다는 리허설이 됨.

(그래서 이후엔 "현재 폴더에"라고 하니 중첩 없이 정상 생성됨)

4-4. 발견 3 — MCP 오버헤드는 사실상 0

모든 툴 호출이 일관되게 0.0s 였음. 3분 넘는 시간은 전부 모델 추론임. MCP는 별도 프로세스로 돌아서 모델 추론과 무관하고, 사내에 여러 개 붙여도 속도 페널티는 없다는 뜻.

4-5. 발견 4 — 4B도 멀티스텝 자기수정은 함

4-2의 실패 로그를 다시 보면, 4B 모델이 실패 메시지를 읽고 → 원인(부모 디렉토리 없음)을 파악하고 → 폴더를 먼저 만들고 → 재시도했음. 로컬 소형 모델의 하한선이 생각보다 낮지 않았음.

4-6. 발견 5 — 병목은 모델 크기가 아니라 컨텍스트 처리

1탄에서 8B → 4B로 파라미터를 절반으로 줄였는데 시간이 3m 27s → 3m 24s로 거의 안 줄었음. 매 턴 18K 토큰짜리 컨텍스트를 처리하는 게 병목이었던 것.

PoC 함의: GPU 사이징할 때 파라미터 수만 볼 게 아니라 메모리 대역폭과 긴 컨텍스트 처리 성능을 봐야 함.


5. 이 실험의 한계

  • n=1 실험일ㅂ 뿐.
  • 교란 요인이 있음. 두 쓰기 테스트의 프롬프트가 달랐음("mcp-test 폴더에" vs "현재 폴더에"). 후자가 더 명확해서 모델이 맞추기 쉬웠을 수 있음. 즉 1m 10s가 온전히 화이트리스트 덕분이라고 단정할 수 없음.
  • 기본 느림은 해결 안 됨. Auxiliary title generation failed: Request timed out(대화 제목 자동 생성)이 계속 뜸. 16GB 에어의 한계는 여전함.

제대로 하려면 프롬프트를 고정하고 각 조건을 10회씩 반복해야 함. 다음 실험 예정.


6. PoC에 가져갈 결론

  1. MCP 연동은 작동함. 설정 문법 → 툴 자동 발견 → 실행 → 경로 스코프까지 전부 검증됨. Kubeflow·사내 DW를 붙일 때도 동일한 mcp_servers 블록 구조를 쓰면 됨. native 툴을 안 짜도 된다는 장점이 있음.
  2. 툴 필터링은 선택이 아니라 필수. MCP를 여러 개 붙이면 툴이 수십 개가 됨. 그때 모델이 맞는 걸 고르게 하려면 화이트리스트가 있어야 함. 특히 온프레미스 소형 모델이면 더더욱.
  3. 필터링은 보안 장치이기도 함. 삭제 툴을 목록에서 빼두면 모델이 실수로든 프롬프트 인젝션으로든 파일을 지울 방법 자체가 없어짐. 사내에선 이게 오히려 주목적이 될 것("조회는 되고 수정은 안 되게 권한 설정").
  4. 속도 병목은 컨텍스트 처리. 장비 견적 낼 때 파라미터 수가 아니라 대역폭을 봐야 함.

7. 다음에 해볼 것

  • 프롬프트 고정 + 10회 반복으로 툴콜 신뢰도 정량 측정 (필터 전/후 A/B)
  • 스킬 자동생성 품질 확인 — Hermes의 핵심 가치인데 아직 못 봄. ~/.hermes/skills/ 내용 뜯어보기
  • 세션 간 메모리 유지 테스트 — 껐다 켜도 이전 대화를 기억하는지
  • /goal 기능 — 단, judge가 매 턴 추가 모델 호출을 해서 4B에선 상당히 느릴 것. 턴 예산 작게

8. 보안 메모 — 카탈로그는 조심

MCP 카탈로그에서 서버를 설치하면 매니페스트가 지정한 것(git clone, pip/npm install, 서버 코드 실행)이 그대로 로컬에서 실행됨. Nous가 PR 리뷰로 게이팅하긴 하지만, 설치 전에 매니페스트의 source: 저장소, install.bootstrap: 명령, transport.command: 호출을 직접 읽어보라는 게 공식 권고임.

그래서 이번 실험은 공식 filesystem 서버 + 더미 폴더 + 화이트리스트로만 했음. GitHub MCP처럼 개인 토큰이 필요한 건 노출 위험이 있어서 패스함.

728x90
반응형

댓글