What it does
The client sends a resources/read request with a single `uri` parameter identifying the target resource. The server validates the URI, resolves the underlying data source (a file, database row, API endpoint, or any other backend), and returns a `contents` array containing one or more `TextResourceContents` or `BlobResourceContents` objects. Each item carries a `uri`, a `mimeType`, and either a `text` string or a base64-encoded `blob` string — never both. The array usually has exactly one element, but servers may return multiple parts when the URI logically maps to a compound document (for example, a directory URI resolved to individual file entries, or a paginated record set returned as discrete chunks). Capability gating is mandatory: the client must confirm the server declared a `resources` key in its `ServerCapabilities` during initialization before sending this request. If the capability is absent, the server is within its rights to return a JSON-RPC `-32601 Method not found` error. The server may additionally return `-32002 Resource not found` when the URI does not exist, and `-32003 Resource not readable` when the resource exists but access is denied or the backing store is temporarily unavailable. Because resources/read is a synchronous point-in-time snapshot, callers must be aware of TOCTOU (time-of-check/time-of-use) races: the server may emit a `notifications/resources/updated` notification between the moment the client decides to call resources/read and the moment the response arrives. Always re-issue the read after receiving an updated notification rather than relying on a cached response. There is no built-in pagination for the `contents` array itself; if a resource is too large to return in one message, the server should split it into logical parts or return a ResourceLink pointing to a streaming endpoint instead.
When to use
Whenever the host needs the actual bytes/text of a resource.
When NOT to use
For metadata-only lookups — resources/list returns that.
Notes
Capability gate before every call
Check that the server's ServerCapabilities includes a non-null `resources` key before sending resources/read. Servers are not required to implement the method if the capability is absent, and some will return -32601 Method not found rather than an empty result. Gate this once after initialize and cache the boolean.
Error codes to handle explicitly
Handle at least three error codes: -32601 Method not found (no resources capability), -32002 Resource not found (URI does not resolve), and -32003 Resource not readable (access denied or transient I/O failure). Treat -32003 as retryable with backoff; treat -32002 as a permanent failure that should invalidate any cached resource list entry.
Multi-part contents array is intentional
The `contents` array is not a pagination cursor — it is a single atomic response that may contain N parts. A directory URI, a compound document, or a server that splits large text into logical sections can legitimately return multiple items. Do not assume index 0 is the only item; iterate the full array and concatenate or display each part in order.
Caching and TOCTOU races
Cache the contents keyed by URI only until the next notifications/resources/updated notification for that URI arrives. Do not use a time-based TTL alone — the notification is the canonical invalidation signal. If you issue a resources/read and receive an updated notification before the response arrives, discard the response and re-issue the read immediately.
Avoid inlining large binaries — use ResourceLink instead
BlobResourceContents base64-encodes the payload, which inflates size by ~33 % and must fit in a single JSON-RPC message. For binary files above a few hundred KB, prefer returning a ResourceLink from tool results and letting the host call resources/read only when it decides to fetch. The MCP Python and TypeScript SDKs do not automatically stream large blobs — you must implement chunking or linking at the server level.
Request parameters
| Name | Type | Purpose |
|---|---|---|
| uri | string | URI of the resource. |
Response fields
| Name | Type | Purpose |
|---|---|---|
| contents | (TextResourceContents | BlobResourceContents)[] | Resource bytes. |
Examples
Read a file
{ "method": "resources/read", "params": { "uri": "file:///README.md" } }
Common mistakes
❌ Reading huge binaries inline
✅ Stream via your transport or use ResourceLink in tool results.