PTENES
MODULE 3.6

📦 Adding Resources

Learn to expose data as Resources — allowing the model to access information without performing actions.

6
Topics
30
Minutes
Intermediate
Level
Practical
Type
1

📦 What Resources Are in Code

So far, we’ve worked with tools — functions that perform actions and return results. Now let's get to know the resources: data the model can read but not modify. While tools are "verbs" (doing something), resources are "nouns" (accessing something). This distinction is fundamental to the MCP architecture.

💎 Core Concept

In FastMCP, a resource is created with the decorator @mcp.resource(), which receives a URI as a unique identifier:

@mcp.resource("config://app")

def get_config() -> str:

"""Returns the app settings."""

return "version: 1.0, mode: production"

The fundamental difference: tools perform actions (send email, calculate, query an API), while resources expose data (settings, documentation, status). The model reads resources to get context, but can't use them to modify anything.

💡 Practical Tip

Think of resources as files in a virtual file system. Each resource has an address (URI) and content. The model can "open and read" these files, but it can't "write" to them. Use resources for anything the model needs to know but doesn't need to do: settings, documentation, constants, and reference data.

❌ Avoid
  • •Use tools when resources are enough
  • •Put actions (side effects) in resources
  • •Expose sensitive data without controls
  • •Mixing data and actions in the same component
✅ Do
  • •Use resources for read-only data
  • •Keep resources as pure functions (without side effects)
  • •Use descriptive, well-organized URIs
  • •Clearly separate tools from resources
2

📄 Static Resources

Static resources return fixed data that doesn’t change between calls — application settings, documentation, constants, business rules. They’re the simplest to implement and the most common in MCP servers. The model can access them at any time to get reference information.

💎 Core Concept

@mcp.resource("config://app")

def get_app_config() -> str:

"""App settings."""

return """

App: My MCP Server

Version: 1.0.0

Environment: production

Max connections: 100

Default timeout: 30s

"""


@mcp.resource("docs://help")

def get_help() -> str:

"""Help documentation."""

return "Use the available tools to calculate and check the weather."

💡 Practical Tip

Static resources are great for providing context to the model. For example, a resource with the company's business rules lets the model answer questions about policies without needing a tool. A resource with the system documentation helps the model guide the user. Think of resources as the "instruction manual" the model can consult.

3

🔄 Dynamic Resources

Unlike static resources, dynamic resources return data that changes with each access. The current date and time, system status, counters, monitoring data — all of this is dynamic. The resource function is called each time the model accesses that URI, ensuring the data is always up to date.

💎 Core Concept

from datetime import datetime


@mcp.resource("status://current-time")

def get_hora_atual() -> str:

"""Returns the server's current date and time."""

now = datetime.now()

return f"Date and time: {agora.strftime('%d/%m/%Y %H:%M:%S')}"


@mcp.resource("status://system")

def get_status_sistema() -> str:

"""Returns the system's current status."""

import platform

return (

f"OS: {platform.system()}\n"

f"Python: {platform.python_version()}\n"

f"Time: {datetime.now().strftime('%H:%M:%S')}"

)

📋 Dynamic Resource Access Flow
Step 1

The model decides it needs a piece of data (e.g., the current time) and requests the resource by URI.

Step 2

FastMCP receives the request and runs the function associated with that URI at that moment.

Step 3

The function returns the updated data (e.g., "14:35:22"), and the model uses it in its response to the user.

📊 Data and Research

Dynamic resources are particularly useful in scenarios involving monitoring and observability. An MCP server can expose resources with system metrics, service status, recent logs, and health dashboards—allowing the model to answer questions like "How is the system's health?" or "What's the current memory usage?" without needing specific tools.

4

🔗 URI Schemes

Each resource is identified by a URI (Uniform Resource Identifier) — a unique address that follows the pattern tipo://caminho. The "type" (scheme) indicates the category of data, and the "path" identifies the specific resource. Well-organized URIs make it easier for the model to discover and use resources.

💎 Core Concept

The URI format is scheme://path, where the scheme indicates the type of data:

config://settings → system settings
file://readme.md → contents of a file
db://users → table data
status://health → system health status
docs://api/endpoints → endpoint documentation

The URI identifies only each resource. Two different URIs always point to different resources. Organize your URIs logically and consistently.

❌ Confusing URIs
  • •data://x1 — meaningless
  • •resource://get_stuff — verb in resource
  • •abc://123 — scheme without semantics
  • •config://ConfiguraçõesDoApp — accents and capitalization
✅ Clear URIs
  • •config://app — clear and concise
  • •status://health — clear semantics
  • •docs://api/endpoints — hierarchical
  • •db://users/schema — specific
5

📋 Listing Resources

The MCP protocol lets the client list all resources available on the server. FastMCP does this automatically—all resources registered with @mcp.resource() appear in the listing. In addition, MCP supports resource templates — parameterized resources where part of the URI is variable.

💎 Core Concept

Resource templates let you create parameterized resources. FastMCP automatically detects parameters in the URI:

@mcp.resource("users://{user_id}/profile")

def get_user_profile(user_id: str) -> str:

"""Returns a user's profile."""

return f"User profile {user_id}"

O {user_id} in the URI becomes a parameter. The model can access users://alice/profile or users://bob/profile — each returning different data. FastMCP registers this as a resource template in the listing.

💡 Practical Tip

The resource listing works like a "catalog" from the server. The MCP client can request the full list of resources before using any of them. This lets the model know exactly what data is available and how to access it. Keep your URIs and descriptions (docstrings) organized to make discovery easier.

🚨 Alert

Be careful about what you expose as a resource. All registered resources are visible to the MCP client. Never expose sensitive data such as passwords, API tokens, private keys, or personal data without adequate protection. Treat resources as public endpoints — if the model shouldn't be able to read some data, don't create a resource for it.

6

🧪 Testing Resources

Let's test the resources we created in Claude Desktop. The model should be able to list the available resources and read the content of each one. Unlike tools (which the model actively calls), resources are data the model can access when it needs context to answer a question.

💎 Core Concept

Test your resources with questions that encourage the model to retrieve them:

  • 1. "What settings are available?" — the model should read the resource config://app.
  • 2. "What's the current date and time?" — the model should read status://hora-atual and return the dynamic value.
  • 3. "What's the system status?" — the model should read status://sistema.
  • 4. "Show me the help documentation." — the model should read docs://ajuda.
💡 Practical Tip

A good practice is to create a resource docs://ajuda in every MCP server that explains which tools and resources are available. When the user asks "What can you do?", the model reads this resource and presents the server's capabilities in an organized way. It's like creating a integrated help menu.

📋 Recommended Testing Sequence
Test 1 — Static resource

Ask about settings. Check that the model returns the fixed data from the config://app resource.

Test 2 — Dynamic resource

Ask for the time twice, with an interval in between. Check that the values change between queries.

Test 3 — Combining tools + resources

Ask questions that use both tools and resources. For example: "Check the weather and tell me the current time."

📝 Module Summary

  • ✓ Resources are data the model reads — unlike tools, which perform actions.
  • ✓ Static resources return fixed data: settings, documentation, constants.
  • ✓ Dynamic resources return updated data on each access: time, status, metrics.
  • ✓ URIs follow the scheme://path pattern and should be clear, organized, and descriptive.
  • ✓ Resource templates allow parameterized resources with variables in the URI.
  • ✓ Resources and tools complement each other — context data + actions make up a complete server.

Next Module: 3.7 — Adding Prompts