MCP 서버 분석 — 인텐트(의도) 및 오류 분석
Amplitude의 MCP Analytics SDK로 계측된 MCP 서버에 대해 세 가지 질문에 답하는 보고서를 생성합니다:
- 어떤 도구가 사용되고, 어떤 도구가 실패하는가? (도구별 호출량 + 오류율)
- 각 도구로 호출자가 무엇을 하려고 했고, 각 인텐트는 어디서 실패하는가? (도구 내 근거 × 오류 메시지)
- 팀이 무엇을 먼저 수정해야 하는가? (감정이 아닌 오류 증거에 기반한 수정 사항)
이 분석을 가치 있게 만드는 핵심 동작: 도구가 수정 위치를 찾아주고, 근거가 그 뒤에 숨은 의도를 설명합니다. 전체 오류율은 "호출의 4.5%가 실패"라고 말합니다. 도구별로 세분화하면 "query_chart가 22% 실패"라고 알려줍니다 — 이제 무엇을 열어볼지 알게 됩니다. 해당 도구 내 근거를 추가하면 "대시보드 새로고침 에이전트가 배치 크기 제한에 걸린다"고 알려줍니다 — 이제 이유를 알게 되었고, 수정 방법은 저절로 드러납니다. 근거는 대체로 도구 범위로 한정됩니다(각 도구마다 고유한 호출 이유가 있음). 따라서 도구가 기본 축이고 근거는 그 안의 두 번째 분석 축입니다 — 근거를 전역적으로 클러스터링하면 도구 경계를 다시 파생하면서 비교 불가능한 인텐트가 혼합됩니다.
전제 조건
-
Amplitude MCP 커넥터가 활성화되어 있어야 합니다. 그렇지 않으면 중단하고 사용자에게 도구/커넥터 설정에서 Amplitude 커넥터를 추가하도록 요청하세요 — 대체 데이터 소스는 없습니다.
-
SDK 이벤트가 포함된 프로젝트. SDK는 SDK 소유 기본 이벤트를 내보내며, 모두
[MCP]접두사가 붙고, 중요한 점은 모든 기본 속성도[MCP]접두사가 붙으며, 사용자 정의 속성을 가질 수도 있습니다.이벤트:
[MCP] Tool Call Response— 핵심 도구 호출 이벤트: 도구 콜백에 도달한 모든 도구 호출당 하나의 이벤트(성공 또는 오류).[MCP] Tool Call Rejected— 도구 실행 전에 실패한tools/call(알 수 없거나 비활성화된 도구, 입력 스키마 유효성 검사). 환각/오타 도구 이름이 여기에 기록되며,[MCP] Attempted Tool Name속성에 담깁니다(예약된[MCP] Tool Name과 별도).[MCP] Session Initialized,[MCP] Session Ended,[MCP] Tools Listed.
[MCP] Tool Call Response의 주요 속성:[MCP] Tool Name,[MCP] Client Name,[MCP] Client Version,[MCP] Session ID,[MCP] Auth Type,[MCP] Rationale,[MCP] Is Error,[MCP] Error Message,[MCP] Error Type(returned_errorvsthrown_exception— 실패를 보고한 도구와 충돌이 발생한 도구를 구분),[MCP] Response Duration,[MCP] Response Size,[MCP] Request Size. -
이벤트/속성 이름은 SDK 버전 간에 변경될 수 있습니다. 절대 추정하지 말고 0단계에서 분류 도구로 확인하세요. 위의 표준 이름은 SDK의
constants.ts(EVENT_PROPERTY_KEYS)에서 가져온 것입니다. 프로젝트 데이터와 일치하지 않으면 프로젝트를 신뢰하고 적응하세요.
0단계 — 데이터 위치 확인 및 검증
- Amplitude 컨텍스트 도구(projectId 없이)를 호출하여 프로젝트를 나열합니다. 둘 이상의 가능한 프로젝트가 있고 사용자가 지정하지 않은 경우 질문합니다.
- 선택한 프로젝트에
[MCP]이벤트가 있는지 확인합니다(이벤트 검색 또는 이벤트 나열;get_events는 정확한 이름으로만 필터링하므로[MCP]접두사 검색에는 검색을 사용). [MCP] Tool Call Response(및[MCP] Tool Call Rejected)의 이벤트 속성을 가져와 정확한 속성 이름을 확인합니다 —[MCP]접두사가 붙고 Title Case임을 기억하세요(예:[MCP] Rationale,tool rationale이 아님). 찾은 내용을 아래 쿼리에서 사용하는 이름에 바인딩합니다.- 하나의 볼륨/최근성 쿼리 실행: 지난 60일 동안
[MCP] Tool Call Response,[MCP] Session Initialized의 총계, 주별 간격. 이를 통해 사용 가능한 날짜 범위와 충분한 데이터가 있는지 알 수 있습니다. 총 도구 호출이 약 5,000건 미만이면 도구별 분석이 부족하고 백분율이 불안정할 것이라고 사용자에게 경고합니다 — 그래도 진행하되 보고서에 명시합니다.
기록: 프로젝트 ID, 날짜 범위, 총 호출량. 이후의 모든 쿼리는 동일한 범위를 사용하여 숫자를 비교 가능하게 유지합니다.
1단계 — 도구별 분석 (기본 축)
이것이 기본 맵이며, 다른 모든 것은 이를 기준으로 세부 분석합니다.
- 도구별 호출량:
[MCP] Tool Call Response의 총계,[MCP] Tool Name으로 그룹화, groupByLimit ~100. - 도구별 오류: 동일하나
[MCP] Is Error is "true"필터 추가. - 시도된 이름별 거부된 호출:
[MCP] Tool Call Rejected의 총계를[MCP] Attempted Tool Name으로 그룹화. 이러한 호출은 콜백에 도달하지 않으므로 위의 두 쿼리에는 보이지 않지만 — 실제 도구가 아닌 시도된 이름이 높은 볼륨을 차지하면 가장 실행 가능한 결과 중 하나입니다(이름 변경 또는 에이전트가 계속 추측하는 환각).
도구별 호출량, 오류 수, 오류율을 계산하고 두 가지 방식으로 도구 순위를 매깁니다: 호출량(부하가 걸린 항목)과 오류량(가장 많은 실패를 초래하는 항목). 심층 분석할 상위 3~5개 도구를 선택합니다 — 단순히 트래픽이 많은 것보다는 높은 오류량에 편향되며, 사용자가 특정 도구를 지정한 경우 그 선택을 존중합니다. 트래픽이 적지만 오류율이 90%인 도구는 바쁘지만 정상적인 도구보다 우선순위가 높을 수 있습니다.
2단계 — 각 상위 도구 내 근거 분석 ("이유")
각 상위 도구에 대해 근거를 샘플링합니다 — [MCP] Tool Call Response의 총계를 [MCP] Rationale으로 그룹화, 해당 도구 하나로 필터링([MCP] Tool Name is "<tool>"), groupByLimit ~150. 그런 다음 읽고 호출자가 이 도구로 무엇을 달성하려고 하는지에 따라 그룹화합니다(문구는 무시). 지침:
- 단일 도구 내에서 일반적으로 2~5개의 인텐트 그룹을 찾을 수 있으며, 아홉 개는 아닙니다 — 도구가 이미 목적을 좁혀줍니다. 인텐트별로 이름을 지정합니다(예:
query_chart도구의 경우: "실시간 대시보드 새로고침", "임시 탐색", "예약된 보고서 생성"). - 고유한 문자열이 아닌 호출량(각 근거 값은 총계를 포함)으로 가중치를 적용합니다.
- 정크 그룹 주의: "placeholder", "ignore", "noop", "test", "dummy", 단일 문자. 그 크기는 근거 위생 상태를 나타내며, 정크는 실제 인텐트를 오염시켜서는 안 됩니다.
- "Retry after rate limit" / "Retrying X"와 같은 근거는 재시도 루프를 나타냅니다 — 기록하세요.
- 비영어 근거는 정상입니다. 의미별로 그룹화하세요.
- 도구별 근거 커버리지 계산(근거가 비어 있지 않은 도구 호출의 비율). 낮으면(<50%) 인텐트는 일부만 설명합니다 — 그렇게 말하고 "계측 시 근거 커버리지 개선" 자체가 권장 사항이 됩니다.
- 도구별 상위 인텐트 점유율 계산(가장 큰 인텐트 그룹이 근거가 있는 호출에서 차지하는 비율). 이것이 집중 신호입니다: ~90%는 도구가 하나의 작업을 수행하며 이를 위해 최적화할 수 있음을 의미합니다(해당 경로에 맞게 스키마/설명 강화); 평평한 분포(상위 인텐트 ~30%)는 도구가 과부하되어 분할이 필요할 수 있거나 오류가 관련 없는 인텐트에 분산됨을 의미합니다. 숫자를 보고하고 상위 인텐트가 지배적일 때 해당 도구 옆에 이름을 지정합니다.
크로스-도구 워크플로우(보조): 일부 근거는 다중 도구 목표("대시보드를 새로고침하기 전에 차트 ID 확인")를 설명합니다. 단일 인텐트가 명확히 여러 도구에 걸쳐 있는 경우(예: search_events → create_chart → create_dashboard), 교차 분석 섹션에서 워크플로우로 언급합니다 — 순수 도구별 관점이 놓치는 유일한 것입니다.
3단계 — 도구별 오류 심층 분석
각 상위 도구에 대해 실행합니다(해당 도구로 필터링 + [MCP] Is Error is "true"):
[MCP] Error Message로 그룹화 → 실패 이유- 메시지가 모호한 경우 선택적으로
[MCP] Error Type(returned_errorvsthrown_exception)으로 분할 — 충돌과 잘 구성된 거부 모두[MCP] Is Error를 발생시키지만, 오류만 도구의 버그입니다.
2단계에서 도구가 지배적인 인텐트 그룹을 가지고 있는 경우 근거로 오류를 한정합니다(근거-contains 필터 추가) -> "이 인텐트는 이렇게 실패합니다" 문장을 얻습니다.
각 중요한 오류 메시지를 유형으로 분류합니다 — 유형이 수정 방법을 결정합니다:
| 유형 | 특성 | 수정 패턴 |
|---|---|---|
| 오래된/환각된 도구 이름 | [MCP] Tool Call Rejected와 [MCP] Attempted Tool Name = 이름이 변경되었거나 그럴듯한 도구 이름 | 이름이 변경된 도구에 대한 서버 측 에일리어스; 가장 가까운 실제 도구 이름을 알려주는 거부 응답으로 에이전트가 한 번에 자체 수정하도록 유도 |
| 필수 매개변수 누락 | 유효성 검사 오류, "Required", 경로가 매개변수 이름 지정 | 스키마 완화(단일 값 또는 배열 허용, 기본값 추가), 또는 도구 설명에 요구 사항을 명시하여 에이전트가 사전에 올바르게 처리하도록 함 |
| 스키마 형태 불일치 | "Expected object, received string" 등 | 서버 측 강제 변환(coercion) 추가, 또는 도구 설명에 인라인 예제 포함 |
| 하드 제한 충돌 | "Maximum of N …", "too_big" | 제한 상향, 서버 측 자동 청크(chunking), 또는 매개변수 설명에 제한 명시 — 현재 에이전트는 실패해야만 제한을 배움 |
| 범위/보존 위반 | "time range too large", "does not retain data before …" | 오류 대신 자동 강제 변환(예: 세분성 다운그레이드); 컨텍스트 페이로드에 보존/범위 제한 광고 |
| 닭과 달걀 매개변수 | 제공하기 위해 존재하는 ID가 필요한 컨텍스트/검색 도구 | 검색 도구를 인증 토큰에서 기본값을 가져와 인수 없이 작동하도록 함 |
| 권한 거부됨 | 역할/권한 언어 | "허용되지 않음"을 "고장"과 분리할 수 있도록 별도의 오류 클래스; 종종 문서/온보딩 격차이기도 함 |
| 반복 예약 오류 | 동일한 메시지가 동일한 도구에서 매일 반복됨 | 내부 작업인 경우 호출자 수정; 제품의 경우 자동으로 조용히 성능이 저하되는 것으로 표시 — 아무도 채팅 창을 보고 있지 않음 |
| 일시적/상위 서비스 오류 | 5xx, 타임아웃, 속도 제한 | 오류 본문에 재시도 후 힌트; 재시도가 실제로 발생하는지 확인(루프 깔때기 참조) |
가장 좋은 오류 메시지는 수정 방법을 명시합니다("start >= …로 재실행"). 모든 높은 볼륨의 오류 메시지를 그 기준으로 평가하세요 — "가장 좋은 오류 메시지만큼 실행 가능하게 만들기"는 종종 합법적인 권장 사항입니다.
4단계 — 선택적 컨텍스트 지표
시간이 허락하면 추가합니다. 이야기를 더 선명하게 만듭니다:
- 반복 오류 루프: 3단계 깔때기, 각 단계
[MCP] Tool Call Responsewith[MCP] Is Error is "true",[MCP] Tool Name고정, ~1시간 전환 창. 오류를 겪는 사용자 중 동일한 도구에서 루프에 빠지는 비율을 보여줍니다. (단계가 연속 이벤트일 필요는 없음 — "1시간 내에 동일한 도구에서 3회 이상 오류", "3회 연속"이 아님.) - 오류 → 복구: 2단계 깔때기, 오류 후 성공, 도구 이름 고정. 높은 복구율 + 높은 루프율이 함께 발생하면 비용이 낭비된 토큰/지연 시간이지 포기가 아님을 의미합니다 — 실질적으로 다른 결론입니다.
- 클라이언트 구성:
[MCP] Client Name으로 그룹화된 고유값. "unknown" 비율이 크거나 거의 중복된 클라이언트 이름(대소문자, 플러그인 접두사 변형)은 보고할 가치가 있는 계측 결과입니다.
5단계 — 검증 후 작성
작성하기 전에 하나 이상의 헤드라인 숫자를 다른 방식으로 재검증합니다(예: 별도의 두 이벤트 총계 쿼리를 통해 전체 오류율). 인용하는 모든 백분율을 원시 총계에서 다시 계산합니다. 숫자를 검증할 수 없으면 제거하거나 추정치로 표시합니다.
보고서 구조
이 템플릿을 사용합니다 — 도구 우선으로 구성:
# MCP 서버 분석 — <서버/프로젝트 이름>
데이터: <프로젝트>, <날짜 범위>, <N> 도구 호출, 전체 오류율 <X>%.
방법론 참고: 도구별 분석은 정확한 쿼리 결과이며, 도구 내 인텐트는 근거에서 도출된 모델 기반(방향성)입니다. 거부된 호출 이름은 [MCP] Tool Call Rejected에서 가져옴.
## 도구 한눈에 보기
<table: 도구 | 호출 | 오류 | 오류율 | 상위 인텐트(점유율 %) | 근거 커버리지>
<중요한 경우 거부/시도된 도구 이름에 대한 한 줄; 중요한 경우 정크 근거 언급>
## 심층 분석: 상위 3~5개 도구(오류량 순)
각 도구:
**도구: <이름> — <호출>, <오류율> — 용도: <한 문장>**
- 인텐트(이 도구 내 근거): <그룹 : 점유율>, …
- 1~4개의 번호 매겨진 권장 사항. 각각 증거(오류 메시지 + 개수), 유형, 구체적인 수정 방법을 명시합니다. 가장 많은 오류량을 제거하는 수정 사항을 먼저 제시합니다.
## 교차 분석 결과
<크로스-도구 워크플로우, 루프/복구율, 클라이언트 이름 위생, 근거 위생, 내부 테스트 트래픽, …>
## 한 문장 결론
<가장 많은 실패량을 제거하는 단일 변경 사항과 그 수치>
스타일: 모든 주장 옆에 숫자를 표시; 오류 메시지를 있는 그대로(축약하여) 명명하여 엔지니어가 grep할 수 있도록 함; 권장 사항은 관찰("도구 이름 지정 개선 가능")이 아닌 행동("'query_chart'에 대한 에일리어스 배포 → 'query_charts'")으로 표현.
출력 내 차트
클라이언트가 지원하는 경우 지원 차트를 렌더링합니다. 임시 차트 쿼리 + 렌더링 도구를 사용하여 eventsSegmentation/funnels 정의를 작성한 다음 렌더링합니다. 무엇이 차트가 될 수 있고 될 수 없는지 신중하게 판단:
- 차트 가능 — 쿼리 기반 모든 것. 실제 Amplitude 세분화/깔때기 결과이므로 렌더링: 도구별 호출 및 오류(
[MCP] Tool Name으로 그룹화), 시간 경과에 따른 오류율,[MCP] Attempted Tool Name별 거부된 호출, 도구별 반복 오류 루프 및 복구 깔때기,[MCP] Client Name별 클라이언트 구성. 도구 분석이 자연스러운 주요 차트입니다. - 차트 불가능 — 도구 내 인텐트 그룹. 근거를 인텐트로 그룹화하는 것은 이 모델 내에서 발생합니다. 해당 그룹화는 Amplitude 속성으로 존재하지 않으므로 "인텐트별 호출"에 대한 저장된 차트는 없습니다. 인텐트는 근거 총계에서 작성된 표로 제시하고, 인텐트 수치는 모델 기반(방향성)이며 렌더링하는 차트는 정확한 쿼리 결과라고 명확히 말합니다. 렌더링된 차트가 인텐트 그룹화를 뒷받침한다고 암시하지 마십시오.
쿼리 쿡북
모든 쿼리는 0단계의 프로젝트 ID에 대한 eventsSegmentation 또는 funnels 정의입니다. 이벤트/속성 이름을 0단계에서 확인된 것으로 조정합니다. 작동하는 것으로 알려진 형태:
도구 분석 (1단계):
{"type":"eventsSegmentation","app":"<PROJECT_ID>","name":"[MCP] 도구별 호출",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Response",
"group_by":[{"type":"event","value":"[MCP] Tool Name"}]}],
"metric":"totals","countGroup":"User","groupBy":[],
"int":"",
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","startComparison":"none",
"endComparison":"none","limitN":100,"groupByLimit":100,
"formula":"","unitAggregation":"totals","interval":"day"}}
오류별 도구 분석 (1단계):
{"type":"eventsSegmentation","app":"<PROJECT_ID>","name":"[MCP] 도구별 오류",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Response",
"group_by":[{"type":"event","value":"[MCP] Tool Name"},{"type":"event","value":"[MCP] Is Error"}],
"filters":[{"property_name":"[MCP] Is Error","value":"true","operator":"is"}]}],
"metric":"totals","countGroup":"User","groupBy":[],
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","startComparison":"none",
"endComparison":"none","limitN":100,"groupByLimit":100,
"formula":"","unitAggregation":"totals","interval":"day"}}
거부된 호출 (1단계):
{"type":"eventsSegmentation","app":"<PROJECT_ID>","name":"[MCP] 거부된 호출",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Rejected",
"group_by":[{"type":"event","value":"[MCP] Attempted Tool Name"}],
"filters":[]}],
"metric":"totals","countGroup":"User","groupBy":[],
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","startComparison":"none",
"endComparison":"none","limitN":100,"groupByLimit":100,
"formula":"","unitAggregation":"totals","interval":"day"}}
도구 내 근거 (2단계):
{"type":"eventsSegmentation","app":"<PROJECT_ID>","name":"[MCP] <도구> 근거",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Response",
"group_by":[{"type":"event","value":"[MCP] Rationale"}],
"filters":[{"property_name":"[MCP] Tool Name","value":"<도구>","operator":"is"}]}],
"metric":"totals","countGroup":"User","groupBy":[],
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","startComparison":"none",
"endComparison":"none","limitN":150,"groupByLimit":150,
"formula":"","unitAggregation":"totals","interval":"day"}}
도구 내 오류 메시지 (3단계):
{"type":"eventsSegmentation","app":"<PROJECT_ID>","name":"[MCP] <도구> 오류 메시지",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Response",
"group_by":[{"type":"event","value":"[MCP] Error Message"},{"type":"event","value":"[MCP] Error Type"}],
"filters":[{"property_name":"[MCP] Tool Name","value":"<도구>","operator":"is"},{"property_name":"[MCP] Is Error","value":"true","operator":"is"}]}],
"metric":"totals","countGroup":"User","groupBy":[],
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","startComparison":"none",
"endComparison":"none","limitN":150,"groupByLimit":150,
"formula":"","unitAggregation":"totals","interval":"day"}}
반복 오류 루프 (4단계):
{"type":"funnels","app":"<PROJECT_ID>","name":"[MCP] <도구> 반복 오류 루프",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Response",
"filters":[{"property_name":"[MCP] Tool Name","value":"<도구>","operator":"is"},{"property_name":"[MCP] Is Error","value":"true","operator":"is"}]},{"event_type":"[MCP] Tool Call Response",
"filters":[{"property_name":"[MCP] Tool Name","value":"<도구>","operator":"is"},{"property_name":"[MCP] Is Error","value":"true","operator":"is"}]},{"event_type":"[MCP] Tool Call Response",
"filters":[{"property_name":"[MCP] Tool Name","value":"<도구>","operator":"is"},{"property_name":"[MCP] Is Error","value":"true","operator":"is"}]}],
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","limitN":100,
"conversion_window_millis":3600000,
"startComparison":"none","endComparison":"none","countGroup":"User","formula":"","unitAggregation":"totals"}}
오류 → 복구 깔때기 (4단계):
{"type":"funnels","app":"<PROJECT_ID>","name":"[MCP] <도구> 오류 → 복구",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Response",
"filters":[{"property_name":"[MCP] Tool Name","value":"<도구>","operator":"is"},{"property_name":"[MCP] Is Error","value":"true","operator":"is"}]},{"event_type":"[MCP] Tool Call Response",
"filters":[{"property_name":"[MCP] Tool Name","value":"<도구>","operator":"is"},{"property_name":"[MCP] Is Error","value":"false","operator":"is"}]}],
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","limitN":100,
"conversion_window_millis":3600000,
"startComparison":"none","endComparison":"none","countGroup":"User","formula":"","unitAggregation":"totals"}}
클라이언트 구성 (4단계):
{"type":"eventsSegmentation","app":"<PROJECT_ID>","name":"[MCP] 클라이언트 구성",
"params":{"range":"지난 30일",
"events":[{"event_type":"[MCP] Tool Call Response",
"group_by":[{"type":"event","value":"[MCP] Client Name"}],
"filters":[]}],
"metric":"uniques","countGroup":"User","groupBy":[],
"start":"<0단계 시작>","end":"<0단계 종료>","category":"","startComparison":"none",
"endComparison":"none","limitN":100,"groupByLimit":100,
"formula":"","unitAggregation":"totals","interval":"day"}}