본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 27. 03:34

사용되지 않는 MCP 플러그인이 조용히 컨텍스트를 잡아먹는다 ― 주간 자동 disable로 상시 경량화

요약

Claude Code 사용 시 사용하지 않는 MCP 플러그인이 컨텍스트 토큰을 점유하는 문제를 해결하기 위한 자동화 가이드를 제공합니다. 30일간 미사용된 플러그인을 탐지하고 자동으로 비활성화하며 캐시를 정리하는 3단계 파이프라인을 소개합니다.

핵심 포인트

  • 활성화된 MCP 플러그인은 호출 여부와 상관없이 tool schema를 주입하여 컨텍스트를 소모함
  • jq를 활용해 실제 tool_use 호출 기록만 정확히 집계하여 휴면 플러그인 판별
  • 탐지, 자동 비활성화, 캐시 아카이브로 이어지는 3단계 자동화 스크립트 구성
  • 주간 단위 자동화를 통해 Claude Code의 컨텍스트 효율성을 상시 유지

「Claude Code 환경」 시리즈의 연속입니다. 전작인 git 설정 백업 자동화에 이어, 이번에는 활성화해 둔 채 방치한 MCP 플러그인이 컨텍스트를 조용히 깎아먹는 문제와, 이를 주간 단위로 자동 disable 하는 3단계 파이프라인을 작성합니다.

플러그인을 enable 하면, 한 번도 호출되지 않더라도 기동 시에 tool schema가 주입됩니다. 「그대로 둔 상태」가 쌓이면 Claude가 실제로 사용할 수 있는 토큰량이 조용히 줄어듭니다. 이 기사에서는 그 탐지부터 자동 disable · 캐시 아카이브까지 실제 코드로 하나로 연결합니다.

새로운 플러그인을 넣는 동기는 명확합니다. 「이 도구를 사용하고 싶다」라는 능동적인 충동이 있습니다. 제거하는 동기는 존재하지 않습니다. 「저 플러그인 최근에 안 썼네」라고 깨달을 기회가 애초에 없습니다.

Claude Code는 세션 시작 시, settings.jsonenabledPlugins에서 true로 되어 있는 플러그인 전건의 tool schema를 context에 주입합니다. 「활성화되어 있지만 30일 동안 한 번도 호출되지 않은」 플러그인이 늘어날수록, 매번 컨텍스트의 앞부분이 기여도 제로인 데이터로 채워집니다.

수개월 동안 테스트하며 enable 해둔 채 잊어버린 플러그인이 쌓이면 Dormant(활성화되어 있지만 미사용)가 30개를 넘는 경우가 있습니다.

plugin-usage.sh → 휴면 플러그인을 가시화 (수동 실행 / 주간 리포트)
plugin-auto-disable.sh → 30일 미사용을 주간 단위로 자동 disable
cleanup-plugin-cache.sh → 무효화된 캐시를 .disabled-cache/ 로 아카이브

plugin-auto-disable.sh apply의 끝부분이 cleanup-plugin-cache.sh apply를 연쇄 호출하는 구성이므로, launchd로부터 기동하는 엔트리 포인트는 하나입니다.

~/.claude/scripts/plugin-usage.sh는 과거 N일(기본 14일)의 세션 JSONL로부터, 실제로 tool_use로서 호출된 플러그인만을 집계합니다.

# plugin-usage.sh 발췌
LOG_DIR="$HOME/.claude/projects/-Users-matsubara"
DAYS="${1:-14}"
...

enabled plugin 수와 distinct 호출 수의 차이를 Dormant로 산출합니다.

TOTAL_ENABLED=$(jq -r '[.enabledPlugins // {} | to_entries[] | select(.value)] | length' "$SETTINGS")
# Dormant = TOTAL_ENABLED - USED_COUNT

왜 grep이 아니라 jq로 집계하는가

이전 구현은 grep으로 부분 문자열 매칭을 했습니다. JSONL 내의 「deferred tools 전체 열거」 행(사용 가능한 도구 이름의 방대한 리스트)을 「호출」로 오계상하여, terraform 등이 호출하지 않았는데 상위에 나타나거나, Dormant 수가 마이너스가 되기도 했습니다. select(.type=="tool_use")를 통과시킴으로써 실제로 호출된 호출만을 세도록 수정했습니다.

출력 이미지:

## Summary
- Enabled plugins: **62**
- Distinct plugins referenced in logs: **29**
...

Dormant가 30을 초과하면 "Heavy dormant load"라고 출력됩니다. 이 임계값은 스크립트 내에 하드코딩되어 있습니다.

~/.claude/scripts/plugin-auto-disable.sh가 본체입니다. 기본값은 dry(변경 없음)이며, apply를 전달하면 실제로 무효화합니다.

# plugin-auto-disable.sh 발췌
MODE="${1:-dry}"
DAYS="${DAYS:-30}" # 관측 윈도우 (기본 30일)
...

동작 플로우:

  • 과거 30일의 JSONL로부터 MCP 호출 + Skill 호출을 인덱스화
  • enabledPlugins에서 true

python3로 플러그인 목록을 가져옴 - PROTECTED 리스트에 포함된 항목은 제외

  • 후보를 캐시 크기 내림차순으로 정렬하고,
    MIN_CACHE_MB

이상의 항목을 WEEKLY_MAX

건까지 압축 -
apply

모드일 때는 plugin-disable.sh apply

cleanup-plugin-cache.sh apply

를 순서대로 실행

# 후보를 크기순으로 정렬하여 WEEKLY_MAX 건 선출
SIZED=()
for p in "${CANDIDATES[@]}"; do
...

캐시 크기 내림차순으로 우선순위를 두는 이유는 삭제할 수 있는 컨텍스트(Context) 양이 큰 것부터 처리하기 위해서입니다.

자동 비활성화(disable)의 가장 큰 리스크는 오탐(False Positive)입니다. "거의 사용하지 않지만 삭제되면 곤란한" 플러그인을 보호하기 위해 PROTECTED 배열이 존재합니다.

PROTECTED=(
remember plugin-dev hookify skill-creator session-report
security-guidance superpowers context7 explanatory-output-style
...

카테고리별 보호 이유:

카테고리대표 사례보호 이유
인프라 계열hookify superpowers remember기동 시 후크(Hook) 및 스킬 호출의 핵심. JSONL에 tool_use로 나타나지 않음
LSP 계열typescript-lspClaude Code 본체가 내부적으로 투명하게 호출. 로그에 기록되지 않음
개발 지원code-review feature-devad-hoc하게 사용. 호출하지 않는 기간이 길더라도 필요함
기지 오탐azure-cosmos-db-assistant과거에 자동 비활성화하여 곤란했던 사례가 있음

LSP 계열을 PROTECTED에 넣지 않으면 즉시 문제가 발생합니다.

typescript-lsp 등은 Claude Code 본체가 내부적으로 사용합니다. 사용자가 명시적으로 Skill 도구나 MCP 도구로서 호출하는 것이 아니기 때문에 tool_use 로그에 나타나지 않습니다. PROTECTED에 넣어두지 않으면, 평소처럼 사용하고 있음에도 불구하고 자동으로 비활성화됩니다.

비활성화하더라도 ~/.claude/plugins/cache/에 캐시는 남습니다. cleanup-plugin-cache.sh가 이를 ~/.claude/plugins/.disabled-cache/로 이동시킵니다.

# cleanup-plugin-cache.sh 발췌
CACHE_DIR="$HOME/.claude/plugins/cache/claude-plugins-official"
ARCHIVE_DIR="$HOME/.claude/plugins/.disabled-cache"
...

실제로 삭제하지는 않습니다. mv 명령어로 대피시키는 것뿐이므로, 복구는 mv 한 번으로 가능한 가역적인 작업입니다.

나아가 purge 서브 모드를 통해 .disabled-cache/PURGE_DAYS (기본 30일) 이상 방치된 항목만 물리적으로 삭제할 수 있습니다.

# 아카이브에서 30일 후 물리 삭제
~/.claude/scripts/cleanup-plugin-cache.sh purge

~/Library/LaunchAgents/com.shun.plugin-auto-disable.plist를 통해 주간 스케줄을 설정했습니다.

<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
...

매주 일요일 06:45에 plugin-auto-disable.sh apply가 실행되며, 로그는 ~/.claude/logs/plugin-auto-disable.log에 추가됩니다.

등록 및 확인:

# 등록
launchctl load ~/Library/LaunchAgents/com.shun.plugin-auto-disable.plist
# 동작 확인
...
  • grep의 부분 일치(partial match)가 deferred tools 열거 행을 "호출"로 잘못 포착함 → jq를 사용하여 type=="tool_use"를 명시하기 전까지 Dormant(휴면) 수가 마이너스로 계산되는 문제가 있었다. terraform 등이 유령처럼 상위에 나타나곤 했다.

  • LSP 계열을 PROTECTED(보호) 목록에 넣는 것을 잊어 비활성화됨typescript-lsp가 사라진 후 타입 체크(type check)가 작동하지 않게 되었다. PROTECTED에 추가하여 복구했다.

  • 5MB 미만은 영향(impact)이 적고 리스크만 있음 → 기본값 5MB로 필터 MIN_CACHE_MB를 설정하지 않으면 미세한 캐시를 가진 플러그인까지 대상이 된다.

  • 주당 5건 제한 → 서둘러 한꺼번에 처리할 필요는 없다. WEEKLY_MAX를 너무 크게 설정하면 필요한 플러그인까지 휘말릴 수 있다.

  • launchd가 Mac 슬립(sleep) 중에 작업을 건너뜀 → 일요일 아침 06:45는 기기가 켜져 있는 경우가 많은 시간대다. 건너뛰더라도 다음 주로 미뤄질 뿐 실질적인 해는 없다.

  • plugin-disable.sh가 존재하지 않으면 apply가 헛스윙함plugin-auto-disable.sh는 내부에서 이 스크립트를 호출하는 래퍼(wrapper) 구성이다. 스크립트 세트를 모두 갖추지 않으면 동작하지 않는다.

  • plugin-usage.sh로 세션 JSONL의 실제 tool_use를 집계하여 Dormant 플러그인을 시각화한다. 기존 grep 구현은 deferred tools 열거 행을 오계산한다. jq로 type=="tool_use"를 명시하는 것이 정답이다.

  • plugin-auto-disable.sh가 30일 미사용 · 캐시 5MB 이상 · 주 5건 상한 조건으로 자동 비활성화(disable)한다.

  • PROTECTED 리스트에 LSP · 인프라 계열 · 알려진 오탐(false positive)을 반드시 넣어야 한다. 넣지 않으면 필요한 플러그인이 사라진다.

  • cleanup-plugin-cache.sh가 캐시를 .disabled-cache/로 아카이브(archive)한다. 30일 후 purge를 통해 물리적으로 삭제한다.

  • launchd의 Weekday=0 / Hour=6 / Minute=45 설정으로 매주 일요일 06:45에 무인 실행된다.

다음에는, 이를 통해 확보한 컨텍스트 여유를 확인하기 위해 만든 **statusline의 실시간 컨텍스트 사용률 미터기(meter)**에 대해 쓰겠습니다.

Lily (@bokuwalily) ― 개인 개발자. Claude Code로 자동화 기반을 구축하며, iOS 앱과 웹 서비스를 양산하고 있습니다.

  • 제작물 및 기사는 bokuwalily.com에 정리되어 있습니다 🖥️
  • AI로 "자고 있어도 돌아가는 시스템"을 만들어 월 120만 엔을 벌게 된 이야기는 note의 유료 기사에 💰
  • OSS: github.com/bokuwalily 🐙
  • 최신 정보 및 문의는 X @bokuwalily 로 🌍

여러분의 ❤️와 공유가 큰 힘이 됩니다!

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0