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)


相关推荐
米小虾5 小时前
CLI + MCP + Skill:2026年AI Agent开发的三大范式
agent·mcp
宋哥转AI17 小时前
MCP 第一天我没写@Tool,先在一个大仓库里划这三层
java·agent·mcp
填满你的记忆17 小时前
MCP协议是什么?为什么它被称为AI时代的“USB接口”?
java·人工智能·agent·mcp
老H科研技术2 天前
第 04 篇:MCP中SDK 对比与选型 —— 选对工具,事半功倍
人工智能·mcp
木雷坞2 天前
Playwright MCP Docker 部署:mcr 镜像、浏览器工具和权限配置
运维·docker·容器·mcp
winlife_2 天前
全程用 AI 做一款商业级手游 · EP10 道具系统:让三个按钮真正改变棋盘
windows·算法·unity·ai编程·游戏开发·mcp·玩法系统
Mr_Morning2 天前
MCP 通信
mcp
MicrosoftReactor2 天前
技术速递|以 Token 经济学驱动的架构:混合模型、AI Runway、AKS Kata MicroVM 与 MCP
人工智能·ai·架构·copilot·mcp
不剪发的Tony老师2 天前
DBHub:一款免费开源的数据库MCP服务器
数据库·mcp
特长腿特长2 天前
Cherry Studio 通过 MCP 接口操作 Obsidian 完全指南
ai·obsidian·mcp