Building MCP Servers

Exposing Resources

5 min read

While tools let the AI perform actions, resources let the AI read data. Resources are perfect for exposing files, database records, or any read-only data.

Resource vs Tool

Aspect Tool Resource
Purpose Perform actions Read data
Side effects May modify state Read-only
Examples Send email, create file Read config, get user profile

Defining Resources

Resources use URIs to identify content:

from mcp.types import Resource

@server.list_resources()
async def list_resources():
    return [
        Resource(
            uri="config://app/settings",
            name="Application Settings",
            description="Current application configuration",
            mimeType="application/json"
        ),
        Resource(
            uri="file:///var/log/app.log",
            name="Application Logs",
            description="Recent application log entries",
            mimeType="text/plain"
        )
    ]

URI Schemes

You can use any URI scheme that makes sense for your data:

Scheme Use Case Example
file:// Local files file:///home/user/doc.txt
db:// Database records db://users/123
config:// Configuration config://app/settings
api:// External APIs api://weather/london

Reading Resources

Implement the read handler to return content:

from mcp.types import TextContent, BlobContent

@server.read_resource()
async def read_resource(uri: str):
    if uri == "config://app/settings":
        settings = load_app_settings()
        return [TextContent(
            type="text",
            text=json.dumps(settings, indent=2)
        )]

    if uri.startswith("file://"):
        path = uri.replace("file://", "")
        content = read_file(path)
        return [TextContent(type="text", text=content)]

    raise ValueError(f"Unknown resource: {uri}")

Binary Resources

For binary data like images, use BlobContent:

import base64

@server.read_resource()
async def read_resource(uri: str):
    if uri.startswith("image://"):
        image_data = load_image(uri)
        return [BlobContent(
            type="blob",
            data=base64.b64encode(image_data).decode(),
            mimeType="image/png"
        )]

Dynamic Resources

Resources can be generated dynamically based on parameters:

@server.list_resources()
async def list_resources():
    # Generate resources from database
    users = await db.get_all_users()
    return [
        Resource(
            uri=f"user://{user.id}",
            name=f"User: {user.name}",
            description=f"Profile for {user.name}"
        )
        for user in users
    ]

Next, let's explore error handling and best practices. :::

Quiz

Module 2 Quiz: Building MCP Servers

Take Quiz