Courses/Introduction to Model Context Protocol (MCP)/Resources: Exposing Read-Only Data
Server PrimitivesLesson 8 of 21

Resources: Exposing Read-Only Data

What a Resource Is

Resources are the second server primitive: read-only data sources that provide context to the AI application — file contents, database schemas, API documentation, calendar entries. If a tool is a verb (do something), a resource is a noun (here is some data). They behave much like GET endpoints in an HTTP server: you ask for data by a URI and get content back.

Resources are APPLICATION-controlled

Unlike tools, the model doesn't decide to fetch a resource. Your application code decides when to read a resource and how to use it — to populate UI, power autocomplete, or inject context into a prompt. Think of Claude's 'Add from Google Drive' button: the app fetches the document and adds it to context; the model didn't call a tool to do it.

Resource methodPurposeReturns
resources/listList available direct resourcesArray of resource descriptors
resources/templates/listDiscover resource templatesArray of templated resource definitions
resources/readRetrieve a resource's contentsThe data plus its MIME type

Resources are discovered and read by URI — no execution, just data retrieval.

Direct Resources

A direct resource has a fixed URI that never changes — perfect for data that takes no parameters, like 'the list of all documents'. You declare a MIME type so the client knows how to parse the result. With the SDK, return any Python object and it's serialized for you.

pythonA direct resource at a static URI returning the list of document IDs as JSON.
@mcp.resource(
    "docs://documents",
    mime_type="application/json"
)
def list_docs() -> list[str]:
    return list(docs.keys())

A client reads this with resources/read and the URI docs://documents, and gets back a JSON array of document IDs — ideal for populating an autocomplete menu when a user types '@'.

Templated Resources

A templated resource embeds parameters in its URI using a template like docs://documents/{doc_id}. When a client reads a matching URI, the SDK parses the parameter out and passes it to your function as a keyword argument. This is how you expose a whole family of resources (one per document) with a single definition.

pythonA templated resource: docs://documents/report.pdf resolves doc_id='report.pdf' automatically.
@mcp.resource(
    "docs://documents/{doc_id}",
    mime_type="text/plain"
)
def fetch_doc(doc_id: str) -> str:
    if doc_id not in docs:
        raise ValueError(f"Doc with id {doc_id} not found")
    return docs[doc_id]
App / Clientuser types '@'MCP Serverresource handlerData + MIMEread URIresultReadResourceRequest (URI) → ReadResourceResult (contents + mimeType)

Resources follow a request/response pattern keyed by URI, returning data and a MIME type the client uses to parse it.

MIME Types and Parameter Completion

The mime_type tells the client how to handle the bytes it receives — application/json for structured data, text/plain for text, application/pdf for binaries. The SDK serializes your return value accordingly, so you return native objects and let it handle the wire format.

  • application/json — structured data the client parses into objects.
  • text/plain — plain text returned as-is.
  • application/pdf and others — binary content for files.

Templated resources also support parameter completion: as a user types, the client can suggest valid values (typing 'Par' for a {city} parameter might suggest 'Paris'). This makes resources discoverable without the user knowing exact identifiers — great for '@mention' style features.

Next primitive

Tools (model-controlled) act; resources (app-controlled) supply data. The third primitive, prompts, is user-controlled — pre-built workflows a user triggers on demand. That's next.

Key Takeaways

  • Resources are the second primitive: read-only data sources (files, schemas, records) addressed by URI — like GET endpoints. If tools are verbs, resources are nouns.
  • Resources are APPLICATION-controlled — your app decides when to read them and how to use them (UI, autocomplete, context injection); the model doesn't fetch them.
  • Methods: resources/list (direct), resources/templates/list (templates), resources/read (retrieve contents + MIME type).
  • Direct resources have a fixed URI (e.g. docs://documents); templated resources embed parameters (docs://documents/{doc_id}) that the SDK parses into function arguments.
  • The mime_type (application/json, text/plain, application/pdf, …) tells the client how to parse the result; the SDK serializes your return value for you.
  • Templated resources support parameter completion, enabling discoverable '@mention'-style features without users knowing exact IDs.

Check Your Understanding

Test what you learned in this lesson.

Q1.How do resources differ from tools in terms of control?

Q2.What is the difference between a direct resource and a templated resource?

Q3.What role does the mime_type play on a resource?

Q4.Which scenario is a natural fit for a resource rather than a tool?

Practice This Lesson