Use manifest-defined endpoints for tool routing
All checks were successful
Deploy Gateway / deploy (push) Successful in 2m35s

This commit is contained in:
2026-08-19 11:43:24 +09:00
parent 422dd8c6e7
commit 60788525d6
19 changed files with 318 additions and 107 deletions

View File

@@ -45,7 +45,7 @@ ToolBundleRegistryClient.fetchTools()
-> ToolBundleDiscovery.discoverAll()
-> GET {manifestUrl}
-> bundleId / tools[] / Tool 필수 필드 검증
-> ToolMetadata 생성 (endpoint는 MCP 배포 설정의 baseEndpoint 사용)
-> ToolMetadata 생성 (endpoint는 Tool Service manifest의 top-level endpoint 또는 _meta.endpoint 사용)
-> enabled=false Tool 제외
-> immutable List<ToolMetadata>를 AtomicReference snapshot에 저장
```
@@ -213,7 +213,7 @@ Content-Type: application/json
3. 모든 Tool에 고유한 표준 `name`, 비어 있지 않은 `description`, object 형태의 `inputSchema`, `_meta.version`을 넣는다.
4. Tool을 숨기려면 `_meta.enabled: false`를 쓰거나 정상 전체 목록에서 제거한다. 둘의 변경 반영 시점은 다음 refresh다.
5. 실행 주소·credential·개인정보·업무 payload를 매니페스트에 넣지 않는다.
6. Tool 자체 실행 endpoint는 별도로 `POST {baseEndpoint}/{toolName}`을 구현한다. manifest endpoint는 실행 endpoint가 아니다.
6. Tool 자체 실행 endpoint는 manifest의 top-level `endpoint` 또는 `_meta.endpoint`에 선언한다. 상대 경로는 Portal registry의 `serviceDomain` 뒤에 붙고, 절대 HTTP(S) URL은 Tool Service가 제공한 실행 주소 원천으로 그대로 사용한다.
## 확인한 구현·테스트

View File

@@ -27,6 +27,7 @@
},
"_meta": {
"version": "1.2.0",
"endpoint": "/mcp/processing.contract.inquiry",
"timeoutMillis": 3000,
"enabled": true
}
@@ -61,6 +62,7 @@
},
"_meta": {
"version": "1.0.1",
"endpoint": "/mcp/processing.payment.history",
"timeoutMillis": 5000,
"enabled": true
}
@@ -86,6 +88,7 @@
},
"_meta": {
"version": "0.9.0",
"endpoint": "/mcp/processing.notice.send",
"timeoutMillis": 10000,
"enabled": false
}

View File

@@ -4,7 +4,7 @@
- 기준일: 2026-07-30
- 대체 대상: push 등록 방식(v0.1). 채택하지 않은 이유는 §2
- 조회 endpoint: `GET {manifestUrl}` — Tool Service가 제공
- 실행 endpoint: `POST {baseEndpoint}/{toolName}` — 현재 구현
- 실행 endpoint: Tool Service manifest의 top-level `endpoint` 또는 `_meta.endpoint` — 현재 구현
## 1. 계약 범위와 원칙
@@ -15,7 +15,7 @@ MCP Server는 자기 설정에 선언된 bundle의 매니페스트를 **주기
|---|---|
| MCP가 가져온다 | Tool Service는 매니페스트를 제공만 한다. MCP에 등록 요청을 보내지 않는다 |
| 조회 대상은 설정이 정한다 | 어떤 bundle이 이 MCP에 속하는지는 배포 시점 YAML로 확정된다 |
| **라우팅 주소는 설정이 소유한다** | 호출 대상 주소는 MCP 설정에서만 온다. 매니페스트가 바꿀 수 없다 |
| **Tool Server domain은 포털이, Tool endpoint는 Tool Service가 소유한다** | 포털은 Tool Server의 `serviceDomain``manifestPath`만 제공하고, 개별 Tool 실행 endpoint는 Tool Service manifest의 top-level `endpoint` 또는 `_meta.endpoint`에서 온다 |
| 매니페스트는 전체 상태 | 응답은 그 bundle의 Tool 전체 목록이다. 증분 없음 |
| 조회 성공이 생존 신호 | 별도 heartbeat·TTL 장치가 없다 |
| bundle 단위 조회 격리 | 한 bundle의 조회 실패가 다른 bundle의 조회를 중단시키지 않는다 |
@@ -170,7 +170,7 @@ MCP는 이 경우 직전 매니페스트를 그대로 유지한다. **선택 기
| `revision` | 아니오 | 매니페스트 버전. 변경 감지·로그·ETag에만 쓰인다 |
| `tools` | 예 | 이 bundle이 노출하는 Tool 전체. 빈 배열은 "노출할 Tool 없음"이다 |
`baseEndpoint`**매니페스트에 넣지 않는다.** 넣어도 MCP는 무시한다(§1 세 번째 원칙).
Tool 실행 endpoint는 각 Tool의 top-level `endpoint` 또는 `_meta.endpoint`에 넣는다. 상대 경로를 쓰면 포털 registry의 `serviceDomain` 뒤에 붙고, 절대 URL을 쓰면 Tool Service manifest가 제공한 실행 주소 원천으로 그대로 사용한다. HTTP(S)가 아닌 scheme은 거부한다.
### `tools[]` 필드
@@ -299,7 +299,7 @@ management port(운영 기본 9090)에서 MCP가 알고 있는 bundle의 조회
이미 구현되어 있는 계약이다. Tool Service는 아래를 받을 수 있어야 한다.
```text
POST {baseEndpoint}/{toolName}
POST {endpoint}
Content-Type: application/json
guid, x-request-id, mcp-session-id, employee-no, virtual-employee-no
Authorization: <설정에 따라 전달>