Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/punkpeye/fastmcp/llms.txt

Use this file to discover all available pages before exploring further.

What are Resources?

Resources in MCP represent any kind of data that an MCP server wants to make available to clients. This can include:
  • File contents
  • Screenshots and images
  • Log files
  • Database records
  • API responses
  • And more
Each resource is identified by a unique URI and can contain either text or binary data.

Basic Usage

Add a resource to your server using the addResource method:
import { FastMCP } from "fastmcp";

const server = new FastMCP({
  name: "My Server",
  version: "1.0.0",
});

server.addResource({
  uri: "file:///logs/app.log",
  name: "Application Logs",
  mimeType: "text/plain",
  async load() {
    return {
      text: await readLogFile(),
    };
  },
});

Resource Properties

URI

The unique identifier for the resource. Use standard URI schemes:
server.addResource({
  uri: "file:///logs/app.log",     // File system
  // uri: "https://api.example.com/data", // HTTP
  // uri: "user://profile/123",    // Custom scheme
  name: "Application Logs",
  async load() {
    return { text: "log content" };
  },
});

MIME Type

Optional MIME type for the resource:
server.addResource({
  uri: "data://users.json",
  name: "User Data",
  mimeType: "application/json",
  async load() {
    return {
      text: JSON.stringify(users),
    };
  },
});

Return Types

Text Content

Return text data using the text property:
server.addResource({
  uri: "config://app.json",
  name: "App Configuration",
  mimeType: "application/json",
  async load() {
    return {
      text: JSON.stringify({
        setting1: "value1",
        setting2: "value2",
      }),
    };
  },
});

Binary Content

Return binary data using the blob property (base64-encoded):
server.addResource({
  uri: "file:///images/logo.png",
  name: "Company Logo",
  mimeType: "image/png",
  async load() {
    const buffer = await readFile("./logo.png");
    return {
      blob: buffer.toString("base64"),
    };
  },
});

Multiple Resources

The load function can return an array of resources:
server.addResource({
  uri: "dir:///logs",
  name: "All Logs",
  description: "Directory of log files",
  async load() {
    return [
      {
        uri: "file:///logs/app.log",
        text: "App log content",
      },
      {
        uri: "file:///logs/error.log",
        text: "Error log content",
      },
    ];
  },
});
Returning multiple resources is useful for directory listings or collections of related data.

Resource Templates

Resource templates allow you to define dynamic resources with URI parameters:
server.addResourceTemplate({
  uriTemplate: "file:///logs/{name}.log",
  name: "Application Logs",
  mimeType: "text/plain",
  arguments: [
    {
      name: "name",
      description: "Name of the log file",
      required: true,
    },
  ],
  async load({ name }) {
    return {
      text: `Log content for ${name}`,
    };
  },
});

URI Templates

Use URI templates with placeholders:
server.addResourceTemplate({
  uriTemplate: "user://{userId}/profile",
  name: "User Profile",
  arguments: [
    {
      name: "userId",
      description: "The user's ID",
      required: true,
    },
  ],
  async load({ userId }) {
    const user = await fetchUser(userId);
    return {
      text: JSON.stringify(user),
    };
  },
});

Multiple Arguments

Templates can have multiple arguments:
server.addResourceTemplate({
  uriTemplate: "docs://project/{section}/{page}",
  name: "Project Documentation",
  mimeType: "text/markdown",
  arguments: [
    {
      name: "section",
      description: "Documentation section",
      required: true,
    },
    {
      name: "page",
      description: "Page name",
      required: true,
    },
  ],
  async load({ section, page }) {
    return {
      text: `# ${section}/${page}\n\nContent here...`,
    };
  },
});

Optional Arguments

Mark arguments as optional:
server.addResourceTemplate({
  uriTemplate: "api://users/{userId}",
  name: "User Data",
  arguments: [
    {
      name: "userId",
      description: "User ID to fetch",
      required: false, // Optional argument
    },
  ],
  async load({ userId }) {
    if (userId) {
      return { text: JSON.stringify(await fetchUser(userId)) };
    }
    return { text: JSON.stringify(await fetchAllUsers()) };
  },
});

Argument Auto-completion

Provide auto-completion for resource template arguments:
server.addResourceTemplate({
  uriTemplate: "file:///logs/{name}.log",
  name: "Application Logs",
  arguments: [
    {
      name: "name",
      description: "Name of the log",
      required: true,
      complete: async (value) => {
        // Filter log files based on input
        const logs = await listLogFiles();
        const filtered = logs.filter(log => 
          log.startsWith(value)
        );
        
        return {
          values: filtered,
        };
      },
    },
  ],
  async load({ name }) {
    return {
      text: `Log content for ${name}`,
    };
  },
});

Completion Response

The complete function returns a completion object:
type Completion = {
  values: string[];        // Array of completion values (max 100)
  total?: number;          // Total number of available completions
  hasMore?: boolean;       // Whether more completions exist
};
Example with metadata:
complete: async (value) => {
  const allOptions = await getAllOptions();
  const filtered = allOptions.filter(opt => 
    opt.startsWith(value)
  );
  
  return {
    values: filtered.slice(0, 100),
    total: filtered.length,
    hasMore: filtered.length > 100,
  };
}

Embedded Resources

The embedded() method simplifies including resources in tool responses:

Basic Example

server.addResource({
  uri: "system://status",
  name: "System Status",
  mimeType: "text/plain",
  async load() {
    return {
      text: "System operational",
    };
  },
});

server.addTool({
  name: "get_system_status",
  description: "Get current system status",
  execute: async () => {
    return {
      content: [
        {
          type: "resource",
          resource: await server.embedded("system://status"),
        },
      ],
    };
  },
});

With Resource Templates

server.addResourceTemplate({
  uriTemplate: "docs://project/{section}",
  name: "Project Documentation",
  mimeType: "text/markdown",
  arguments: [
    {
      name: "section",
      required: true,
    },
  ],
  async load(args) {
    const docs = {
      "getting-started": "# Getting Started\n\nWelcome!",
      "api-reference": "# API Reference\n\nAuth required.",
    };
    return {
      text: docs[args.section] || "Not found",
    };
  },
});

server.addTool({
  name: "get_documentation",
  description: "Retrieve project documentation",
  parameters: z.object({
    section: z.enum(["getting-started", "api-reference"]),
  }),
  execute: async (args) => {
    return {
      content: [
        {
          type: "resource",
          resource: await server.embedded(`docs://project/${args.section}`),
        },
      ],
    };
  },
});

Authentication Context

Resources can access authentication context:
server.addResource({
  uri: "session://current-user",
  name: "Current User Information",
  mimeType: "application/json",
  load: async (auth) => {
    if (!auth) {
      return {
        text: JSON.stringify({ authenticated: false }),
      };
    }
    
    return {
      text: JSON.stringify({
        authenticated: true,
        user: {
          id: auth.userId,
          username: auth.username,
          role: auth.role,
        },
      }),
    };
  },
});

Complete Example

Here’s a complete example combining multiple features:
import { FastMCP } from "fastmcp";
import { z } from "zod";

const server = new FastMCP({
  name: "Documentation Server",
  version: "1.0.0",
});

// Static resource
server.addResource({
  uri: "docs://readme",
  name: "README",
  mimeType: "text/markdown",
  description: "Project README file",
  async load() {
    return {
      text: "# My Project\n\nWelcome to the project!",
    };
  },
});

// Resource template with auto-completion
server.addResourceTemplate({
  uriTemplate: "docs://api/{endpoint}",
  name: "API Documentation",
  mimeType: "text/markdown",
  arguments: [
    {
      name: "endpoint",
      description: "API endpoint to document",
      required: true,
      complete: async (value) => {
        const endpoints = ["users", "posts", "comments"];
        return {
          values: endpoints.filter(e => e.startsWith(value)),
        };
      },
    },
  ],
  async load({ endpoint }) {
    const docs = {
      users: "# Users API\n\nManage users...",
      posts: "# Posts API\n\nManage posts...",
      comments: "# Comments API\n\nManage comments...",
    };
    
    return {
      text: docs[endpoint] || "Endpoint not found",
    };
  },
});

// Tool using embedded resources
server.addTool({
  name: "get_docs",
  description: "Get API documentation",
  parameters: z.object({
    endpoint: z.string(),
  }),
  execute: async (args) => {
    return {
      content: [
        {
          type: "resource",
          resource: await server.embedded(`docs://api/${args.endpoint}`),
        },
      ],
    };
  },
});

API Reference

Resource Type

type Resource<T> = {
  uri: string;
  name: string;
  description?: string;
  mimeType?: string;
  load: (auth?: T) => Promise<ResourceResult | ResourceResult[]>;
};

ResourceTemplate Type

type ResourceTemplate<T, Arguments> = {
  uriTemplate: string;
  name: string;
  description?: string;
  mimeType?: string;
  arguments: ResourceTemplateArgument[];
  load: (args: Args, auth?: T) => Promise<ResourceResult | ResourceResult[]>;
  complete?: (name: string, value: string, auth?: T) => Promise<Completion>;
};

ResourceResult Type

type ResourceResult =
  | { text: string; mimeType?: string; uri?: string }
  | { blob: string; mimeType?: string; uri?: string };