跳到主要内容

Tools / Resources / Prompts

问题

MCP 的三种核心原语(Tools、Resources、Prompts)分别是什么?如何定义?

答案

一、三种原语对比

原语控制方用途是否有副作用类比
Tools模型调用(LLM 决策)执行操作可能有POST API
Resources用户/应用选择读取数据无(只读)GET API
Prompts用户触发交互模板API 文档模板

二、Tools(工具)

工具是模型可以调用的操作,由 LLM 根据上下文自主决策是否调用:

// Server 端定义工具
server.setRequestHandler("tools/list", async () => ({
tools: [
{
name: "query_database",
description: "执行只读 SQL 查询",
inputSchema: {
type: "object",
properties: {
sql: {
type: "string",
description: "SELECT 查询语句"
},
database: {
type: "string",
enum: ["users", "orders", "products"]
}
},
required: ["sql"]
}
}
]
}));

// 工具调用处理
server.setRequestHandler("tools/call", async (request) => {
const { name, arguments: args } = request.params;

if (name === "query_database") {
const result = await db.query(args.sql);
return {
content: [
{ type: "text", text: JSON.stringify(result, null, 2) }
]
};
}
});
工具设计原则
  • 命名清晰query_database 优于 do_stuff
  • 描述精确:让 LLM 理解何时该调用此工具
  • inputSchema 完整:类型、枚举、必填字段都要定义
  • 错误处理:返回 isError: true 而非抛异常

三、Resources(资源)

资源是 Server 暴露的只读数据,由用户或应用决定加载哪些:

// 列出可用资源
server.setRequestHandler("resources/list", async () => ({
resources: [
{
uri: "file:///project/README.md",
name: "项目说明",
mimeType: "text/markdown"
},
{
uri: "db://users/schema",
name: "用户表结构",
mimeType: "application/json"
}
]
}));

// 读取资源内容
server.setRequestHandler("resources/read", async (request) => {
const { uri } = request.params;

if (uri === "file:///project/README.md") {
const content = await fs.readFile("/project/README.md", "utf-8");
return {
contents: [
{
uri,
mimeType: "text/markdown",
text: content
}
]
};
}
});

资源模板支持动态 URI:

{
uriTemplate: "db://{table}/schema",
name: "数据表结构",
description: "获取指定表的 Schema"
}

资源订阅

Client 可以订阅资源变更通知:

// Client 订阅
client.send("resources/subscribe", { uri: "file:///config.json" });

// Server 发送变更通知
server.notify("notifications/resources/updated", {
uri: "file:///config.json"
});

四、Prompts(提示模板)

Prompts 是预定义的交互模板,由用户主动选择:

// 列出 Prompt 模板
server.setRequestHandler("prompts/list", async () => ({
prompts: [
{
name: "code_review",
description: "代码审查模板",
arguments: [
{
name: "language",
description: "编程语言",
required: true
},
{
name: "code",
description: "待审查的代码",
required: true
}
]
}
]
}));

// 获取 Prompt 内容
server.setRequestHandler("prompts/get", async (request) => {
const { name, arguments: args } = request.params;

if (name === "code_review") {
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `请审查以下 ${args.language} 代码:\n\n${args.code}\n\n
请从以下维度评审:
1. 代码质量与可读性
2. 潜在 Bug
3. 性能问题
4. 安全漏洞`
}
}
]
};
}
});

五、三者协作示例


常见面试问题

Q1: Tools 和 Resources 有什么本质区别?

答案

  • Tools模型决策调用,可能有副作用(修改数据、发送请求)
  • Resources用户/应用选择加载,是只读的数据
  • 类比:Tools 像 POST/PUT,Resources 像 GET

Q2: 为什么需要 Prompts?直接写 prompt 不行吗?

答案

  • Prompts 提供可复用的交互模板,避免每次手写
  • 模板支持参数化,可动态填充
  • 可以嵌入 Resources 引用,自动加载相关数据
  • 让非技术用户也能使用复杂的 AI 工作流

相关链接