MCP 에이전트를 오프라인으로 테스트하기: 녹화본 자체가 서버가 되다
요약
mcp-cassette은 Model Context Protocol (MCP) 세션을 JSONL 파일로 녹화하여, 이 파일을 독립적인 MCP 서버처럼 활용할 수 있게 합니다. 이를 통해 개발자는 자격 증명이나 네트워크 연결 없이도 오프라인 환경에서 에이전트의 도구 호출 테스트를 수행할 수 있습니다. 이는 기존 Mocking 방식의 한계를 극복합니다.
핵심 포인트
- MCP 세션을 JSONL 파일로 녹화하여 서버처럼 사용 가능
- 자격 증명, 속도 제한, 네트워크 연결 없이 오프라인 테스트 지원
- 녹화본을 통해 에이전트 도구 계약(tool contract) 검증 용이
- Jest/Vitest와 연동하여 빠진 요청 시 테스트 실패 유도
요약 (TL;DR) 📼 mcp-cassette은 실제 MCP 세션을 하나의 JSONL 파일로 기록한 다음, 그 파일을 MCP 서버처럼 제공합니다. 어떤 언어로 작성된 클라이언트든 이 녹화본을 오프라인으로 테스트할 수 있습니다: 자격 증명(credentials)도, 속도 제한(rate limits)도, 네트워크 연결도 필요 없습니다.
🤔 문제점 (The problem)
만약 에이전트가 Model Context Protocol(MCP)을 통해 도구를 호출한다면, 그 테스트는 자신이 통제할 수 없는 것에 의존하게 됩니다: 자격 증명과 속도 제한, 네트워크를 가진 라이브 MCP 서버입니다.
일반적인 해결책들은 모두 단점이 있습니다:
- 🧪 MCP 클라이언트 라이브러리를 Mock하면, 모든 테스트가 하나의 SDK에 묶이게 됩니다.
- 🛠️ 직접 레코더(recorder)를 작성해야 하는데, 제가 접했던 여러 프로젝트들이 각자 이 작업을 수행하고 있었습니다.
mcp-cassette은 세 번째 방법을 취합니다: 녹화본 자체가 서버가 되는 것입니다.
🎙️ 한 번 녹화하기 (Record once)
npx mcp-cassette record -o session.cassette.jsonl -- npx -y @modelcontextprotocol/server-github
이 레코더는 클라이언트와 실제 서버 사이에 투명한 프록시(proxy)로 위치하며, 양방향의 모든 프레임을 열린 JSONL 카세트(cassette)에 기록합니다. 기본적으로 인식되는 비밀 정보(secrets)는 파일에 도달하기 전에 마스킹됩니다.
💡 패턴 매칭으로는 모든 비밀 정보를 포착할 수 없으므로, 커밋하기 전에 카세트를 빠르게 검토해 보세요.
🔁 영원히 재생하기 (Replay forever)
npx mcp-cassette check --stdio
- 📣 서버가 자체적으로 푸시한 알림은 해당 세션에 도착했던 지점에서 재연됩니다.
- 🧭 2025-11-25 개정 버전과 상태 비저장(stateless) 방식의 2026-07-28 개정 버전 모두 지원됩니다.
- 🔌 한 연결에서 프로빙을 수행하고 두 번째 연결에서 세션을 실행하는 클라이언트는 `--mode append`를 사용하여 이 두 가지를 하나의 파일에 기록합니다.
### 🧪 테스트 러너 내부
import { describe, expect, it } from "vitest";
import { useCassette } from "mcp-cassette/vitest";
...
`mcp-cassette/jest`라는 쌍둥이(twin)가 있습니다. 녹화본에 포함되지 않은 요청은 해당 테스트를 실패시키고 그 이유를 알려줍니다.
## 🚦 도구 계약 게이팅 (Gate your tool contract)
도구 계약(tool contract)은 API입니다. `snapshot`은 이를 커밋하는 파일에 기록하고, `snapshot --check`는 위반 시 CI에서 실패합니다:
npx mcp-cassette snapshot --check --stdio "node dist/my-server.js"
[BREAKING] slugify: tool removed (tool-removed)
[BREAKING] add: parameter "precision" is now required (input-property-became-required)
[DANGEROUS] add: parameter "mode" added (input-property-added-optional)
...
## 🛡️ 모델이 읽는 내용을 린트하기 (Lint what the model reads)
도구 오염(Tool poisoning)은 에이전트가 읽지만 사람이 보여주지 않는 텍스트, 즉 도구 설명, 입력 스키마, 프롬프트, 리소스에 숨어 있습니다. `check`는 이 모든 것에 대해 열여섯 가지 결정론적 규칙을 실행하며, 각 규칙은 커버하는 OWASP MCP Top 10 위험 요소를 인용합니다. 그리고 `lint`는 녹화된 서버가 _반환한_ 내용(간접 프롬프트 주입이 발생하는 곳)에 대해 의미 있는 규칙들을 실행합니다.
npx mcp-cassette check --stdio "node dist/my-server.js" --format sarif --sarif-location mcp-contract.snapshot.json > mcp-cassette.sarif
결과는 텍스트, JSON 또는 GitHub 코드 스캐닝을 위한 SARIF 형식으로 나옵니다.
> ⚠️ 이것들은 모델이 아닙니다. 빠르고 간편한 CI 트립와이어(tripwire)이며, README에는 놓치는 부분이 명확히 설명되어 있습니다.
## 🤖 세 줄로 끝내는 CI
- uses: ivermin1123/[email protected]
with:
server-command: node dist/my-server.js
이는 커밋한 스냅샷에 대해 안전성 검사(safety check)와 계약 게이트(contract gate)를 실행하고, 풀 리퀘스트에 코멘트를 남기며, 푸시할 때마다 그 내용이 업데이트됩니다.
## 🚀 10초 만에 사용해 보세요
npx mcp-cassette check --stdio "npx -y @modelcontextprotocol/server-everything stdio"
surface: 13 tools, 7 resources, 4 prompts
[OK] no findings
...
##  [ivermin1123](https://github.com/ivermin1123) / [mcp-cassette](https://github.com/ivermin1123/mcp-cassette)
### 실제 MCP 세션을 한 번 녹화하고, 영원히 재현하세요. VCR 스타일의 기록/재생, 계약 스냅샷, 그리고 Model Context Protocol 서버를 위한 안전성 검사.
[](https://github.com/ivermin1123/mcp-cassette/actions/workflows/ci.yml) [](https://www.npmjs.com/package/mcp-cassette)
[](https://github.com/ivermin1123/mcp-cassette/.github/demo.gif)
# mcp-cassette
**캐세트 자체가 MCP 서버이므로, 어떤 언어의 클라이언트든 실제 서버에 연결하는 방식 그대로 연결할 수 있습니다: 가져올 라이브러리가 필요 없고, 변경할 제품 코드가 없으며, 래핑할 전송 계층(transport)도 없습니다.**
실제 [Model Context Protocol](https://modelcontextprotocol.io) 서버를 대상으로 한 세션을 녹화한 다음, 그 기록을 기반으로 에이전트 테스트를 실행하세요: 자격 증명(credentials) 불필요, 속도 제한(rate limits) 없음, 네트워크 연결 필요 없음. 이 재생은 스텁(stub)이 아니라 서버입니다: 기록된 서버가 자체적으로 발행했던 알림들을 기록이 지정한 위치에서 돌려주고, 전체 `io.modelcontextprotocol/tasks` 폴링 시퀀스를 제공합니다. 하나의 파일이 두 프로토콜 시대, 즉 클래식 라이프사이클과 2026-07-28을 모두 다룹니다.
동일한 바이너리는 도구 계약(tool contract)이 변경 사항으로 인해 깨지는 것을 막고, 서버가 모델에 게시하는 모든 텍스트를 중독화(poisoning)하여 검사하며, 기록된 서버가 되돌려준 내용물까지 검사합니다. 이 부분이 간접적인 프롬프트 인젝션(indirect prompt injection)이 발생하는 지점입니다.
npx mcp-cassette check --stdio
…
[GitHub에서 보기](https://github.com/ivermin1123/mcp-cassette)
Apache-2.0 · TypeScript · Node 22 이상
## 💬 이제 당신 차례입니다
오늘날 MCP 에이전트를 테스트하려면 어떻게 해야 할까요? 그리고 녹화본은 어디에 들어맞지 않을까요? 댓글로 알려주세요 👇
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기