36시간 만에 MCP 서버의 4.4%가 도구 계약(tool contract)을 변경했습니다
요약
MCP(Model Context Protocol) 서버의 도구 계약(tool contract) 변경 빈도를 분석한 결과, 36시간 만에 샘플의 4.4%가 스키마를 변경했습니다. 이는 에이전트 개발 시 가동 시간(uptime) 확인만으로는 대응할 수 없는 스키마 불일치 위험이 존재함을 시사합니다.
핵심 포인트
- MCP 서버의 4.4%가 36시간 내에 도구 스키마를 변경함
- 도구 이름은 유지되나 inputSchema가 변경되어 에이전트 호출 오류 유발 가능
- 단순 가동 시간(uptime) 모니터링으로는 스키마 변경을 감지할 수 없음
- 스키마 변경은 에이전트의 인자 유효성 검사 오류나 모델 환각처럼 보일 수 있음
이틀 전, 저는 공개 MCP 레지스트리의 도구 표면(tool surface)을 카탈로그화했습니다. 500개의 라이브 서버를 무작위로 샘플링하여 477개의 인벤토리를 캡처했고, 각 도구의 inputSchema를 해싱(hashing)했습니다.
오늘 동일한 서버들을 대상으로 — 동일한 시드(seed), 동일한 샘플을 사용하여 — 다시 실행한 뒤 해시 값을 비교(diff)했습니다.
비교 가능한 475개의 서버 중 21개가 약 36시간 만에 도구 계약(tool contract)을 변경했습니다. 이는 4.4%에 달합니다.
무엇이 변했는가
| 변경 사항 | 서버 수 |
|---|---|
| 이미 존재하던 도구의 스키마(Schema) 변경 | 15 |
| ... |
중간 행은 지루한 내용입니다. 도구를 추가하는 것은 안전합니다. 어제 작동하던 것이 작동을 멈추는 일은 없습니다.
나머지 두 가지가 문제입니다.
위험한 카테고리는 조용히 찾아온다
15개의 서버가 이름을 유지한 채 도구의 inputSchema를 변경했습니다. 그중에는 다음과 같은 것들이 있습니다:
get_model_pricing modelpricewatch.com
poll_for_upload ai.moda/mcp-servers/remote-camera
search_incidents gateway.pipeworx.io/ai-incident-db
...
만약 당신의 에이전트(agent)가 어제 get_model_pricing을 발견하고 그 형태를 캐싱(caching)했다면, 이제 잘못된 형태(shape)로 해당 도구를 호출하게 됩니다. 아무런 공지도 없었습니다. 서버는 가동 중입니다. 도구도 존재합니다. 이름도 동일합니다. 업타임 모니터링(Uptime monitoring)은 완벽한 녹색(정상)을 보고합니다.
당신은 실행 도중, 즉 호출 시점에 이 사실을 알게 되며, 이는 인자 유효성 검사 오류(argument validation error)로 나타나거나 — 더 최악의 경우 — 모델이 매개변수(parameter)를 환각(hallucination)한 것처럼 보이게 됩니다. 이는 디버깅하기 매우 고통스러운 일입니다. 왜냐하면 모든 본능이 제3자의 스키마가 당신 밑에서 변경된 것이 아니라, 당신의 프롬프트(prompt)를 의심하게 만들기 때문입니다.
한 서버는 도구를 완전히 삭제했습니다: mcp.argo.games에서 invite_user_by_email이 사라졌습니다. 그 경우는 적어도 명확하게 실패(fail loudly)를 알립니다.
이 수치가 의미하는 것과 의미하지 않는 것
저는 **36시간 동안 4.4%**를 측정했습니다. 이것이 정직한 진술이며, 저는 이 수치를 바탕으로 무엇을 구축할지에 대해 신중하고 싶습니다.
단순하게 연간 수치로 환산할 수도 있습니다. 매일 2.9%씩 일정하게 발생한다고 가정하면 한 달 안에 약 59%의 서버가 변경된다는 의미가 되는데, 저는 저를 포함하여 그 수치를 신뢰해서는 안 된다고 생각합니다. 스키마 변경(Schema changes)은 독립적인 동전 던지기가 아닙니다. 그것들은 군집을 이룹니다. 활발하게 개발 중인 서버는 여러 번 변경되는 반면, 휴면 상태인 서버는 전혀 변경되지 않습니다. 이번 주에 움직인 21개의 서버는 다음 주에도 움직일 가능성이 매우 높은 서버들입니다.
따라서 유용한 주장은 더 좁지만 여전히 놀랍습니다: 어느 특정 날이든, 당신이 의존하는 MCP 서버의 몇 퍼센트가 도구 계약(tool contracts)을 변경할 것이며, 그러한 변경의 대부분은 호스트의 가동 여부(uptime)를 확인하는 그 어떤 것에게도 보이지 않을 것입니다.
실제 수치를 얻는 방법은 더 나은 외삽(extrapolation)이 아닙니다. 더 많은 스냅샷(snapshots)을 찍는 것입니다. 저는 계속해서 스냅샷을 찍을 것입니다.
내가 가동 시간(uptime) 수치보다 이것에 더 관심을 두는 이유
저는 이제 이 레지스트리에 대해 세 가지를 측정했습니다: 엔드포인트의 약 4분의 1이 익명 클라이언트에 서비스를 제공하지 않으며, 장애는 호스팅 플랫폼별로 집중되며, 이제는 계약(contracts)이 매일 몇 퍼센트씩 당신의 밑에서 움직인다는 사실입니다.
저는 처음에 다운타임(downtime)이 흥미로운 장애라고 가정하며 시작했습니다. 하지만 그렇지 않습니다. 다운타임은 소란스럽고, 즉시 알 수 있습니다. 정말 흥미로운 장애는 서버가 _분명히 가동 중(up)_임에도 불구하고, 당신의 에이전트가 학습했던 기능을 더 이상 수행하지 않는 경우입니다.
그러한 관점의 전환은 제가 아닌 한 독자로부터 나왔습니다. 해당 조사 게시물에서, Mads Hansen은 결과를 '연결 가능(reachable)' 대 '장애(broken)'로 단순화하는 것을 멈추고, 대신 네 가지 직교하는 상태(orthogonal states)를 추적해야 한다고 주장했습니다: 전송 연결성 (transport reachability), 프로토콜 협상 (protocol negotiation), 인증된 동작 (authenticated behaviour), 그리고 계약 호환성 (contract compatibility). 401 에러는 앞의 두 가지에 대해서는 긍정적인 증거가 되지만, 뒤의 두 가지에 대해서는 아무것도 말해주지 않습니다. 그의 말이 맞았으며, 이 포스트는 기본적으로 네 번째 상태를 처음으로 측정하는 것에 관한 것입니다.
방법론 (Method)
익명 핸드셰이크 (anonymous handshake)를 완료하는 레지스트리 등록 서버 5,346개 중에서 500개의 엔드포인트를 무작위 샘플링하였으며, 재실행 시 동일한 서버를 대상으로 할 수 있도록 random.seed(20260730)를 사용했습니다. 각 서버에 대해: initialize → notifications/initialized → tools/list 과정을 거치며, SSE 프레임 응답 (SSE-framed responses)을 처리하고 후속 요청에 Mcp-Session-Id를 스레딩(threading)했습니다 (여러 서버가 이 두 가지를 모두 요구하며, 하나라도 누락하면 빈 인벤토리(empty inventory)를 받게 됩니다). 각 도구의 inputSchema에 대해 정렬된 키(sorted keys)를 기준으로 SHA-256 해시를 생성했습니다.
기준점(Baseline)은 2026-07-30이며, 재실행은 2026-08-01에 수행되었고, 두 날짜 모두에서 비교 가능한 서버는 475개였습니다. 두 개는 읽기 가능한 집합에서 제외되었고 하나는 다시 나타났으나, 무슨 일이 일어났는지 추측하는 대신 이 세 개를 모두 제외했습니다.
스냅샷은 진리가 아니라 특정 순간의 기록입니다. 그중 두 개는 추세(trend)가 아닌 단일 지점(line)에 불과합니다. 이것이 두 번째 기록입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기