Repository navigation
Return get_alerts as {"alerts": [...]} so 2025-11-25 clients can use it - #296
Conversation
Closes #272 with option A. Also closes the Python half of #191. All five servers declared `get_alerts`' output schema with a top-level array root and sent it on every session. 2025-11-25 and earlier require an object root, and 2025-11-25 is what most clients negotiate today. Python failed `tools/list` outright (`-32603 "Handler returned an invalid result"`, so no tools at all). Go, Ruby and Rust sent the array, which strict clients reject and Inspector drops. Only TypeScript worked, because its SDK wraps the array as `{"result": [...]}`. No SDK release converts the schema for older sessions yet, so until they do, the servers wrap the list themselves: - `get_alerts` now returns `{"alerts": [...]}` with an object-rooted schema in all five servers, and an empty list when there are no alerts - Python: `Alerts` is a plain `BaseModel`, no longer a `RootModel` - Go: dropped the hand-written schema override and the SDK infers the schema; `jsonschema-go` becomes an indirect dependency - TypeScript, Ruby, Rust: wrapped the schema and the returned value - Tests: each server test now first opens a raw JSON-RPC 2025-11-25 session (`initialize`, `tools/list`) without the SDK, which could quietly drop or rewrite a bad tool. It checks that the call succeeds and that every `outputSchema` has an `object` root. Then it connects through the SDK as before (it negotiates 2026-07-28 and now logs the version) and checks object roots and object `structuredContent` there too - READMEs: each server README explains what a 2025-11-25 client sees and why the list is wrapped; `tests/README.md` describes the new check
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are reported for the alert-response compatibility changes.
No open issues 🎉
What changed in this PR
Updates all five weather-server examples to return {"alerts": [...]} with an object-rooted output schema. This addresses the legacy-client compatibility issue in #272 and the Python tool-listing failure reported in #191.
Changes:
- Wrap alert results consistently across Python, TypeScript, Go, Rust, and Ruby, preserving empty lists when no alerts exist.
- Add raw
2025-11-25session checks alongside SDK-based schema and structured-result checks. - Document protocol compatibility and simplify Go schema generation to use SDK inference.
| File | Description |
|---|---|
weather-server-typescript/src/index.ts |
Wraps the alert schema and structured results in an object. |
weather-server-typescript/README.md |
Explains wrapping and TypeScript SDK compatibility behavior. |
weather-server-rust/src/main.rs |
Adds an Alerts wrapper for schema generation and results. |
weather-server-rust/README.md |
Documents the wrapped result and legacy compatibility. |
weather-server-ruby/weather.rb |
Wraps the alert schema and structured results. |
weather-server-ruby/README.md |
Updates output documentation while retaining the separate protocol limitation. |
weather-server-python/weather.py |
Replaces the root-list model with an object containing alerts. |
weather-server-python/README.md |
Explains how wrapping avoids legacy tool-listing failures. |
weather-server-go/README.md |
Documents inferred schemas and non-null empty lists. |
weather-server-go/main.go |
Returns an Alerts struct and removes the schema override. |
weather-server-go/go.mod |
Marks jsonschema-go as an indirect dependency. |
tests/README.md |
Describes legacy-session checks and object-result validation. |
tests/helpers/mcp-test-client.ts |
Adds raw legacy-session checks, version logging, and object-root assertions. |
Review effort: Balanced
olaservo
left a comment
There was a problem hiding this comment.
Read through all five servers and the test client. Wrapping the list as {"alerts": [...]} with an object root in every server is the right call while four of the five SDKs send the schema as written to 2025-11-25 clients, and the raw JSON-RPC session in the test is a good regression guard, since it sees exactly what an older client receives. The READMEs explain the reason and point at #272 for when the wrap can go. CI is green. Merging.
Two notes, neither blocking:
- Ruby:
GetAlerts.output_schemanow has no explicittype: "object"whileGetForecastdeclares one. The gem fills it in, and the 2025-11-25 check proves that, but declaring it would keep the two tools in the same file alike. - The clients print
[get_alerts returned N items]only whenstructured_contentis an array, so against the quickstart servers that line no longer appears. The mock server still covers the array path in the client tests, so nothing breaks, but the client READMEs and the build-client tutorial describe that output and may want a word on it.
Generated by Claude Code
|
Thank you, @olaservo ! |
Motivation and Context
Closes #272, and also closes the Python half of #191.
All five servers declared
get_alerts' output schema with a top-level array root and sent it on every session. 2025-11-25 and earlier require an object root, and 2025-11-25 is what most clients negotiate today. Python failedtools/listoutright (-32603 "Handler returned an invalid result", so no tools at all). Go, Ruby and Rust sent the array, which strict clients reject and Inspector drops. Only TypeScript worked, because its SDK wraps the array as{"result": [...]}.No SDK release converts the schema for older sessions yet, so until they do, the servers wrap the list themselves:
get_alertsnow returns{"alerts": [...]}with an object-rooted schema in all five servers, and an empty list when there are no alertsAlertsis a plainBaseModel, no longer aRootModeljsonschema-gobecomes an indirect dependencyinitialize,tools/list) without the SDK, which could quietly drop or rewrite a bad tool. It checks that the call succeeds and that everyoutputSchemahas anobjectroot. Then it connects through the SDK as before (it negotiates 2026-07-28 and now logs the version) and checks object roots and objectstructuredContentthere tootests/README.mddescribes the new checkHow Has This Been Tested?
golang:1.25andruby:3.4containersmain: it fails with the-32603error from Stop breaking 2025-11-25 clients withget_alerts' array output schema #272, so it catches the regressiontsc(servers, clients, test helpers),cargo fmt/clippy -D warnings,gofmt/go vetandruby -wcpassBreaking Changes
N/a
Types of changes
Checklist
Additional context
Assisted with Claude Code.