TellWorldAI World Archive
Ask中文

Home›Practice›Practice

Practice

Resources and prompts in FastMCP

How to expose data with @mcp.resource, generate resources from URI templates, mask error details, and define reusable prompts with @mcp.prompt.

Who this is for and what you will learn

This article is for readers who can already run a FastMCP server and want clients to read data, or to request reusable prompt templates. By the end you should be able to expose data with @mcp.resource, generate resources from URI templates, define reusable prompts with @mcp.prompt, and mask error details when needed.

What resources and prompts are

Resources are data or files that an MCP client can read. Resource templates extend them, so a client can request a dynamically generated resource based on parameters in the URI[1]. Resources provide read-only access. When a client requests a resource URI, FastMCP finds the definition, runs the function if the resource is dynamic, and returns the content[1].

Prompts are reusable message templates that help LLMs generate structured, purposeful responses. FastMCP defines them mainly with the @mcp.prompt decorator[2]. When a client requests a prompt, FastMCP finds the definition, validates the parameters against the function signature, runs the function, and returns the generated messages to the model[2].

Define a resource with @mcp.resource

The most common approach is to decorate a Python function with @mcp.resource. The decorator requires the resource's unique URI[1]. The example below defines two resources, one returning a string and one returning JSON data[1]:

import json
from fastmcp import FastMCP

mcp = FastMCP(name="DataServer")

# Basic dynamic resource returning a string
@mcp.resource("resource://greeting")
def get_greeting() -> str:
    """Provides a simple greeting message."""
    return "Hello from FastMCP Resources!"

# Resource returning JSON data
@mcp.resource("data://config")
def get_config() -> str:
    """Provides application configuration as JSON."""
    return json.dumps({
        "theme": "dark",
        "version": "1.2.0",
        "features": ["tools", "resources"],
    })

A few points about this code[1]:

  • The first argument is the URI, which clients use to request the data, such as "resource://greeting".
  • The function is lazy. It runs only when a client requests its URI through resources/read.
  • By default, the resource name comes from the function name, and the description comes from the docstring.
  • The decorator also accepts uri, name, description, mime_type, tags and meta. For example, mime_type="application/json" sets an explicit MIME type.

Return values decide the content type

  • A str is sent as TextResourceContents, with text/plain as the default MIME type[1].
  • bytes are base64-encoded and sent as BlobResourceContents. Declare a suitable MIME type, such as image/png[1].
  • JSON-native values (dict, list, tuple, numbers, booleans and None) are serialized to JSON text. They keep the declared MIME type, which is text/plain unless you set another. To make clients parse the payload as JSON, set mime_type="application/json" explicitly[1].
  • For custom classes that are not JSON-native, return a ResourceResult, or a list of ResourceContent, so that serialization and MIME types are explicit[1].

Resource templates: parameters in the URI

A resource template uses the same @mcp.resource decorator. The URI contains {parameter_name} placeholders, and the function signature has matching arguments[1]. Each distinct set of parameters yields its own resource. If "user://profile/{name}" is registered, a client can request "user://profile/ford" without any separate registration for that profile[1].

The example below defines two templates. One has a {city} placeholder, and the other has two parameters and annotations[1]:

# Template URI includes {city} placeholder
@mcp.resource("weather://{city}/current")
def get_weather(city: str) -> str:
    """Provides weather information for a specific city."""
    return json.dumps({
        "city": city.capitalize(),
        "temperature": 22,
        "condition": "Sunny",
        "unit": "celsius"
    })

A few rules apply[1]:

  • Required function parameters, those without default values, must appear in the URI path template.
  • Resource templates do not accept *args, but they do accept **kwargs, because the URI template names the parameters.
  • FastMCP implements RFC 6570 URI templates, including simple expansion, wildcard path parameters and form-style query parameters[1].

Error handling for resources

A resource function can raise a standard Python exception, such as ValueError or FileNotFoundError, or a FastMCP ResourceError[1]. By default, exceptions and their details are logged and converted into an MCP error response that goes back to the client[1].

To hide internal details, set mask_error_details=True when you create the server, as in FastMCP(name="SecureServer", mask_error_details=True)[1]. Then only ResourceError messages include details, and other exceptions become a generic message[1]. Note that ResourceError contents are sent back to clients whatever the mask_error_details setting is. Its messages should therefore be safe to show to callers[1].

Define a prompt with @mcp.prompt

Decorate a function with @mcp.prompt to define a prompt. The function name becomes the prompt's identifier[2]. The examples below define two prompts. One returns a string, which becomes a user message. The other returns a conversation made of several messages[2]:

from fastmcp import FastMCP
from fastmcp.prompts import Message

mcp = FastMCP(name="PromptServer")

# Basic prompt returning a string (converted to user message automatically)
@mcp.prompt
def ask_about_topic(topic: str) -> str:
    """Generates a user message asking for an explanation of a topic."""
    return f"Can you please explain the concept of '{topic}'?"

# Prompt returning multiple messages
@mcp.prompt
def generate_code_request(language: str, task_description: str) -> list[Message]:
    """Generates a conversation for code generation."""
    return [
        Message(f"Write a {language} function that performs the following task: {task_description}"),
        Message("I'll help you write that function.", role="assistant"),
    ]

By default, the prompt name comes from the function name, and the description comes from the summary of the docstring. Parameter descriptions in the docstring fill in the description of each argument[2].

The MCP specification requires prompt arguments to be strings. FastMCP lets you use annotations such as list[int] and dict[str, str], converts incoming string arguments to those types, and adds JSON format descriptions to the arguments, so that people and models know how to fill them in[2].

Prompt return values

A prompt function returns one of three shapes[2]:

  • A str, sent as a single user message.
  • A list[Message | str], which is a conversation. Strings are converted to user messages.
  • A PromptResult, when you need full control over messages, description and metadata.

The roleplay example below returns two messages, a user message and an assistant message[2]:

from fastmcp.prompts import Message

@mcp.prompt
def roleplay_scenario(character: str, situation: str) -> list[Message]:
    """Sets up a roleplaying scenario with initial messages."""
    return [
        Message(f"Let's roleplay. You are {character}. The situation is: {situation}"),
        Message("Okay, I understand. I am ready. What happens next?", role="assistant")
    ]

Parameters without default values are required. Prompts do not accept *args or **kwargs either[2].

Limits

  • Resource templates do not accept *args. Prompts accept neither *args nor **kwargs[1][2].
  • The MCP specification allows only string arguments, so clients must fill complex types in the JSON format that FastMCP describes[2].
  • With mask_error_details on, only ResourceError messages keep their details. Keep the messages you expose to callers within safe bounds[1].

Next steps

For parameter options, component visibility, async resources and context access, read the full resources and prompts pages of the FastMCP documentation[1][2].

Adapted from the Resources and Prompts pages of the FastMCP official documentation[1][2], released under the Apache-2.0 License.

Sources

  1. 1
    FastMCP Resources & TemplatesFastMCP docs (Apache-2.0)
  2. 2
    FastMCP PromptsFastMCP docs (Apache-2.0)

Cite this page: Resources and prompts in FastMCP. TellWorld, https://www.tellworld.net/practice/practice-fastmcp-resources-prompts. Updated 2026-11-14

Related news

View all