Resources

In previous exercises, you learned how to extend your MCP server with tools—server-defined functions that let clients perform actions or retrieve data. But sometimes, what you want to expose isn't just a function, but a resource: a file, a database record, or some other piece of structured data that can be read (and sometimes listed or searched) by clients.
The Model Context Protocol (MCP) has the concept of resources to make this possible. Resources are a standardized way for servers to share contextual data with clients—such as files, database entries, or application metadata—using a uniform interface. Each resource is uniquely identified by a URI and can be described with metadata like a name, description, and MIME type.
From the MCP Spec: Resources in MCP are designed to be application-driven, with host applications determining how to incorporate context based on their needs. However, implementations are free to expose resources through any interface pattern that suits their needs—the protocol itself does not mandate any specific user interaction model.
Here's what this user experience may feel like.
Reminder, the MCP spec only defines the relationship between client and server. The rest of the user experience is controled by the creator of the client.
Example request to read a resource:
{
	"jsonrpc": "2.0",
	"id": 2,
	"method": "resources/read",
	"params": {
		"uri": "taco://menu/items/carne-asada"
	}
}
Example response:
{
	"jsonrpc": "2.0",
	"id": 2,
	"result": {
		"contents": [
			{
				"uri": "taco://menu/items/carne-asada",
				"mimeType": "application/json",
				"text": "{\"name\":\"Carne Asada Taco\",\"ingredients\":[\"steak\",\"tortilla\",\"onion\",\"cilantro\"],\"instructions\":\"Grill the steak, chop into small pieces, serve on warm tortillas\"}"
			}
		]
	}
}
This approach enables a wide range of use cases:
  • Exposing files or documents for LLMs to read and reference
  • Making database records (like journal entries or tags) available as structured resources
Really, a resource is anything you would traditionally have done with a GET request on a web server.
Here are a couple other examples of URIs you might use for a resource:
datetime://Euroupe/London/now
http://example.com/llms.txt
jira://myworkspace/ticket/304
amazon://product/1234567890
📜 If you're unfamiliar with URIs and their formats, you can read more about them on Wikipedia: Uniform Resource Identifier.
MCP resources are designed to be application-driven: you decide what to expose, and how. Clients can list available resources, read their contents, and (optionally) subscribe to updates or changes. The protocol supports both static resources (like a credits file) and dynamic, parameterized resources (like a database entry with a specific ID).
In this exercise, you'll extend your EpicMe journaling app to expose new types of resources:
  • Tags: A simple resource returning all available tags.
  • Resource Templates: Journal entries and tags, each accessible via a unique URI and discoverable through resource templates.
By the end, you'll have hands-on experience with MCP's resource capabilities, including resource registration, templates, and embedding resources in tool responses. This will set the stage for building applications that can share rich, structured context with language models and other clients.
You'll notice we have a bunch of tools for reading data which you might think we should just use resources for. Unfortunately, all the popular MCP clients as of today are very limited in their use of resources so we'll keep those tools around. In the future, we should just use resources for this stuff.