MCP 서버 테스트 플레이북: Apidog 활용 수동 및 자동화

Ashley Innocent

Ashley Innocent

11 May 2026

MCP 서버 테스트 플레이북: Apidog 활용 수동 및 자동화

이번 주 초, “Ableton Live MCP” Show HN 게시물이 118점과 78개의 댓글을 받았습니다. 이제 익숙한 패턴입니다. 누군가가 예상치 못한 도구를 위한 모델 컨텍스트 프로토콜(Model Context Protocol) 서버를 작성했고, Claude Desktop 사용자들은 이를 좋아했으며, “X를 위해 하나 만들까요?”라는 질문이 이어졌습니다. MCP는 1년도 채 되지 않아 Anthropic 전용 실험에서 기본 에이전트 통합 계층으로 발전했습니다.

이러한 성장은 도구의 빈틈을 감추고 있습니다. MCP 서버를 깔끔하게 테스트할 수 있는 방법을 아무도 제공하지 않았습니다. 디버거를 사용하여 stdio를 통해 JSON-RPC를 수동으로 실행하는 것은 "hello-world" 수준에서는 괜찮지만, 서버에 12개의 도구, 3개의 프롬프트, 그리고 불안정한 업스트림 API가 있을 때는 무너집니다. 이 가이드는 MCP 서버를 수동으로 테스트하고 Apidog를 사용하여 테스트를 자동화하는 실용적인 플레이북을 제공하여, 다른 API를 출시하는 방식과 동일하게 계약, 목(mock), 그리고 회귀 테스트 스위트를 통해 MCP 서버를 출시할 수 있도록 돕습니다.

만약 더 일반적인 에이전트 컨텍스트에서 오셨다면, 저희의 agents.md 가이드가 이 내용과 잘 어울립니다. 해당 가이드의 규칙은 MCP 서버 계약을 팀에 더 쉽게 전달할 수 있도록 합니다.

버튼

요약 (TL;DR)

2분 만에 알아보는 MCP란 무엇인가

모델 컨텍스트 프로토콜 사양은 작은 표면을 가진 JSON-RPC 2.0 와이어 형식을 정의합니다. 클라이언트(Claude Desktop, Cursor, 또는 자체 에이전트)는 MCP 서버를 시작하고, initialize 핸드셰이크를 수행한 다음, 호출을 발행합니다.

시간의 90퍼센트를 할애하여 테스트할 다섯 가지 호출:

전송 방식은 stdio (stdin/stdout에서 개행 문자로 구분된 JSON-RPC 프레임) 또는 스트림 가능한 HTTP (일반적으로 스트리밍을 위한 SSE가 포함된 POST /)입니다. 대부분의 로컬 서버는 stdio를 사용하며, 원격 서버는 HTTP를 사용합니다.

테스트가 중요한 이유: 모든 Claude Desktop 사용자, 모든 Cursor 사용자, MCP 지원을 추가하는 모든 IDE가 귀하의 서버를 호출할 것입니다. tools/list 형태의 버그는 모든 클라이언트를 동시에 중단시킵니다. 회귀(regression)의 비용은 높습니다.

무엇을 테스트해야 하는가

견고한 MCP 서버 테스트 스위트는 여섯 가지 측면을 다룹니다.

프로토콜 준수. initialize가 올바른 protocolVersion을 반환합니까? 서버가 실제로 지원하는 기능을 광고합니까?

스키마 정확성. tools/list의 각 도구가 인수에 대한 유효한 JSON 스키마를 가지고 있습니까? 필수 필드가 표시되어 있습니까? 설명이 세 단어보다 길습니까? 비어있는 설명은 Claude에서 도구 선택을 방해합니다.

도구 동작. 각 도구에 대해 tools/call이 올바른 유형(text, image, resource)의 콘텐츠 블록을 반환합니까? 오류의 경우 JSON-RPC 오류를 throw하는 대신 isError: true 결과를 반환합니까?

리소스 접근. resources/read를 통해 호출될 때 resources/list URI가 해결됩니까? 첫 페이지 이후에도 페이지네이션이 작동합니까?

프롬프트 렌더링. 프롬프트가 잘 구성된 messages 배열을 반환합니까? 인수 대체가 올바른 위치에 들어갑니까?

실패 모드. 업스트림 API가 다운되면 어떻게 됩니까? 도구 인수가 누락되면? 클라이언트 타임아웃이 발생하면? 이러한 버그는 "hello-world" 단계가 아니라 프로덕션 환경에서 나타납니다.

이 가이드의 나머지 부분에서는 이러한 각 사항을 수동으로 먼저 다루고, 그 다음 자동화된 방식으로 다룹니다.

stdio를 이용한 수동 테스트

가장 간단한 설정으로 시작하세요: 터미널, 서버 바이너리, 그리고 MCP 인스펙터 또는 직접 JSON-RPC를 수동으로 실행하는 것입니다.

아직 서버를 구축하지 않았다면, Python 또는 TypeScript로 공식 MCP SDK 퀵스타트를 사용하여 스캐폴드(scaffold)를 만드세요. 두 개의 도구를 가진 날씨 예제만으로도 충분히 테스트할 수 있습니다.

인스펙터 모드에서 서버를 실행하세요:

npx @modelcontextprotocol/inspector node your-server.js

인스펙터는 서버에 MCP를 사용하는 로컬 웹 UI를 부팅하고 모든 요청과 응답을 보여줍니다. 이는 서버가 시작되고, 기능을 광고하며, tools/list에 응답하는지 확인하는 가장 빠른 방법입니다.

인스펙터 보기가 올바르게 보이면, Apidog를 위한 프레임을 캡처할 수 있도록 동일한 흐름을 원시 stdio로 실행하세요:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-04-01","capabilities":{}}}' | node your-server.js

stdout으로 JSON-RPC 응답을 받을 것입니다. 요청과 응답을 저장하세요. tools/list, tools/call, resources/list 등에도 동일하게 반복하세요. 이 연습을 마치면 서버의 와이어 레벨 계약을 정의하는 6개에서 12개의 표준 요청-응답 쌍을 얻게 됩니다.

두 가지 주의할 점.

첫째, 콘텐츠 블록입니다. 도구 결과는 content: [{ type: "text", text: "..." }] 또는 content: [{ type: "image", data: "...", mimeType: "image/png" }]를 반환합니다. 하나의 응답에서 유형을 혼합하는 것은 허용되지만, 클라이언트에 따라 렌더링 방식이 다릅니다.

둘째, 오류입니다. MCP 사양은 명확합니다: 도구 실행 오류는 isError: true와 실패를 설명하는 콘텐츠 블록을 포함하는 정상적인 결과를 반환합니다. 도구 내부에서 JSON-RPC 오류 응답을 throw하지 마세요. 이는 도구 수준의 실패가 아닌 프로토콜 수준의 실패를 나타냅니다. 많은 클라이언트가 프로토콜 오류 발생 시 연결을 끊습니다.

수동에서 자동화로: Apidog에서 테스트 스위트 구축하기

수동 테스트는 명백한 버그를 찾아냅니다. "내 마지막 변경 사항이 도구 7의 인수 스키마를 망가뜨렸나?"라고 묻기 시작하고 이를 알아내기 위해 12개의 curl 명령을 입력하고 싶지 않을 때 자동화로 전환하게 됩니다.

패턴: 수동 테스트 중에 저장한 모든 요청-응답 쌍을 Apidog에 저장된 요청으로 붙여넣고, 어설션을 추가한 다음, 푸시할 때마다 스위트를 실행합니다.

1. MCP 서버를 위한 Apidog 프로젝트 생성

Apidog를 열고 새 프로젝트를 생성한 다음, 기본 URL을 MCP 서버의 HTTP 엔드포인트(또는 stdio 브릿지 URL; 아래 참조)로 설정하세요. Apidog 프로젝트는 REST와 JSON-RPC를 모두 지원하므로 JSON-RPC 환경을 생성하세요.

HTTP 인터페이스가 없는 stdio 서버의 경우, 테스트를 위해 얇은 HTTP 래퍼 뒤에서 실행하세요. 공식 인스펙터가 하나를 제공하며, 또는 HTTP를 통해 JSON-RPC를 읽고 stdio로 전달하는 30줄짜리 Node 스크립트도 잘 작동합니다. 우리는 비-HTTP 백엔드를 위한 2026년 Postman 없이 API 테스트하기에서도 동일한 패턴을 사용합니다.

2. 표준 요청 저장

initialize, tools/list, tools/call, resources/list, resources/read, prompts/list, prompts/get 각각에 대해 JSON-RPC 본문을 요청으로 저장하세요. Apidog는 본문, 헤더, 예상 상태와 함께 이를 저장합니다.

Apidog의 요청 본문 보기에서 tools/call 요청은 다음과 같습니다:

{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "city": "Tokyo"
    }
  }
}

3. 어설션 추가

자동화의 핵심은 요청을 보내는 것이 아니라 응답에 대해 어설션하는 것입니다. Apidog는 JSONPath 어설션을 기본적으로 지원합니다. tools/list의 경우 최소한 다음이 필요합니다:

알려진 유효한 입력에 대한 tools/call의 경우 다음이 필요합니다:

알려진 잘못된 입력(필수 인수가 누락된 경우)에 대한 tools/call의 경우 다음이 필요합니다:

Apidog는 이러한 어설션을 요청별로 저장합니다. 실패는 실행 보고서에 표시됩니다.

4. 업스트림 API 모의(Mock)

대부분의 MCP 서버는 외부 API(날씨 데이터, GitHub, Linear, 내부 데이터베이스)를 감싸고 있습니다. CI 실행이 모든 커밋에서 라이브 API를 호출하는 것을 원치 않을 것입니다. 두 가지 이유가 있습니다: 비용과 불안정성.

Apidog의 내장 목 서버가 이를 해결합니다. 각 업스트림 엔드포인트를 현실적인 JSON 본문을 반환하는 모의(mocked) 경로로 정의하세요. 테스트 중에는 MCP 서버의 구성을 목 URL로 지정하고, 실제 실행 중에는 프로덕션 URL로 지정하세요. 우리는 계약 우선 API 개발에서 목 워크플로우를 자세히 다룹니다.

결과: 몇 초 만에 실행되고, 외부 네트워크가 필요 없으며, 스키마 회귀를 출시 훨씬 전에 잡아내는 테스트 스위트입니다.

5. CI에서 스위트 실행

Apidog 프로젝트는 CLI 러너로 내보낼 수 있습니다. apidog run 명령은 프로젝트 ID를 받아 모든 저장된 요청을 실행하고, 어설션을 평가하며, 실패 시 0이 아닌 값으로 종료됩니다. 이를 GitHub Actions 또는 이미 사용 중인 모든 CI 공급자에 연결하세요.

최소한의 워크플로우:

name: MCP server tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - name: Start MCP HTTP wrapper
        run: node test/wrapper.js &
      - name: Run Apidog suite
        run: npx apidog run --project-id $APIDOG_PROJECT --env ci
        env:
          APIDOG_PROJECT: ${{ secrets.APIDOG_PROJECT }}
          APIDOG_TOKEN:   ${{ secrets.APIDOG_TOKEN }}

모든 푸시는 전체 MCP 계약을 실행합니다. 도구 7의 스키마 회귀는 드러나지 않고는 배포될 수 없습니다.

좋은 테스트 커버리지는 어떤 모습일까

Apidog에서 완전한 MCP 서버 테스트 계획은 일반적으로 다음을 포함합니다:

3개의 리소스와 4개의 프롬프트를 가진 10개의 도구 서버의 경우, 스위트는 50~70개의 요청을 처리합니다. Apidog는 목 서버가 준비된 상태에서 이를 로컬에서 10초 이내에 실행합니다.

MCP 서버 테스트 시 흔한 실수

이것들은 우리가 가장 자주 보는 패턴입니다.

initialize 왕복 건너뛰기. 일부 서버는 핸드셰이크 내에서 도구 레지스트리를 지연 빌드하기 때문에 initialize가 호출되지 않으면 tools/list에서 충돌합니다. 항상 initialize를 먼저 실행하세요.

원시 오류 문자열에 대한 어설션. 도구 실패 메시지는 변경될 수 있습니다. 정확한 문자열 일치가 아닌, isError: true와 안정적인 오류 코드 또는 정규식에 대해 어설션하세요.

목(mock)이 프로덕션과 동떨어지게 두는 것. 실제 API가 절대 반환하지 않는 형태를 반환하는 목은 깨진 통합에 대해 녹색 테스트를 제공합니다. 매 릴리스마다 실제 응답에서 목 픽스처를 다시 기록하세요.

스트리밍을 잊는 것. HTTP MCP 서버는 SSE를 통해 도구 결과를 스트리밍합니다. 테스트 러너는 SSE를 처리해야 합니다. Apidog는 이를 지원하지만, 요청에서 스트리밍을 활성화해야 합니다.

동시성 테스트를 하지 않는 것. MCP 클라이언트는 에이전트 루프에서 동시적인 tools/call 요청을 보냅니다. 서버가 잠금 없이 공유 상태를 유지한다면, 단일 요청 테스트는 통과하고 프로덕션은 고장납니다. 스위트에 병렬 실행 테스트를 추가하세요.

프로토콜 오류와 도구 오류를 혼동하는 것. MCP 사양은 의도적으로 이들을 분리합니다. 이를 혼동하면 Claude Desktop이 연결을 끊게 됩니다. 우리는 API 플랫폼 계약 우선 개발에서 이와 같은 종류의 계약 버그를 다뤘습니다.

실제 사용 사례

회사 내부의 사고 관리 API를 위한 MCP 서버를 구축하는 한 팀은 Apidog의 tools/list 형태에 대한 어설션을 사용하여 일주일 만에 세 가지 회귀(regression)를 발견했습니다. 이 테스트가 없었다면, 버그는 Claude Desktop을 사용하는 모든 엔지니어에게 동시에 배포되었을 것입니다.

Notion용 오픈소스 MCP 서버를 게시하는 한 개인 개발자는 CI 중에 Notion의 호출 제한에 도달하지 않으면서 테스트 스위트를 실행하기 위해 Apidog 목(mock)을 사용합니다. 이 스위트는 모든 PR에서 실행되며, 8초가 소요되고, Apidog의 목 픽스처를 레포에 캐싱하여 기여자들이 개발을 위해 API 접근 권한이 필요 없도록 합니다.

14개의 내부 MCP 서버를 운영하는 플랫폼 팀은 모든 서버의 계약이 저장되는 공유 Apidog 워크스페이스를 구축했습니다. 새로운 서버는 기본 테스트 스위트를 상속받으며, 검토자는 병합 전에 스키마 차이점을 나란히 비교할 수 있습니다. 이 팀은 첫 분기에 두 번의 서비스 중단을 막았다고 보고했는데, 두 번 모두 회사 내 모든 Claude Desktop 사용자에게 이름이 바뀐 인수를 배포했을 PR에서 tools/list 형태 어설션에 의해 발견되었습니다.

내부 관측 가능성(observability) 플랫폼을 위한 MCP 서버를 구축하는 두 번째 팀은 Apidog의 환경 스위처를 사용하여 스테이징 및 프로덕션 환경에 대해 동일한 스위트를 실행합니다. 각 환경은 다른 목 픽스처 파일을 가리키므로, 동일한 60개의 어설션으로 단일 요청을 다시 작성할 필요 없이 두 배포를 모두 확인할 수 있습니다.

결론

MCP는 올해 주류가 되었지만, 테스트는 여전히 10년 전 REST API 테스트가 있던 자리(임시적이고, 수동적이며, 취약한)에 머물러 있습니다. 생태계가 따라잡을 때까지 기다릴 필요가 없습니다. MCP 서버를 하나의 API로 취급하고, 계약을 설계하며, 업스트림을 목(mock)하고, CI에서 어설션을 실행하세요.

다섯 가지 핵심 요약:

다음 단계: Apidog를 열고, 프로젝트를 생성하고, 수동으로 캡처한 요청 본문을 붙여넣고, tools/list에 대한 JSONPath 어설션을 추가한 다음, 스위트를 실행하세요. 한 시간 이내에 서버의 계약이 출시하기에 충분히 견고한지 알 수 있을 것입니다.

자주 묻는 질문

MCP란 무엇인가요?

MCP, 즉 모델 컨텍스트 프로토콜(Model Context Protocol)은 AI 클라이언트(예: Claude Desktop)가 외부 도구, 리소스 및 프롬프트를 호출하는 방식에 대한 Anthropic의 공개 사양입니다. stdio 또는 스트림 가능한 HTTP를 통해 JSON-RPC 2.0으로 작동합니다. 전체 MCP 사양modelcontextprotocol.io에 게시되어 있습니다.

HTTP 래퍼 없이 MCP 서버를 테스트할 수 있나요?

네, 그렇습니다. 공식 MCP 인스펙터는 stdio를 직접 사용하며 수동 테스트를 위한 UI를 제공합니다. Apidog에서 자동화된 테스트를 위해서는 CI 중에 stdio를 얇은 HTTP 서버로 감싸세요. 프로덕션 트래픽은 여전히 stdio를 통해 이루어집니다.

MCP 서버가 호출하는 업스트림 API를 어떻게 모의(mock)하나요?

각 업스트림 엔드포인트를 Apidog 프로젝트에서 목(mock)으로 정의하고, 테스트 중에는 MCP 서버의 구성을 목 URL로 지정한 다음, 런타임에는 프로덕션 URL로 전환하세요. 우리는 QA 엔지니어를 위한 API 테스트 도구에서 동일한 패턴을 자세히 다룹니다.

도구 결과 스트리밍은 어떻게 처리하나요?

HTTP MCP 서버는 SSE(Server-Sent Events)를 통해 도구 결과를 스트리밍합니다. Apidog는 저장된 요청에서 SSE를 지원합니다. 요청 설정에서 이를 켜고, 조립된 스트림에 대해 어설션하세요.

프로토콜 버전을 테스트해야 하나요?

네. initialize에서 지원하는 protocolVersion을 고정하고 이에 대해 어설션하세요. 불일치는 클라이언트의 조용한 비호환성을 유발합니다.

실제 Claude Desktop에 대해 MCP 서버를 테스트할 수 있나요?

그럴 수 있으며, 각 릴리스 전에 최소 한 번은 그렇게 해야 합니다. 하지만 Claude Desktop을 테스트 루프로 의존하지 마세요. 느리고, 수동적이며, 비결정론적입니다. 회귀 스위트에는 Apidog를 사용하고, 스모크 테스트에는 Claude Desktop을 사용하세요.

실제 MCP 서버 예시는 어디서 볼 수 있나요?

공식 MCP 서버 저장소에는 파일 시스템, GitHub, Slack, Postgres 등을 위한 수십 가지 참조 구현이 있습니다. 도구 정의를 읽어보세요. 이는 좋은 MCP 형태가 무엇인지 이해하는 가장 쉬운 방법입니다.

Apidog에서 API 설계-첫 번째 연습

API를 더 쉽게 구축하고 사용하는 방법을 발견하세요

MCP 서버 테스트 플레이북: Apidog 활용 수동 및 자동화