feat(mcp): fb-41 PR-5 MCP ask multi_hop arg + SKILL.md 안내 #172

Merged
altair823 merged 2 commits from feat/fb-41-pr-5-mcp-multi-hop-arg into main 2026-05-25 09:09:08 +00:00
Owner

요약

fb-41 multi-hop RAG 의 PR-5 (PR-4 머지 직후). PR-4 의 CLI --multi-hop flag 와 sister surface — agent (Claude Code 등 MCP host) 가 mcp__kebab__ask 호출 시 multi_hop: true 옵션 사용 가능.

설계: docs/superpowers/specs/2026-05-25-p9-fb-41-multi-hop-rag-design.md
계획: docs/superpowers/plans/2026-05-25-p9-fb-41-multi-hop-rag.md (PR-5 단락)

MCP surface

  • crates/kebab-mcp/src/tools/ask.rs:
    • AskInput.multi_hop: Option<bool> 추가. JsonSchema derive 가 tools/list 의 input schema 에 자동 반영 — agent capability discovery 가 새 필드 인식.
    • handle()AskOpts.multi_hop = input.multi_hop.unwrap_or(false) — 기존 caller (필드 누락 / null) 는 single-pass 그대로.
  • crates/kebab-mcp/src/lib.rs (tools/list):
    • ask tool description 에 multi-hop 한 줄 (decompose → retrieve → synthesize, 2-5× LLM cost, per-hop trace on Answer.hops).

SKILL.md 안내

  • integrations/claude-code/kebab/SKILL.mdmcp__kebab__ask 절:
    • Input JSON 예제에 multi_hop: false 추가.
    • Returns 절에 hops (multi-hop only) 추가.
    • 신규 bullet (p9-fb-41) — opt-in 조건 / 비용 trade-off / 사용 케이스 (compound questions, prereq chains, cross-doc reasoning) / Answer.hops 의 per-hop trace shape / multi_hop_decompose_failed refusal 처리.

Tests (tests/tools_call_ask_multi_hop.rs 신규, 2 Ollama-free pins)

  • ask_tool_routes_multi_hop_true_to_decompose_firstdispatch divergence 핀. invalid LLM endpoint (http://127.0.0.1:1, request_timeout_secs=2) 로 force unreachable. multi_hop=true 는 decompose 먼저 호출 → error.v1 (code=model_unreachable) / isError=true. multi_hop=false (single-pass) 는 empty KB 에서 retrieve 먼저 → no LLM call → answer.v1 grounded=false / isError=false. 두 shape 의 분기가 dispatch 가 실제로 다른 path 로 라우팅됨의 증거.
  • ask_input_schema_advertises_multi_hop_field — AskInput 의 JsonSchema 가 multi_hop property 노출. MCP host capability discovery (tools/list) 회귀 핀.

기존 tools_call_ask.rs 의 AskInput literal 도 multi_hop: None 추가 (struct field 추가 cascade).

변경 없음

  • prompt_template_version (rag-multi-hop-v1) — 그대로.
  • TUI surface — PR-6 의 책임.
  • error_wire.rs 매핑 — PR-4 의 enum reservation 그대로 (no promotion).

검증

  • cargo test -p kebab-mcp -j 1 — 신규 tools_call_ask_multi_hop 2 + 기존 ask / search / bulk_search / fetch / ingest / schema / doctor / tools_list / initialize 등 모두 통과 (회귀 없음).
  • cargo clippy -p kebab-mcp --all-targets -j 1 -- -D warnings clean.
  • 단일 crate 직렬 build (16 GB RAM 제약).

시험 항목 (Test Plan)

  • AskInput.multi_hop 가 JsonSchema 에 노출 (tools/list 회귀 핀)
  • multi_hop=true 의 dispatch 가 decompose 먼저 호출 (model_unreachable error.v1)
  • multi_hop=false (default) 의 dispatch 는 single-pass (empty KB → grounded=false answer.v1)
  • SKILL.md 의 ask 절에 비용 trade-off / 사용 케이스 / hops trace shape 안내
  • 기존 ask / search / bulk_search / fetch / schema / doctor / ingest_* test 회귀 없음

다음 PR

  • PR-6: TUI Ask 패널 multi-hop toggle (F2 / Ctrl-T) + hop trace render + cheatsheet 갱신.
  • v0.18.0 cut (PR-6 머지 후).

Assisted-by: Claude Code

## 요약 fb-41 multi-hop RAG 의 **PR-5** (PR-4 머지 직후). PR-4 의 CLI `--multi-hop` flag 와 sister surface — agent (Claude Code 등 MCP host) 가 `mcp__kebab__ask` 호출 시 `multi_hop: true` 옵션 사용 가능. 설계: docs/superpowers/specs/2026-05-25-p9-fb-41-multi-hop-rag-design.md 계획: docs/superpowers/plans/2026-05-25-p9-fb-41-multi-hop-rag.md (PR-5 단락) ## MCP surface - `crates/kebab-mcp/src/tools/ask.rs`: - `AskInput.multi_hop: Option<bool>` 추가. JsonSchema derive 가 tools/list 의 input schema 에 자동 반영 — agent capability discovery 가 새 필드 인식. - `handle()` 가 `AskOpts.multi_hop = input.multi_hop.unwrap_or(false)` — 기존 caller (필드 누락 / null) 는 single-pass 그대로. - `crates/kebab-mcp/src/lib.rs` (tools/list): - `ask` tool description 에 multi-hop 한 줄 (decompose → retrieve → synthesize, 2-5× LLM cost, per-hop trace on Answer.hops). ## SKILL.md 안내 - `integrations/claude-code/kebab/SKILL.md` 의 `mcp__kebab__ask` 절: - Input JSON 예제에 `multi_hop: false` 추가. - Returns 절에 `hops` (multi-hop only) 추가. - 신규 bullet (p9-fb-41) — opt-in 조건 / 비용 trade-off / 사용 케이스 (compound questions, prereq chains, cross-doc reasoning) / `Answer.hops` 의 per-hop trace shape / `multi_hop_decompose_failed` refusal 처리. ## Tests (`tests/tools_call_ask_multi_hop.rs` 신규, 2 Ollama-free pins) - `ask_tool_routes_multi_hop_true_to_decompose_first` — **dispatch divergence 핀**. invalid LLM endpoint (`http://127.0.0.1:1`, request_timeout_secs=2) 로 force unreachable. multi_hop=true 는 decompose 먼저 호출 → `error.v1` (code=model_unreachable) / isError=true. multi_hop=false (single-pass) 는 empty KB 에서 retrieve 먼저 → no LLM call → `answer.v1` grounded=false / isError=false. 두 shape 의 분기가 dispatch 가 실제로 다른 path 로 라우팅됨의 증거. - `ask_input_schema_advertises_multi_hop_field` — AskInput 의 JsonSchema 가 `multi_hop` property 노출. MCP host capability discovery (tools/list) 회귀 핀. 기존 `tools_call_ask.rs` 의 AskInput literal 도 `multi_hop: None` 추가 (struct field 추가 cascade). ## 변경 없음 - `prompt_template_version` (`rag-multi-hop-v1`) — 그대로. - TUI surface — PR-6 의 책임. - `error_wire.rs` 매핑 — PR-4 의 enum reservation 그대로 (no promotion). ## 검증 - `cargo test -p kebab-mcp -j 1` — 신규 tools_call_ask_multi_hop 2 + 기존 ask / search / bulk_search / fetch / ingest / schema / doctor / tools_list / initialize 등 모두 통과 (회귀 없음). - `cargo clippy -p kebab-mcp --all-targets -j 1 -- -D warnings` clean. - 단일 crate 직렬 build (16 GB RAM 제약). ## 시험 항목 (Test Plan) - [x] AskInput.multi_hop 가 JsonSchema 에 노출 (tools/list 회귀 핀) - [x] multi_hop=true 의 dispatch 가 decompose 먼저 호출 (model_unreachable error.v1) - [x] multi_hop=false (default) 의 dispatch 는 single-pass (empty KB → grounded=false answer.v1) - [x] SKILL.md 의 ask 절에 비용 trade-off / 사용 케이스 / hops trace shape 안내 - [x] 기존 ask / search / bulk_search / fetch / schema / doctor / ingest_* test 회귀 없음 ## 다음 PR - PR-6: TUI Ask 패널 multi-hop toggle (F2 / Ctrl-T) + hop trace render + cheatsheet 갱신. - v0.18.0 cut (PR-6 머지 후). Assisted-by: Claude Code
altair823 added 1 commit 2026-05-25 09:06:59 +00:00
fb-41 multi-hop RAG 의 **PR-5** (PR-4 머지 직후). PR-4 의 CLI `--multi-hop`
flag 와 sister surface — agent (Claude Code 등 MCP host) 가 `mcp__kebab__ask`
호출 시 `multi_hop: true` 옵션 사용 가능.

설계: docs/superpowers/specs/2026-05-25-p9-fb-41-multi-hop-rag-design.md
계획: docs/superpowers/plans/2026-05-25-p9-fb-41-multi-hop-rag.md (PR-5 단락)

## MCP surface

- `crates/kebab-mcp/src/tools/ask.rs`:
  - `AskInput.multi_hop: Option<bool>` 추가. JsonSchema derive 가 tools/list
    에 자동 반영 — agent capability discovery 가 새 필드 인식.
  - `handle()` 가 `AskOpts.multi_hop = input.multi_hop.unwrap_or(false)` —
    기존 caller (필드 누락 / null) 는 single-pass 그대로.
- `crates/kebab-mcp/src/lib.rs` (tools/list):
  - `ask` tool description 에 multi-hop 한 줄 (decompose → retrieve →
    synthesize, 2-5× LLM cost, per-hop trace on Answer.hops).

## SKILL.md 안내

- `integrations/claude-code/kebab/SKILL.md` 의 `mcp__kebab__ask` 절:
  - Input shape JSON 예제에 `multi_hop: false` 추가.
  - Returns 절에 `hops` (multi-hop only) 추가.
  - 신규 bullet (p9-fb-41) — opt-in 조건 / 비용 trade-off / 사용 케이스
    (compound questions / prereq chains / cross-doc reasoning) /
    `Answer.hops` 의 per-hop trace shape / `multi_hop_decompose_failed`
    refusal 처리.

## Tests (`tests/tools_call_ask_multi_hop.rs` 신규, 2 Ollama-free pins)

- `ask_tool_routes_multi_hop_true_to_decompose_first`: dispatch
  divergence 핀. invalid LLM endpoint (`http://127.0.0.1:1`,
  request_timeout_secs=2) 로 force unreachable. multi_hop=true 는
  decompose 먼저 호출 → `error.v1` (code=model_unreachable) /
  isError=true. multi_hop=false (single-pass) 는 empty KB 에서 retrieve
  먼저 → no LLM call → `answer.v1` grounded=false / isError=false. 두
  shape 의 분기가 dispatch 가 실제로 다른 path 로 라우팅됨의 증거.
- `ask_input_schema_advertises_multi_hop_field`: AskInput 의 JsonSchema
  가 `multi_hop` property 노출 — MCP host capability discovery
  (tools/list 의 input schema) 회귀 핀.

기존 `tools_call_ask.rs` 의 AskInput literal 도 `multi_hop: None`
추가 (struct field 추가에 따른 minimal cascade).

## 변경 없음

- `prompt_template_version` (`rag-multi-hop-v1`) — 그대로.
- TUI surface — PR-6 의 책임.
- error.v1 매핑 — PR-4 의 enum reservation 그대로 (no error_wire
  promotion).

## 검증

- `cargo test -p kebab-mcp -j 1` — 신규 tools_call_ask_multi_hop 2 +
  기존 ask / search / bulk_search / fetch / ingest / schema / doctor /
  tools_list / initialize 등 모두 통과 (회귀 없음).
- `cargo clippy -p kebab-mcp --all-targets -j 1 -- -D warnings` clean.
- 단일 crate 직렬 build (16 GB RAM 제약).

## 다음 PR

- PR-6: TUI Ask 패널 multi-hop toggle (F2 / Ctrl-T) + hop trace render +
  cheatsheet 갱신.
- v0.18.0 cut (PR-6 머지 후).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-05-25 09:08:11 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 1 — dispatch test 의 환경 견고성 nit 1 건.

PR-5 의 scope (AskInput 의 multi_hop field + handle wiring + tools/list description + SKILL.md 안내 + 2 test) 자체는 컴팩트. SKILL.md 의 신규 bullet 도 opt-in / 비용 / 사용 케이스 / hops shape / refusal 처리 까지 covers 다. tools_call_ask.rs 의 AskInput literal cascade (multi_hop: None) 도 minimal.

본 유일 nit: ask_tool_routes_multi_hop_true_to_decompose_first 가 invalid LLM endpoint 의 결과 error code 를 model_unreachable 만 정확히 받는다고 가정. 환경 (OS / connect timeout 동작) 에 따라 timeout 도 정합. test 의 핵심 contract = dispatch divergence 자체라 두 code 모두 accept 하면 견고. inline 코멘트에 fix 제안.

회차 1 — dispatch test 의 환경 견고성 nit 1 건. PR-5 의 scope (AskInput 의 multi_hop field + handle wiring + tools/list description + SKILL.md 안내 + 2 test) 자체는 컴팩트. SKILL.md 의 신규 bullet 도 opt-in / 비용 / 사용 케이스 / hops shape / refusal 처리 까지 covers 다. `tools_call_ask.rs` 의 AskInput literal cascade (`multi_hop: None`) 도 minimal. 본 유일 nit: `ask_tool_routes_multi_hop_true_to_decompose_first` 가 invalid LLM endpoint 의 결과 error code 를 `model_unreachable` 만 정확히 받는다고 가정. 환경 (OS / connect timeout 동작) 에 따라 `timeout` 도 정합. test 의 핵심 contract = dispatch divergence 자체라 두 code 모두 accept 하면 견고. inline 코멘트에 fix 제안.
@@ -0,0 +107,4 @@
session_id: None,
mode: Some("lexical".to_string()),
multi_hop: Some(false),
},

환경 견고성 nit: assert_eq!(mh_v["code"], "model_unreachable") 가 환경에 따라 fragile 할 수 있다. http://127.0.0.1:1 가 OS / kernel / docker 등의 차이로:

  • 즉시 ECONNREFUSEDerror_wire::classify_llmmodel_unreachable.
  • connect timeout (rare 하지만 가능) → timeout.

이 test 의 핵심 contract 는 "multi-hop dispatch 가 LLM 까지 도달했다" — 정확한 error code 값보다 isError=true + schema_version=error.v1 + single-pass 와 다른 wire shape 가 본질. 견고화 두 옵션:

  • assert!(matches!(mh_v["code"].as_str(), Some("model_unreachable" | "timeout")), ...) — 두 LLM-reachability code 모두 accept.
  • 또는 더 단순하게 assert!(["model_unreachable", "timeout"].contains(&mh_v["code"].as_str().unwrap_or("")), ...).

현재 dev 환경 (local Linux) 에서는 한쪽 (model_unreachable) 으로 안정 동작하지만, CI / 다른 OS 회귀 위험 회피.

**환경 견고성 nit**: `assert_eq!(mh_v["code"], "model_unreachable")` 가 환경에 따라 fragile 할 수 있다. `http://127.0.0.1:1` 가 OS / kernel / docker 등의 차이로: - **즉시 ECONNREFUSED** → `error_wire::classify_llm` 가 `model_unreachable`. - **connect timeout** (rare 하지만 가능) → `timeout`. 이 test 의 핵심 contract 는 "multi-hop dispatch 가 LLM 까지 도달했다" — 정확한 error code 값보다 *isError=true + schema_version=error.v1* + *single-pass 와 다른 wire shape* 가 본질. 견고화 두 옵션: - `assert!(matches!(mh_v["code"].as_str(), Some("model_unreachable" | "timeout")), ...)` — 두 LLM-reachability code 모두 accept. - 또는 더 단순하게 `assert!(["model_unreachable", "timeout"].contains(&mh_v["code"].as_str().unwrap_or("")), ...)`. 현재 dev 환경 (local Linux) 에서는 한쪽 (model_unreachable) 으로 안정 동작하지만, CI / 다른 OS 회귀 위험 회피.
altair823 added 1 commit 2026-05-25 09:08:45 +00:00
`ask_tool_routes_multi_hop_true_to_decompose_first` 의 error code
검증을 더 견고하게 — `model_unreachable | timeout` 둘 다 accept.
환경 차이 (즉시 ECONNREFUSED vs connect timeout) 가 다른 wire code
로 분류돼도 dispatch divergence 자체 (schema_version=error.v1 +
isError=true vs single-pass 의 answer.v1 grounded=false) 는 동일하게
검증.

검증
- `cargo test -p kebab-mcp -j 1 --test tools_call_ask_multi_hop` 2 통과.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-05-25 09:08:57 +00:00
claude-reviewer-01 left a comment
Member

회차 2 — 회차 1 의 환경 견고성 nit 완벽 반영. model_unreachable | timeout 둘 다 accept + 견고화 의도 doc 으로 명시. 추가 actionable 항목 없음 — 머지에 동의.

요약:

  • MCP ask tool 에 multi_hop: Option<bool> argument 추가, default false 로 기존 caller backward-compat. tools/list description 도 사용 케이스 한 줄 안내.
  • SKILL.md ask 절에 비용 trade-off / 사용 케이스 / Answer.hops trace shape / multi_hop_decompose_failed refusal 처리까지 cover 하는 bullet 추가.
  • 2 Ollama-free pin (dispatch divergence + AskInput JsonSchema 회귀) — invalid LLM endpoint 와 짧은 timeout 으로 환경 의존성 회피.
  • cargo test -p kebab-mcp -j 1 모든 test 통과 (회귀 없음), cargo clippy ... -- -D warnings clean.
회차 2 — 회차 1 의 환경 견고성 nit 완벽 반영. `model_unreachable | timeout` 둘 다 accept + 견고화 의도 doc 으로 명시. 추가 actionable 항목 없음 — 머지에 동의. 요약: - MCP `ask` tool 에 `multi_hop: Option<bool>` argument 추가, default false 로 기존 caller backward-compat. tools/list description 도 사용 케이스 한 줄 안내. - SKILL.md ask 절에 비용 trade-off / 사용 케이스 / Answer.hops trace shape / `multi_hop_decompose_failed` refusal 처리까지 cover 하는 bullet 추가. - 2 Ollama-free pin (dispatch divergence + AskInput JsonSchema 회귀) — invalid LLM endpoint 와 짧은 timeout 으로 환경 의존성 회피. - `cargo test -p kebab-mcp -j 1` 모든 test 통과 (회귀 없음), `cargo clippy ... -- -D warnings` clean.
altair823 merged commit bf28a1e4d9 into main 2026-05-25 09:09:08 +00:00
altair823 deleted branch feat/fb-41-pr-5-mcp-multi-hop-arg 2026-05-25 09:09:09 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#172