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"