Skip to main content
Technology & EngineeringMcp Server238 lines

MCP Resources

Exposing data and content to AI clients through MCP resources. Covers resource URIs, listing and reading resources, resource templates with URI patterns, MIME types, subscriptions for real-time updates, and patterns for exposing files, database records, and API data as browsable resources.

Quick Summary24 lines
You are an AI assistant helping developers expose resources through MCP servers. Resources are application-controlled data that clients can read and display — files, database records, API responses, live system data. Unlike tools (which the model invokes), resources are typically selected by the user or client application for inclusion in the conversation context.

## Key Points

- `uri` — unique identifier following URI format. Can use any scheme (`file://`, `db://`, custom schemes).
- `name` — human-readable display name.
- `description` — optional explanation of what the resource contains.
- `mimeType` — optional MIME type to help clients render the content.
- **Using resources for actions** — resources are for reading data, not triggering side effects. If reading a resource sends an email or modifies state, use a tool instead.
- **Listing thousands of resources** — if you have a large dataset, use resource templates instead of listing every item. List a curated subset and let templates handle the rest.
- **Returning enormous content** — resources go into the AI's context window. A 10 MB log file will blow the context. Truncate, summarize, or paginate large content.
- **Custom URI schemes without documentation** — if you invent `myapp://` URIs, document the scheme in the resource description so the model knows what to request.
- **Ignoring MIME types** — setting the correct MIME type helps clients render content appropriately (syntax highlighting, image display, etc.).
- Use standard URI schemes where applicable (`file://`, `https://`). Use custom schemes for domain-specific resources (`db://`, `config://`).
- Set accurate MIME types — `application/json` for JSON, `text/markdown` for Markdown, `text/plain` for generic text.
- Keep resource content concise. Summarize large datasets rather than dumping everything.

## Quick Example

```json
{ "method": "resources/read", "params": { "uri": "db://production/tables/orders/schema" } }
```
skilldb get mcp-server-skills/MCP ResourcesFull skill: 238 lines
Paste into your CLAUDE.md or agent config

MCP Resources

You are an AI assistant helping developers expose resources through MCP servers. Resources are application-controlled data that clients can read and display — files, database records, API responses, live system data. Unlike tools (which the model invokes), resources are typically selected by the user or client application for inclusion in the conversation context.

Philosophy

Resources represent data the AI can read, not actions it can take. Think of resources as a file browser for AI — the server lists what is available, and the client (or user) selects what to include in the context. Resources should be stable, identifiable by URI, and return content in a format the model can reason about. Use resources for context and tools for actions.

Techniques

Listing Resources

Servers expose resources through the resources/list method:

{
  "resources": [
    {
      "uri": "file:///project/src/main.ts",
      "name": "main.ts",
      "description": "Application entry point",
      "mimeType": "text/typescript"
    },
    {
      "uri": "db://production/users/schema",
      "name": "Users Table Schema",
      "description": "Column definitions for the users table",
      "mimeType": "application/json"
    },
    {
      "uri": "config://app/settings",
      "name": "Application Settings",
      "description": "Current application configuration",
      "mimeType": "application/json"
    }
  ]
}

Each resource has:

  • uri — unique identifier following URI format. Can use any scheme (file://, db://, custom schemes).
  • name — human-readable display name.
  • description — optional explanation of what the resource contains.
  • mimeType — optional MIME type to help clients render the content.

Reading Resources

Clients read resources via the resources/read method:

// Request
{ "method": "resources/read", "params": { "uri": "db://production/users/schema" } }

// Response
{
  "contents": [
    {
      "uri": "db://production/users/schema",
      "mimeType": "application/json",
      "text": "{\n  \"columns\": [\n    {\"name\": \"id\", \"type\": \"integer\", \"primary_key\": true},\n    {\"name\": \"email\", \"type\": \"varchar(255)\", \"unique\": true},\n    {\"name\": \"created_at\", \"type\": \"timestamp\"}\n  ]\n}"
    }
  ]
}

Resources return either text (for text content) or blob (base64-encoded binary):

{
  "contents": [
    {
      "uri": "file:///project/logo.png",
      "mimeType": "image/png",
      "blob": "iVBORw0KGgoAAAANSUhEUgAA..."
    }
  ]
}

Resource Templates

Resource templates define parameterized URIs using RFC 6570 URI template syntax. They let servers expose dynamic resources without listing every possible instance:

{
  "resourceTemplates": [
    {
      "uriTemplate": "db://production/tables/{table}/schema",
      "name": "Table Schema",
      "description": "Get the schema for any table in the production database",
      "mimeType": "application/json"
    },
    {
      "uriTemplate": "github://repos/{owner}/{repo}/issues/{issue_number}",
      "name": "GitHub Issue",
      "description": "Fetch a specific GitHub issue by owner, repo, and issue number"
    },
    {
      "uriTemplate": "logs://app/{service}/{date}",
      "name": "Service Logs",
      "description": "Application logs for a specific service and date (YYYY-MM-DD)"
    }
  ]
}

Clients fill in the template parameters when requesting:

{ "method": "resources/read", "params": { "uri": "db://production/tables/orders/schema" } }

Implementing Resources (TypeScript)

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

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

// Static resource
server.resource(
  "project-config",
  "file:///project/config.json",
  "Current project configuration",
  async (uri) => ({
    contents: [{
      uri: uri.href,
      mimeType: "application/json",
      text: await fs.readFile("/project/config.json", "utf-8"),
    }],
  })
);

// Dynamic resource using a template
server.resource(
  "table-schema",
  new ResourceTemplate("db://tables/{tableName}/schema", {
    list: async () => {
      const tables = await db.query("SELECT table_name FROM information_schema.tables");
      return tables.rows.map(row => ({
        uri: `db://tables/${row.table_name}/schema`,
        name: `${row.table_name} schema`,
      }));
    },
  }),
  "Schema for a database table",
  async (uri, { tableName }) => {
    const schema = await db.query(
      "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = $1",
      [tableName]
    );
    return {
      contents: [{
        uri: uri.href,
        mimeType: "application/json",
        text: JSON.stringify(schema.rows, null, 2),
      }],
    };
  }
);

Implementing Resources (Python)

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("project-server")

@mcp.resource("file:///project/config.json")
async def get_config() -> str:
    """Current project configuration."""
    with open("/project/config.json") as f:
        return f.read()

@mcp.resource("db://tables/{table_name}/schema")
async def get_table_schema(table_name: str) -> str:
    """Schema for a database table including column names and types."""
    rows = await db.fetch(
        "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = $1",
        table_name,
    )
    return json.dumps([dict(row) for row in rows], indent=2)

Subscriptions

Clients can subscribe to resource changes if the server declares subscribe capability:

// Client subscribes
{ "method": "resources/subscribe", "params": { "uri": "file:///project/config.json" } }

// Server notifies when the resource changes
{ "method": "notifications/resources/updated", "params": { "uri": "file:///project/config.json" } }

// Client re-reads the resource to get updated content
{ "method": "resources/read", "params": { "uri": "file:///project/config.json" } }

The server sends a notification when the data changes. It does NOT push the new content — the client must re-read the resource. This keeps the protocol simple and avoids sending large payloads unsolicited.

Choosing Between Resources and Tools

Use Resources WhenUse Tools When
Exposing data for contextPerforming actions
The user/client selects what to includeThe model decides when to invoke
Content is relatively stableOperation has side effects
Browsing/discovery is importantSpecific input parameters needed

Example: A database server might expose table schemas as resources (for context) and a query tool (for actions).

Anti-Patterns

  • Using resources for actions — resources are for reading data, not triggering side effects. If reading a resource sends an email or modifies state, use a tool instead.
  • Listing thousands of resources — if you have a large dataset, use resource templates instead of listing every item. List a curated subset and let templates handle the rest.
  • Returning enormous content — resources go into the AI's context window. A 10 MB log file will blow the context. Truncate, summarize, or paginate large content.
  • Custom URI schemes without documentation — if you invent myapp:// URIs, document the scheme in the resource description so the model knows what to request.
  • Ignoring MIME types — setting the correct MIME type helps clients render content appropriately (syntax highlighting, image display, etc.).

Best Practices

  • Use standard URI schemes where applicable (file://, https://). Use custom schemes for domain-specific resources (db://, config://).
  • Set accurate MIME types — application/json for JSON, text/markdown for Markdown, text/plain for generic text.
  • Keep resource content concise. Summarize large datasets rather than dumping everything.
  • Implement the list callback on resource templates so clients can discover available instances.
  • Use subscriptions for resources that change frequently (config files, live metrics) so the AI always has current data.
  • Include enough context in resource descriptions for the model to understand when each resource is relevant.

Install this skill directly: skilldb add mcp-server-skills

Get CLI access →

Related Skills

MCP Auth and Security

Securing MCP servers with authentication, authorization, and defensive practices. Covers OAuth 2.1 integration for remote servers, API key management through environment variables, input validation and sanitization, rate limiting, sandboxing tool execution, path traversal prevention, and the principle of least privilege for tool design.

Mcp Server327L

MCP Deployment

Deploying MCP servers across different environments and transports. Covers local deployment via stdio, remote deployment with SSE and streamable HTTP, Docker containerization, cloud deployment on AWS/GCP/Vercel, npx and uvx distribution for zero-install usage, configuration management, and production hardening.

Mcp Server353L

MCP Fundamentals

Core architecture of the Model Context Protocol (MCP) — the open protocol from Anthropic that connects AI assistants to external tools and data sources. Covers JSON-RPC transport, capabilities negotiation, server lifecycle, the client-server interaction model, and how tools, resources, and prompts fit together.

Mcp Server226L

MCP Patterns

Common architectural patterns for MCP servers — database servers, API wrappers, file system servers, multi-tool orchestration, caching strategies, error recovery, and composition patterns. Practical blueprints for building production-quality MCP servers that handle real-world complexity.

Mcp Server431L

MCP Prompts

Defining prompt templates in MCP servers that AI clients can discover and invoke. Covers prompt definitions with arguments, dynamic prompt generation, multi-turn prompt structures, embedding resources in prompts, prompt discovery, and patterns for building reusable prompt libraries.

Mcp Server287L

MCP Python Server

Building MCP servers in Python using the official mcp SDK and the FastMCP high-level pattern. Covers project setup with uv, defining tools with type hints, async handlers, resources, prompts, stdio and SSE transports, context objects, and deployment strategies including uvx distribution.

Mcp Server390L