Expose Resources from an MCP Server

@mcp.resource("project://{project_id}/readme")
async def project_readme(project_id: str) -> str:
    """Return the project's README."""
    return await load_readme(project_id)

Resources are useful for addressable read-only context. Templates let you model large resource spaces without enumerating every possible URI.

Use stable URI design

Choose identifiers that can remain stable if storage internals change. Do not put access tokens or secrets in resource URIs.

Authorize every read

A client knowing a URI does not grant access. Enforce tenant/user permissions in the resource handler.

Think about cacheability

For the 2026 protocol, decide how long a resource stays fresh and whether results are user-specific. Private cache scope is the safe default for permission-dependent data.