1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Shared error type and response-wrapping helpers for the MCP tool dispatcher.
//!
//! Why: the `DispatchError` variants and the `wrap_*` helpers are referenced
//! from multiple submodules (search, index, misc). Centralising them here
//! prevents import cycles and keeps each tool group focused on its own logic.
//! What: exports `DispatchError`, `require_str`, and the four `wrap_*`
//! response-shaping functions consumed by `dispatch` in `mod.rs`.
//! Test: coverage via the public dispatch tests in `tests.rs` and
//! `tests_lane.rs`; the types themselves are structural, not logic-bearing.
use Value;
/// Transport-layer and parameter errors that `call_tool` can return.
///
/// Why: a typed enum lets `dispatch` branch on the failure kind and map it
/// to the correct JSON-RPC error code or in-band MCP tool error shape without
/// parsing error strings.
/// What: four variants — `UnknownTool` (no route), `InvalidParams` (bad args),
/// `Transport` (HTTP-level failure), `StageNotReady` (issue #138 pre-flight
/// failure with structured retry hint).
/// Test: every variant is exercised by at least one unit test in `tests.rs` or
/// `tests_lane.rs`.
pub
/// Extract a required `&str` field from a JSON args object.
///
/// Why: every tool arm needs to pull required string fields and return a
/// uniform `INVALID_PARAMS` error when they are missing or not strings.
/// What: returns `Ok(&str)` on success, `Err(DispatchError::InvalidParams)`
/// with a human-readable message on failure.
/// Test: `missing_params_returns_invalid_params` in `tests.rs`.
pub
/// Wrap a structured JSON result in MCP's `content[]` envelope (bare-method
/// form).
///
/// Why: bare-method callers (not using `tools/call`) expect a plain
/// `{content: [{type, text}]}` wrapper rather than the `isError` form.
/// What: pretty-prints the value into a single text content node.
/// Test: indirect coverage via all search dispatch tests in `tests.rs`.
pub
/// Wrap a successful `tools/call` payload with the spec-required `isError`
/// flag.
///
/// Why: the MCP spec's `tools/call` response shape always includes `isError`
/// so MCP clients can branch without parsing text content.
/// What: pretty-prints the value and embeds it alongside `"isError": is_error`.
/// Test: indirect coverage via `tools/call`-form tests in `tests.rs`.
pub
/// Wrap a tool execution failure as `{content, isError: true}` per MCP spec.
///
/// Why: the `tools/call` protocol requires in-band error signalling via
/// `isError: true` rather than a JSON-RPC error envelope.
/// What: formats the message into a text content node with `"isError": true`.
/// Test: `search_semantic_tool_returns_stage_not_ready_when_stage_2_missing`
/// in `tests_lane.rs`.
pub
/// Wrap a STAGE_NOT_READY error in MCP's structured tool-error envelope
/// (issue #138).
///
/// Why: MCP `tools/call` failures use `isError: true` rather than the
/// JSON-RPC error envelope. The LLM gets the human-readable text in
/// `content[]` AND a machine-readable `_meta` block with the exact retry
/// hint (`suggested_tools`) and the current stages snapshot so it can
/// pick the right fallback tool without a second probe.
/// What: returns a JSON object matching the spec in issue #138 — `isError:
/// true`, single text content node, and `_meta` carrying `error_code`,
/// `current_stages`, and `suggested_tools`.
/// Test: `search_semantic_tool_returns_stage_not_ready_when_stage_2_missing`
/// in `tests_lane.rs`.
pub