MCP溯源与认知

「前言」读完本文你将收获:

  • 工程角度上对ai聊天的完全理解
  • 对Function Call与MCP的清晰认知

对话历史构建---消息类型

与大模型的对话消息可分为三类:

System

  • role: "system"
  • 设定AI的行为和角色
  • 定义回答的风格、限制,ai会始终遵循
  • 一般不展示给用户
  • 例如:你是一名专业的客服助手,回答要简洁,态度友好,不要透露用户个人信息

User

  • role: "user"
  • 用户发送的问题或指令
  • 例如:我想找一个100元以内的手机,拍照要清晰

Assistant

  • role: "assistant"
  • AI回复的内容,根据System指令 + 历史上下文生成
  • 例如:在100以内,没有拍照清晰的手机...

Tips

应用开发时,后端请求ai接口,对话历史需要包含System、User和Assistant等所有类型的消息,但前端UI中一般不展示System类型的消息

模型对话api对接

文本型

(即一次性对话。用户问,模型回答,对话结束)

向大模型供应商发出请求:

js 复制代码
// 伪代码
const response = await fetch(
  'https://api.openai.com/v1/chat/completions',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`
    },
    body: JSON.stringify({
      model: 'gpt-3.5.turbo',
      messages: [
        { role: 'user', content: userMessage }
      ]
    })
  }
)
​
// 或SDK
import OpenAI from 'openai';
​
const openai = new OpenAI({
  appKey: process.env.OPENAI_API_KEY
})
​
async function chatWithAI(userMessage) {
  const completion = await openai.chat.completions.create({
    model: 'gpt-3.5.turbo',
    message: [
      { role: 'user', content: userMessage }
    ]
  })
  
  return completion.choices[0].message.content;
}

对话型

(包含对话历史。模型的回复基于用户与模型的所有对话上下文)

在应用中维护对话历史

js 复制代码
let concersationHistory = [];
​
async function chat(userMessage) {
  // 添加用户消息至历史
  concersationHistory.push({
    role: 'user',
    content: userMessage
  })
  
  // 发送整个对话历史至ai接口
  const response = await openai.chat.completions.create({
    model: 'gpt-3.5.turbo',
    messages: concersationHistory
  })
  
  // 添加AI消息到历史
  const aiMessage = response.choices[0].message;
  concersationHistory.push(aiMessage);
  
  return aiMessage.content;
}

api调用对话的瓶颈

举例

若用户询问:帮我查询北京今天的天气,ai知识滞后(不联网),所以无法做到这个查询

又比如一些专业领域的知识,但模型仅靠文本生成算法无法很好的解决此类问题

解决方案一、提示词工程

使用提示词来规范模型的输出,服务端对接这些格式化的输出,最终触发外部工具调用来解决问题

例如,输入system消息:

你可以访问天气,当你需要获取天气信息时,请你返回合法的JSON格式的模拟结果,必须包含如下示例中的字段。我会查询后告诉你结果,你再回复用户。示例:

json 复制代码
{
  "action": "getWeather",
  "parameters": {
    "city": "地点名称",
    "date": "遵循日期格式(比如2025-03-16)"
  }
}

缺点:

  • 存在不可靠性:AI可能不遵循提示词,JSON不可控,一旦内容非法或者语法错误,都会影响正常运行

解决方案二、Function Calling

2023,openAi发布Function Calling功能

Function Calling本质上即支持在ai接口层面,声明可用的工具列表

js 复制代码
import OpenAI from 'openai';
​
const openai = new OpenAI({
  appKey: process.env.OPENAI_API_KEY
})
​
async function chatWithFunctionCalling(userMessage) {
  // 1. 定义可用的函数
  const functions = [
    {
      name: 'getWeather',
      description: '获取指定城市的天气信息',
      parameters: {
        type: 'object',
        properties: {
          location: {
            type: 'string',
            description: '城市名称'
          }
        },
        required: ['location']
      }
    }
  ];
  
  // 2. 传参functions & function_call: 'auto'
  const response = await openai.chat.completions.create({
    model: 'gpt-3.5.turbo',
    message: [ { role: 'user', content: userMessage } ],
    functions,
    function_call: 'auto' // 让AI决定是否调用函数
  })
  
  const message = response.choices[0].message;
  
  // 3. 检查是否调用函数
  if(message.function_call) {
    // 4. 获取函数调用详情
    const functionName = message.function_call.name;
    const args = JSON.parse(message.function_call.arguments)
    
    // 5. 函数(工具)调用
    if(functionName === 'getWeather') {
      const weatherData = await getWeatherApi(args.location);
      // 6. 手动总结返回用户(或让ai总结后返回,好处在于ai回复语言更生动)
      return `${args.location}的天气:${weatherData.condition},温度${weatherData.temperature}`
    }
  }
}

示意图如下,与提示词工程的区别只有红色部分

ChatGPT插件

ChatGPT插件是Function Calling发展衍生出来的方向,本质上是借助开源社区丰富ChatGPT客户端的function,打造生态。

基于Function Calling,用户在与openai客户端聊天时,每支持一种工具,都需要openai自己的客户端和服务端进行工具适配工作,为了让适配工作开源给社区,打造生态系统,故推出ChatGPT插件:

  • 由第三方提供
  • 仅仅服务于ChatGPT的web端(不服务于自己的app)
  • 工具执行于非chatGpt的服务端

本质上,ChatGPT插件的核心即提供function calling清单与工具具体的实现(实现的请求地址),例如:

  1. 创建manifeat.json描述文件,重点关注api.url配置项,指定一个yaml配置文件,文件内包含function calling相关配置
json 复制代码
{
  "schema_version": "v1",
  "name_for_human": "天气查询",
  "name_for_model": "weather",
  "description_for_human": "获取全球天气预报",
  "description_for_model": "获取城市天气信息,包括温度、湿度等",
  "auth": {
    "type": "none"
  },
  "api": {
    "type": "openai",
    "url": "https://example.com/openapi.yaml"
  },
  "logo_url": "https://example.com/logo.png",
  "contact_email": "[email protected]"
}
  1. openapi.yaml如下,创建OpenAPI规范描述。重点关注配置项servers与paths,即具体工具的实现(url地址)
yaml 复制代码
openapi: 3.0.1
info:
  title: 天气查询插件
  description: 一个可以获取全球天气预报的API服务
  version: v1
servers:
  - url: https://weather-api.example.com
paths:
  /weather:
    get:
      operationId: getCurrentWeather
      summary: 获取当前天气预报
      description_for_model: 获取城市天气信息,包括温度、湿度等
      parameters: 
        - name: city
        in: query
        description: 城市名称或地区
        required: true
        schema: 
          type: string
        - name: date
        # ...

MCP

MCP是什么?

借用上文在Funciton Call章节提到的让AI查询天气的例子,基于MCP如何实现:functions列表不再写死在接口调用里,请求外部API不再由appServer自身去做,而是把所有工具调用、资源访问相关的事情都交由一个独立的服务器来完成,也就是MCP服务器(这个服务器遵循Model Context Protocol协议进行开发)。MCP服务器可能是appClient,也可能是appServer去跟MCP服务器直接通信。

示意图如下:

理解上述过程,可以总结:基于MCP协议实现的MCP服务器,抽取了ai外部工具调用的逻辑,以客户端为中介与ai服务通信。

Function Call为一切的基石,本质上是让ai能够结构化的输出JSON格式来调用函数,并且几乎所有的大模型都支持Function call接口规范:

scss 复制代码
Function Call(基石) => ChatGPT插件(OpenAIWeb专用) => MCP协议(通用标准)

MCP就是对Function Call流程规范化:

  • MCP服务器的tools/list接口,提供可调用的工具列表,即提供functions参数

  • MCP服务器的tools/call接口,完成具体的工具的调用

  • resources/list:获取可用资源、resources/read:读取资源内容、prompts/list:获取可用提示等等都是对ai访问外部资源这个流程的动作拆分与规范化实现

  • 除了Function Call,MCP还拓展更多的高级功能,如核心三大功能:

    • 工具(Tools):让AI能执行具体操作,如发送邮件、查天气、执行命令、调用API,如调用一些公司内网提供的服务,本质上是借助MCP服务器去代理调用

      底层使用Function Call实现,与OpenAI格式兼容

    • 资源(Resources):给AI提供参考信息,如文件内容,数据库记录、系统状态等

      MCP独有,Function Call没有此功能

    • 提示(Prompts):预设的对话模版,如快捷命令、标准工作流、指导性提示等

      MCP独有,Function Call没有

相关推荐
Anlici37 分钟前
跨域解决方案还有优劣!?
前端·面试
uhakadotcom39 分钟前
MaxCompute Python UDF开发指南:从入门到精通
后端·面试·github
庸俗今天不摸鱼43 分钟前
【万字总结】构建现代Web应用的全方位性能优化体系学习指南(二)
前端·性能优化·webp
追寻光1 小时前
Java 绘制图形验证码
java·前端
前端snow1 小时前
爬取数据利用node也行,你知道吗?
前端·javascript·后端
村头一颗草1 小时前
高德爬取瓦片和vue2使用
前端·javascript·vue.js
远山无期1 小时前
vue3+vite项目接入qiankun微前端关键点
前端·vue.js
陈随易1 小时前
告别Node.js:2025年,我为何全面拥抱Bun
前端·后端·程序员
还是鼠鼠1 小时前
Node.js--exports 对象详解:用法、示例与最佳实践
前端·javascript·vscode·node.js·web
CQU_JIAKE1 小时前
2.5[frontEnd]
前端