Skip to content

Validate the src and sizes of an icon against the specification - #563

Merged
koic merged 1 commit into
modelcontextprotocol:mainfrom
koic:validate_icon_src_and_sizes
Sep 19, 2026
Merged

koic merged 1 commit into
modelcontextprotocol:mainfrom
koic:validate_icon_src_and_sizes

Conversation

@koic

@koic koic commented Sep 19, 2026

Copy link
Copy Markdown
Member

Motivation and Context

MCP::Icon validated theme but accepted anything for src and sizes: src: defaulted to nil, so MCP::Icon.new.to_h was {}, an icon with no source, and a sizes given as a String reached to_h unchanged and serialized as a JSON string where the specification's Icon type requires an array of strings. Nothing on the server side reported either; the server answered every request with 200 and the failure surfaced in a client, with no reference to the field responsible. The TypeScript SDK types sizes as string[] and src as required, and the Python SDK's model refuses such an icon at construction, so this SDK was the one that let it through.

src is now a required keyword and must be a non-empty String, sizes must be nil or an Array of Strings, and mime_type must be nil or a String, each refused with ArgumentError at construction the way theme already was. The checks stop at the schema's types, as the reference SDKs do: the scheme of a URL and the WxH form of a size stay the caller's to get right. A message names the class of the rejected value, never the value, since src may carry a data: URI of any length. Coercing a String into a one-element Array was considered and rejected: it would hide the caller's mistake that the class exists to surface. The theme check let false through its truthiness test and serialized it; it now refuses everything but nil, "light", and "dark".

Fixes #562.

How Has This Been Tested?

New tests in test/mcp/icon_test.rb. Against the previous library, an icon without src and an icon whose sizes is a String are both constructed and serialized.

Breaking Changes

MCP::Icon.new now raises ArgumentError where earlier releases produced an icon the specification's schema rejects: src: is required and must be a non-empty String, so a call without it, or with nil, an empty String, or a non-String, fails; sizes: must be nil or an Array of Strings, so a String, or an Array holding nil or a non-String, fails; mime_type: must be nil or a String; theme: must be nil, "light", or "dark", so false fails where it used to be serialized. Leaving the optional keywords out, or passing nil for them, is unchanged.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

## Motivation and Context

`MCP::Icon` validated `theme` but accepted anything for `src` and `sizes`: `src:` defaulted to `nil`,
so `MCP::Icon.new.to_h` was `{}`, an icon with no source, and a `sizes` given as a String reached `to_h` unchanged
and serialized as a JSON string where the specification's `Icon` type requires an array of strings.
Nothing on the server side reported either; the server answered every request with 200 and the failure surfaced
in a client, with no reference to the field responsible. The TypeScript SDK types `sizes` as `string[]`
and `src` as required, and the Python SDK's model refuses such an icon at construction, so this SDK was
the one that let it through.

`src` is now a required keyword and must be a non-empty String, `sizes` must be `nil` or an Array of Strings,
and `mime_type` must be `nil` or a String, each refused with `ArgumentError` at construction the way `theme` already was.
The checks stop at the schema's types, as the reference SDKs do: the scheme of a URL and the `WxH` form of a size stay
the caller's to get right. A message names the class of the rejected value, never the value,
since `src` may carry a `data:` URI of any length. Coercing a String into a one-element Array was considered and rejected:
it would hide the caller's mistake that the class exists to surface. The `theme` check let `false` through its truthiness test
and serialized it; it now refuses everything but `nil`, `"light"`, and `"dark"`.

Fixes modelcontextprotocol#562.

## How Has This Been Tested?

New tests in `test/mcp/icon_test.rb`. Against the previous library, an icon without `src` and an icon whose `sizes` is
a String are both constructed and serialized.

## Breaking Changes

`MCP::Icon.new` now raises `ArgumentError` where earlier releases produced an icon the specification's schema rejects:
`src:` is required and must be a non-empty String, so a call without it, or with `nil`, an empty String, or a non-String,
fails; `sizes:` must be `nil` or an Array of Strings, so a String, or an Array holding `nil` or a non-String, fails;
`mime_type:` must be `nil` or a String; `theme:` must be `nil`, `"light"`, or `"dark"`, so `false` fails where it used
to be serialized. Leaving the optional keywords out, or passing `nil` for them, is unchanged.
@koic
koic merged commit 538a364 into modelcontextprotocol:main Sep 19, 2026
11 checks passed
@koic
koic deleted the validate_icon_src_and_sizes branch September 19, 2026 16:04
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.

MCP::Icon does not validate sizes or require src

1 participant