Commit d0dd7fe
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.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 7b7f81e commit d0dd7fe
8 files changed
Lines changed: 808 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 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 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 | + | |
| 24 | + | |
| 25 | + | |
19 | 26 | | |
20 | 27 | | |
21 | 28 | | |
| |||
24 | 31 | | |
25 | 32 | | |
26 | 33 | | |
| 34 | + | |
27 | 35 | | |
28 | 36 | | |
29 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
30 | 57 | | |
31 | 58 | | |
32 | 59 | | |
| |||
52 | 79 | | |
53 | 80 | | |
54 | 81 | | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
55 | 95 | | |
56 | 96 | | |
57 | 97 | | |
| |||
93 | 133 | | |
94 | 134 | | |
95 | 135 | | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
96 | 140 | | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
| 141 | + | |
101 | 142 | | |
102 | 143 | | |
103 | 144 | | |
104 | | - | |
105 | | - | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
106 | 156 | | |
107 | 157 | | |
108 | 158 | | |
| |||
179 | 229 | | |
180 | 230 | | |
181 | 231 | | |
182 | | - | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
183 | 236 | | |
184 | 237 | | |
185 | 238 | | |
| |||
194 | 247 | | |
195 | 248 | | |
196 | 249 | | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
197 | 261 | | |
198 | 262 | | |
199 | 263 | | |
| |||
0 commit comments