Community연구 & 데이터 분석github.com

DataRecce/recce

데이터 검증 도구로서, 강화된 dbt PR 리뷰를 지원합니다.

recce란 무엇인가요?

이 스킬은 dbt 프로젝트의 PR 리뷰 과정에서 데이터 검증을 자동화하는 Recce MCP 서버를 개발하고 유지보수하는 방법을 설명합니다. MCP SDK를 기반으로 `list_tools`와 `call_tool` 핸들러를 등록하고, 오류를 분류하며, 메트릭을 로깅하고 전송합니다. 주요 기능으로는 단일 환경 경고 추가, 응답 계약 관리, 그리고 세 가지 테스트 계층(단위, 통합, 수동 E2E)을 통한 품질 보증이 포함됩니다. 이 스킬은 Claude Code와 같은 AI 도구가 dbt 기반 데이터 파이프라인의 변경 사항을 안전하게 검토하고 배포할 수 있도록 지원합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add DataRecce/recce

Installed? Explore more 연구 & 데이터 분석 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Recce MCP 서버 개발

아키텍처

RecceMCPServer는 MCP SDK Server를 통해 list_tools/call_tool 핸들러를 등록합니다. call_tool은 _tool_* 메서드로 디스패치하고, 오류를 분류한 후 로깅/메트릭 전송 후 재발생시킵니다.

진입점 run_mcp_server()는 single_env를 pop한 후 나머지 kwargs를 load_context()에 전달합니다.

주요 패턴

오류 분류 — 공유된 지표 리스트는 recce/tasks/rowcount.py에 정의됩니다. 우선 순위(PERMISSION_DENIED > TABLE_NOT_FOUND > SYNTAX_ERROR)는 mcp_server.py의 _classify_db_error()와 rowcount.py의 _query_row_count()에서 적용됩니다. 분류된 경우 → logger.warning() + sentry_metrics.count() (sentry_sdk가 있을 때). 분류되지 않은 경우 → logger.error() + traceback.

MCP SDK 특성 — 핸들러는 SDK가 isError=True를 설정하도록 raise해야 합니다.

응답 계약 — CLAUDE.md 참조. 추가적인 _meta만 허용됩니다. summary.py: dict.get(key, 0) 대신 is None으로 검사합니다. N/A 표시에는 이유를 포함합니다: "N/A (table_not_found)".

단일 환경 — _maybe_add_single_env_warning()은 diff 결과에 _warning을 추가합니다. 설명에 조건부 노트가 붙습니다.

테스트 (세 가지 계층)

계층파일데이터 소스실행 환경목적
단위tests/test_mcp_server.pyMock RecceContextCI (pytest)로직 정확성 — 툴 핸들러, 오류 분류, 응답 형식
통합tests/test_mcp_e2e.pyDbtTestHelper + DuckDB (고정 데이터)CI (pytest)MCP 프로토콜이 anyio 메모리 스트림을 통해 종단 간 동작
수동 (E2E)/recce-mcp-e2e 스킬사용자의 실제 dbt 프로젝트 + 실제 데이터베이스수동8개 모든 도구가 실제 데이터에 대해 유효한 결과 반환

새로운 MCP 기능이나 동작 변경은 세 가지 계층에서 모두 테스트되어야 합니다.

테스트 커버리지 갭 분석

MCP 변경 작업(아래 E2E 게이트 참조)이 완료된 후, E2E 검증을 요청하기 전에 세 가지 계층에서 누락된 테스트 커버리지를 적극적으로 스캔하십시오.

확인 방법:

  1. 변경된 사항 식별 — 새로운 툴 핸들러? 새로운 오류 경로? 새로운 응답 필드?
  2. 각 변경 사항에 대해 각 계층에서 커버리지가 있는지 확인:
    • 단위: tests/test_mcp_server.py에 새로운 동작에 대한 테스트 케이스가 있습니까? (정상 경로 + 오류 경로)
    • 통합: tests/test_mcp_e2e.py가 MCP 프로토콜을 통해 새로운 도구/기능을 실행합니까?
    • 수동: /recce-mcp-e2e 템플릿이 새로운 도구를 포함합니까? (새 도구가 추가된 경우 템플릿 업데이트가 필요할 수 있음)

갭이 발견되면, E2E 게이트 프롬프트 전에 사용자에게 보고:

테스트 커버리지 갭 발견:

  • 단위: _tool_foo 오류 경로(table_not_found)에 대한 테스트 누락
  • 통합: test_mcp_e2e.py가 foo 도구를 실행하지 않음
  • 수동: /recce-mcp-e2e 템플릿에 foo 도구가 포함되지 않음

E2E 실행 전에 이 갭을 채우시겠습니까?

스캔하지 않음: 테스트 전용 변경, 주석/문서 편집, import 재정렬.

E2E 검증 게이트

MCP 변경의 각 의미 있는 라운드 후에, 반드시 사용자에게 질문:

이번 라운드 MCP 변경이 완료되었습니다. /recce-mcp-e2e를 실행하여 확인하시겠습니까?

사용자가 예라고 하면 /recce-mcp-e2e를 호출하십시오. 이전 세션에서 dbt 프로젝트 경로가 사용된 경우 자동으로 재사용하고, 그렇지 않으면 물어보십시오.

"라운드"로 간주되는 경우:

  • 툴 핸들러 추가 또는 수정 + 해당 단위 테스트 통과
  • 오류 분류 로직 변경 + 테스트 통과
  • 단일 환경 또는 응답 형식 변경 + 테스트 통과

질문하지 않음: 테스트 전용 변경, 주석/문서 편집, import 재정렬.

이는 tests/test_mcp_e2e.py와 별개입니다 — 해당 파일은 CI에서 DbtTestHelper + DuckDB로 테스트합니다. /recce-mcp-e2e는 실제 데이터베이스가 있는 실제 dbt 프로젝트에 대해 8개 모든 도구를 검증합니다.

주의사항

  • sentry_sdk import: except 블록에 # pragma: no cover (CI에는 항상 있음)
  • Python 3.9: Union[X, Y] (not X | Y)
  • Pre-commit: black/isort가 재포맷할 수 있음 — 다시 스테이징하고 커밋
  • run.py의 schema_diff_should_be_approved() try/except는 의도적입니다 (체크 생성 보장)

파일 맵

recce/mcp_server.py (서버 + 핸들러), recce/tasks/rowcount.py (오류 지표, RowCountStatus), recce/run.py (CLI 프리셋), recce/summary.py (표시 로직), recce/event/__init__.py (Sentry)

관련 스킬