CLI 도구의 블라인드스팟 디버깅: ‘Reload’ 명령이 항상 모든 것을 다시 로드하지 않는 이유
Source: Dev.to
유령 같은 “429 플랜 만료” 오류
내 설정은 특정 API 플랜(GLM Coding Plan)으로 구동되는 Claude Code를 사용했습니다. 초기 API 키가 만료된 후 구독을 갱신하고 새 키를 받아 CLI 도우미가 제공한 표준 명령어로 자격 증명을 다시 로드했습니다:
chelper auth reload claude
내장된 상태 검사(chelper doctor)를 실행했으며, 모든 것이 초록색 체크 표시가 가득한 완벽한 문자열을 반환했습니다.
- 경로? 유효함.
- API 키 및 네트워크? 유효함.
- 플랜? 활성화됨.
하지만 Model Context Protocol (MCP) 도구, 특히 web-reader 도구를 호출하려는 순간, 에이전트가 즉시 다음 오류와 함께 충돌했습니다:
Error: MCP error -429: {"error":{"code":1309,"message":"Your GLM Coding Plan has expired, please renew to restore access."}}
상태 검사는 통과했고, 일반 채팅은 완벽히 작동했지만, MCP 도구는 내 계정이 만료되었다고 외쳤습니다.
조사: 차이점 찾기
UI와 CLI 도구가 서로 충돌하는 정보를 보여주었기 때문에, 나는 이를 우회하고 직접 기본 설정 파일을 확인했다.
자격 증명이 이론적으로 저장될 수 있는 두 위치를 확인했다:
- CLI 헬퍼의 메인 설정 (
~/.chelper/config.yaml) – 새롭고 유효한 API 키가 들어 있었다. - Claude Code의 MCP 설정 (
~/.claude.json) –mcpServers객체를 보면, MCP 도구용Authorization: Bearer헤더가 여전히 오래된, 만료된 API 키를 사용하고 있었다.
우리는 ‘분열된 사고’ 상황에 처했다. MCP 도구들은 오래된 설정 파일을 읽고 있었다.
Root Cause Analysis: Diving into node_modules
왜 chelper auth reload가 MCP 설정을 업데이트하지 못했을까요? 저는 node_modules/@z_ai/coding-helper/dist/lib/claude-code-manager.js에 위치한 CLI 소스 코드를 열어 설정을 다시 로드하는 함수가 어디에 있는지 찾았습니다:
loadGLMConfig(plan, apiKey) {
// 1. Ensure onboarding is completed
this.ensureOnboardingCompleted();
// 2. Clean up shell environment variables
this.cleanupShellEnvVars();
// 3. Update ANTHROPIC_AUTH_TOKEN in settings.json
this.saveSettings(glmConfig);
}
Claude Code는 실제로 설정을 두 개의 별도 파일로 나눕니다:
~/.claude/settings.json– 표준 Claude API 호출에 사용됩니다.~/.claude.json– MCP 서버와 해당 인증 헤더를 등록하는 데 사용됩니다.
CLI 개발자는 this.saveSettings()를 표준 API 토큰을 업데이트하도록만 구현했으며, MCP 서버 설정은 전혀 고려하지 않았습니다. 그 결과, 이전에 등록된 HTTP 기반 MCP 도구들은 만료된 인증 정보와 함께 남겨졌습니다.
The Fix
If you encounter a similar misbehaving CLI wrapper, you can’t rely on its reload command. Choose one of the following options:
Option 1: The Nuclear Option (Recommended)
Run the initialization command again from scratch. This usually forces the tool to overwrite all files completely.
npx @z_ai/coding-helper init
Option 2: The Python Automation Fix
If you have heavily customized your mcpServers and don’t want to reset everything, use a script to update the headers automatically:
import json
import os
config_path = os.path.expanduser('~/.claude.json')
new_key = "YOUR_NEW_VALID_API_KEY"
try:
with open(config_path, 'r') as f:
config = json.load(f)
# Iterate through all configured MCP servers
for mcp_name, mcp_config in config.get('mcpServers', {}).items():
# Update only those that use HTTP headers for authentication
if 'headers' in mcp_config:
config['mcpServers'][mcp_name]['headers']['Authorization'] = f'Bearer {new_key}'
print(f"Updated auth token for MCP tool: {mcp_name}")
with open(config_path, 'w') as f:
json.dump(config, f, indent=2)
print("All MCP keys updated successfully!")
except FileNotFoundError:
print("Error: ~/.claude.json configuration file not found.")
SDET 요약
이것이 소프트웨어 개발 엔지니어 인 테스트 (SDETs) 가 UI의 녹색 표시나 일반 CLI 출력에만 의존하지 않는 이유입니다. 자동화 도구가 “Success!” 라고 알려도 시스템이 실패한 것처럼 동작한다면, 거의 항상 그 아래에 상태‑동기화 문제가 존재합니다. 우리를 돕기 위해 설계된 추상화 레이어가 금세 사각지대가 될 수 있습니다.
디버깅 툴체인 골든 룰: 시스템 동작이 구성 상태와 모순될 때, 관리 도구를 신뢰하는 것을 멈추고 원시 .json 및 .yaml 파일을 읽기 시작하세요.