← Back to Writing
Article· 3 min read· Last updated

MCP Resources Explained with Practical Examples

Model Context ProtocolMCP ResourcesMCP Server.NET AIAI Engineering
Diagram highlighting MCP resources as read-only context for an AI agent

Summary

Learn what MCP resources are, how they differ from tools, and how to use them for logs, portfolios, documents, APIs, and enterprise AI workflows.

Short answer: An MCP resource is read-only data the model can fetch by URI. Resources give the AI context — a customer profile, a log file, a document, an API spec — without implying any action or side effect. If a tool is a POST, a resource is a GET.

This article is part of a series. For the overview, see Model Context Protocol Tools, Resources, and Prompts Explained. For the formal spec, see the official MCP documentation.

What are MCP resources?

In Model Context Protocol, a resource is a named, addressable piece of read-only data exposed by an MCP server. Each resource has a URI template — for example `customer://profile/{customerId}` — and returns structured content (usually JSON or text) when the host requests it.

Resources let the model know things about your systems. They are the context layer of MCP.

Resources are context, not actions

The single most important rule: resources do not change state. Fetching a resource should be safe to repeat, safe to cache, and free of side effects. If invoking something can create, modify, or delete data, it is a tool, not a resource. See MCP Prompts Explained for the third primitive.

Resource URI examples

URIReturns
`customer://profile/CUST-2048`Customer profile, tier, open tickets
`portfolio://account/ACC-1024`Holdings, cash balance, allocation weights
`logs://service/payments/2026-06-19`A production log slice for one service/day
`docs://api/orders`The OpenAPI description for the orders API

Good use cases

  • Customer or account profiles the model should reference.
  • Portfolio or inventory snapshots.
  • Documentation and API specs the model should ground answers in.
  • Read-only log slices for investigation.

Bad use cases

  • Anything that mutates state (use a tool).
  • Unbounded data dumps — paginate or scope by ID and date.
  • Cross-tenant data without isolation — never let one tenant's resource leak another's data.

Example: portfolio holdings resource

[McpServerResourceType]
public sealed class PortfolioResourceHandler(IPortfolioService portfolio)
{
    [McpServerResource("portfolio://account/{accountId}")]
    [Description("Returns holdings, cash balance, and allocation weights as JSON.")]
    public async Task<string> GetPortfolioAsync(string accountId, CancellationToken ct)
    {
        var snapshot = await portfolio.GetSnapshotAsync(accountId, ct)
            ?? throw new InvalidOperationException($"No portfolio for '{accountId}'.");
        return JsonSerializer.Serialize(snapshot, new JsonSerializerOptions { WriteIndented = true });
    }
}

A typical payload:

{
  "accountId": "ACC-1024",
  "cash": { "amount": 12500.00, "currencyCode": "USD" },
  "holdings": [
    { "symbol": "AAPL", "quantity": 40, "avgCost": 182.50, "weightPct": 18.2 }
  ],
  "asOf": "2026-06-19T09:30:00Z"
}

Example: production logs resource

`logs://service/{name}/{date}` returns a scoped, redacted slice of logs for one service and day. Scope and redaction matter: never expose raw, unbounded logs that may contain secrets or PII.

Example: API documentation resource

`docs://api/{name}` returns the OpenAPI spec or a curated summary so the model can reason about endpoints accurately instead of guessing. This pairs well with RAG over your wider docs — see Private RAG Systems Without External APIs.

Resources vs tools

AspectResourceTool
DirectionReadRead or write
Side effectsNoneAllowed
Addressed byURIName + arguments
Safe to repeatYesNot always
Mental modelGETPOST

A practical tip from designing real servers: when a client may not auto-fetch resources, also offer a read tool (e.g. `get_portfolio`) that returns the same payload. That redundancy is discussed in Can ChatGPT MCP Connectors Use Resources and Prompts or Only Tools?.

Design checklist

  • Is the operation truly read-only and side-effect free?
  • Is the URI template scoped by a stable identifier?
  • Is the payload bounded and tenant-isolated?
  • Are secrets and PII redacted?
  • Is there a read-tool fallback for clients that do not auto-fetch resources?

Final takeaway

Resources are how you give an AI context safely. Keep them read-only, scoped by URI, bounded, and tenant-isolated — and reserve tools for anything that acts. Get that boundary right and your MCP server stays auditable and predictable.

References

Frequently asked questions

What is an MCP resource?
An MCP resource is read-only data exposed by an MCP server and addressed by a URI, such as customer://profile/CUST-2048. It gives the model context without any side effects.
How is an MCP resource different from a tool?
A resource is read-only and safe to repeat, like a GET request. A tool can change state and may have side effects, like a POST request.
When should I add a read-tool fallback for a resource?
When a client may not auto-fetch resources, expose a read tool that returns the same payload so the model can still reach the context it needs.

Related reading