Claude Code가 실제로 호출하는 방식대로 MCP 서버를 테스트하기 위한 stdio 하네스 (harness)
요약
Claude Code와 동일한 방식으로 MCP 서버를 테스트하기 위한 stdio 하네스 작성법을 소개합니다. 클라이언트의 동작을 모방하여 초기화, 도구 목록 확인, 에러 처리 및 실패 모드를 검증하는 과정을 다룹니다.
핵심 포인트
- stdio를 통해 클라이언트와 동일한 환경에서 서버를 구동하여 검증
- 잘못된 파라미터나 자격 증명 누락 시 모델이 이해 가능한 에러 반환 확인
- 실패 모드 테스트를 통해 모델이 임의의 우회 방법을 만들지 않도록 방지
- 비동기 작업 시 모델이 작업 ID 반환을 인지할 수 있도록 도구 설명 최적화
- request id 매칭과 엄격한 타임아웃 설정을 통한 안정적인 테스트 구현
저는 계속해서 MCP 서버를 배포해 왔지만, Claude Code 내부에서 무언가가 제대로 작동하지 않을 때서야 비로소 그것들이 어색하게 구현되었다는 사실을 깨닫곤 했습니다. 그래서 클라이언트가 하는 것과 동일하게 stdio를 통해 서버를 구동하는 하네스(harness)를 작성했고, 이는 수동으로는 찾아낼 수 없었던 문제들을 잡아냈습니다.
이 하네스가 실행하는 순서는 다음과 같습니다: 클라이언트 설정과 정확히 일치하도록 stdio를 통해 서브프로세스(subprocess)로 서버를 생성(Spawn)합니다. protocolVersion, capabilities, clientInfo를 사용하여 초기화(initialize)합니다. serverInfo를 돌려받는지, 그리고 프로토콜 버전이 예상과 일치하는지 확인(Assert)합니다. 알림(notifications)/initialized를 전송합니다. tools/list를 실행합니다. 모든 도구(tool)가 비어 있지 않은 설명(description)과 유효한 inputSchema를 가지고 있는지 확인합니다. 이 과정은 지루하지만 실제 문제들을 잡아냅니다. 그럴듯한 인자(arguments)를 사용하여 실제 tools/call을 실행한 다음, 반환되는 결과의 실제 형태(shape)를 확인합니다.
그다음은 해피 패스(happy path)보다 더 중요하다고 밝혀진 부분입니다: 의도적으로 잘못된 파라미터(params)로 도구를 호출합니다. 에러가 모델이 읽고 복구할 수 있는 형태로 돌아오는지, 아니면 가공되지 않은 스택 트레이스(stack trace)로 나타나는지 확인합니다. 존재하지 않는 도구를 호출합니다. 깔끔하게 거부되어야 합니다. 잘못된 API 키로 전체 과정을 실행해 보고, 다시 키가 아예 없는 상태로 실행해 봅니다. 자격 증명(credentials)이 누락된 경우, 모델이 이를 우회하려고 시도하는 도구 호출 내부에서 나중에 실패하는 것이 아니라, 해당 변수 이름을 명시하는 메시지와 함께 즉시 실패해야 합니다.
실패 모드(failure modes)는 아무도 테스트하지 않기 때문에 서버가 대개 가장 취약한 부분입니다. 읽을 수 없는 에러를 받은 모델은 문제를 드러내기보다 종종 임의의 우회 방법을 만들어내며, 결국 서버가 아닌 모델을 디버깅하게 됩니다.
확인할 가치가 있는 한 가지가 더 있습니다: 만약 도구 중 일부가 실행 시간이 길고 결과 대신 작업 ID(job id)를 반환한다면, 모델이 도구 설명(tool description)만으로 실제로 그 사실을 알 수 있는지 확인하십시오. 저는 응답 페이로드(payload)만으로 충분하다고 가정했었습니다. 하지만 그렇지 않았습니다.
직접 구현할 경우를 위한 구현 노트: 백그라운드 스레드에서 stdout을 한 줄씩 읽고 각 줄을 JSON으로 파싱하십시오. 순서를 가정하는 대신 request id를 통해 응답을 매칭하고, 폴링 루프(poll loop)에 엄격한 타임아웃(hard timeout)을 설정하여 서버가 멈췄을 때 테스트 자체가 멈추는 대신 실패하도록 만드십시오. 오후 시간을 들여 작업했으며, 이제 저는 이것 없이는 MCP 서버를 출시하지 않을 것입니다. /u/Confident-Truck-7186 제출 [link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/ClaudeAI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기