취소 패턴
취소 패턴 (Cancellation)
MCP는 알림 메시지를 통해 진행 중인 요청의 선택적 취소를 지원합니다. 클라이언트는 취소 알림을 보내(SHOULD) 이전에 발행한 요청을 종료하라고 표시할 수 있어요.
서버가 구독 스트림을 내릴 때는 그 subscriptions/listen 요청 ID를 참조하는 notifications/cancelled를 보내야 합니다(MUST)(see Subscriptions). 서버는 다른 목적으로는 notifications/cancelled를 보내면 안 됩니다(MUST NOT).
취소 흐름 (Cancellation Flow)
클라이언트가 진행 중인 요청을 취소하려면 다음을 담은 notifications/cancelled 알림을 보냅니다:
- 취소할 요청의 ID
- 로깅하거나 표시할 수 있는 선택적 이유 문자열
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
전송별 취소 (Transport-Specific Cancellation)
클라이언트가 취소를 알리는 방식은 전송에 따라 달라요:
- Streamable HTTP: SSE 응답 스트림을 닫는 것이 취소 신호입니다. 서버는 클라이언트 연결 해제를 그 요청의 취소로 반드시(MUST) 처리해야 합니다.
notifications/cancelled메시지는 필요하지도 기대되지도 않아요. - stdio: 닫을 요청별 스트림이 없습니다. 클라이언트는 요청 ID를 참조하는
notifications/cancelled알림을 보내야 합니다(MUST).
타임아웃 (Timeouts)
구현은 중단된 연결과 리소스 고갈을 막기 위해 보낸 모든 요청에 타임아웃을 설정하는 것이 좋습니다(SHOULD). 타임아웃 기간 안에 성공 또는 오류 응답을 받지 못하면, 발신자는 요청을 취소하고 응답 대기를 멈춰야 합니다(SHOULD). 전송별 취소에 설명된 대로 이는 다음을 뜻해요:
- Streamable HTTP: 요청의 응답 스트림을 닫는다 — 이것이 곧 취소.
- stdio: 요청 ID를 참조하는
notifications/cancelled알림을 보낸다.
SDK 및 기타 미들웨어는 이런 타임아웃을 요청별로 설정 가능하게 해야 합니다(SHOULD).
구현은 요청에 해당하는 진행률 알림을 받으면 타임아웃 시계를 리셋할 수 있어요(MAY). 실제 작업이 진행 중이라는 뜻이니까요. 하지만 구현은 잘못 동작하는 클라이언트나 서버의 영향을 제한하려고, 진행률 알림과 무관하게 항상 최대 타임아웃을 강제해야 합니다(SHOULD).
동작 요건 (Behavior Requirements)
- 취소 알림은 다음 요청만 참조해야 합니다(MUST):
- 클라이언트가 이전에 발행한 요청
- 아직 진행 중이라고 여겨지는 요청
- 서버 발신 취소 알림은
subscriptions/listen요청을 참조해, 그 구독 스트림을 종료해야 합니다(MUST) - 취소 알림을 받은 서버는 다음을 해야 합니다(SHOULD):
- 취소된 요청 처리를 중단
- 관련 리소스를 해제
- 취소된 요청에 대한 응답을 보내지 않음
- 서버는 다음 경우 취소 알림을 무시할 수 있습니다(MAY):
- 참조된 요청을 모름
- 처리가 이미 완료됨
- 요청을 취소할 수 없음
- 클라이언트는 취소한 요청에 대해 나중에 도착하는 응답을 무시해야 합니다(SHOULD)
타이밍 고려 (Timing Considerations)
네트워크 지연 때문에 취소 알림이 요청 처리 완료 후, 심지어 응답이 이미 나간 후에 도착할 수 있어요.
양측 모두 이런 경합 조건을 우아하게 처리해야 합니다(MUST):
sequenceDiagram
participant Client
participant Server
Client->>Server: Request (ID: 123)
Note over Server: Processing starts
Client--)Server: notifications/cancelled (ID: 123)
alt
Note over Server: Processing may have<br/>completed before<br/>cancellation arrives
else If not completed
Note over Server: Stop processing
end
구현 참고 (Implementation Notes)
- 양측 모두 디버깅을 위해 취소 이유를 로깅하는 것이 좋습니다(SHOULD)
- 애플리케이션 UI는 취소가 요청됐음을 표시해야 합니다(SHOULD)
오류 처리 (Error Handling)
잘못된 취소 알림은 무시하는 것이 좋습니다(SHOULD):
- 알 수 없는 요청 ID
- 이미 완료된 요청
- 잘못된 형식의 알림
이렇게 하면 알림의 "발사 후 잊기(fire and forget)" 특성이 유지되면서, 비동기 통신에서의 경합 조건도 허용할 수 있어요.