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.txtconfig 설정
~/.hermes/config.yaml에 mcp_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. 실험 설계
기왕 붙인 김에 측정을 해보기로 함. 확인하고 싶었던 것:
- MCP 툴이 실제로 실행되는가 (native 툴 없이 붙는다는 세일즈 포인트 검증)
- 툴 개수가 소형 모델(4B)의 신뢰도에 주는 영향 — 화이트리스트 필터링의 효과
- 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에 가져갈 결론
- MCP 연동은 작동함. 설정 문법 → 툴 자동 발견 → 실행 → 경로 스코프까지 전부 검증됨. Kubeflow·사내 DW를 붙일 때도 동일한
mcp_servers블록 구조를 쓰면 됨. native 툴을 안 짜도 된다는 장점이 있음. - 툴 필터링은 선택이 아니라 필수. MCP를 여러 개 붙이면 툴이 수십 개가 됨. 그때 모델이 맞는 걸 고르게 하려면 화이트리스트가 있어야 함. 특히 온프레미스 소형 모델이면 더더욱.
- 필터링은 보안 장치이기도 함. 삭제 툴을 목록에서 빼두면 모델이 실수로든 프롬프트 인젝션으로든 파일을 지울 방법 자체가 없어짐. 사내에선 이게 오히려 주목적이 될 것("조회는 되고 수정은 안 되게 권한 설정").
- 속도 병목은 컨텍스트 처리. 장비 견적 낼 때 파라미터 수가 아니라 대역폭을 봐야 함.
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처럼 개인 토큰이 필요한 건 노출 위험이 있어서 패스함.

댓글