这篇适合谁,读完能做到什么
适合已经能跑起 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 许可证发布。
来源
- 1FastMCP Resources & TemplatesFastMCP docs (Apache-2.0)
- 2FastMCP PromptsFastMCP docs (Apache-2.0)
引用本页: FastMCP 的 resources 和 prompts:资源、模板与提示词. TellWorld, https://www.tellworld.net/zh/practice/practice-fastmcp-resources-prompts. 更新于 2026-11-14