Back to Learn
intermediate20 min

MCP Resources & Prompts

Learn how to expose data with resources and create reusable prompt templates.

Beyond tools, MCP servers can expose two other powerful capabilities:

Resources

Expose data sources that AI can read from (files, databases, APIs)

Prompts

Create reusable prompt templates with parameters

What are Resources?

Resources allow MCP servers to expose data sources to AI. Think of them as read-only endpoints that provide content like files, database records, API responses, or any other data.

Resource Components
URI: Unique identifier (e.g., file:///config.json, user://123)
MIME Type: Content type (text/plain, application/json, etc.)
Content: The actual data (text, JSON, binary, etc.)

Basic Resource Example

Here's a simple resource that exposes configuration data:

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

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

// Define a simple text resource
server.resource(
  "config://app",                          // Resource URI
  "Application configuration",             // Description
  "text/plain",                           // MIME type
  async () => {                           // Handler function
    const config = {
      app: "MyApp",
      version: "1.0.0",
      environment: "production"
    };

    return {
      contents: [{
        uri: "config://app",
        mimeType: "text/plain",
        text: JSON.stringify(config, null, 2)
      }]
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);
Resources use URI schemes (like config://) to organize data. The scheme can be anything meaningful for your use case!

Dynamic Resources with Parameters

Resources can use URI templates to handle dynamic data. Here's an example that retrieves user profiles by ID:

user-server.js
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

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

// Resource with dynamic URI parameters
server.resource(
  "user://{userId}",                      // URI template
  "User profile by ID",                   // Description
  "application/json",                     // MIME type
  async (uri) => {                        // Handler receives the URI
    // Extract userId from the URI
    const userId = uri.split("://")[1];

    // In a real app, fetch from database
    const users: Record<string, any> = {
      "1": { id: 1, name: "Alice", role: "admin" },
      "2": { id: 2, name: "Bob", role: "user" },
      "3": { id: 3, name: "Charlie", role: "user" }
    };

    const user = users[userId];

    if (!user) {
      throw new Error(`User ${userId} not found`);
    }

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

const transport = new StdioServerTransport();
await server.connect(transport);
How it works: When AI requests user://1, the handler extracts "1" from the URI and returns that user's data. The same resource definition handles all user IDs!
Common Resource Use Cases
Files: file:///path/to/file.txt
Database: db://users/123
API Data: api://weather/london
Config: config://app/settings

Putting It All Together

Resources, prompts, and tools work together to create powerful MCP servers. Here's an example documentation server that combines all three:

docs-server.js
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

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

// Resource: Expose documentation files
server.resource(
  "docs://{category}/{page}",
  "Documentation pages",
  "text/markdown",
  async (uri) => {
    const [category, page] = uri.split("://")[1].split("/");

    // In real app, read from file system or database
    const docs: Record<string, any> = {
      "getting-started/installation": "# Installation\n\nRun: npm install...",
      "getting-started/quickstart": "# Quick Start\n\nCreate your first...",
      "api/authentication": "# Authentication\n\nUse API keys to..."
    };

    const content = docs[`${category}/${page}`];

    if (!content) {
      throw new Error(`Doc not found: ${category}/${page}`);
    }

    return {
      contents: [{
        uri,
        mimeType: "text/markdown",
        text: content
      }]
    };
  }
);

// Prompt: Help users search documentation
server.prompt(
  "find-docs",
  "Search documentation by topic",
  {
    topic: z.string().describe("Topic to search for")
  },
  async ({ topic }) => {
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Find documentation about: ${topic}\n\nSearch through available docs:// resources and provide relevant links and summaries.`
          }
        }
      ]
    };
  }
);

// Tool: List all available docs
server.tool(
  "list-docs",
  "List all documentation pages",
  {},
  async () => {
    const docsList = [
      "docs://getting-started/installation",
      "docs://getting-started/quickstart",
      "docs://api/authentication"
    ];

    return {
      content: [{
        type: "text",
        text: "Available documentation:\n" + docsList.join("\n")
      }]
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);
Resource
Exposes documentation files via docs:// URIs
Prompt
Helps users search and find relevant documentation
Tool
Lists all available documentation pages
Try It in the Playground
Experiment with resources and prompts without setting up a local environment
No local setup required! You can test all the code examples above directly in our interactive playground. Just copy the code, paste it in the playground, and try it out.
Resources & Prompts Playground

Try resources, prompts, and tools together

Loading...

Key Takeaways

Resources

  • • Expose data sources to AI
  • • Use URI schemes for organization
  • • Support dynamic parameters in URIs
  • • Specify appropriate MIME types

Prompts

  • • Create reusable prompt templates
  • • Accept parameters with Zod schemas
  • • Ensure consistency across uses
  • • Combine with resources and tools

Ready for More?

You now know how to create tools, resources, and prompts. Try building a complete MCP server in the challenges!