Files
dap-was-dapms/docs/contracts/agent-builder-mcp/protocol-v0.3-streaming-policy.md
koseokmin 37fc0d5ebe 사원 식별자를 암호화 전제 없이 불투명 값으로 서술한다
README와 계약 v0.3이 employee-no·virtual-employee-no를 "암호화된 사원번호"로
적고 MCP가 복호화하지 않는다고 설명했다. 암호화 여부는 MCP가 확인할 수 없고
계약이 요구하는 것도 아니므로, MCP 관점에서 참인 것만 남긴다. 해석하지 않고
그대로 전달하는 불투명 값이라는 사실이다.

로그 규칙은 그대로 둔다. 로그에는 guid와 x-request-id만 남기고 사원 식별자는
기록하지 않는다.

IntelliJ 마크다운 포맷터가 표 정렬과 줄바꿈을 함께 정리해 diff가 크다.
서식 외의 실제 변경은 위 두 가지와 운영 설정 절의 미정 표기 추가다.

남은 정리: ADR-0006은 전제 2에서 여전히 "암호화되어 전달되고 복호화 키는
사내 KMS에서 발급받는다"고 적고 있어 이 변경과 어긋난다. ADR의 전제를 바꾸는
것은 별도 결정이므로 이 커밋에 포함하지 않는다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 23:32:12 +09:00

9.9 KiB

Agent Builder-MCP 동기 JSON 계약 v0.3

  • 상태: Implemented
  • 기준일: 2026-07-16
  • 공개 endpoint: POST https://{mcpHost}{publicPath}
  • 컨테이너 endpoint: 공개 URL과 동일한 POST {publicPath}
  • JSON-RPC: 2.0
  • protocolVersion: 2025-11-25

이 계약의 현재 구현은 stateless MCP 실행 계층의 transport를 동기 JSON으로 고정한다. 현재 in-memory snapshot의 표준 Tool name metadata를 조회해 확정된 endpoint로 POST하며, Mcp-Session-Id는 lifecycle correlation 값일 뿐 서버는 initialize 성공 시 이를 발급하지만 대화·readiness 상태를 저장하지 않는다.

한 환경은 공개 host를 공유하지만 path마다 독립된 MCP Deployment와 Tool Service에 연결된다. Agent Builder는 각 공개 URL을 별도 MCP로 등록하고 initialize한다. URL 사이에는 session ID, Tool 목록, lifecycle 상태를 공유하지 않는다. Route는 path를 바꾸지 않으며 컨테이너가 같은 path를 처리한다. 이 매핑은 ADR-0009이 정본이며 JSON-RPC payload에는 영향을 주지 않는다.

HTTP 선택 정책

  • Agent Builder는 Accept: application/json, text/event-stream을 보낸다.
  • 서버는 항상 Content-Type: application/json과 단일 JSON-RPC response를 반환한다.
  • Accept는 수용 가능 형식의 선언이며, text/event-stream이 포함되어도 응답 transport를 바꾸지 않는다.
  • 독립적인 server-push SSE channel은 제공하지 않으므로 공개 endpoint의 GET405 Method Not Allowed다.
  • initialize 요청에는 MCP-Protocol-Version header를 요구하지 않는다.
  • initialize 이후 notifications/initialized, tools/list, tools/call 요청에는 정확히 MCP-Protocol-Version: 2025-11-25이 필수다. version 등 임의 header는 대체하지 않는다. header가 없거나 지원하지 않는 값이면 server는 JSON-RPC body 대신 HTTP 400 Bad Requesterror, message, supportedVersions, guid를 가진 JSON 오류 body를 반환한다.

호출자 식별 header

MCP-Protocol-Version 외에 Agent Builder가 보내는 header는 다섯 개이며 모두 선택값이다.

header 형식 서버 동작
guid UUID 없으면 서버가 생성한다. 응답 header와 오류 body에 되돌려준다
x-request-id 안전 문자 1~128자 없으면 서버가 생성한다. 응답 header에 되돌려준다
mcp-session-id 안전 문자 1~128자 initialize lifecycle 상관 값. 서버는 저장하지 않는다
employee-no 사원번호 해석하지 않는다
virtual-employee-no 가상사원번호 해석하지 않는다

사원 식별자 둘은 불투명 값이다. MCP는 검증하지 않고 Tool Service로 그대로 전달한다. 값의 의미는 보지 않되, 개행이나 공백이 섞여 downstream 요청 header를 조작하는 것은 거부한다 (출력 가능 문자 1~2048자가 아니면 -32600).

initialize와 notification

initializev0.2 요청 예시를 그대로 사용하며, 응답은 v0.3 응답 예시 처럼 원 요청 id, protocolVersion: 2025-11-25, serverInfo(name/title/version), capabilities.tools.listChanged: false를 반환한다. HTTP response header에는 새 UUID Mcp-Session-Id가 포함된다. Agent Builder는 응답 version을 이후 모든 HTTP 요청의 MCP-Protocol-Version header에 사용하고, session ID를 notifications/initialized 및 이후 Tool 요청의 correlation header로 보낸다. MCP 2025-11-25 lifecycle에 따라 Agent Builder는 notifications/initialized를 반드시 보내고 두 header를 포함한다. 서버는 notification을 HTTP 202 Accepted와 빈 body로 수용하되 stateless 원칙상 수신 여부를 저장하거나 이후 요청을 차단하는 readiness gate로 사용하지 않는다.

tools/list

tools/listresult.tools에 현재 snapshot의 공개 Tool 필드(name, title, description, inputSchema, outputSchema, annotations)를 반환한다. _meta의 version,

현재 tools/callstructuredContent를 반환하거나 Tool 응답을 outputSchema로 검증하지 않는다. 따라서 outputSchema를 가진 Tool 정의를 그대로 노출하는 동작은 현재 코드의 사실이지만 MCP 2025-11-25의 구조화 출력 계약을 완전히 충족하지 않는다. 운영 Tool은 구조화 출력 지원이 도입되기 전까지 outputSchema를 생략해야 한다.

원천은 profile이 정한다. local은 Tool Service 매니페스트를 먼저 조회하고 최초 실패 시 config/local-core-tools-manifest-sample-v1.json fallback을 사용한다(파일이 곧 목록이므로 여기에 Tool 이름을 옮겨 적지 않는다). 운영은 설정된 Tool Service 매니페스트뿐이다.

동기 Tool 호출

기본 Tool 호출은 요청 예시처럼 params.name과 object params.arguments를 사용한다. name은 tools/list와 실행 사이의 유일한 식별자다. MCP는 snapshot metadata에서 endpoint를 확정하고 arguments 전체를 JSON body로 전달한다. 성공 및 Tool 실행 실패는 각각 성공 응답, 실행 실패 응답처럼 application/json JSON-RPC response로 반환한다.

성공 응답은 Tool의 plain text를 result.content[0].text, 소요 시간(ms)을 result.content[0]._meta.searchTime, 성공 여부를 result.isError: false에 넣는다. JSON object/array 응답은 compact JSON 문자열로 text에 보존하며, outer JSON serializer가 올바른 quote escaping을 수행한다. 실행·timeout·권한 실패는 result.isError: true이며, JSON-RPC envelope/params/method 오류는 기존 JSON-RPC error다. Registry의 inputSchema는 모든 tools/call에서 Tool 호출 전에 검증한다.

tools/call 성공·오류 응답 기준

Agent Builder는 HTTP 상태만으로 성공 여부를 판단하지 않고 JSON-RPC body의 최상위 result 또는 error를 확인해야 한다. 일반적인 JSON-RPC 요청 오류는 HTTP 200 OK와 함께 최상위 error로 반환될 수 있다. -32602error.messageInvalid params: <상세 원인> 형식이며, 예를 들어 필수 query가 없으면 Invalid params: 'query' is required를 반환한다. 선택적인 error.data에는 guid와 상세 원인을 추가로 담을 수 있다. 단, MCP-Protocol-Version 누락·미지원처럼 HTTP transport 단계에서 거부된 요청은 HTTP 400 Bad Request다.

상황 HTTP 상태 JSON-RPC body isError 현재 구현의 처리 주체
Tool 정상 완료 200 result.content 반드시 false ToolsCallHandler
Tool Service timeout, upstream 4xx/5xx, downstream 권한 거부 200 result.content 반드시 true ToolsCallHandler
Tool이 실행된 뒤 업무 검증·업무 규칙으로 실패 200 result.content 반드시 true Tool Service 또는 실행 계층
JSON 문법 오류 200 최상위 error (-32700) 없음 McpExceptionHandler
JSON-RPC envelope 오류 200 최상위 error (-32600) 없음 JsonRpcRequestParser
알 수 없는 MCP method 또는 Tool 200 최상위 error (-32601 또는 Tool 조회 오류) 없음 method/registry 계층
params.name 누락, params.arguments 형식 오류, 공개된 inputSchema의 필수 값 누락 200 최상위 error (-32602) 없음 Adapter/parameter/schema validator
서버 설정·Registry 장애 등 서버가 Tool 호출을 시작할 수 없는 경우 200 최상위 error (-32603 또는 서버 정의 오류) 없음 transport/execute 계층
MCP-Protocol-Version 누락 또는 미지원 400 transport 오류 body 없음 McpProtocolVersionValidator

모든 routing은 공통 name/arguments 형식과 선택된 Tool의 inputSchema를 실행 전에 검증한다. Tool Service가 반환한 HTTP 400은 검증을 통과해 Tool 실행을 시작한 뒤의 실패이므로 result.isError: true로 반환한다.

실행 가능한 응답 형태는 성공 예시, Tool 실행 실패 예시, 잘못된 인자 예시 를 따른다.

호환성 메모

  • v0.2의 일반 JSON 요청·응답 형식은 그대로 호환된다.
  • Agent Builder의 기존 Accept: application/json, text/event-stream header는 계속 수용한다.