Skip to content

Commit b6f0273

Browse files
authored
Merge pull request #621 from modelcontextprotocol/carlpeaslee/fix-resource-template-list-metadata
Adding tests to prevent regressions for: fixes metadata for listed resources from resource templates so that they favor their own metadata
2 parents 9d3374c + bc53129 commit b6f0273

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

src/server/mcp.test.ts

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3457,4 +3457,144 @@ describe("prompt()", () => {
34573457
expect(typeof receivedRequestId === 'string' || typeof receivedRequestId === 'number').toBe(true);
34583458
expect(result.messages[0].content.text).toContain("Received request ID:");
34593459
});
3460+
3461+
/***
3462+
* Test: Resource Template Metadata Priority
3463+
*/
3464+
test("should prioritize individual resource metadata over template metadata", async () => {
3465+
const mcpServer = new McpServer({
3466+
name: "test server",
3467+
version: "1.0",
3468+
});
3469+
const client = new Client({
3470+
name: "test client",
3471+
version: "1.0",
3472+
});
3473+
3474+
mcpServer.resource(
3475+
"test",
3476+
new ResourceTemplate("test://resource/{id}", {
3477+
list: async () => ({
3478+
resources: [
3479+
{
3480+
name: "Resource 1",
3481+
uri: "test://resource/1",
3482+
description: "Individual resource description",
3483+
mimeType: "text/plain",
3484+
},
3485+
{
3486+
name: "Resource 2",
3487+
uri: "test://resource/2",
3488+
// This resource has no description or mimeType
3489+
},
3490+
],
3491+
}),
3492+
}),
3493+
{
3494+
description: "Template description",
3495+
mimeType: "application/json",
3496+
},
3497+
async (uri) => ({
3498+
contents: [
3499+
{
3500+
uri: uri.href,
3501+
text: "Test content",
3502+
},
3503+
],
3504+
}),
3505+
);
3506+
3507+
const [clientTransport, serverTransport] =
3508+
InMemoryTransport.createLinkedPair();
3509+
3510+
await Promise.all([
3511+
client.connect(clientTransport),
3512+
mcpServer.server.connect(serverTransport),
3513+
]);
3514+
3515+
const result = await client.request(
3516+
{
3517+
method: "resources/list",
3518+
},
3519+
ListResourcesResultSchema,
3520+
);
3521+
3522+
expect(result.resources).toHaveLength(2);
3523+
3524+
// Resource 1 should have its own metadata
3525+
expect(result.resources[0].name).toBe("Resource 1");
3526+
expect(result.resources[0].description).toBe("Individual resource description");
3527+
expect(result.resources[0].mimeType).toBe("text/plain");
3528+
3529+
// Resource 2 should inherit template metadata
3530+
expect(result.resources[1].name).toBe("Resource 2");
3531+
expect(result.resources[1].description).toBe("Template description");
3532+
expect(result.resources[1].mimeType).toBe("application/json");
3533+
});
3534+
3535+
/***
3536+
* Test: Resource Template Metadata Overrides All Fields
3537+
*/
3538+
test("should allow resource to override all template metadata fields", async () => {
3539+
const mcpServer = new McpServer({
3540+
name: "test server",
3541+
version: "1.0",
3542+
});
3543+
const client = new Client({
3544+
name: "test client",
3545+
version: "1.0",
3546+
});
3547+
3548+
mcpServer.resource(
3549+
"test",
3550+
new ResourceTemplate("test://resource/{id}", {
3551+
list: async () => ({
3552+
resources: [
3553+
{
3554+
name: "Overridden Name",
3555+
uri: "test://resource/1",
3556+
description: "Overridden description",
3557+
mimeType: "text/markdown",
3558+
// Add any other metadata fields if they exist
3559+
},
3560+
],
3561+
}),
3562+
}),
3563+
{
3564+
name: "Template Name",
3565+
description: "Template description",
3566+
mimeType: "application/json",
3567+
},
3568+
async (uri) => ({
3569+
contents: [
3570+
{
3571+
uri: uri.href,
3572+
text: "Test content",
3573+
},
3574+
],
3575+
}),
3576+
);
3577+
3578+
const [clientTransport, serverTransport] =
3579+
InMemoryTransport.createLinkedPair();
3580+
3581+
await Promise.all([
3582+
client.connect(clientTransport),
3583+
mcpServer.server.connect(serverTransport),
3584+
]);
3585+
3586+
const result = await client.request(
3587+
{
3588+
method: "resources/list",
3589+
},
3590+
ListResourcesResultSchema,
3591+
);
3592+
3593+
expect(result.resources).toHaveLength(1);
3594+
3595+
// All fields should be from the individual resource, not the template
3596+
expect(result.resources[0].name).toBe("Overridden Name");
3597+
expect(result.resources[0].description).toBe("Overridden description");
3598+
expect(result.resources[0].mimeType).toBe("text/markdown");
3599+
});
34603600
});

0 commit comments

Comments
 (0)