refactor: consolidate content annotations into Annotations (#242)

Updates all Content types to represent annotations as nested objects
instead of directly on the content itself.

- Refactor TextContent, ImageContent, and EmbeddedResource to use Annotations object instead of separate audience/priority fields
- Add backward-compatible deprecated methods for audience() and priority() accessors
- Add parameterized tests for message annotations across different message types (success, error, debug)
- Test both text and image content annotations with proper priority and audience validation

This brings the implementation in line with the content types as modeled by the specification:
c87a0da6d8/schema/2025-03-26/schema.json (L1970-L1973)
This commit is contained in:
Luca Chang 2025-05-16 15:49:43 -07:00 • committed by Christian Tzolov
commit fb40047c39

View file

@ -1384,22 +1384,68 @@ public final class McpSchema {
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonIgnoreProperties(ignoreUnknown = true)
public record TextContent( // @formatter:off
@JsonProperty("audience") List<Role> audience,
@JsonProperty("priority") Double priority,
@JsonProperty("text") String text) implements Content { // @formatter:on
@JsonProperty("annotations") Annotations annotations,
@JsonProperty("text") String text) implements Annotated, Content { // @formatter:on
public TextContent(String content) {
this(null, null, content);
this(null, content);
}
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link TextContent#TextContent(Annotations, String)} instead.
*/
public TextContent(List<Role> audience, Double priority, String content) {
this(audience != null || priority != null ? new Annotations(audience, priority) : null, content);
}
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link TextContent#annotations()} instead.
*/
public List<Role> audience() {
return annotations == null ? null : annotations.audience();
}
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link TextContent#annotations()} instead.
*/
public Double priority() {
return annotations == null ? null : annotations.priority();
}
}
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonIgnoreProperties(ignoreUnknown = true)
public record ImageContent( // @formatter:off
@JsonProperty("audience") List<Role> audience,
@JsonProperty("priority") Double priority,
@JsonProperty("annotations") Annotations annotations,
@JsonProperty("data") String data,
@JsonProperty("mimeType") String mimeType) implements Content { // @formatter:on
@JsonProperty("mimeType") String mimeType) implements Annotated, Content { // @formatter:on
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link ImageContent#ImageContent(Annotations, String, String)} instead.
*/
public ImageContent(List<Role> audience, Double priority, String data, String mimeType) {
this(audience != null || priority != null ? new Annotations(audience, priority) : null, data, mimeType);
}
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link ImageContent#annotations()} instead.
*/
public List<Role> audience() {
return annotations == null ? null : annotations.audience();
}
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link ImageContent#annotations()} instead.
*/
public Double priority() {
return annotations == null ? null : annotations.priority();
}
}
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@ -1413,9 +1459,33 @@ public final class McpSchema {
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonIgnoreProperties(ignoreUnknown = true)
public record EmbeddedResource( // @formatter:off
@JsonProperty("audience") List<Role> audience,
@JsonProperty("priority") Double priority,
@JsonProperty("resource") ResourceContents resource) implements Content { // @formatter:on
@JsonProperty("annotations") Annotations annotations,
@JsonProperty("resource") ResourceContents resource) implements Annotated, Content { // @formatter:on
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link EmbeddedResource#EmbeddedResource(Annotations, ResourceContents)}
* instead.
*/
public EmbeddedResource(List<Role> audience, Double priority, ResourceContents resource) {
this(audience != null || priority != null ? new Annotations(audience, priority) : null, resource);
}
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link EmbeddedResource#annotations()} instead.
*/
public List<Role> audience() {
return annotations == null ? null : annotations.audience();
}
/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link EmbeddedResource#annotations()} instead.
*/
public Double priority() {
return annotations == null ? null : annotations.priority();
}
}
// ---------------------------