Building MCP Servers: Part 3 — Adding Prompts

转载


背景介绍:

  • 这是一个四部分教程的第三部分,讲的是如何在 MCP(Model Context Protocol)服务器中添加 Prompt(提示词)功能
  • 前两部分已经完成了基本的服务器搭建、资源(resources)和资源模板(resource templates)的管理。
  • 本部分重点是:引入 Prompt,优化代码组织

什么是 MCP Prompts?

  • Prompt 是一种标准化的结构化模板,用来统一 LLM(大模型)交互的方式。
  • 与 resource(提供数据)或 tool(执行动作)不同,prompt 是可重复使用的消息序列模板,可以带参数定制。
  • 类比餐厅菜单:Prompt 就像菜单上的菜品,你可以点菜并定制做法。

为什么要使用 Prompts?

  • 标准化可重复使用:提高与大模型交互的一致性和效率。

  • 例子:


代码审查 Prompts

  • 名称code-review

  • 模板内容

    css 复制代码
    Please review the following {{language}} code focusing on {{focusAreas}} for the following block of code:
    ```{{language}}
    {{codeBlock}}
  • 示例使用

    用户输入:

    less 复制代码
    Please review the following Python code focusing on security and performance:
    ```Python
    ... code

数据分析 Prompts

  • 名称analyze-sales-data

  • 模板内容

    csharp 复制代码
    Analyze {{timeframe}} sales data focusing on {{metrics}}
  • 示例使用

    用户输入:

    csharp 复制代码
    Analyze Q1 sales data focusing on revenue and growth

内容生成 Prompts

  • 名称generate-email

  • 模板内容

    arduino 复制代码
    Generate a {{tone}} {{type}} email for {{context}}
  • 示例使用

    用户输入:

    css 复制代码
    Generate a formal support email for a refund request to Bob's Barbecue LLC.

明白了!你的要求是:

  • 整体内容翻译成中文 ✅
  • 代码部分、Prompt内容、示例内容原样保留英文,不要翻译 ✅
  • 保持清晰、有条理的结构 ✅

下面是根据你的要求整理和翻译后的版本:


Code Organization

在 Part 2 中,我们已经把 index.ts 中的 handler 逻辑抽离到了 handlers.ts 文件中。

但是随着功能增加,handlers.ts 会变得过大,因此需要进一步模块化:


src/resources.ts

arduino 复制代码
export const resources = [
  {
    uri: "hello://world",
    name: "Hello World Message",
    description: "A simple greeting message",
    mimeType: "text/plain",
  },
];

export const resourceHandlers = {
  "hello://world": () => ({
    contents: [
      {
        uri: "hello://world",
        text: "Hello, World! This is my first MCP resource.",
      },
    ],
  }),
};

src/resource-templates.ts

ini 复制代码
export const resourceTemplates = [
  {
    uriTemplate: "greetings://{name}",
    name: "Personal Greeting",
    description: "A personalized greeting message",
    mimeType: "text/plain",
  },
];

const greetingExp = /^greetings://(.+)$/;
const greetingMatchHandler =
  (uri: string, matchText: RegExpMatchArray) => () => {
    const name = decodeURIComponent(matchText[1]);
    return {
      contents: [
        {
          uri,
          text: `Hello, ${name}! Welcome to MCP.`,
        },
      ],
    };
  };

export const getResourceTemplate = (uri: string) => {
  const greetingMatch = uri.match(greetingExp);
  if (greetingMatch) return greetingMatchHandler(uri, greetingMatch);
};

更新 handlers 文件:src/handlers.ts

typescript 复制代码
import {
  ListResourcesRequestSchema,
  ListResourceTemplatesRequestSchema,
  ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { type Server } from "@modelcontextprotocol/sdk/server/index.js";
import { resourceHandlers, resources } from "./resources.js";
import {
  getResourceTemplate,
  resourceTemplates,
} from "./resource-templates.js";

export const setupHandlers = (server: Server): void => {
  // 列出所有可用资源
  server.setRequestHandler(
    ListResourcesRequestSchema,
    () => ({ resources }),
  );
  // 列出所有资源模板
  server.setRequestHandler(ListResourceTemplatesRequestSchema, () => ({
    resourceTemplates,
  }));
  // 返回特定资源内容
  server.setRequestHandler(ReadResourceRequestSchema, (request) => {
    const { uri } = request.params ?? {};
    const resourceHandler =
      resourceHandlers[uri as keyof typeof resourceHandlers];
    if (resourceHandler) return resourceHandler();
    const resourceTemplateHandler = getResourceTemplate(uri);
    if (resourceTemplateHandler) return resourceTemplateHandler();
    throw new Error("Resource not found");
  });
};

添加 Prompts(Adding Prompts)

新增一个管理 prompts 的模块:


src/prompts.ts

typescript 复制代码
export const prompts = {
  "create-greeting": {
    name: "create-greeting",
    description: "Generate a customized greeting message",
    arguments: [
      { 
        name: "name",
        description: "Name of the person to greet",
        required: true,
      },
      {
        name: "style",
        description: "The style of greeting, such a formal, excited, or casual. If not specified casual will be used"
      }
    ],
  },
};

export const promptHandlers = {
  "create-greeting": ({ name, style = "casual" }: { name: string, style?: string }) => {
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Please generate a greeting in ${style} style to ${name}.`,
          },
        },
      ],
    };
  },
};

更新 handlers 文件,支持 prompts

继续修改 src/handlers.ts,引入 prompts 相关逻辑:

typescript 复制代码
import {
  GetPromptRequestSchema,
  ListPromptsRequestSchema,
  // ... 其他导入
} from "@modelcontextprotocol/sdk/types.js";
// ... 其他导入
import { promptHandlers, prompts } from "./prompts.js";

export const setupHandlers = (server: Server): void => {
  // ... 其他 resource handler
  
  // Prompts
  server.setRequestHandler(ListPromptsRequestSchema, () => ({
    prompts: Object.values(prompts),
  }));
  server.setRequestHandler(GetPromptRequestSchema, (request) => {
    const { name, arguments: args } = request.params;
    const promptHandler = promptHandlers[name as keyof typeof promptHandlers];
    if (promptHandler) return promptHandler(args as { name: string, style?: string });
    throw new Error("Prompt not found");
  });
};

更新服务器初始化:src/index.ts

javascript 复制代码
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { setupHandlers } from "./handlers.js";

const server = new Server(
  {
    name: "hello-mcp",
    version: "1.0.0",
  },
  {
    capabilities: {
      prompts: {}, // <-- 新增 prompts
      resources: {},
    },
  },
);

setupHandlers(server);

// 其他代码...

理解代码结构(Understanding the Code)

模块组织(Module Organization)

  • 资源(resources)、资源模板(templates)、prompts 分模块存放。
  • handlers.ts 只负责路由分发,保持简洁。

Prompt 结构(Prompt Structure)

  • 每个 prompt 包含:名字(name)、描述(description)、参数(arguments)。
  • 参数描述了 prompt 所需输入。

消息序列(Message Sequences)

  • prompt 生成消息数组(messages)。
  • 消息有角色(role: userassistant)。
  • 内容可以是单步请求或多步流程(多步流程目前支持有限)。

测试方法(Testing)

使用 MCP Inspector 测试:

  • 启动:

    bash 复制代码
    npx @modelcontextprotocol/inspector node build/index.js
  • 测试 Prompts:

    • 点击 Prompts 标签页

    • 找到 create-greeting

    • 尝试不同参数:

      json 复制代码
      {
        "name": "Alice",
        "style": "excited"
      }
    • 返回示例:

      json 复制代码
      {
        "messages": [
          {
            "role": "user",
            "content": {
              "type": "text",
              "text": "Please generate a greeting in excited style to Alice."
            }
          }
        ]
      }

使用 Claude Desktop 测试:

  1. 打开 Claude Desktop

  2. 点击聊天输入框右下角的插件图标(Attach from MCP)

  3. 弹出框里选择 "create-greeting"

  4. 填写 name(如 John),提交

  5. 会生成一个附加的 prompt:"Please generate a casual greeting to John."

  6. 提交后,Claude 回复类似:

    sql 复制代码
    Hi John! How are you doing today?

进阶:更改风格

  • 重新选择 "create-greeting" prompt

  • 填写:

    makefile 复制代码
    name: Alice
    style: formal
  • Claude 返回:

    css 复制代码
    Dear Alice,
    
    I hope this message finds you well. I am writing to extend my warmest greetings.
    
    Best regards,
    Claude

下一步(What's Next)

在 Part 4 中,将:

  • 了解 MCP 中的 Tools(工具)及其与 Prompts 的区别
  • 给服务器添加 Tool 支持
  • 让服务器可以提供更动态的功能
  • 完成包含全部核心功能的 MCP 服务器

参考资料(Sources)


相关推荐
MobotStone10 小时前
MCP还是AI智能体?如何为你的AI应用选择最佳"大脑"架构
mcp
shelgi12 小时前
Cursor结合MCP实现自动编写项目文档
人工智能·mcp
小白跃升坊13 小时前
干货分享|智能问数方案及步骤详解
ai·大语言模型·it运维·mcp·max kb
yaocheng的ai分身13 小时前
MCP的Resources 和 Prompts
mcp
一只韩非子15 小时前
什么是MCP?为什么引入MCP?(通俗易懂版)
人工智能·aigc·mcp
MCPFlow16 小时前
Cursor+高德MCP制定五一出游攻略
mcp
叫我阿杰好了16 小时前
Trae中 使用MCP 案例
mcp·trae
Yan-英杰17 小时前
百度搜索AI开放计划:让应用连接精准流量的秘诀
ai·mcp·百度搜索开放平台·百度ai开放计划·mcpserver·create2025
码云之上17 小时前
聊聊MCP Client及其实践
前端·架构·mcp