Skip to main content

Resources — Exposing Structured Data to AI Models

13/40
Chapter 4 MCP Resources and Prompts — Expose Data and Workflows to AI

Resources — Exposing Structured Data to AI Models

20 min read Lesson 13 / 40 Preview

Resources — Exposing Structured Data to AI Models

While tools let AI take action, resources let AI read data. Resources are how your MCP server exposes files, configurations, database records, and any other structured data for the AI model to consume.

Tools vs Resources

Aspect Tools Resources
Purpose Perform actions Expose data
Direction AI calls, server executes AI reads, server provides
Side effects Yes (create, update, delete) No (read-only)
Trigger AI decides when to call Client fetches as needed
Analogy API endpoints (POST/PUT) API endpoints (GET)

Defining Static Resources

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

const server = new McpServer({ name: "resource-demo", version: "1.0.0" });

// A simple text resource
server.resource(
  "readme",
  "docs://readme",
  { description: "Project README documentation" },
  async () => ({
    contents: [{
      uri: "docs://readme",
      text: "# My Project\n\nThis is the project documentation...",
      mimeType: "text/markdown",
    }],
  })
);

// A JSON resource
server.resource(
  "app-config",
  "config://app",
  { description: "Current application configuration" },
  async () => ({
    contents: [{
      uri: "config://app",
      text: JSON.stringify({
        version: "2.1.0",
        environment: process.env.NODE_ENV,
        features: { darkMode: true, betaFeatures: false },
        limits: { maxUploadSize: "10MB", rateLimit: "100/min" },
      }, null, 2),
      mimeType: "application/json",
    }],
  })
);

Resource URIs

Every resource needs a unique URI. Use custom schemes to organize:

config://app              → Application config
config://database         → Database settings
docs://readme             → README file
docs://api/endpoints      → API documentation
db://users/schema         → User table schema
metrics://dashboard       → Dashboard metrics

Dynamic Resources with Templates

Resource templates let you define parameterized resources:

// Template resource — the AI can request any user's profile
server.resource(
  "user-profile",
  "users://{userId}/profile",
  { description: "User profile data. Replace {userId} with a valid user ID." },
  async (uri) => {
    // Extract userId from the URI
    const match = uri.href.match(/users:\/\/(.+)\/profile/);
    const userId = match?.[1];

    if (!userId) {
      throw new Error("Invalid user ID in URI");
    }

    const user = await db.query("SELECT * FROM users WHERE id = $1", [userId]);

    return {
      contents: [{
        uri: uri.href,
        text: JSON.stringify(user.rows[0], null, 2),
        mimeType: "application/json",
      }],
    };
  }
);

Python Resources

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("resource-demo")

@mcp.resource("config://app")
def get_app_config() -> str:
    """Current application configuration and feature flags."""
    import json
    return json.dumps({
        "version": "2.1.0",
        "environment": "production",
        "features": {"dark_mode": True, "beta": False},
    }, indent=2)

@mcp.resource("docs://api/{endpoint}")
def get_api_docs(endpoint: str) -> str:
    """API documentation for a specific endpoint."""
    docs = load_api_docs(endpoint)
    return docs

Resource Update Notifications

When a resource changes, notify the client so the AI can re-read it:

// When data changes, notify the client
server.notification({
  method: "notifications/resources/updated",
  params: { uri: "metrics://dashboard" },
});

Key Takeaway

Resources are the read-only counterpart to tools. Use them to expose configuration, documentation, database schemas, metrics, and any data the AI model needs as context. Well-designed resources make your AI dramatically smarter about your system.