Skip to content

feat: add optional size property to Resource with builder #331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,9 @@ public record Annotations( // @formatter:off
* by clients to improve the LLM's understanding of available resources. It can be
* thought of like a "hint" to the model.
* @param mimeType The MIME type of this resource, if known.
* @param size The size of the raw resource content, in bytes (i.e., before base64
* encoding or any tokenization), if known. This can be used by Hosts to display file
* sizes and estimate context window usage.
* @param annotations Optional annotations for the client. The client can use
* annotations to inform how objects are used or displayed.
*/
Expand All @@ -492,7 +495,72 @@ public record Resource( // @formatter:off
@JsonProperty("name") String name,
@JsonProperty("description") String description,
@JsonProperty("mimeType") String mimeType,
@JsonProperty("size") Long size,
@JsonProperty("annotations") Annotations annotations) implements Annotated {

/**
* @deprecated Only exists for backwards-compatibility purposes. Use
* {@link Resource#builder()} instead.
*/
@Deprecated
public Resource(String uri, String name, String description, String mimeType, Annotations annotations) {
this(uri, name, description, mimeType, null, annotations);
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private String uri;
private String name;
private String description;
private String mimeType;
private Long size;
private Annotations annotations;

public Builder uri(String uri) {
this.uri = uri;
return this;
}

public Builder name(String name) {
this.name = name;
return this;
}

public Builder description(String description) {
this.description = description;
return this;
}

public Builder mimeType(String mimeType) {
this.mimeType = mimeType;
return this;
}

public Builder size(Long size) {
this.size = size;
return this;
}

public Builder annotations(Annotations annotations) {
this.annotations = annotations;
return this;
}

public Resource build() {
if (uri == null) {
throw new IllegalStateException("uri cannot be null");
}

if (name == null) {
throw new IllegalStateException("name cannot be null");
}

return new Resource(uri, name, description, mimeType, size, annotations);
}
}
} // @formatter:on

/**
Expand Down
53 changes: 53 additions & 0 deletions mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,59 @@ void testResource() throws Exception {
{"uri":"resource://test","name":"Test Resource","description":"A test resource","mimeType":"text/plain","annotations":{"audience":["user","assistant"],"priority":0.8}}"""));
}

@Test
void testResourceBuilder() throws Exception {
McpSchema.Annotations annotations = new McpSchema.Annotations(
Arrays.asList(McpSchema.Role.USER, McpSchema.Role.ASSISTANT), 0.8);

McpSchema.Resource resource = McpSchema.Resource.builder()
.uri("resource://test")
.name("Test Resource")
.description("A test resource")
.mimeType("text/plain")
.size(256L)
.annotations(annotations)
.build();

String value = mapper.writeValueAsString(resource);
assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
.when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
.isObject()
.isEqualTo(
json("""
{"uri":"resource://test","name":"Test Resource","description":"A test resource","mimeType":"text/plain","size":256,"annotations":{"audience":["user","assistant"],"priority":0.8}}"""));
}

@Test
void testResourceBuilderUriRequired() {
McpSchema.Annotations annotations = new McpSchema.Annotations(
Arrays.asList(McpSchema.Role.USER, McpSchema.Role.ASSISTANT), 0.8);

McpSchema.Resource.Builder resourceBuilder = McpSchema.Resource.builder()
.name("Test Resource")
.description("A test resource")
.mimeType("text/plain")
.size(256L)
.annotations(annotations);

assertThatThrownBy(resourceBuilder::build).isInstanceOf(IllegalStateException.class);
}

@Test
void testResourceBuilderNameRequired() {
McpSchema.Annotations annotations = new McpSchema.Annotations(
Arrays.asList(McpSchema.Role.USER, McpSchema.Role.ASSISTANT), 0.8);

McpSchema.Resource.Builder resourceBuilder = McpSchema.Resource.builder()
.uri("resource://test")
.description("A test resource")
.mimeType("text/plain")
.size(256L)
.annotations(annotations);

assertThatThrownBy(resourceBuilder::build).isInstanceOf(IllegalStateException.class);
}

@Test
void testResourceTemplate() throws Exception {
McpSchema.Annotations annotations = new McpSchema.Annotations(Arrays.asList(McpSchema.Role.USER), 0.5);
Expand Down