Commit ca2b563
Add structured output to the Rust weather server and client
Both tools now declare an outputSchema and return structuredContent
alongside the human-readable text.
get_alerts declares Vec<Alert> as its output schema, so its structured
content is a top-level JSON array rather than an array nested in an
object. Protocol revision 2026-07-28 is the first to allow this: through
2025-11-25 an outputSchema had to be object-rooted, forcing a wrapper key
for what is naturally a list. No alerts is now simply [], not a special
case. get_forecast returns an object, for contrast.
Failure paths return a tool-level error result rather than a bare text
result: a tool that declares an outputSchema MUST return conforming
structured content, so a path with no data to return has to fail.
The client compiles every declared outputSchema at connect time and
validates results against it, per the spec's client-side SHOULD. rmcp
does not do this for you; its docs point at the jsonschema crate, which
is the one new dependency here. The client also prefers
structuredContent when forwarding to the model.
The client no longer treats a missing .env as fatal, and checks for
ANTHROPIC_API_KEY after connecting rather than before. Connecting and
listing tools needs no credentials, so this matches the Python and
TypeScript clients, which report the missing key and exit cleanly - the
behaviour the smoke tests rely on.
This supersedes modelcontextprotocol#143. That PR bumped rmcp 0.3 -> 1.4 and failed CI
because the 0.3 #[tool] macro API does not survive the jump; the rewrite
here was required either way, so the bump is folded in and taken further,
to 3.0.0-beta.2 - the first version with the 2026-07-28 model.
Two rmcp gaps worth knowing about, both discovered by connecting a
TypeScript SDK client to this server:
list_tools is hand-written. #[tool_handler] generates one that hardcodes
ttl_ms: None, cache_scope: None, but both are required on a paginated
result at 2026-07-28 (SEP-2549), and a strict client rejects the response
outright. The macro skips generation when the impl defines the method.
Without this workaround the server is unusable from such a client.
get_info does not pin ProtocolVersion::V_2026_07_28. rmcp's server never
implements server/discover - the string appears only in its client - so
it cannot serve a modern-era opening, and pinning the version only
overstates support.
Note also that rmcp sends an array-rooted schema as written on every
connection; it does not project it down to the object form older
revisions require, the way the TypeScript SDK does. Adopting an array
root is therefore a breaking change for pre-2026-07-28 clients. The
README says so.
The model identifier moves to claude-sonnet-5, the current Sonnet. All
four quickstart clients now name the same model; they had drifted onto three
different ones, and the Rust client was on claude-sonnet-4-20250514, which is
past end of life and warns on every run.
Each channel goes to its stated reader. `content` is what the model reads,
so that is what the client forwards, narrowed to the text blocks. Structured
content is for the application around the model - already validated against
the declared schema - so the client uses it as data, reporting how many items
came back.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 7b7f81e commit ca2b563
8 files changed
Lines changed: 761 additions & 207 deletions
File tree
- mcp-client-rust
- src
- weather-server-rust
- src
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| 11 | + | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
13 | | - | |
| 15 | + | |
14 | 16 | | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
19 | 24 | | |
20 | 25 | | |
21 | 26 | | |
| |||
24 | 29 | | |
25 | 30 | | |
26 | 31 | | |
| 32 | + | |
27 | 33 | | |
28 | 34 | | |
29 | 35 | | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
30 | 54 | | |
31 | 55 | | |
32 | 56 | | |
| |||
52 | 76 | | |
53 | 77 | | |
54 | 78 | | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
55 | 91 | | |
56 | 92 | | |
57 | 93 | | |
| |||
93 | 129 | | |
94 | 130 | | |
95 | 131 | | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
96 | 136 | | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
| 137 | + | |
101 | 138 | | |
102 | 139 | | |
103 | 140 | | |
104 | | - | |
105 | | - | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
106 | 159 | | |
107 | 160 | | |
108 | 161 | | |
| |||
179 | 232 | | |
180 | 233 | | |
181 | 234 | | |
182 | | - | |
| 235 | + | |
| 236 | + | |
183 | 237 | | |
184 | 238 | | |
185 | 239 | | |
| |||
194 | 248 | | |
195 | 249 | | |
196 | 250 | | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
197 | 262 | | |
198 | 263 | | |
199 | 264 | | |
| |||
0 commit comments