Add resources and prompts
Add a notes resource
Expose the note catalog as readable, addressable context without turning a simple read into a tool call.
8 minute lesson
A tool asks the server to perform an operation. A resource gives readable context a stable address.
Our catalog is a good resource because reading it has no side effect and needs no search arguments. Add this registration inside createServer():
server.registerResource(
'notes-catalog',
'notes://catalog',
{
title: 'Project notes catalog',
mimeType: 'application/json'
},
async uri => ({
contents: [{
uri: uri.href,
mimeType: 'application/json',
text: JSON.stringify(
notes.map(({ id, title, tags }) => ({ id, title, tags })),
null,
2
)
}]
})
)
The custom notes: scheme describes an application resource, not a file on the server. The URI is an identifier. A client must still call resources/read to receive its contents.
The returned uri must identify what was requested, and mimeType tells the client how to interpret the text. Keep the JSON valid and the catalog bounded.
We expose only id, title, and tags. Note bodies remain behind get_note, where the caller names one stable ID. This prevents catalog discovery from loading every note into context.
Resource URIs are untrusted input when they contain variables. This resource has one fixed URI, so there is no path to expand or normalize. If you later add notes://note/{id}, validate the decoded ID and apply the same authorization as the lookup tool.
Use the Inspector to list resources and read notes://catalog.
Check three things: the listed URI matches the read URI, the media type is application/json, and the parsed value contains no note body.
Lesson completed