Skip to main content
Glama

pebble-index-mcp

로컬 Obsidian 볼트와 Hermes Agent 인스턴스를 Pebble Index 01 스마트 링의 더블클릭 MCP 샌드박스에 노출하는 MCP 브리지입니다. 링에서 캡처한 음성은 Pebble 앱의 클라우드 에이전트를 통해 이 서버의 도구로 라우팅되며, 답변은 휴대폰 알림으로 돌아옵니다.

아키텍처

[Index ring] → [Pebble app] → [Pebble cloud agent] → [this MCP server]
                                                        ├─ vault tools (local files)
                                                        └─ ask_hermes → Hermes API server
  • 서버는 Streamable HTTP를 통해 MCP를 사용합니다(공식 mcp SDK, FastMCP).

  • 모든 요청은 bearer 토큰을携带해야 하며, 그 외에는 401을 반환합니다.

  • FastMCP의 DNS 리바인딩 보호가 활성화되어 있습니다: 허용된 호스트는 루프백과 MCP_ALLOWED_HOSTS에 나열된 모든 항목입니다.

  • 공개 노출은 루프백 포트로의 cloudflared 터널입니다. 그 외에 클라우드 인프라는 필요하지 않습니다.

Related MCP server: Obsidian MCP Server

구성 요소

경로

역할

src/pebble_index_mcp/vault.py

Vault: 경로 샌드박스가 적용된 읽기/추가 + 볼트에 대한 ripgrep 검색. 모든 경로는 볼트 루트 내부에서 해석됩니다. 절대 경로, .. 탐색, 심볼릭 링크 탈출은 거부됩니다. 추가는 추가 전용이며, 타임스탬프가 찍히고 덮어쓰지 않습니다.

src/pebble_index_mcp/hermes.py

HermesClient: 질문을 OpenAI 호환 채팅 완료 엔드포인트로 전달하며, 짧은 답변 시스템 힌트를 포함합니다. 시간 초과/전송 실패/잘못된 형태를 HermesTimeout/HermesError로 매핑합니다.

src/pebble_index_mcp/server.py

FastMCP 앱: 네 가지 도구와 ring_persona 프롬프트를 등록하고, streamable-http 앱을 bearer 인증(상수 시간 비교)으로 감싸고 호스트 허용 목록을 구성합니다.

도구

  • vault_search(query, max_results=5) — 대소문자를 구분하지 않는 텍스트 검색; path: excerpt 줄을 반환합니다.

  • vault_read(note_path, max_chars=1500) — 노트의 앞부분을 읽습니다.

  • vault_append(note_path, text) — 타임스탬프가 찍힌 - HH:MM text 줄을 추가하며, 필요시 노트를 생성합니다.

  • ask_hermes(question) — Hermes API 서버로 전달합니다. 60초 시간 초과이며, 실패 시 정직한 확인을 반환합니다.

보안

  • 인증: 정적 bearer 토큰(MCP_BEARER_TOKEN), 상수 시간 비교, 모든 요청에 필수. 빈 토큰은 실패 시 닫힘(모든 요청 401) 및 시작 시 경고를 기록합니다.

  • 전송: TLS는 터널 가장자리에서 종료됩니다. 오리진은 루프백에서만 수신합니다.

  • 호스트 검증: DNS 리바인딩 보호는 Host 헤더가 루프백이거나 MCP_ALLOWED_HOSTS에 없는 요청을 거부합니다.

  • 경로 샌드박스: 볼트 도구는 모든 경로를 해석하고 볼트 루트 내부에 있어야 합니다. 심볼릭 링크 탈출은 거부되며 파일 열기는 최종 구성 요소에 O_NOFOLLOW를 사용합니다. 샌드박스는 우발적 및 원격 오용을 방지합니다. 적대적인 로컬 프로세스가 상위 디렉터리 교체를 경쟁적으로 수행하면 여전히 이길 수 있습니다(문서화된 TOCTOU 경계 — 볼트는 신뢰할 수 있는 단일 사용자 디렉터리로 가정).

  • 구성은 가져오기 시 한 번 읽습니다: bearer 토큰을 회전하거나 허용된 호스트를 변경하려면 서비스 재시작이 필요합니다.

  • 비밀: Hermes API 키와 MCP 토큰은 이 저장소 외부의 0600 환경 파일에 있으며, 코드, 로그, 커밋에 절대 포함되지 않습니다.

  • 개인정보 참고: 더블클릭 샌드박스를 통해 라우팅된 녹음은 Pebble 앱의 클라우드 에이전트를 통과합니다. 싱글클릭 캡처는 기기에만 남습니다. 민감한 생각은 싱글클릭에 속합니다.

구성 (env)

변수

기본값

용도

VAULT_PATH

—

필수. 파일 도구용 볼트 루트

MCP_HOST / MCP_PORT

127.0.0.1 / 8765

수신 주소

MCP_BEARER_TOKEN

—

필수; 요청 인증 토큰

MCP_ALLOWED_HOSTS

—

쉼표로 구분된 추가 허용 Host 값 (공개 터널 호스트 이름이 여기에 들어감)

HERMES_API_URL

http://127.0.0.1:8642/v1/chat/completions

ask_hermes 대상

HERMES_API_KEY

—

API 서버 bearer 키

RING_MODEL

pebble-ring

업스트림으로 전송되는 모델 별칭 (API 서버의 model_routes를 통해 저렴한 모델로 매핑)

RING_PERSONA_FILE

—

일반 클라우드 에이전트 페르소나를 대체하는 텍스트 파일의 선택적 경로

HERMES_API_URL은 모든 OpenAI 호환 채팅 완료 엔드포인트를 허용하므로 ask_hermes는 OpenRouter, Ollama 또는 기타 호환 API에서 직접 작동합니다. Hermes는 기본값일 뿐입니다.

개발

python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest -v

로컬 실행: 위의 환경 변수를 설정하고 python -m pebble_index_mcp.server를 실행합니다.

배포

deploy/에는 systemd 사용자 유닛 템플릿과 cloudflared 터널 템플릿이 포함되어 있습니다(호스트 이름과 자격 증명은 이 저장소가 아닌 호스트에서 채워집니다). 휴대폰 측 설정 및 테스트 매트릭스는 docs/ring-checklist.md를 참조하세요.

라이선스

MIT — LICENSE 참조.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers