Resources and resource templates in MCP

This article is not available in Polish yet. It is shown in English.

A resource in the Model Context Protocol (MCP) is data that a server exposes to a client for use as context: the contents of a file, a database schema, a document, a record of an application. Each resource is identified by a URI. A resource template describes a whole family of resources with a URI template, for example weather://forecast/{city}/{date}, so that the client can build the URI of the resource it needs.

Resources have been part of MCP since the first published version of the specification, 2024-11-05. Version 2026-07-28 changed how clients learn about changes of resources: the resources/subscribe method was replaced by the general subscriptions/listen stream. The same version added caching hints and changed the error code for a missing resource. This article follows the current version, 2026-07-28. The basic concepts of the protocol are described in the article What is MCP.

Overview

Property Value
Kind Server primitive
Who decides to use The application (host)
Identifier URI (RFC 3986)
Templates URI templates (RFC 6570)
Methods resources/list, resources/read, resources/templates/list
Notifications notifications/resources/list_changed, notifications/resources/updated
Server capability resources, optional listChanged and subscribe
Contents Text (text) or binary data in Base64 (blob)
Specification 2026-07-28

The problem resources solve

A model answers better when it has the right context: the file being discussed, the schema of a database, the documentation of an API. Without a protocol, every AI application obtains such data in its own way. A resource gives this data a uniform address and a uniform way to read it from any server.

The specification calls resources application-driven. The host decides which resources to include in the context and how. According to the specification, an application can show resources in a tree or list for the user to select, offer search and filters, or include context automatically, by heuristics or by the choice of the model. The protocol does not prescribe any of these interfaces.

The documentation describes resources as passive data sources with read-only access. This separates them from tools, which perform actions and are chosen by the model. The differences are summarized at the end of the article; tools are described in the article Tools in MCP.

History

The table lists the changes to resources in each version of the specification.

Date Event
November 2024 First version of the specification, 2024-11-05: resources/list, resources/read, resources/templates/list, subscriptions with resources/subscribe, change notifications, text and binary contents, schemes https://, file:// and git://
March 2025 Specification 2025-03-26: the completions capability for argument completion
June 2025 Specification 2025-06-18: the title field, resource links in tool results, context of previous arguments in completion requests
November 2025 Specification 2025-11-25: icons for resources and resource templates (SEP-973)
28 July 2026 Specification 2026-07-28: subscriptions/listen instead of resources/subscribe and resources/unsubscribe (SEP-2575), error code -32602 instead of -32002 for a missing resource, caching hints ttlMs and cacheScope (SEP-2549), input_required results for resources/read (SEP-2322)

URIs and schemes

Every resource has a URI in the sense of RFC 3986. The URI can use any scheme, and the server decides how to interpret it. The specification describes several common schemes and states that the list is not exhaustive.

Scheme Use according to the specification
https:// A resource on the web that the client can fetch directly, without the MCP server
file:// Resources that behave like a file system; they do not have to map to a real file system
git:// Integration with the Git version control system
Custom Any scheme that conforms to RFC 3986

The https:// scheme has a restriction. A server should use it only when the client can fetch and load the resource from the web on its own. If the server itself downloads the contents over the internet, it should still prefer another scheme or define a custom one.

For file:// resources a server may use an XDG MIME type such as inode/directory for objects that have no standard MIME type, for example directories.

Custom schemes are common. The documentation of MCP gives examples such as calendar://events/2024 and travel://activities/{city}/{category}. The MCP Apps extension uses the ui:// scheme for resources with interactive interfaces; extensions are described in the article Extensions in MCP.

Resource definition

The server describes each resource with an object. The table lists its fields in the 2026-07-28 schema.

Field Required Purpose
uri Yes Unique identifier of the resource
name Yes Programmatic name of the resource
title No Display name for people
description No What the resource represents; a hint to the model
mimeType No MIME type, if known
size No Size of the raw contents in bytes, before Base64 encoding
annotations No Hints about the audience, importance and time of change
icons No Icons for the user interface
_meta No Additional metadata

According to the schema, a host can use size to show file sizes and to estimate how much of the context window the resource will take.

Listing resources

The client requests the list of resources with resources/list. The method supports pagination: if the result contains nextCursor, the client passes this value in cursor to get the next page.

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "resources/list",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "resources": [
      {
        "uri": "file:///project/README.md",
        "name": "README.md",
        "title": "Project Documentation",
        "mimeType": "text/markdown",
        "size": 4120,
        "annotations": {
          "audience": ["user", "assistant"],
          "priority": 0.8,
          "lastModified": "2026-10-30T09:12:00Z"
        }
      }
    ],
    "nextCursor": "page-2",
    "ttlMs": 300000,
    "cacheScope": "private"
  }
}

The rules for the list are the same as for tools. The list contains the resources currently available to the requesting client, may be empty and may change over time. It must not vary per connection or as a side effect of other requests, but may vary by the authorization of the request, for example by the scopes of the token.

Reading a resource

The client reads a resource with resources/read, passing its URI:

JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "resources/read",
  "params": {
    "uri": "file:///project/src/main.rs",
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "contents": [
      {
        "uri": "file:///project/src/main.rs",
        "mimeType": "text/x-rust",
        "text": "fn main() {\n    println!(\"Hello world!\");\n}"
      }
    ],
    "ttlMs": 60000,
    "cacheScope": "private"
  }
}

The result is the contents array. A server may return several items for one request: for example, the contents of several files when a directory resource is read.

Over Streamable HTTP the request carries the headers Mcp-Method: resources/read and Mcp-Name with the URI of the resource, so that gateways can route requests without parsing the body. The transports are described in the article Transports in MCP.

A server may also answer resources/read with a result of type input_required if it needs additional input before the resource can be read. The client then repeats the request with the answers in inputResponses. This mechanism is described in the article Stateless MCP.

Text and binary contents

Each item of contents contains the URI, an optional mimeType and the data in one of two forms. Text contents use the text field, which is set only if the data can actually be represented as text. Binary contents use the blob field with the data encoded in Base64:

JSON
{
  "uri": "file:///project/docs/architecture.png",
  "mimeType": "image/png",
  "blob": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
}

The MIME type lets the client handle the data appropriately. The specification requires binary data to be properly encoded.

Errors

If the requested resource does not exist, the server must return a JSON-RPC error with code -32602 (Invalid params). For internal errors it should return -32603.

JSON
{
  "jsonrpc": "2.0",
  "id": 5,
  "error": {
    "code": -32602,
    "message": "Resource not found",
    "data": { "uri": "file:///nonexistent.txt" }
  }
}

Up to version 2025-11-25 a missing resource was reported with code -32002. The code stays reserved, and clients should still accept it from servers of earlier versions.

A server must not return an empty contents array for a resource that does not exist. An empty array is ambiguous: it could mean that the resource exists but has no contents.

Resource templates

A resource template describes parameterized resources with a URI template according to RFC 6570. The client requests the templates with resources/templates/list, which supports pagination and caching like the other lists:

JSON
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "resultType": "complete",
    "resourceTemplates": [
      {
        "uriTemplate": "weather://forecast/{city}/{date}",
        "name": "weather-forecast",
        "title": "Weather Forecast",
        "description": "Weather forecast for any city and date",
        "mimeType": "application/json"
      }
    ],
    "ttlMs": 3600000,
    "cacheScope": "public"
  }
}

A template has the fields uriTemplate, name, title, description, mimeType, annotations, icons and _meta. The mimeType field is included only if all resources that match the template have the same type.

The documentation distinguishes two discovery patterns. Direct resources have fixed URIs and appear in resources/list, such as calendar://events/2024. Templates describe dynamic URIs with parameters, such as travel://activities/{city}/{category}. The client substitutes the values into the template, gets a URI such as travel://activities/barcelona/museums and reads it with resources/read.

Completion of template arguments

A server can suggest values for the parameters of a template while the user types them. A server that supports this declares the completions capability. The client sends completion/complete with a reference of type ref/resource, the URI template, the name of the argument and its current value:

JSON
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "completion/complete",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    },
    "ref": { "type": "ref/resource", "uri": "weather://forecast/{city}/{date}" },
    "argument": { "name": "city", "value": "Par" }
  }
}
JSON
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "resultType": "complete",
    "completion": { "values": ["Paris", "Park City"], "total": 2, "hasMore": false }
  }
}

A response contains at most 100 values, sorted by relevance, with an optional total and the hasMore flag. For templates with several parameters the client passes the values already chosen in context.arguments. The same mechanism serves the arguments of prompts, which are described in the article Prompts in MCP.

Annotations

Resources, resource templates and content blocks support optional annotations. They are hints that help the client decide how to use or display the data.

Field Meaning
audience Intended audience: user, assistant or both
priority Importance from 0 to 1: 1 means effectively required, 0 means entirely optional
lastModified Time of the last change, in ISO 8601 format

According to the specification, a client can use annotations to filter resources by audience, to choose which resources to include in the context and to sort them by recency. The specification does not define how exactly a host must react to particular values.

Resources in tool results

A tool can return resources in its result in two ways. The table compares them.

Resource link Embedded resource
Content type resource_link resource
What it carries URI, name and other fields of a resource definition Contents: uri and text or blob
How the client gets the data Reads the URI with resources/read or subscribes to it The data is already in the result
Requirement for the server The link is not guaranteed to appear in resources/list The server should implement the resources capability
JSON
{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "resultType": "complete",
    "content": [
      {
        "type": "resource_link",
        "uri": "file:///project/src/main.rs",
        "name": "main.rs",
        "description": "Primary application entry point",
        "mimeType": "text/x-rust"
      },
      {
        "type": "resource",
        "resource": {
          "uri": "file:///project/Cargo.toml",
          "mimeType": "text/plain",
          "text": "[package]\nname = \"demo\"\nversion = \"0.1.0\""
        },
        "annotations": { "audience": ["assistant"], "priority": 0.7 }
      }
    ]
  }
}

Both forms support the same annotations as resources. Prompts can contain embedded resources in their messages as well; according to the schema, it is up to the client how to render them for the model or the user. Tool results are described in the article Tools in MCP.

Change notifications and subscriptions

A server declares two optional features in the resources capability:

  • listChanged: the server sends notifications/resources/list_changed when the list of resources changes;
  • subscribe: the server sends notifications/resources/updated when a resource the client watches changes.
JSON
{
  "capabilities": {
    "resources": { "listChanged": true, "subscribe": true }
  }
}

Since 2026-07-28 both kinds of notifications arrive only on a stream that the client opens with subscriptions/listen. This request replaced the former resources/subscribe and resources/unsubscribe methods and the separate HTTP GET endpoint. The client names the notification types it wants; the server must not send other types.

JSON
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "subscriptions/listen",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    },
    "notifications": {
      "resourcesListChanged": true,
      "resourceSubscriptions": ["file:///project/config.json"]
    }
  }
}

The server first sends notifications/subscriptions/acknowledged with the part of the filter it agreed to honor; unsupported types are omitted. The client should compare it with what it requested. After that the server sends notifications as resources change:

JSON
{
  "jsonrpc": "2.0",
  "method": "notifications/resources/updated",
  "params": {
    "_meta": { "io.modelcontextprotocol/subscriptionId": 8 },
    "uri": "file:///project/config.json"
  }
}

Every message on the stream carries io.modelcontextprotocol/subscriptionId, equal to the JSON-RPC id of the subscriptions/listen request. A client may keep several subscriptions at once and tells them apart by this field. The URI in a notification can be a sub-resource of the one the client subscribed to. The notification does not carry the new contents: the client reads the resource again with resources/read.

A subscription ends when the client closes the SSE stream (Streamable HTTP) or sends notifications/cancelled (stdio), when the server ends it, or when the transport closes. A server that ends a subscription on its own should first send a normal response to the subscriptions/listen request. A transport that closes without such a response indicates an unexpected disconnection, after which the client may reconnect. On stdio the server keeps no subscription state across reconnections, so the client sends subscriptions/listen again.

Caching

The complete results of resources/list, resources/templates/list and resources/read must carry caching hints. ttlMs is the time in milliseconds during which the result may be considered fresh; cacheScope defines who may reuse it. The fields are described in the article Tools in MCP; a few rules concern resources in particular.

  • The cache key is the method together with the parameters that affect the result. For resources/read this is the uri.
  • private suits results of resources/read that depend on the authenticated user. public suits data that is identical for all users.
  • A result obtained by a repeated request with inputResponses or requestState must not be cached.
  • A relevant notification, for example notifications/resources/list_changed for a cached list, makes the cached result stale at once, even before its TTL expires.

A server may still change the data before the TTL expires: TTL is a freshness hint, not a guarantee. The specification also requires servers to apply access control to every primitive and not to rely on cacheScope alone.

Security

The specification sets requirements for servers that expose resources:

  • a server must validate all resource URIs;
  • access control should be implemented for sensitive resources, and permissions should be checked before operations;
  • binary data must be properly encoded;
  • for file:// resources the server must sanitize paths to prevent directory traversal.

The contents of a resource get into the context of the model. Text from documents, web pages or tickets can contain instructions addressed to the model; this risk is described in the articles Security of MCP and Prompt injection.

Resource and tool

Resources and tools can give the model access to the same data, but they work differently. The table compares them.

Resource Tool
Purpose Data for context Action or computation
Who decides to use The application The model
Identification URI Name
Parameters Parts of the URI, through a template Arguments according to inputSchema
Discovery resources/list, resources/templates/list tools/list
Access resources/read tools/call
Result contents: text or blob with a MIME type content blocks and structuredContent
Errors JSON-RPC error, -32602 for a missing resource Protocol error or result with isError: true
Caching of the result Hints in the resources/read result No hints in the tools/call result
Change notifications List changes and updates of individual resources List changes only
Mcp-Name header URI Name of the tool

The main difference is who initiates access. A resource is chosen by the application or the user and is added to the context. The host decides what to pass to the model: a part of the data, the results of a search or all of it. A tool is chosen by the model during the conversation, with arguments that the model fills in itself.

The two primitives are used together. A tool can return a resource link, and the client reads the resource when it needs the data. In MCP Apps a tool refers to a ui:// resource with an interface in its _meta, and the host can read this resource even before the call. A prompt can combine resources and tools in one scenario; prompts are described in the article Prompts in MCP.

Terms

Term Meaning
Resource Data identified by a URI that a server exposes for use as context
Resource template Description of parameterized resources with a URI template according to RFC 6570
Direct resource Resource with a fixed URI that appears in resources/list
Resource link Content block of type resource_link that points to a resource by its URI
Embedded resource Content block of type resource that contains the contents of a resource
Resource annotations Hints audience, priority and lastModified for resources and content blocks
Resource subscription Request for notifications about changes of resources with given URIs through subscriptions/listen

Sources

Series

Model Context Protocol (MCP)
  1. What is MCP (Model Context Protocol)
  2. Tools in MCP
  3. Resources and resource templates in MCPCurrent
  4. Prompts in MCP
  5. MCP transports: stdio and Streamable HTTP
  6. Stateless MCP: changes in 2026-07-28
  7. Authorization in MCP
  8. MCP security
  9. MCP extensions
  10. MCP server over an existing API
  11. Testing MCP servers: the basics
  12. Evaluating an MCP server with models
  13. Regression testing of an MCP server
  14. Publishing an MCP server to the MCP Registry

Wiki articles are written and maintained by the ComplexQA team.