TellWorldAI 世界档案
问档案English

首页›实践›实践

实践

FastMCP 的 resources 和 prompts:资源、模板与提示词

用 @mcp.resource 暴露数据、用 URI 模板动态生成资源,用 @mcp.prompt 定义可复用的提示词,并屏蔽内部错误细节。

这篇适合谁,读完能做到什么

适合已经能跑起 FastMCP 服务器、想让客户端读到数据或直接调用提示词模板的读者。读完你应该能用 @mcp.resource 暴露一份数据,用 URI 模板按参数动态生成资源,用 @mcp.prompt 定义可复用的提示词,并知道错误信息如何屏蔽。

resources 和 prompts 各是什么

resources 是客户端可以读取的数据或文件。资源模板则让客户端通过 URI 里的参数,请求动态生成的资源[1]。resources 提供的是只读访问:客户端请求某个资源 URI 时,FastMCP 找到对应定义,如果是动态资源就执行函数,再把内容返回给客户端[1]。

prompts 是可复用的消息模板,帮助大模型生成结构清楚、目的明确的回答。FastMCP 主要用 @mcp.prompt 装饰器定义它们[2]。客户端请求提示词时,FastMCP 找到定义、按函数签名校验参数、执行函数,再把生成的消息返回给模型[2]。

用 @mcp.resource 定义资源

最常见的做法是给一个 Python 函数加上 @mcp.resource 装饰器。装饰器必须给出资源的唯一 URI[1]。下面的例子定义了两个资源,一个返回字符串,一个返回 JSON 数据[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"],
    })

这里有几点需要注意[1]:

  • 第一个参数是 URI,客户端用它来请求数据,例如 "resource://greeting"。
  • 函数是惰性执行的:只有客户端通过 resources/read 请求该 URI 时,函数才会运行。
  • 默认情况下,资源名取自函数名,描述取自 docstring。
  • 装饰器还可以设置 uri、name、description、mime_type、tags 和 meta。例如 mime_type="application/json" 可以显式指定 MIME 类型。

返回值决定内容类型

  • 返回 str:以 TextResourceContents 发送,默认 MIME 类型是 text/plain[1]。
  • 返回 bytes:做 base64 编码后以 BlobResourceContents 发送,应当指定合适的 MIME 类型,如 image/png[1]。
  • 返回 JSON 原生值(dict、list、tuple、数字、布尔值和 None):会序列化成 JSON 文本,MIME 类型保持资源声明的值。默认是 text/plain,所以想让客户端按 JSON 解析,要显式写 mime_type="application/json"[1]。
  • 非 JSON 原生的自定义类:返回 ResourceResult,或返回 ResourceContent 列表,让序列化和 MIME 类型都明确[1]。

资源模板:URI 里带参数

资源模板同样用 @mcp.resource,只是 URI 里要写 {参数名} 占位符,函数签名里也要有同名参数[1]。这样客户端每请求一组不同的参数,就得到一个新的资源。比如注册了 "user://profile/{name}" 之后,客户端请求 "user://profile/ford",不需要为每个用户单独注册[1]。

下面的例子定义了两个模板,一个带 {city} 占位符,另一个带两个参数并附加了注解[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"
    })

几条规则要记住[1]:

  • 没有默认值的函数参数必须出现在 URI 路径模板中。
  • 资源模板不支持 *args,但支持 **kwargs,因为 URI 模板定义了参数名,会以关键字参数的形式传入。
  • FastMCP 按 RFC 6570 实现 URI 模板,包括简单展开、通配符路径参数和表单式查询参数[1]。

资源的错误处理

资源函数可以抛出普通的 Python 异常,例如 ValueError、FileNotFoundError,也可以抛出 FastMCP 的 ResourceError[1]。默认情况下,所有异常及其细节都会被记录,并转换成 MCP 错误响应发回客户端,让模型知道出了什么问题[1]。

如果出于安全考虑要隐藏内部细节,可以在创建服务器时加上 mask_error_details=True,例如 FastMCP(name="SecureServer", mask_error_details=True)[1]。开启后,只有 ResourceError 的消息会带上细节,其他异常都会变成通用消息[1]。ResourceError 的内容无论 mask_error_details 如何设置,都会发回客户端,所以它的消息也必须能安全地公开[1]。

用 @mcp.prompt 定义提示词

给函数加上 @mcp.prompt 装饰器即可定义提示词。函数名就是提示词的标识名[2]。下面的例子定义了两个提示词:一个返回字符串,会自动变成用户消息;另一个返回多条消息组成的对话[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"),
    ]

默认情况下,提示词的名字取自函数名,描述取自 docstring 的摘要部分;docstring 中的参数说明会填入每个参数的描述[2]。

MCP 规范要求提示词的参数都是字符串。FastMCP 允许你使用 list[int]、dict[str, str] 这样的类型标注,会自动把客户端传来的字符串转换成对应类型,并在参数描述里补充 JSON 格式的说明,让人和模型都知道该怎么填写[2]。

提示词的返回值

提示词函数的返回值可以是三种之一[2]:

  • str:作为一条用户消息发送。
  • list[Message | str]:一段对话。字符串会自动转换成用户消息。
  • PromptResult:需要完全控制消息、描述和元数据时使用。

下面是一个角色扮演的例子,返回两条消息,一条用户消息和一条助手消息[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")
    ]

签名中没有默认值的参数是必填的。提示词同样不支持 *args 和 **kwargs[2]。

限制

  • 资源模板不支持 *args,提示词也不支持 *args 和 **kwargs[1][2]。
  • MCP 规范只允许字符串参数,复杂类型需要客户端按 FastMCP 生成的 JSON 格式填写[2]。
  • 开启 mask_error_details 后,只有 ResourceError 的消息会保留细节,因此要把对外可见的消息限定在安全范围内[1]。

下一步

想看更完整的参数、组件可见性、异步资源和上下文访问,可以接着读 FastMCP 的资源和提示词两页文档[1][2]。

本文改编自 FastMCP 官方文档中的资源(Resources)与提示词(Prompts)页面[1][2],原文以 Apache-2.0 许可证发布。

来源

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

引用本页: FastMCP 的 resources 和 prompts:资源、模板与提示词. TellWorld, https://www.tellworld.net/zh/practice/practice-fastmcp-resources-prompts. 更新于 2026-11-14

相关动态