Discover and read MCP server resources

Discover resources by confirming the server advertises resource support, calling `resources/list`, choosing only the URI relevant to the current task, and sending `resources/read` for that URI. Then handle each returned item as text or base64-encoded binary according to its MIME type instead of loading the entire catalog into model context.
Prerequisites
Start with an initialized MCP client connection. The server must declare the resources capability during initialization; otherwise, do not send resource requests. If the connection itself is still undecided, settle whether the integration needs a remote or local MCP server before implementing discovery.
A resource browser also needs somewhere to show descriptors before content is read. That can be a visible picker, a search interface, or application logic that selects a URI. The protocol does not require one interface, but the application must make the selection.
Discover and read a resource
-
Confirm that the server exposes resources
Inspect the server capabilities returned during initialization. A supporting server includes a
resourcesobject. The object may also say that the server supports subscriptions or notifications when its resource list changes, but both features are optional.This check prevents the client from treating an unsupported method as a failed resource lookup. According to the MCP resources specification dated 2025-11-25, servers that expose resources must declare the capability, while
subscribeandlistChangedcan each be present or absent.Stop here if the capability is missing. A tool that happens to return document data is still a tool; it does not create a resource interface.
-
Keep resources separate from tools and prompts
Treat a resource as application-controlled context identified by a URI. It exposes information for the application to retrieve and potentially provide to a model. A tool is different: it asks the server to perform an action through a named operation with defined inputs. The model can decide to request a tool call, whereas the application controls how resources are discovered, selected, and incorporated.
The MCP server-concepts guide, accessed August 26, 2026, distinguishes resources as passive, application-controlled data from tools as model-controlled operations. That distinction should shape the client UI and execution path. Put resources in a context picker or selection pipeline; put tools in the tool registry and approval flow.
Prompts are a third primitive: reusable templates selected by the user. Do not put a resource URI into the prompt menu merely because its content might support a prompt. If the server exposes both, discover its server-provided prompt templates separately.
-
List the available resource descriptors
Send a JSON-RPC request whose method is
resources/list:{ "jsonrpc": "2.0", "id": 1, "method": "resources/list" }The result contains a
resourcesarray. Each descriptor has a uniqueuriand aname; it may also carry a display title, description, MIME type, byte size, icons, or annotations. At this stage, the client has discovered what can be read. It has not retrieved every resource’s contents.Support pagination rather than assuming the first response is complete. If the result includes
nextCursor, repeatresources/listwith that cursor and append the returned descriptors. Finish discovery when the server stops returning a next cursor.Preserve each URI as an opaque identifier. The specification permits familiar schemes such as
file:,https:, andgit:, as well as conforming custom schemes. Afile:URI does not prove that the resource maps to a physical file on the client’s machine, so do not replace server reads with local filesystem access based on the scheme alone. -
Select the resource that fits the current task
Choose from the descriptors before reading content. The client lists resources and then reads a selected URI; it should not assume that every advertised resource belongs in model context.
Use the descriptor fields to make that decision.
name,title, anddescriptioncan support a human-readable picker.mimeTypecan rule out content the client cannot handle. Optional annotations can help filter by intended audience, priority, or modification time. Because these fields beyonduriandnameare optional, the selection path must still work when descriptions, sizes, or MIME types are absent.Application-controlled does not mean that selection must always be manual. The application may expose a list, offer search and filters, or apply its own selection rule. The condition is that selection remains a client decision: discovery should not silently place the full catalog into the model’s prompt.
Read multiple resources only when the task needs each one. For example, a request that depends on both a schema and a project document can justify two selected URIs. Mere availability does not.
-
Read the selected URI
Send
resources/readwith the selected descriptor’s exact URI:{ "jsonrpc": "2.0", "id": 2, "method": "resources/read", "params": { "uri": "file:///project/src/main.rs" } }Match the response to the request ID, then inspect
result.contents. The result is an array, so handle every returned content item rather than assuming one URI always produces one item.A server can return the JSON-RPC resource-not-found error
-32002. Treat that as a failed read, not as empty content. The descriptor may have become stale between listing and reading, or the URI may no longer be available. Re-listing can establish what the server currently exposes. If the application must keep already-selected resources current, add resource subscriptions only when the server advertises that optional capability. -
Process each content item by representation and MIME type
A resource response may contain text or binary content. The MCP schema reference for version 2025-11-25 defines
ReadResourceResult.contentsas an array containingTextResourceContentsorBlobResourceContents.A text item carries a
textfield. A binary item carries ablobfield containing base64-encoded data. Both carry their resource URI and may include a MIME type. Do not test only for a familiar filename extension: branch on whether the item containstextorblob, then usemimeType, when supplied, to decide how the client presents or processes it.For text, retain the MIME type when handing the value to a renderer or parser so that plain text, Markdown, JSON, and source code need not be treated identically. For binary data, base64-decode the blob before passing it to a compatible image, audio, document, or file handler. Binary data should not be displayed as if its encoded string were the resource’s readable contents.
The schema makes
mimeTypeoptional. When it is missing, classify the item only as text or binary and use an unknown-content fallback; do not invent a type from the URI. When it is present but unsupported, preserve the item and report that the client cannot present that MIME type rather than corrupting it through an unsuitable decoder.
Expected result
The client confirms resource support, obtains the complete descriptor list, selects the URI relevant to the current task, and reads that URI explicitly. It handles every returned item as text or base64-encoded binary, using the supplied MIME type when available. Only the selected content enters the application’s presentation or model-context path.
Sources
- MCP resources specification dated 2025-11-25modelcontextprotocol.io
- MCP server-concepts guide, accessed August 26, 2026modelcontextprotocol.io
- MCP schema reference for version 2025-11-25modelcontextprotocol.io
See also
What the Environment Config MCP server changes, why shared presets and transformations have broad reach, and what reviewers need to record.
When a marketplace plugin is the right way to install MCP servers and skills, when a hand-written config entry is, and why most teams end up with both.
How MCP 2026-07-28 removes handshake and session state, makes requests self-describing, and keeps application state explicit.
How MCP clients request contextual suggestions for prompt and resource-template arguments, and why suggestions provide neither authorization nor validation.