본문으로 건너뛰기

MCP (Model Context Protocol)

MCP는 Hermes Agent가 Hermes 밖에 있는 외부 도구 서버에 연결할 수 있게 합니다. GitHub, 데이터베이스, 파일 시스템, 브라우저 스택, 내부 API 등 이미 다른 곳에 존재하는 도구를 에이전트가 사용할 수 있습니다.

Hermes가 외부에 이미 존재하는 도구를 쓰게 만들고 싶다면, MCP가 보통 가장 깔끔한 방법입니다.

MCP가 제공하는 것

  • 네이티브 Hermes 도구를 먼저 작성하지 않고 외부 도구 생태계에 접근
  • 로컬 stdio 서버와 원격 HTTP MCP 서버를 같은 설정에서 사용
  • 시작 시 자동 도구 검색 및 등록
  • 서버가 지원할 경우 MCP 리소스와 프롬프트를 위한 유틸리티 래퍼 제공
  • 서버별 필터링으로 Hermes가 실제로 봐야 하는 MCP 도구만 노출

빠른 시작

  1. MCP 지원을 설치합니다. 표준 설치 스크립트를 사용했다면 이미 포함되어 있습니다.
cd ~/.hermes/hermes-agent
uv pip install -e ".[mcp]"
  1. ~/.hermes/config.yaml에 MCP 서버를 추가합니다.
mcp_servers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
  1. Hermes를 시작합니다.
hermes chat
  1. Hermes에게 MCP 기반 기능을 사용하라고 요청합니다.

예:

/home/user/projects의 파일을 나열하고 저장소 구조를 요약해 줘.

Hermes는 MCP 서버의 도구를 검색하고 다른 도구와 같은 방식으로 사용합니다.

MCP 서버의 두 종류

Stdio 서버

Stdio 서버는 로컬 하위 프로세스로 실행되며 stdin/stdout으로 통신합니다.

mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "***"

다음 경우 stdio 서버를 사용합니다.

  • 서버가 로컬에 설치되어 있음
  • 로컬 리소스에 낮은 지연 시간으로 접근해야 함
  • MCP 서버 문서가 command, args, env를 사용하는 예제를 보여 줌

HTTP 서버

HTTP MCP 서버는 Hermes가 직접 연결하는 원격 엔드포인트입니다.

mcp_servers:
remote_api:
url: "https://mcp.example.com/mcp"
headers:
Authorization: "Bearer ***"

다음 경우 HTTP 서버를 사용합니다.

  • MCP 서버가 다른 곳에 호스팅되어 있음
  • 조직이 내부 MCP 엔드포인트를 노출함
  • 해당 통합을 위해 Hermes가 로컬 하위 프로세스를 생성하지 않게 하고 싶음

기본 설정 참조

Hermes는 ~/.hermes/config.yamlmcp_servers 아래에서 MCP 설정을 읽습니다.

공통 키

유형의미
commandstringstdio MCP 서버 실행 파일
argsliststdio 서버 인수
envmappingstdio 서버에 전달할 환경 변수
urlstringHTTP MCP 엔드포인트
headersmapping원격 서버용 HTTP 헤더
timeoutnumber도구 호출 제한 시간
connect_timeoutnumber초기 연결 제한 시간
enabledboolfalse이면 Hermes가 서버를 완전히 건너뜁니다.
supports_parallel_tool_callsbooltrue이면 이 서버의 도구를 동시에 실행할 수 있습니다.
toolsmapping서버별 도구 필터링 및 유틸리티 정책

최소 stdio 예제

mcp_servers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]

최소 HTTP 예제

mcp_servers:
company_api:
url: "https://mcp.internal.example.com"
headers:
Authorization: "Bearer ***"

Hermes가 MCP 도구를 등록하는 방식

Hermes는 MCP 도구 이름 앞에 접두사를 붙여 내장 이름과 충돌하지 않게 합니다.

mcp_<server_name>_<tool_name>

예:

서버MCP 도구등록 이름
filesystemread_filemcp_filesystem_read_file
githubcreate-issuemcp_github_create_issue
my-apiquery.datamcp_my_api_query_data

실무에서는 접두사가 붙은 이름을 수동으로 호출할 필요가 거의 없습니다. Hermes가 도구를 보고 일반 추론 과정에서 선택합니다.

MCP 유틸리티 도구

지원되는 경우 Hermes는 MCP 리소스와 프롬프트를 다루는 유틸리티 도구도 등록합니다.

  • list_resources
  • read_resource
  • list_prompts
  • get_prompt

이 유틸리티 도구는 서버별로 같은 접두사 패턴을 사용해 등록됩니다. 예:

  • mcp_github_list_resources
  • mcp_github_get_prompt

중요

이 유틸리티 도구들은 이제 서버 기능을 확인한 뒤 등록됩니다.

  • MCP 세션이 리소스 작업을 실제로 지원할 때만 Hermes가 리소스 유틸리티를 등록합니다.
  • MCP 세션이 프롬프트 작업을 실제로 지원할 때만 Hermes가 프롬프트 유틸리티를 등록합니다.

따라서 호출 가능한 도구는 있지만 리소스/프롬프트가 없는 서버에는 추가 래퍼가 생기지 않습니다.

서버별 필터링

각 MCP 서버가 Hermes에 제공하는 도구를 제어할 수 있습니다. 이렇게 하면 도구 네임스페이스를 세밀하게 관리할 수 있습니다.

서버 완전히 비활성화

mcp_servers:
legacy:
url: "https://mcp.legacy.internal"
enabled: false

enabled: false이면 Hermes는 해당 서버를 완전히 건너뛰며 연결도 시도하지 않습니다.

서버 도구 허용 목록

mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "***"
tools:
include: [create_issue, list_issues]

지정한 MCP 서버 도구만 등록됩니다.

서버 도구 차단 목록

mcp_servers:
stripe:
url: "https://mcp.stripe.com"
tools:
exclude: [delete_customer]

제외한 도구를 빼고 모든 서버 도구가 등록됩니다.

우선순위 규칙

둘 다 있으면:

tools:
include: [create_issue]
exclude: [create_issue, delete_issue]

include가 우선합니다.

유틸리티 도구도 필터링

Hermes가 추가하는 유틸리티 래퍼도 따로 비활성화할 수 있습니다.

mcp_servers:
docs:
url: "https://mcp.docs.example.com"
tools:
prompts: false
resources: false

의미:

  • tools.resources: falselist_resourcesread_resource를 비활성화합니다.
  • tools.prompts: falselist_promptsget_prompt를 비활성화합니다.

전체 예제

mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "***"
tools:
include: [create_issue, list_issues, search_code]
prompts: false

stripe:
url: "https://mcp.stripe.com"
headers:
Authorization: "Bearer ***"
tools:
exclude: [delete_customer]
resources: false

legacy:
url: "https://mcp.legacy.internal"
enabled: false

모든 것이 필터링되면 어떻게 되나요?

설정이 호출 가능한 도구를 모두 필터링하고, 지원되는 유틸리티도 모두 비활성화하거나 생략했다면 Hermes는 해당 서버에 대해 빈 런타임 MCP 툴셋을 만들지 않습니다.

도구 목록을 깔끔하게 유지하기 위한 동작입니다.

런타임 동작

검색 시점

Hermes는 시작 시 MCP 서버를 검색하고 해당 도구를 일반 도구 레지스트리에 등록합니다.

동적 도구 검색

MCP 서버는 런타임에 사용 가능한 도구가 바뀌면 notifications/tools/list_changed 알림을 보내 Hermes에 알릴 수 있습니다. Hermes가 이 알림을 받으면 서버의 도구 목록을 자동으로 다시 가져오고 레지스트리를 업데이트합니다. 수동 /reload-mcp는 필요 없습니다.

이는 기능이 동적으로 바뀌는 MCP 서버에 유용합니다. 예를 들어 새 데이터베이스 스키마가 로드될 때 도구를 추가하거나, 서비스가 오프라인이 되면 도구를 제거하는 서버가 여기에 해당합니다.

새로고침은 lock으로 보호됩니다. 같은 서버에서 알림이 빠르게 여러 번 와도 겹치는 새로고침이 발생하지 않습니다. 프롬프트와 리소스 변경 알림(prompts/list_changed, resources/list_changed)은 수신하지만 아직 동작에 반영하지 않습니다.

다시 로드

MCP 설정을 바꿨다면 다음을 사용합니다.

/reload-mcp

이 명령은 설정에서 MCP 서버를 다시 로드하고 사용 가능한 도구 목록을 새로고침합니다. 서버가 런타임 도구 변경을 직접 푸시하는 경우는 위의 동적 도구 검색을 참고하세요.

툴셋

설정된 MCP 서버가 하나 이상의 등록된 도구를 제공하면 런타임 툴셋도 생성됩니다.

mcp-<server>

툴셋 수준에서 MCP 서버를 더 쉽게 이해할 수 있게 하기 위한 동작입니다.

보안 모델

Stdio 환경 변수 필터링

stdio 서버의 경우 Hermes는 사용자의 전체 셸 환경을 무조건 넘기지 않습니다.

명시적으로 설정한 env와 안전한 기본값만 전달합니다. 이렇게 하면 비밀값이 우발적으로 새는 위험을 줄일 수 있습니다.

설정 수준 노출 제어

새 필터링 지원은 보안 제어이기도 합니다.

  • 모델에게 보이면 안 되는 위험한 도구 비활성화
  • 민감한 서버에는 최소 허용 목록만 노출
  • 노출하고 싶지 않은 리소스/프롬프트 래퍼 비활성화

사용 사례 예제

최소 이슈 관리 표면을 가진 GitHub 서버

mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "***"
tools:
include: [list_issues, create_issue, update_issue]
prompts: false
resources: false

사용 예:

bug 라벨이 붙은 열린 이슈를 보여 주고, 불안정한 MCP 재연결 동작에 대한 새 이슈 초안을 작성해 줘.

위험한 작업을 제거한 Stripe 서버

mcp_servers:
stripe:
url: "https://mcp.stripe.com"
headers:
Authorization: "Bearer ***"
tools:
exclude: [delete_customer, refund_payment]

사용 예:

최근 실패한 결제 10건을 조회하고 공통 실패 원인을 요약해 줘.

단일 프로젝트 루트용 Filesystem 서버

mcp_servers:
project_fs:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/my-project"]

사용 예:

프로젝트 루트를 검사하고 디렉터리 구성을 설명해 줘.

문제 해결

MCP 서버가 연결되지 않음

확인할 것:

# MCP 의존성이 설치되어 있는지 확인합니다(표준 설치에는 이미 포함됨).
cd ~/.hermes/hermes-agent && uv pip install -e ".[mcp]"

node --version
npx --version

그런 다음 설정을 확인하고 Hermes를 재시작합니다.

도구가 나타나지 않음

가능한 원인:

  • 서버 연결 실패
  • 검색 실패
  • 필터 설정이 도구를 제외함
  • 해당 서버에 유틸리티 기능이 없음
  • 서버가 enabled: false로 비활성화됨

의도적으로 필터링 중이라면 정상입니다.

리소스 또는 프롬프트 유틸리티가 왜 나타나지 않나요?

Hermes는 이제 다음 두 조건이 모두 참일 때만 래퍼를 등록합니다.

  1. 설정이 해당 유틸리티를 허용함
  2. 서버 세션이 실제로 기능을 지원함

이는 의도된 동작이며 도구 목록을 실제 기능과 일치하게 유지합니다.

병렬 도구 호출

기본적으로 MCP 도구는 하나씩 순차 실행됩니다. MCP 서버가 동시에 실행해도 안전한 도구를 제공한다면(예: 읽기 전용 쿼리, 독립 API 호출), 병렬 실행을 옵트인할 수 있습니다.

mcp_servers:
docs:
command: "docs-server"
supports_parallel_tool_calls: true

supports_parallel_tool_callstrue이면 Hermes는 내장 읽기 전용 도구(web_search, read_file 등)처럼 한 도구 호출 배치 안에서 해당 서버의 여러 도구를 동시에 실행할 수 있습니다.

주의

동시에 실행해도 안전한 MCP 서버에만 병렬 호출을 켜세요. 도구가 공유 상태, 파일, 데이터베이스, 외부 리소스를 읽고 쓴다면 이 설정을 켜기 전에 읽기/쓰기 경쟁 조건을 검토해야 합니다.

MCP Sampling 지원

MCP 서버는 sampling/createMessage 프로토콜을 통해 Hermes에 LLM 추론을 요청할 수 있습니다. 이를 통해 MCP 서버는 자체 모델 접근 권한이 없어도 Hermes에게 텍스트 생성을 대신 요청할 수 있습니다.

sampling은 MCP SDK가 지원하는 경우 모든 MCP 서버에 대해 기본으로 활성화됩니다. 서버별로 sampling 키 아래에서 설정합니다.

mcp_servers:
my_server:
command: "my-mcp-server"
sampling:
enabled: true # sampling 활성화(기본값: true)
model: "openai/gpt-4o" # sampling 요청에 사용할 모델 재정의(선택)
max_tokens_cap: 4096 # sampling 응답당 최대 토큰 수(기본값: 4096)
timeout: 30 # 요청당 제한 시간(초, 기본값: 30)
max_rpm: 10 # 속도 제한: 분당 최대 요청 수(기본값: 10)
max_tool_rounds: 5 # sampling 루프에서 도구 사용 최대 라운드(기본값: 5)
allowed_models: [] # 서버가 요청할 수 있는 모델 이름 허용 목록(비어 있으면 제한 없음)
log_level: "info" # 감사 로그 수준: debug, info, warning(기본값: info)

sampling 핸들러에는 폭주 사용량을 막기 위해 슬라이딩 윈도우 레이트 리미터, 요청별 제한 시간, 도구 루프 깊이 제한이 포함됩니다. 지표(request count, errors, tokens used)는 서버 인스턴스별로 추적됩니다.

특정 서버에서 sampling을 비활성화하려면:

mcp_servers:
untrusted_server:
url: "https://mcp.example.com"
sampling:
enabled: false

Hermes를 MCP 서버로 실행

Hermes는 MCP 서버에 연결할 뿐 아니라, 자체적으로 MCP 서버가 될 수도 있습니다. 이 기능을 사용하면 Claude Code, Cursor, Codex 또는 다른 MCP 지원 에이전트가 Hermes의 메시징 기능을 사용할 수 있습니다. 대화 목록을 보고, 메시지 기록을 읽고, 연결된 모든 플랫폼으로 메시지를 보낼 수 있습니다.

사용할 때

  • Claude Code, Cursor 또는 다른 코딩 에이전트가 Hermes를 통해 Telegram/Discord/Slack 메시지를 읽고 보내게 하고 싶음
  • Hermes에 연결된 모든 메시징 플랫폼으로 브리지하는 단일 MCP 서버가 필요함
  • 연결된 플랫폼이 있는 Hermes 게이트웨이가 이미 실행 중임

빠른 시작

hermes mcp serve

이 명령은 stdio MCP 서버를 시작합니다. 프로세스 생명주기는 사용자가 아니라 MCP 클라이언트가 관리합니다.

MCP 클라이언트 설정

Hermes를 MCP 클라이언트 설정에 추가합니다. 예를 들어 Claude Code의 ~/.claude/claude_desktop_config.json:

{
"mcpServers": {
"hermes": {
"command": "hermes",
"args": ["mcp", "serve"]
}
}
}

Hermes를 특정 위치에 설치했다면:

{
"mcpServers": {
"hermes": {
"command": "/home/user/.hermes/hermes-agent/venv/bin/hermes",
"args": ["mcp", "serve"]
}
}
}

사용 가능한 도구

MCP 서버는 OpenClaw의 채널 브리지 인터페이스에 Hermes 전용 채널 브라우저를 더한 10개 도구를 노출합니다.

도구설명
conversations_list활성 메시징 대화를 나열합니다. 플랫폼으로 필터링하거나 이름으로 검색할 수 있습니다.
conversation_get세션 키로 특정 대화의 상세 정보를 가져옵니다.
messages_read대화의 최근 메시지 기록을 읽습니다.
attachments_fetch특정 메시지에서 텍스트가 아닌 첨부파일(image, media)을 추출합니다.
events_poll커서 위치 이후의 새 대화 이벤트를 폴링합니다.
events_wait다음 이벤트가 올 때까지 long-poll/block합니다(준실시간).
messages_send플랫폼을 통해 메시지를 보냅니다. 예: telegram:123456, discord:#general
channels_list모든 플랫폼에서 사용 가능한 메시징 대상을 나열합니다.
permissions_list_open이 브리지 세션에서 관찰된 대기 중인 승인 요청을 나열합니다.
permissions_respond대기 중인 승인 요청을 allow 또는 deny합니다.

이벤트 시스템

MCP 서버에는 Hermes 세션 데이터베이스에서 새 메시지를 폴링하는 실시간 이벤트 브리지가 포함되어 있습니다. 이를 통해 MCP 클라이언트는 들어오는 대화를 거의 실시간으로 인식할 수 있습니다.

# 새 이벤트를 폴링합니다(논블로킹).
events_poll(after_cursor=0)

# 다음 이벤트를 기다립니다(제한 시간까지 블로킹).
events_wait(after_cursor=42, timeout_ms=30000)

이벤트 유형: message, approval_requested, approval_resolved

이벤트 큐는 인메모리이며 브리지가 연결될 때 시작됩니다. 이전 메시지는 messages_read로 접근할 수 있습니다.

옵션

hermes mcp serve              # 일반 모드
hermes mcp serve --verbose # stderr에 디버그 로그 출력

동작 방식

MCP 서버는 Hermes 세션 저장소(~/.hermes/sessions/sessions.json 및 SQLite 데이터베이스)에서 대화 데이터를 직접 읽습니다. 백그라운드 스레드가 데이터베이스에서 새 메시지를 폴링하고 인메모리 이벤트 큐를 유지합니다. 메시지 전송에는 Hermes 에이전트 자체와 같은 send_message 인프라를 사용합니다.

게이트웨이는 읽기 작업(conversation listing, 기록 읽기, 이벤트 폴링)에는 실행 중일 필요가 없습니다. 전송 작업에는 플랫폼 어댑터의 활성 연결이 필요하므로 게이트웨이가 실행 중이어야 합니다.

현재 제한

  • stdio transport만 지원(아직 HTTP MCP transport 없음)
  • mtime 최적화 DB 폴링으로 약 200ms 간격 이벤트 폴링(file이 바뀌지 않으면 작업을 건너뜀)
  • 아직 claude/channel 푸시 알림 프로토콜 없음
  • 텍스트 전송만 지원(messages_send로 미디어/첨부파일 전송 불가)