main이 6078852의 endpoint 소유권 반전을 ADR-0010으로 기록하면서 이 브랜치의 ADR-0010과 번호가 겹쳤다. 두 문서는 다른 결정이므로 나중에 문서를 합칠 때 한쪽을 옮겨야 한다. 이 브랜치가 0012까지 쓰고 있어 0011·0012를 건드리지 않는 첫 번호인 0013을 쓴다. 파일명과 제목, 대체 관계를 가리키는 ADR-0007·ADR-0009, 결정 목록, architecture 문서, Portal 계약 문서, Helm 설명, 그리고 application.yml 주석의 참조를 함께 바꾼다. 결정 내용은 바뀌지 않는다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Portal-MCP 계약 문서
이 디렉터리는 Portal과 MCP Server 사이의 Tool Server endpoint 목록 조회 계약을 관리한다.
Portal ──[portal-mcp 계약]──▶ MCP Server ──[tool-service-mcp 계약]──▶ Tool Service
(endpoint 목록) (Tool 목록과 실행)
| 문서 | 상태 | 용도 |
|---|---|---|
| protocol-v0.1-registry.md | MCP 측 구현 완료, Portal 측 미합의 | Portal registry 조회 요청·응답과 실패 처리 계약 |
이 계약이 존재하는 이유
mcp.bundles로 배포 YAML에 Tool Service를 직접 선언하는 구성에서는 이 계약이 필요 없다.
Portal이 route별 Tool Server 목록을 관리하는 구성(mcp.portal.enabled=true)에서만 사용하며,
이때 Portal은 endpoint 목록의 원천이 된다.
내부망 운영은 이 구성을 채택했다(ADR-0013). 따라서 이 계약은 선택 사항이 아니라 운영 경로의 정본이다. 배포 하나가 N개 route를 서비스하고 route 하나에 N개 Tool Service가 붙을 수 있다.
현재 원칙
- Portal은 어디에 Tool Server가 있는가만 답한다. 어떤 Tool이 있는가는 여전히 Tool Service 매니페스트가 답한다.
- MCP는 Portal registry와 Tool Service 매니페스트를 서로 다른 주기로 조회한다.
- Portal 조회 실패는 목록을 비우지 않는다. in-memory endpoint snapshot을 유지하고, cold start일 때만 Redis fallback을 읽는다.
- 요청 경로(
tools/list,tools/call)는 Portal을 호출하지 않는다. in-memory snapshot만 읽는다. - 이 구성에서 outbound 주소의 원천은 배포 YAML이 아니라 Portal이다. 따라서 Portal은 신뢰 경계 안에 있어야 하며, MCP→Portal 구간은 network 수준에서 제한한다. 근거와 요구사항은 v0.1 계약 §8에 있다.
예제와 검증
examples/registry-v0.1의 응답 JSON을 PortalRegistryContractExampleTest가 직접 읽어
PortalToolRegistryClient의 실제 파싱 경로에 태운다. 예제와 구현은 같은 변경에서 함께 고친다.
현재 producer는 외부망 검증용 PoC다
운영 Portal은 아직 이 API를 제공하지 않는다. 현재 응답을 만드는 것은 외부망 통합 검증용 PoC Portal이며, 이 계약 문서가 PoC와 운영 Portal이 공유해야 할 유일한 정본이다. PoC 구현이 저장소를 떠나도 이 문서와 예제는 남는다.
운영 적용 전에 Portal 개발 파트와 다음 항목을 확정한다.
- Portal registry API의 인증 방식과 MCP→Portal NetworkPolicy
- Tool Service 매니페스트 조회용 credential 전달 경로 (현재 registry 응답에 없다, §9)
registryRevision채번 주체와 단조 증가 보장 범위- route key 명명 규칙과 route 삭제 시 rolling 절차
상세 필드와 실패 처리는 v0.1 계약을 따른다.