当前位置: 首页 > article >正文

构建 MCP 服务器:第 2 部分 — 使用资源模板扩展资源

该图像是使用 AI 图像创建程序创建的。

这个故事是在多位人工智能助手的帮助下写成的。

这是构建MCP 服务器教程(共四部分)的第二部分。在第一部分中,我们使用基本资源创建了第一个 MCP 服务器。现在,我们将使用资源模板扩展服务器的功能。本文中的代码假设您从上次中断的地方继续学习。

什么是资源模板?

资源模板允许您使用 URI 模式定义动态资源。与具有固定 URI 的静态资源不同,模板允许您创建可根据参数生成 URI 和内容的资源。

可以将它们想象成 Web 框架中的 URL 模式,其中资源更具动态性,通常基于某些标签或 ID - 它们允许您使用单个定义匹配和处理整个资源系列。

为什么要使用资源模板?

当您需要处理动态数据、按需生成内容或创建基于参数的资源等时,资源模板非常强大。

以下是一些示例:

动态数据

“users://{userId}”  ->用户资料
“products://{sku}”  ->产品信息

用户:“你能告诉我关于用户 12345 的情况吗?”
AI 助手:“正在查找用户 12345......他于 2023 年加入,已进行 50 次购买。”

按需生成内容

“reports://{year}/{month}”  ->月度报告
“analytics://{dateRange}”  ->自定义分析

用户:“给我看看2024年3月的报告”
AI助手:“正在访问2024年3月的报告……与2月份相比,收入增长了15%。”

基于参数的资源

"search://{query}"  ->搜索结果
"filter://{type}/{value}"  ->过滤数据

用户:“查找所有超过 1000 美元的交易”
AI 助手:“使用过滤资源...找到 23 笔符合您条件的交易。”

组织我们的代码

我们再来改进一下上篇文章中构建的代码结构,分离一些关注点。首先,把处理程序拆分成一个新文件 (handlers.ts),这样就不会太杂乱了:

// src/handlers.ts
import {ListResourcesRequestSchema,ReadResourceRequestSchema,ListResourceTemplatesRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { type Server } from "@modelcontextprotocol/sdk/server/index.js";export const setupHandlers = (server: Server): void => {// List available resources when clients request themserver.setRequestHandler(ListResourcesRequestSchema, async () => {return {resources: [{uri: "hello://world",name: "Hello World Message",description: "A simple greeting message",mimeType: "text/plain",},],};});// Return resource content when clients request itserver.setRequestHandler(ReadResourceRequestSchema, async (request) => {if (request.params.uri === "hello://world") {return {contents: [{uri: "hello://world",text: "Hello, World! This is my first MCP resource.",},],};}throw new Error("Resource not found");});
};

更新我们的主要文件src/index.ts

// src/index.ts
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: {resources: {},},}
);setupHandlers(server);// Start server using stdio transport
const transport = new StdioServerTransport();
await server.connect(transport);
console.info('{"jsonrpc": "2.0", "method": "log", "params": { "message": "Server running..." }}');

添加新资源

现在是时候添加我们的新资源模板了。

首先,让我们添加清单,以便 AI 助手知道它在那里。在资源清单(第一个参数为 的那个)src/handlers.js之后添加以下代码。hello://worldListResourcesRequestSchema

export const setupHandlers = (server: Server): void => {// Existing "hello://world" resource listing here ...// Resource Templatesserver.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({resourceTemplates: [{greetings: {uriTemplate: 'greetings://{name}',name: 'Personal Greeting',description: 'A personalized greeting message',mimeType: 'text/plain',},},],}));// Existing "hello://world" resource content here ... 
};

接下来我们可以添加内容处理程序。这不需要额外的请求处理程序。我们只需为这种格式的请求添加一个新的检查即可。

// Return resource content when clients request it
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {// ... Existing content handler code// Template-based resource codeconst greetingExp = /^greetings:\/\/(.+)$/;const greetingMatch = request.params.uri.match(greetingExp);if (greetingMatch) {const name = decodeURIComponent(greetingMatch[1]);return {contents: [{uri: request.params.uri,text: `Hello, ${name}! Welcome to MCP.`,},],};}// ...
});

理解代码

处理程序组织

  • 我们已将处理程序移至单独的文件以便更好地组织
  • setupHandlers 函数封装了所有处理程序的设置
  • 主文件保持干净且专注

模板定义

  • 处理程序公开可用的模板 ListResourceTemplateRequestSchema
  • 模板名称格式遵循RFC 6570{text} (用于表达参数化的URL )
  • 模板包括名称和描述等元数据

模板处理

  • 处理程序现在检查模板匹配 ReadResourceRequestSchema
  • 我们使用正则表达式格式从 URI 中提取名称参数
  • 我们根据参数生成动态内容

使用检查器进行测试

在上一篇文章中,我们讨论了如何使用MCP 检查器。现在启动检查器:

npx tsc
npx @modelcontextprotocol/inspector node build/index.js

测试我们上次创建的静态资源,以确保它仍然有效:

  • 点击“资源”选项卡
  • 找到并点击“Hello World Message”
  • 您应该会看到“Hello, World! 这是我的第一个 MCP 资源。”的消息。

测试模板:

  • 点击“资源模板”选项卡
  • 找到“个人问候语”
  • 输入名字“Alice”
{"contents": [{"uri": "greetings://Alice","text": "Hello, Alice! Welcome to MCP."}]
}

使用 Claude Desktop 进行测试

这次您不需要在 Claude 中更新任何内容,但您可能需要重新加载(同时,确保您已经使用构建了服务npx tsc)。

正如我上一篇文章所述,我为 Mac 使用的 Claude Desktop 似乎还不支持资源,但您可以在其他支持 MCP 的工具中尝试此操作,例如 Cline,您可能必须专门使用支持 MCP 的模型,例如 Anthropic 的 Sonnet 3.5。

尝试以下示例(响应可能有所不同):

静态资源:

用户: “问候语里有什么?” 
Claude: “问候语是:‘来自 MCP 的问候!这是您的第一个资源。’”

模板资源:

用户: “你能给爱丽丝找个问候语吗?”
克劳德: “我去看看个性化问候语……上面写着:‘你好,爱丽丝!欢迎来到 MCP。’”

列出可用资源:

用户:“有哪些资源和模板可用?” 
Claude:“服务器提供:
1. 静态‘问候语’资源
2. 可以为任何姓名创建自定义问候语的‘个人问候语’模板”

下一步是什么?

在第 3 部分中,我们将:

  • 通过将资源和模板分离到各自的文件中,进一步改善代码组织
  • 了解 MCP 提示以及它们与资源的区别
  • 为我们的服务器添加提示功能
  • 看看提示如何增强我们的问候功能

第 4 部分将通过向我们的服务器添加工具来完成我们的课程。

资源和其他阅读材料:

  • Introduction - Model Context Protocol
  • Cline - Visual Studio Marketplace
  • RFC 6570: URI Template
  • App unavailable \ Anthropic
http://www.lryc.cn/news/2403917.html

相关文章:

  • 【算法设计与分析】实验——汽车加油问题, 删数问题(算法实现:代码,测试用例,结果分析,算法思路分析,总结)
  • Ubuntu2404 下搭建 Zephyr 开发环境
  • 现代C++特性(一):基本数据类型扩展
  • 【C++进阶篇】C++11新特性(下篇)
  • 全生命周期的智慧城市管理
  • echarts柱状图实现动态展示时报错
  • Redis故障转移
  • STM32学习笔记:定时器(TIM)原理与应用(详解篇)
  • JAVA获取ES连接并查询所有数据
  • 408第一季 - 数据结构 - 线性表
  • 第23讲、Odoo18 邮件系统整体架构
  • 【QT面试题】(三)
  • DeepSeek09-open-webui使用
  • HarmonyOS:Counter计数器组件
  • 数据类型 -- 字符
  • WordZero:让Markdown与Word文档自由转换的Golang利器
  • sqlsugar WhereIF条件的大于等于和等于查出来的坑
  • Pandas 技术解析:从数据结构到应用场景的深度探索
  • 数据库系统概论(十七)超详细讲解数据库规范化与五大范式(从函数依赖到多值依赖,再到五大范式,附带例题,表格,知识图谱对比带你一步步掌握)
  • [c#]判定当前软件是否用管理员权限打开
  • 并发编程实战(生产者消费者模型)
  • 分布式微服务系统架构第144集:FastAPI全栈开发教育系统
  • el-tabs 切换时数据不更新的问题
  • git小乌龟不显示图标状态解决方案
  • 获取 OpenAI API Key
  • 【Android基础回顾】五:AMS(Activity Manager Service)
  • pycharm中提示C++ compiler not found -- please install a compiler
  • 类型别名与类型自动推导
  • 一站式直播工具:助力内容创作者高效开启直播新时代
  • 【学习笔记】Lamba表达式[匿名函数]