Skip to content

Add structured content to the Ruby weather server and client - #184

Draft
olaservo wants to merge 3 commits into
modelcontextprotocol:mainfrom
olaservo:structured-output-2026-07-28/ruby
Draft

Add structured content to the Ruby weather server and client#184
olaservo wants to merge 3 commits into
modelcontextprotocol:mainfrom
olaservo:structured-output-2026-07-28/ruby

Conversation

@olaservo

Copy link
Copy Markdown
Member

Completes the set with #164 (Python), #165 (TypeScript), #166 (Go), #167 (Rust): both tools declare an output_schema and return matching structured_content, and the client validates results against the declared schema.

Draft — blocked on an mcp gem release. 1.1.0 negotiates 2026-07-28 but its server never stamps the resultType field the revision makes mandatory, so a spec-strict client rejects every response. The fix is on ruby-sdk main and unreleased; 1.1.0 is still the newest gem. The version floor here should name that release rather than 1.1.0 once it ships.

Until then the Ruby weather server cannot be added to the smoke tests (see #183, which covers the Ruby client only), so nothing in this diff is exercised by CI.

olaservo and others added 3 commits August 9, 2026 21:20
The mcp gem 1.1.0 (2026-08-01) is the first to negotiate 2026-07-28, so the
Ruby examples can finally show the same thing the other four do: get_alerts
declares an array-rooted output_schema and returns a bare top-level JSON
array, get_forecast returns an object. Declaring `type:` at the root is what
suppresses the SDK object-root default.

Failure paths return an error result rather than a bare text one, because a
tool declaring an output_schema MUST return conforming structured content.
No alerts is an empty array, not an error.

The client compiles each declared schema at connect time and validates every
non-error result. The SDK client does not do this itself, so the spec
client-side SHOULD costs real code here, as it does in Go and Rust.

NOT READY TO SHIP. The gem never emits the `resultType` field that the
2026-07-28 schema marks mandatory, and no user-level knob sets it, so a
spec-strict client rejects every response including tools/list. Verified
end-to-end against the Ruby client, which does not check the field; blocked
against the TypeScript SDK client. See the server README.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The gem's default_capabilities advertises tools, prompts, resources and
logging. This server has only tools; logging is additionally deprecated as of
2026-07-28 (SEP-2577).

Passing capabilities: { tools: {} } makes server/discover honest. No
listChanged flag, because change notifications at this revision are delivered
over subscriptions/listen and this server does not serve it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The spec never uses the phrase "structured output". It defines two separate
things under Tool Result: "Structured Content" (the `structuredContent` field)
and "Output Schema" (the `outputSchema` field). Collapsing them into
"structured output" conflates the two.

It is also actively confusing here. In LLM tooling "structured output" means
constrained decoding — making the *model* emit conforming JSON. These clients
call a model API, so a reader could reasonably take the phrase to mean the
tool constrains the model's response, which is the opposite of what is going
on: the tool describes the shape of its own result.

Headings and prose now say "structured content". References to real
identifiers are left alone: the Python SDK's own docs page is called
Structured Output and lives at docs/servers/structured-output.md, and its
decorator parameter is `structured_output`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant