diff --git a/enterprise/e2e/html/hurl/mcp-2025-11-25-resources.all.hurl b/enterprise/e2e/html/hurl/mcp-2025-11-25-resources.all.hurl index 9d499e69..09400db5 100644 --- a/enterprise/e2e/html/hurl/mcp-2025-11-25-resources.all.hurl +++ b/enterprise/e2e/html/hurl/mcp-2025-11-25-resources.all.hurl @@ -233,7 +233,7 @@ jsonpath "$.result.resources[42].uri" == "{{base}}/self/v1/schemas/mcp/tools/cal jsonpath "$.result.resources[42].name" == "response" jsonpath "$.result.resources[42].description" == "Sourcemeta One's response to a tool invocation" jsonpath "$.result.resources[42].mimeType" == "application/schema+json" -jsonpath "$.result.resources[42].size" == 4491 +jsonpath "$.result.resources[42].size" == 4706 jsonpath "$.result.resources[43].uri" == "{{base}}/self/v1/schemas/mcp/tools/list/request" jsonpath "$.result.resources[43].name" == "request" jsonpath "$.result.resources[43].description" == "Request from a client to list MCP tools" diff --git a/enterprise/e2e/html/hurl/mcp-2025-11-25-search_schemas.all.hurl b/enterprise/e2e/html/hurl/mcp-2025-11-25-search_schemas.all.hurl index 35ecf01c..e976a4bf 100644 --- a/enterprise/e2e/html/hurl/mcp-2025-11-25-search_schemas.all.hurl +++ b/enterprise/e2e/html/hurl/mcp-2025-11-25-search_schemas.all.hurl @@ -252,22 +252,22 @@ jsonpath "$.result.content[6].description" == "A schema with both a title and a jsonpath "$.result.content[6].mimeType" == "application/schema+json" jsonpath "$.result.content[7].type" == "resource_link" jsonpath "$.result.content[7].uri" == "http://localhost:8000/test/description-only/01" -jsonpath "$.result.content[7].name" not exists +jsonpath "$.result.content[7].name" == "/test/description-only/01" jsonpath "$.result.content[7].description" == "A schema with only a description (01)" jsonpath "$.result.content[7].mimeType" == "application/schema+json" jsonpath "$.result.content[8].type" == "resource_link" jsonpath "$.result.content[8].uri" == "http://localhost:8000/test/description-only/02" -jsonpath "$.result.content[8].name" not exists +jsonpath "$.result.content[8].name" == "/test/description-only/02" jsonpath "$.result.content[8].description" == "A schema with only a description (02)" jsonpath "$.result.content[8].mimeType" == "application/schema+json" jsonpath "$.result.content[9].type" == "resource_link" jsonpath "$.result.content[9].uri" == "http://localhost:8000/test/description-only/03" -jsonpath "$.result.content[9].name" not exists +jsonpath "$.result.content[9].name" == "/test/description-only/03" jsonpath "$.result.content[9].description" == "A schema with only a description (03)" jsonpath "$.result.content[9].mimeType" == "application/schema+json" jsonpath "$.result.content[10].type" == "resource_link" jsonpath "$.result.content[10].uri" == "http://localhost:8000/test/description-only/04" -jsonpath "$.result.content[10].name" not exists +jsonpath "$.result.content[10].name" == "/test/description-only/04" jsonpath "$.result.content[10].description" == "A schema with only a description (04)" jsonpath "$.result.content[10].mimeType" == "application/schema+json" jsonpath "$.result.structuredContent.results" count == 10 @@ -396,12 +396,12 @@ jsonpath "$.result.content" count == 3 jsonpath "$.result.content[0].type" == "text" jsonpath "$.result.content[1].type" == "resource_link" jsonpath "$.result.content[1].uri" == "http://localhost:8000/test/description-only/01" -jsonpath "$.result.content[1].name" not exists +jsonpath "$.result.content[1].name" == "/test/description-only/01" jsonpath "$.result.content[1].description" == "A schema with only a description (01)" jsonpath "$.result.content[1].mimeType" == "application/schema+json" jsonpath "$.result.content[2].type" == "resource_link" jsonpath "$.result.content[2].uri" == "http://localhost:8000/test/description-only/02" -jsonpath "$.result.content[2].name" not exists +jsonpath "$.result.content[2].name" == "/test/description-only/02" jsonpath "$.result.content[2].description" == "A schema with only a description (02)" jsonpath "$.result.content[2].mimeType" == "application/schema+json" jsonpath "$.result.structuredContent.results" count == 2 @@ -498,12 +498,12 @@ jsonpath "$.result.content" count == 3 jsonpath "$.result.content[0].type" == "text" jsonpath "$.result.content[1].type" == "resource_link" jsonpath "$.result.content[1].uri" == "http://localhost:8000/test/bare/01" -jsonpath "$.result.content[1].name" not exists +jsonpath "$.result.content[1].name" == "/test/bare/01" jsonpath "$.result.content[1].description" not exists jsonpath "$.result.content[1].mimeType" == "application/schema+json" jsonpath "$.result.content[2].type" == "resource_link" jsonpath "$.result.content[2].uri" == "http://localhost:8000/test/bare/02" -jsonpath "$.result.content[2].name" not exists +jsonpath "$.result.content[2].name" == "/test/bare/02" jsonpath "$.result.content[2].description" not exists jsonpath "$.result.content[2].mimeType" == "application/schema+json" jsonpath "$.result.structuredContent.results" count == 2 diff --git a/enterprise/e2e/path/hurl/mcp-2025-03-26.all.hurl b/enterprise/e2e/path/hurl/mcp-2025-03-26.all.hurl index c41ba43e..aefc594e 100644 --- a/enterprise/e2e/path/hurl/mcp-2025-03-26.all.hurl +++ b/enterprise/e2e/path/hurl/mcp-2025-03-26.all.hurl @@ -349,9 +349,9 @@ jsonpath "$.result.content" count == 5 jsonpath "$.result.content[0].type" == "text" jsonpath "$.result.content[0].text" isString jsonpath "$.result.content[1].type" == "text" -jsonpath "$.result.content[1].text" == "{{base}}/v1/catalog/example/bare" +jsonpath "$.result.content[1].text" == "/v1/catalog/example/bare: {{base}}/v1/catalog/example/bare" jsonpath "$.result.content[2].type" == "text" -jsonpath "$.result.content[2].text" == "A schema with only a description and no title: {{base}}/v1/catalog/example/description-only" +jsonpath "$.result.content[2].text" == "/v1/catalog/example/description-only (A schema with only a description and no title): {{base}}/v1/catalog/example/description-only" jsonpath "$.result.content[3].type" == "text" jsonpath "$.result.content[3].text" == "Example With Both (A schema that has both a title and a description): {{base}}/v1/catalog/example/full" jsonpath "$.result.content[4].type" == "text" diff --git a/enterprise/e2e/path/hurl/mcp-2025-11-25-list_directory.all.hurl b/enterprise/e2e/path/hurl/mcp-2025-11-25-list_directory.all.hurl index 62734cee..e231b7e0 100644 --- a/enterprise/e2e/path/hurl/mcp-2025-11-25-list_directory.all.hurl +++ b/enterprise/e2e/path/hurl/mcp-2025-11-25-list_directory.all.hurl @@ -28,12 +28,12 @@ jsonpath "$.result.content" count == 5 jsonpath "$.result.content[0].type" == "text" jsonpath "$.result.content[1].type" == "resource_link" jsonpath "$.result.content[1].uri" == "{{base}}/v1/catalog/example/bare" -jsonpath "$.result.content[1].name" not exists +jsonpath "$.result.content[1].name" == "/v1/catalog/example/bare" jsonpath "$.result.content[1].description" not exists jsonpath "$.result.content[1].mimeType" == "application/schema+json" jsonpath "$.result.content[2].type" == "resource_link" jsonpath "$.result.content[2].uri" == "{{base}}/v1/catalog/example/description-only" -jsonpath "$.result.content[2].name" not exists +jsonpath "$.result.content[2].name" == "/v1/catalog/example/description-only" jsonpath "$.result.content[2].description" == "A schema with only a description and no title" jsonpath "$.result.content[2].mimeType" == "application/schema+json" jsonpath "$.result.content[3].type" == "resource_link" @@ -158,12 +158,12 @@ jsonpath "$.result.content" count == 5 jsonpath "$.result.content[0].type" == "text" jsonpath "$.result.content[1].type" == "resource_link" jsonpath "$.result.content[1].uri" == "{{base}}/v1/catalog/example/bare" -jsonpath "$.result.content[1].name" not exists +jsonpath "$.result.content[1].name" == "/v1/catalog/example/bare" jsonpath "$.result.content[1].description" not exists jsonpath "$.result.content[1].mimeType" == "application/schema+json" jsonpath "$.result.content[2].type" == "resource_link" jsonpath "$.result.content[2].uri" == "{{base}}/v1/catalog/example/description-only" -jsonpath "$.result.content[2].name" not exists +jsonpath "$.result.content[2].name" == "/v1/catalog/example/description-only" jsonpath "$.result.content[2].description" == "A schema with only a description and no title" jsonpath "$.result.content[2].mimeType" == "application/schema+json" jsonpath "$.result.content[3].type" == "resource_link" diff --git a/enterprise/e2e/path/hurl/mcp-2025-11-25-resources.all.hurl b/enterprise/e2e/path/hurl/mcp-2025-11-25-resources.all.hurl index afb7b69a..fc1c186b 100644 --- a/enterprise/e2e/path/hurl/mcp-2025-11-25-resources.all.hurl +++ b/enterprise/e2e/path/hurl/mcp-2025-11-25-resources.all.hurl @@ -233,7 +233,7 @@ jsonpath "$.result.resources[42].uri" == "{{base}}/v1/catalog/self/v1/schemas/mc jsonpath "$.result.resources[42].name" == "response" jsonpath "$.result.resources[42].description" == "Sourcemeta One's response to a tool invocation" jsonpath "$.result.resources[42].mimeType" == "application/schema+json" -jsonpath "$.result.resources[42].size" == 4502 +jsonpath "$.result.resources[42].size" == 4717 jsonpath "$.result.resources[43].uri" == "{{base}}/v1/catalog/self/v1/schemas/mcp/tools/list/request" jsonpath "$.result.resources[43].name" == "request" jsonpath "$.result.resources[43].description" == "Request from a client to list MCP tools" diff --git a/enterprise/e2e/path/hurl/mcp-2025-11-25-search_schemas.all.hurl b/enterprise/e2e/path/hurl/mcp-2025-11-25-search_schemas.all.hurl index 326cacbc..4ed72083 100644 --- a/enterprise/e2e/path/hurl/mcp-2025-11-25-search_schemas.all.hurl +++ b/enterprise/e2e/path/hurl/mcp-2025-11-25-search_schemas.all.hurl @@ -33,7 +33,7 @@ jsonpath "$.result.content[1].description" == "A schema that has both a title an jsonpath "$.result.content[1].mimeType" == "application/schema+json" jsonpath "$.result.content[2].type" == "resource_link" jsonpath "$.result.content[2].uri" == "{{base}}/v1/catalog/example/description-only" -jsonpath "$.result.content[2].name" not exists +jsonpath "$.result.content[2].name" == "/v1/catalog/example/description-only" jsonpath "$.result.content[2].description" == "A schema with only a description and no title" jsonpath "$.result.content[2].mimeType" == "application/schema+json" jsonpath "$.result.content[3].type" == "resource_link" diff --git a/src/actions/action_dependency_tree_v1.h b/src/actions/action_dependency_tree_v1.h index 40153b65..21f407d8 100644 --- a/src/actions/action_dependency_tree_v1.h +++ b/src/actions/action_dependency_tree_v1.h @@ -129,7 +129,8 @@ class ActionDependencyTree_v1 : public sourcemeta::one::RouterAction { content.push_back(sourcemeta::core::mcp_make_text_block(payload.str())); for (const auto uri : unique_uris) { content.push_back(sourcemeta::core::mcp_make_resource_link( - version, uri, "application/schema+json")); + version, uri, "application/schema+json", + uri.substr(this->server_uri().size()))); } return sourcemeta::core::mcp_make_tool_success( diff --git a/src/actions/action_list_directory_v1.h b/src/actions/action_list_directory_v1.h index 37cde837..d12d7030 100644 --- a/src/actions/action_list_directory_v1.h +++ b/src/actions/action_list_directory_v1.h @@ -117,10 +117,11 @@ class ActionListDirectory_v1 : public sourcemeta::one::RouterAction { if (!entry.defines("identifier")) { continue; } + const auto &title{entry.at_or("title", EMPTY_STRING).to_string()}; content.push_back(sourcemeta::core::mcp_make_resource_link( version, entry.at("identifier").to_string(), "application/schema+json", - entry.at_or("title", EMPTY_STRING).to_string(), + title.empty() ? entry.at("path").to_string() : title, entry.at_or("description", EMPTY_STRING).to_string())); } } diff --git a/src/actions/action_schema_search_v1.h b/src/actions/action_schema_search_v1.h index 98dd7ad2..bd60634e 100644 --- a/src/actions/action_schema_search_v1.h +++ b/src/actions/action_schema_search_v1.h @@ -207,9 +207,11 @@ class ActionSchemaSearch_v1 : public sourcemeta::one::RouterAction { content.push_back(sourcemeta::core::mcp_make_text_block(payload.str())); for (const auto &entry : envelope.at("results").as_array()) { + const auto &title{entry.at("title").to_string()}; content.push_back(sourcemeta::core::mcp_make_resource_link( version, entry.at("identifier").to_string(), - "application/schema+json", entry.at("title").to_string(), + "application/schema+json", + title.empty() ? entry.at("path").to_string() : title, entry.at("description").to_string())); } diff --git a/src/self/v1/schemas/mcp/tools/call/response.json b/src/self/v1/schemas/mcp/tools/call/response.json index 95c14939..7db45fd2 100644 --- a/src/self/v1/schemas/mcp/tools/call/response.json +++ b/src/self/v1/schemas/mcp/tools/call/response.json @@ -143,8 +143,9 @@ "additionalProperties": false }, { + "$comment": "Per the Model Context Protocol specification, the ResourceLink content block requires a name (https://modelcontextprotocol.io/specification/2025-06-18/server/tools#resource-links)", "type": "object", - "required": [ "type", "uri", "mimeType" ], + "required": [ "type", "uri", "name", "mimeType" ], "properties": { "type": { "const": "resource_link"