当大型语言模型刚出现时,用户想要与之进行交互时必须将代码复制并粘贴到聊天文本界面中。很明显这是不够的,想要更好的效果就只能加载更多的上下文或者定制开发。定制开发的话就不够通用,每个功能都需要单独开发。

MCP(Model Context Protocol)通过提供通用协议来解决这个问题,该协议用于与本地和远程资源进行高效的人工智能交互。

协议

  • 用户主机使用LLM应用(如Claude Desktop、 Cherry Studio、 Cursor等等)来进行初始化连接
  • 客户端维护着一条与服务器的连接
  • 服务器提供上下文、工具和提示词给客户端

使用FastMCP来创建MCP Server

MCP Server分为两种启动方式:

  • 本地启动方式 stdio
  • 远程服务启动方式 sse
例子1 Dog-MCP-Server

这里使用一个框架FastMCP来辅助快速创建一个MCP服务,具体的可以参考fastmcp

import { FastMCP } from 'fastmcp'
import { z } from 'zod'

const server = new FastMCP({
name: 'dog-mcp-server', //创建一个MCP服务器
version: '1.0.0'
})

server.addTool({ //给服务添加一个工具
name: 'get-dog-picture', //工具名称
description: '获取一张狗的图片', //工具描述
parameters: z.object({}), //参数
execute: async () => { //工具执行,call了一个API获取狗狗图片
const response = await fetch('https://dog.ceo/api/breeds/image/random')
const data = await response.json()
return data.message
}
})

//本地启动方式
server.start({
transportType: 'stdio'
})

//远程服务启动方式
server.start({
transportType: 'sse',
sse: {
endpoint: '/sse',
port: 3000
}
})

我们使用Cherry Studio来查看效果,在Cherry Studio中MCP设置里面填入对应的设置,可以使用本地标准输入输出的方式(stdio),也可以使用服务器发送事件的方式(sse)。配置完成之后,询问大模型获取狗狗图片

例子2 V2EX-MCP-Server

V2EX是我很喜欢逛的一个论坛,将其添加到MCP服务中后,就可以使用大模型来辅助刷帖

import { FastMCP } from 'fastmcp'
import { z } from 'zod'

const server = new FastMCP({
name: 'v2ex-mcp-server',
version: '1.0.0',
})

//添加两个工具,一个用于获取指定节点下的主题列表
server.addTool({
name: 'get-node-topics',
description: 'v2ex获取指定节点下的主题列表',
parameters: z.object({
node_name: z.string().describe('节点名称'), //传入两个参数 一个是节点名称,一个是页码,默认为1
page: z.number().default(1).describe('页码'),
}),
execute: async ({ node_name, page }) => {
const headers = {
Authorization: 'Bearer xxxxxxxxxxxxxxxxxxxxxxx', //填入api token
}
const response = await fetch(
`https://www.v2ex.com/api/v2/nodes/${node_name}/topics?p=${page}`,
{
headers,
}
)
const data = await response.json()
return { //如果是列表返回的话,fastmcp 需要将结果格式化成 {content: { type: 'xxx', text: 'xxx'}[]}的形式,具体可以查看文档
content: data.result.map((cell: any) => {
return {
type: 'text',
text: `${cell.id} - ${cell.title}`, //这里将对应的主题title和主题id返回,id用于后面查看详情使用
}
}),
}
},
})

//添加查看主题详情的工具
server.addTool({
name: 'get-topic',
description: 'v2ex获取指定主题内容',
parameters: z.object({
topic_id: z.string().describe('主题ID'), //传入参数主题id
}),
execute: async ({ topic_id }) => {
const headers = {
Authorization: 'Bearer xxxxxxxxxxxxxxxxxxxxxxxx',
}
const response = await fetch(
`https://www.v2ex.com/api/v2/topics/${topic_id}`,
{
headers,
}
)
const data = await response.json()
return data.result.content //返回内容
},
})


//一样可以使用两种方式启动
server.start({
// transportType: "stdio",
transportType: 'sse',
sse: {
endpoint: '/sse',
port: 3001,
},
})

这回我们使用cursor来测试结果

配置cursor的MCP服务

效果