MCPMCP Python SDK 2.2 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
24 small wins to finish your pathNext lesson

Resources: data an application loads

A tool is what the model decides to call. A resource is data the application decides to load, such as a policy, and put in front of the model.

Exampleshop.py, new
@mcp.resource("policy://refunds", mime_type="text/markdown")
def refund_policy() -> str:
    """The shop's refund policy."""
    return "# Refunds\n\nFull refund within 30 days of delivery. Damaged items: refund or replacement."

@mcp.resource(uri) registers a function as a resource. A resource is found by its URI, policy://refunds, not by the function's name. mime_type says what kind of text it is; without it, the type is plain text.

Example
import asyncio

from mcp import Client
from shop import mcp


async def main():
    async with Client(mcp) as client:
        listed = await client.list_resources()
        for resource in listed.resources:
            print(resource.uri, resource.name, resource.mime_type)

        result = await client.read_resource("policy://refunds")
        print(result.contents[0].text)


asyncio.run(main())

list_resources shows what exists; read_resource runs the function for one URI and returns its contents. Listing never calls the function, so a server can offer many resources and only pay for the ones that are opened.

Who decides

The SDK's docs split the three things a server offers by who decides to use them. The model decides to call a tool. The application decides to attach a resource, often because the user picked it: in Claude Desktop and Claude Code you can add a server's resource to the conversation yourself. The user picks a prompt, which is lesson 10.

Like a web API, a resource is the GET: it loads data and changes nothing. A tool can be the POST.

Try it yourself
  • Add a policy://shipping resource with the shop's delivery times.
  • Return a dictionary from a resource with mime_type="application/json" and read it.
  • Read policy://returns, which does not exist, and read the error.

Slow is fine. Stopping is the only problem.