Published on

Understanding Resources in MCP Servers: A Complete Guide

Authors
  • avatar
    Name
    Anablock
    Twitter

    AI Insights & Innovations

MCPservers_1 Resources in MCP servers allow you to expose data to clients, similar to GET request handlers in a typical HTTP server. They're perfect for scenarios where you need to fetch information rather than perform actions.

Understanding Resources Through an Example

Let's say you want to build a document mention feature where users can type @document_name to reference files. This requires two operations:

  1. Getting a list of all available documents (for autocomplete)
  2. Fetching the contents of a specific document (when mentioned)

When a user types @, you need to show available documents. When they submit a message with a mention, you automatically inject that document's content into the prompt sent to Claude.

How Resources Work

Resources follow a request-response pattern. Your client sends a ReadResourceRequest with a URI, and the MCP server responds with the data. The URI acts like an address for the resource you want to access.

Types of Resources

There are two types of resources:

Direct Resources

Static URIs that don't change, like docs://documents

Templated Resources

URIs with parameters, like docs://documents/{doc_id}

For templated resources, the Python SDK automatically parses parameters from the URI and passes them as keyword arguments to your function.

Implementing Resources

Resources are defined using the @mcp.resource() decorator. Here's how to create both types:

Direct Resource (List Documents)

@mcp.resource(
    "docs://documents",
    mime_type="application/json"
)
def list_docs() -> list[str]:
    return list(docs.keys())

This creates a static resource that returns a list of all available document IDs. Perfect for populating an autocomplete menu.

Templated Resource (Fetch Document)

@mcp.resource(
    "docs://documents/{doc_id}",
    mime_type="text/plain"
)
def fetch_doc(doc_id: str) -> str:
    if doc_id not in docs:
        raise ValueError(f"Doc with id {doc_id} not found")
    return docs[doc_id]

This creates a templated resource where {doc_id} becomes a parameter. The SDK automatically extracts the value from the URI and passes it to your function.

MIME Types

Resources can return any type of data - strings, JSON, binary, etc. The mime_type parameter gives clients a hint about what kind of data you're returning:

  • application/json - Structured JSON data
  • text/plain - Plain text content
  • Any other valid MIME type for different data formats

The MCP Python SDK automatically serializes your return values. You don't need to manually convert to JSON strings.

Testing Resources

You can test your resources using the MCP Inspector. Run your server with:

uv run mcp dev mcp_server.py

Then connect to the inspector in your browser. You'll see:

  • Resources: Lists your direct/static resources
  • Resource Templates: Shows templated resources that accept parameters

Click on any resource to test it and see the exact response structure your client will receive.

Real-World Use Cases

Document Management

Expose a library of documents that can be referenced in conversations:

  • List all available documents
  • Fetch specific document content
  • Search documents by keyword

Configuration Access

Provide access to configuration data:

  • System settings
  • User preferences
  • Environment variables

Data Browsing

Enable exploration of structured data:

  • Database records
  • File system navigation
  • API endpoint discovery

Status and Monitoring

Expose real-time information:

  • Server health metrics
  • Job status
  • Log entries

Best Practices

Use Descriptive URIs

Make your resource URIs self-documenting:

# Good
"docs://documents/{doc_id}"
"config://settings/{setting_name}"

# Less clear
"resource://{id}"
"data://{param}"

Handle Errors Gracefully

Always validate parameters and provide clear error messages:

@mcp.resource("docs://documents/{doc_id}")
def fetch_doc(doc_id: str) -> str:
    if doc_id not in docs:
        raise ValueError(f"Document '{doc_id}' not found")
    return docs[doc_id]

Choose Appropriate MIME Types

Use the correct MIME type to help clients understand your data:

  • JSON data → application/json
  • Plain text → text/plain
  • HTML → text/html
  • Binary data → application/octet-stream

Keep Resources Focused

Each resource should have a single, clear purpose. Don't try to do too much in one resource.

Resources vs. Tools

Understanding when to use resources versus tools is crucial:

| Resources | Tools | |---------------|----------| | Fetch/read data | Perform actions | | GET-like operations | POST/PUT/DELETE-like operations | | Idempotent (same input = same output) | May have side effects | | Examples: list files, read config | Examples: create file, send email |

Key Points

Resources expose data, tools perform actions
Use direct resources for static data, templated resources for parameterized queries
MIME types help clients understand response format
The SDK handles serialization automatically
Parameter names in templated URIs become function arguments

Conclusion

Resources provide a clean, standardized way to make data available to MCP clients. Whether you're building document mentions, file browsing, configuration access, or any scenario where you need to fetch information from your server, resources give you a powerful and flexible pattern.

By following the examples and best practices in this guide, you can create robust, well-structured resources that make your MCP server a valuable data source for AI applications.

Start experimenting with resources in your MCP server today, and see how they can enhance your AI-powered workflows!