1为什么需要MCP
1.1大模型的局限与扩展
大模型虽然功能强大,但它也有自己的局限性:
●一旦训练完成,它的能力就基本固定了
●面对实时数据和本地数据,它往往无能为力
●对于超出它知识范围的功能需求,也无法满足 要训练这样一个大模型,成本非常高昂:
○需要大量的显卡同时工作
○耗时耗力
1.2MCP的作用
MCP协议正是为了解决大模型的局限性提出的一种的插件系统
2 什么是MCP协议
MCP协议:大模型的「万能插头」系统
正如一个优质插座能兼容多种彩色插头,MCP协议就是大模型的通用接口标准 让各类服务像「即插即用」的插头一样,轻松扩展大模型能力
2.1核心组件解析
组件 | 对应物 | 作用 |
MCP协议 | 插座接口 | 定义统一的通信规则 📜 |
服务器插件 | 功能插头 | 提供具体能力(如数据分析⚙️) |
大模型 | 电器主机 | 通过插头获取新技能 💪 |
2.2三大核心功能
1️⃣ 实时数据处理插件 📊💨
●实时流式计算
●数据清洗/聚合
●事件驱动响应
2️⃣ 本地文件操作插件 📁🔧
●文件读写加密
●跨平台兼容
●版本控制管理
3️⃣ 个性化功能扩展插件 🎨✨
●用户习惯学习
●多语言支持
●定制化UI生成
💡 优势对比 传统集成需要「重新布线」,而MCP协议实现「即插即用」,开发效率提升💯
3MCP 协议概述
MCP (Model Context Protocol) 是 Anthropic 为 Claude 开发并开源的一个协议
允许 AI 模型与外部服务进行通信,扩展其能力范围
目前只有Claude AI模型提供MCP支持, MCP的相关服务构成了Claude的生态.
1Claude AI:使用 MCP 协议与外部服务通信
2OpenAI 模型(如 GPT-4):使用 Function Calling API 或 Plugin 系统
3Google 模型(如 Gemini):使用 Extension API
官方文档:Introduction - Model Context Protocol
官方Github:Model Context Protocol · GitHub
希望国产大模型快速推出自己的类似服务!
3.1MCP 的核心思想
MCP 的核心思想
是让 AI模型 能够通过标准化的接口访问外部工具、数据和服务
3.2MCP 的主要特点
1工具和资源访问:允许 AI 使用外部工具和访问外部资源
2标准化通信:定义了 AI 与服务器之间的通信格式
3安全边界:维持 AI 与外部系统之间的安全隔离
4能力扩展:使 AI 能够执行原本无法完成的任务
4MCP 工作流程
MCP 的工作流程可以概括为以下步骤:
1用户向 Claude 提出需要使用外部工具或数据的请求
2Claude 识别需要使用 MCP 服务,通过 MCP 协议发送请求
3MCP 服务器接收请求,处理并调用相应的外部服务或 API
4外部服务返回结果给 MCP 服务器
5MCP 服务器将结果格式化后返回给 Claude
6Claude 使用这些信息回答用户的问题
4.1MCP 服务器组件
一个基本的 MCP 服务器包含以下核心组件:
1通信层:处理与 Claude 的通信,通常使用标准输入/输出 (stdio)
2请求处理器:解析和处理来自 Claude 的请求
3工具实现:实现各种工具功能的代码
4资源提供者:提供对外部资源的访问
5错误处理:处理可能出现的错误并返回适当的响应
4.2搭建 MCP 服务器的思路
4.2.1环境准备
首先,我们需要准备开发环境:
安装 Node.js(推荐使用 v18 或更高版本)
●创建项目目录
●初始化 npm 项目
●安装 MCP SDK:npm install @modelcontextprotocol/sdk
4.2.2创建基本 MCP 服务器
创建 MCP 服务器的思路
4.2.3配置 Claude 使用 MCP 服务器
最后,配置 Claude 使用我们的 MCP 服务器:
5具体实现
5.1开发环境
5.1.1MCP客户端
首先我们要准备一个支持MCP的客户端, 具体大家可以参考下面的链接
https://modelcontextprotocol.io/llms-full.txt
这里, 我选择使用的是Cursor 0.46.11
5.2项目初始化
创建一个项目文件mcp
初始化
npm init -y
安装依赖
npm install @modelcontextprotocol/sdk zod
{
"name": "mcp",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.6.1",
"zod": "^3.24.2"
}
}
5.3编写服务器
// 导入MCP SDK
const {
McpServer,
ResourceTemplate,
} = require('@modelcontextprotocol/sdk/server/mcp.js')
const {
StdioServerTransport,
} = require('@modelcontextprotocol/sdk/server/stdio.js')
const { z } = require('zod')
// 导入牛排数据
const steakData = require('./steakData')
// 创建MCP服务器
const server = new McpServer({
name: 'SteakInfoServer',
version: '1.0.0',
description: '提供牛排相关信息的MCP服务器',
})
// 添加牛排资源
server.resource(
'steak',
new ResourceTemplate('steak://{id}', { list: 'steak://list' }),
async (uri, { id }) => {
// 如果请求的是列表
if (uri.href === 'steak://list') {
return {
contents: [
{
uri: 'steak://list',
text:
'可用的牛排信息:\n' +
steakData
.filter((item) => item.type !== 'tips')
.map(
(steak) => `${steak.id}. ${steak.name} (${steak.englishName})`
)
.join('\n'),
},
],
}
}
// 查找特定ID的牛排
const steak = steakData.find((s) => s.id === parseInt(id))
if (!steak) {
return {
contents: [
{
uri: uri.href,
text: `未找到ID为${id}的牛排信息。`,
},
],
}
}
// 返回牛排信息
let text = ''
if (steak.type === 'tips') {
text =
`${steak.name}:\n` +
steak.tips.map((tip, index) => `${index + 1}. ${tip}`).join('\n')
} else {
text =
`${steak.name} (${steak.englishName})\n\n` +
`描述: ${steak.description}\n\n` +
`烹饪方法: ${steak.cookingMethods.join(', ')}\n` +
`建议熟度: ${steak.recommendedDoneness}\n\n` +
`营养成分:\n` +
`- 热量: ${steak.nutritionFacts.calories}\n` +
`- 蛋白质: ${steak.nutritionFacts.protein}\n` +
`- 脂肪: ${steak.nutritionFacts.fat}`
}
return {
contents: [
{
uri: uri.href,
text: text,
},
],
}
}
)
// 添加获取牛排推荐的工具
server.tool(
'getSteakRecommendation',
{
preference: z.enum(['嫩', '多汁', '风味浓郁', '低脂肪']).optional(),
cookingMethod: z.enum(['煎', '烤', '低温慢煮', '炭烤']).optional(),
},
async ({ preference, cookingMethod }) => {
let recommendedSteaks = [
...steakData.filter((item) => item.type !== 'tips'),
]
// 根据偏好筛选
if (preference) {
switch (preference) {
case '嫩':
recommendedSteaks = recommendedSteaks.filter(
(s) => s.name === '菲力牛排' || s.description.includes('嫩')
)
break
case '多汁':
recommendedSteaks = recommendedSteaks.filter((s) =>
s.description.includes('多汁')
)
break
case '风味浓郁':
recommendedSteaks = recommendedSteaks.filter((s) =>
s.description.includes('风味浓郁')
)
break
case '低脂肪':
recommendedSteaks = recommendedSteaks.filter(
(s) => s.description.includes('没有脂肪') || s.name === '菲力牛排'
)
break
}
}
// 根据烹饪方法筛选
if (cookingMethod) {
recommendedSteaks = recommendedSteaks.filter((s) =>
s.cookingMethods.includes(cookingMethod)
)
}
// 如果没有匹配的牛排,返回所有牛排
if (recommendedSteaks.length === 0) {
recommendedSteaks = steakData.filter((item) => item.type !== 'tips')
}
// 构建推荐文本
let responseText = '根据您的偏好,我推荐以下牛排:\n\n'
recommendedSteaks.forEach((steak) => {
responseText += `${steak.name} (${steak.englishName}):\n`
responseText += `${steak.description}\n`
responseText += `建议烹饪方法: ${steak.cookingMethods.join(', ')}\n`
responseText += `建议熟度: ${steak.recommendedDoneness}\n\n`
})
// 添加烹饪小技巧
const tips = steakData.find((item) => item.type === 'tips')
if (tips) {
responseText +=
`${tips.name}:\n` +
tips.tips.map((tip, index) => `${index + 1}. ${tip}`).join('\n')
}
return {
content: [{ type: 'text', text: responseText }],
}
}
)
// 添加获取牛排烹饪方法的工具
server.tool(
'getSteakCookingMethod',
{
steakType: z.enum(['菲力牛排', '肋眼牛排', '纽约客牛排', 'T骨牛排']),
doneness: z
.enum(['一分熟', '三分熟', '五分熟', '七分熟', '全熟'])
.optional(),
},
async ({ steakType, doneness }) => {
const steak = steakData.find((s) => s.name === steakType)
if (!steak) {
return {
content: [{ type: 'text', text: `未找到${steakType}的信息。` }],
}
}
let cookingTime
switch (doneness) {
case '一分熟':
cookingTime = '每面约1分钟'
break
case '三分熟':
cookingTime = '每面约2-3分钟'
break
case '五分熟':
cookingTime = '每面约3-4分钟'
break
case '七分熟':
cookingTime = '每面约4-5分钟'
break
case '全熟':
cookingTime = '每面约5-6分钟'
break
default:
cookingTime = steak.recommendedDoneness
}
const tips = steakData.find((item) => item.type === 'tips')
let responseText = `${steakType}的烹饪方法:\n\n`
responseText += `推荐烹饪方法: ${steak.cookingMethods.join(', ')}\n`
responseText += `建议熟度: ${steak.recommendedDoneness}\n`
responseText += `烹饪时间: ${cookingTime}\n\n`
if (tips) {
responseText +=
`烹饪小技巧:\n` +
tips.tips.map((tip, index) => `${index + 1}. ${tip}`).join('\n')
}
return {
content: [{ type: 'text', text: responseText }],
}
}
)
// 启动服务器
async function startServer() {
try {
console.log('启动牛排信息MCP服务器...')
const transport = new StdioServerTransport()
await server.connect(transport)
console.log('MCP服务器已连接')
} catch (error) {
console.error('启动MCP服务器时出错:', error)
}
}
startServer()
// 牛排数据
const steakData = [
{
id: 1,
name: '菲力牛排',
englishName: 'Filet Mignon',
description:
'菲力牛排是从牛里脊中最嫩的部分切出来的,质地极其柔软多汁,几乎没有脂肪。它是最受欢迎的高档牛排之一,通常价格较高。',
cookingMethods: ['煎', '烤', '低温慢煮'],
recommendedDoneness: '三分熟到五分熟',
nutritionFacts: {
calories: '约200-250卡路里/100克',
protein: '约26-28克/100克',
fat: '约15-18克/100克',
},
},
{
id: 2,
name: '肋眼牛排',
englishName: 'Ribeye Steak',
description:
'肋眼牛排来自牛的肋骨部位,肉质鲜嫩多汁,带有丰富的大理石纹理(脂肪分布),风味浓郁。它是许多牛排爱好者的首选。',
cookingMethods: ['煎', '烤', '炭烤'],
recommendedDoneness: '四分熟到七分熟',
nutritionFacts: {
calories: '约290-320卡路里/100克',
protein: '约24-26克/100克',
fat: '约22-25克/100克',
},
},
{
id: 3,
name: '纽约客牛排',
englishName: 'New York Strip Steak',
description:
'纽约客牛排(也称为西冷牛排)来自牛的短腰部位,肉质较为紧实但仍然嫩滑,风味浓郁,脂肪含量适中。',
cookingMethods: ['煎', '烤', '炭烤'],
recommendedDoneness: '四分熟到六分熟',
nutritionFacts: {
calories: '约260-290卡路里/100克',
protein: '约25-27克/100克',
fat: '约19-22克/100克',
},
},
{
id: 4,
name: 'T骨牛排',
englishName: 'T-Bone Steak',
description:
'T骨牛排因其T形骨而得名,一侧是菲力牛排,另一侧是纽约客牛排,提供两种不同口感的牛肉。适合喜欢多种口感的食客。',
cookingMethods: ['煎', '烤'],
recommendedDoneness: '四分熟到六分熟',
nutritionFacts: {
calories: '约250-280卡路里/100克',
protein: '约25-27克/100克',
fat: '约18-21克/100克',
},
},
{
id: 5,
name: '牛排煎制小技巧',
type: 'tips',
tips: [
'煎牛排前,将牛排从冰箱取出,放置至室温(约20-30分钟)',
'煎制前用厨房纸巾擦干牛排表面的水分',
'热锅冷油,确保锅温足够高再放入牛排',
'煎制过程中不要频繁翻动牛排',
'煎好后让牛排静置3-5分钟再切,可以保持肉汁',
],
},
]
module.exports = steakData