掘金 人工智能 11小时前
AI 发展 && MCP
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了Model Context Protocol(MCP)——一种由Anthropic推出的开放标准,旨在标准化大语言模型(LLM)与外部世界(如插件、工具、数据库等)的交互。MCP通过定义统一的上下文管理、工具调用和多模型协作机制,降低了集成成本,提升了AI模型的智能性和安全性,并促进了AI Agent生态的发展。文章详细介绍了MCP的工作原理、优势,以及如何在Cursor等工具中使用MCP,为AI应用开发者提供了有价值的参考。

💡 MCP(Model Context Protocol)是一种开放标准,由Anthropic推出,旨在标准化LLM与外部世界的交互,核心在于统一上下文管理、工具调用和多模型协作方式。

⚙️ MCP架构基于客户端-服务器模式,包括MCP Hosts(如Cursor)、MCP Clients、MCP Servers、本地数据源和远程服务。MCP Server提供资源、工具和提示,增强LLM的实用性和灵活性。

🛠️ MCP的主要优势在于标准化交互,降低集成成本,丰富上下文,提高安全性和可控性,支持多模型协作。它简化了AI Agent的开发,使其能够自主地与外部系统交互,完成复杂任务。

🔑 MCP是AI时代的“USB协议”,通过MCP Server和Client,实现AI与数据、文件系统、开发工具等互联,构建强大的协作工作能力,极具发展潜力。

🚀 在Cursor等工具中使用MCP,可以连接外部系统和数据源,扩展AI Agent的功能。开发者无需重复造轮子,即可利用MCP生态中已有的服务来增强AI应用。

文章目录

一、AI 的发展历程

二、关键技术演进

三、重要里程碑产品/工具

四、MCP

一、AI 的发展历程

二、关键技术演进

2.1 架构演进

2.2 训练方法演进

2.3 应用领域扩展

三、重要里程碑产品/工具

3.1 开发框架

3.2 AI 应用

四、MCP

在2024.11月之前,AI 技术虽然日新月异,但是 AI 应用层的开发并没有多少新的东西,大体还是Prompt、RAG(Retrieval Augmented Generation)、Agent。

但是自从去年 11 月底 Claude(Anthropic) 主导发布了 MCP(Model Context Protocol 模型上下文协议) 后,AI 应用层的开发算是进入了新的时代。

MCP逐渐被接受,是因为MCP是开放标准。在AI项目开发中可以发现,集成AI模型复杂。MCP的优势:一是开放标准利于服务商开发API,二是避免重复造轮子,可利用现有MCP服务增强Agent。

查看全球热点趋势的网站 Google Trends

4.1 什么是MCP(Model Context Protocol)

4.1.1 定义

MCP(Model Context Protocol,模型上下文协议) ,2024年11月底,由 Anthropic(Claude的母公司) 推出的一种开放标准,是一种为大语言模型(LLM)和AI Agent生态设计的上下文管理与交互协议,帮助 AI 模型更好地理解上下文。它的核心目标是标准化模型与外部世界(如插件、工具、数据库、其他模型等)之间的上下文信息交换和调用方式。定义了模型如何获取上下文、调用外部函数、管理会话状态、处理多轮对话等机制。

简单来说,MCP 是一个 AI 大模型的标准化工具箱。大模型可以通过这些工具与 外界互动获取信息,并 完成具体任务

为什么需要MCP?

主要内容包括:

MCP 服务器可以提供三种主要类型的功能:

价值:MCP是AI时代的USB协议

举个例子,在过去,为了让大模型等 AI 应用使用数据,要么复制粘贴,要么上传知识库,非常局限。

即使是最强大模型也会受到数据隔离的限制,形成信息孤岛,要做出更强的大模型,每个新数据源都需要自己重新定制实现,使真正互联的系统难以扩展,存在很多的局限性。

现在,MCP 可以直接在 AI 与数据(包括本地数据和互联网数据)之间架起一座桥梁,通过 MCP 服务器和 MCP 客户端,大家只要都遵循这套协议,就能实现“万物互联”。有了MCP,可以和数据和文件系统、开发工具、Web 和浏览器自动化、生产力和通信、各种社区生态能力全部集成,实现强大的协作工作能力,它的价值远不可估量。

4.1.2 为什么MCP是一个突破

我们知道过去一年时间,AI 模型的发展非常迅速,从 GPT 4 到 Claude Sonnet 3.5 到 Deepseek R1,推理和幻觉都进步的非常明显。

新的 AI 应用也很多,但我们都能感受到的一点是,目前市场上的 AI 应用基本都是全新的服务,和我们原来常用的服务和系统并没有集成,换句话说,AI 模型和我们已有系统集成发展的很缓慢。

例如我们目前还不能同时通过某个 AI 应用来做到联网搜索、发送邮件、发布自己的博客等等,这些功能单个实现都不是很难,但是如果要全部集成到一个系统里面,就会变得遥不可及。

如果你还没有具体的感受,我们可以思考一下日常开发中,想象一下在 IDE 中,我们可以通过 IDE 的 AI 来完成下面这些工作。

以上谈到的这些功能通过 MCP 目前正在变为现实,大家可以关注 Cursor MCPWindsurf MCP 获取更多的信息。可以试试用 Cursor MCP + browsertools 插件来体验一下在 Cursor 中自动获取 Chrome dev tools console log 的能力。

为什么 AI 集成已有服务的进展这么缓慢?这里面有很多的原因,一方面是企业级的数据很敏感,大多数企业都要很长的时间和流程来动。另一个方面是技术方面,我们缺少一个开放的、通用的、有共识的协议标准。

MCP 就是 Claude(Anthropic) 主导发布的一个开放的、通用的、有共识的协议标准,如果我们对 AI 模型熟悉,想必对 Anthropic 这个公司不会陌生,2025.5.22他们发布了 Claude Sonnet 4、Claude Opus 4 的模型(更精准地执行指令、且在“记忆”能力上实现提升,在需要持续专注且涉及数千步骤的长期任务中保持稳定性能),到目前为止应该还是最强的编程 AI 模型。在一项对比不同大型语言模型软件工程任务表现的基准测试中,Anthropic的两款模型击败了OpenAI的最新模型,而谷歌的最佳模型则表现落后。

www.anthropic.com/

这里还是要多提一句,这个协议的发布最好机会应该是属于 OpenAI 的,如果 OpenAI 刚发布 GPT 时就推动协议,相信大家都不会拒绝,但是 OpenAI 变成了 CloseAI,只发布了一个封闭的 GPTs,这种需要主导和共识的标准协议一般很难社区自发形成,一般由行业巨头来主导。

Claude 发布了 MCP 后,官方的 Claude Desktop 就开放了 MCP 功能,并且推动了开源组织 Model Context Protocol,由不同的公司和社区进行参与,例如下面就列举了一些由不同组织发布 MCP 服务器的例子。

MCP 官方集成教学

第三方平台官方支持 MCP 的例子

由第三方平台构建的 MCP 服务器。

社区 MCP 服务器

下面是一些由开源社区开发和维护的 MCP 服务器。

4.2 Prompt/LLM/FunctionCall/Agent/MCP区别(为什么是 MCP)

看到这里你可能有一个问题,在 23 年 OpenAI 发布 GPT function calling 的时候,不是也是可以实现类似的功能吗?目前热门的 AI Agent,不就是用来集成不同的服务吗?为什么又出现了 MCP。

function call、AI Agent、MCP 这三者之间有什么区别?

网上有个说法:Agent是智能体,MCP是AI时代的USB协议。

概念简述

    Prompt:提出的问题或想说的话。SYSTEM PROMPT 描述AI的角色、性格、背景知识、语气等LLM:大语言模型(如GPT-4),能理解和生成自然语言文本Function Call:LLM通过结构化方式调用外部函数/工具的机制(单一API调用)AI Agent:具备自主决策、任务分解、调用工具能力的智能体,通常基于LLM,利用Function Calling和MCP来分析和执行任务,实现特定目标(复杂任务自动化)MCP:Model Context Protocol,标准化模型与外部世界(工具、Agent等)交互的协议,使大模型与API无缝交互(场景:多Agent协作、插件生态)

区别与联系

1.LLM(大语言模型)

    本质:核心的AI能力提供者,负责理解和生成文本。局限:本身不具备调用外部工具、记忆复杂上下文、主动决策等能力。

2.Function Call(函数调用)

    本质:让LLM能以结构化方式调用外部函数/API的机制。充当 AI 模型与外部系统之间的桥梁,不同的模型有不同的 Function Calling 实现,代码集成的方式也不一样。由不同的 AI 模型平台来定义和实现(通过代码给 LLM 提供一组 functions,并且提供清晰的函数描述、函数输入和输出,LLM 就可以根据清晰的结构化数据进行推理、执行函数)局限:通常是一次性、无复杂上下文管理,功能有限。处理不好多轮对话和复杂需求,适合边界清晰、描述明确的任务。如果需要处理很多的任务,那么 Function Calling 的代码比较难维护

3.AI Agent(智能体)

    本质:智能系统,自主运行以实现特定目标。在LLM基础上,能自主决策、任务分解、调用多种工具/函数的。(传统的 AI 聊天仅提供建议或者需要手动执行任务,AI Agent 则可以分析具体情况、做出决策、并自行采取行动)
      AI Agent 可以利用 MCP 提供的功能描述来理解更多的上下文,并在各种平台/服务自动执行任务Agent概念的核心:让AI真正实现自主完成任务 想+做
    联系:通常用LLM作为“思考大脑”,通过Function Call等方式与外部世界交互。优势:能处理复杂、多步任务,维护长期目标和上下文。

4.MCP(Model Context Protocol)

    本质:一个标准协议,定义模型与外部世界(工具、Agent、环境等)如何结构化交互、共享上下文、管理会话,如同电子设备的 Type C 协议(可以充电也可以传输数据)。 旨在替换碎片化的 Agent 代码集成,建立通用标准,服务商可以基于协议推出自己服务的AI能力、更强大的AI应用;开发者也无需重复造轮子,通过开源项目可以建立强大的 AI Agent 生态联系:
      MCP可以规范Function Call的格式和流程。MCP为AI Agent提供统一的上下文、工具发现、权限管理等能力。LLM通过MCP可以更好地与外部世界协作,成为Agent的一部分。
    优点:可以在不同的应用/服务之间保持上下文,从而增强整体自主执行任务的能力

MCP 与 Function Call 的区别

这两种技术都旨在增强 AI 模型与外部数据的交互能力,但 MCP 不止可以增强 AI 模型,还可以是其他的应用系统。

MCP 协议Function Calling相似,MCP最大优点是整合之前各大模型不同的Function Call标准,形成一个统一的标准协议

4.2.1 具体示例

1.LLM 只做问答

用户问:“北京天气如何?”

2.Function Call

用户问:“北京天气如何?”

3.AI Agent

用户问:“帮我订明天去北京的机票,并告诉我天气。”

4.MCP

同样的任务,MCP提供:

MCP交互示例:

{    "function_call": {      "name": "getWeather",      "arguments": {"city": "Beijing"}    }}

4.2.2 思考

为什么 Claude 推出 MCP 后会被广泛接受呢?开发AI项目过程中,将 AI 模型集成现有的系统或者第三方系统比较麻烦。虽然市面上有一些框架支持 Agent 开发,例如 LangChain Tools, LlamaIndex 或者是 Vercel AI SDK

LangChain 和 LlamaIndex 虽然都是开源项目,但是整体发展还是挺混乱的,首先是代码的抽象层次太高了,想要推广的都是让开发人员几行代码就完成某某 AI 功能,这在 Demo 阶段是挺好用的,但是在实际开发中,只要业务一旦开始复杂,糟糕的代码设计带来了非常糟糕的编程体验。还有就是这几个项目都太想商业化了,忽略了整体生态的建设。

还有一个就是 Vercel AI SDK,尽管 Vercel AI SDK 代码抽象的比较好,但是也只是对于前端 UI 结合和部分 AI 功能的封装还不错,最大的问题是和 Nextjs 绑定太深了,对其它的框架和语言支持度不够。

所以 Claude 推动 MCP 可以说是一个很好的时机,首先是 Claude Sonnet 3.5 在开发人员心中有较高的地位,而 MCP 又是一个开放的标准,所以很多公司和社区都愿意参与进来,希望 Claude 能够一直保持一个良好的开放生态。

MCP 对于社区生态的好处主要是下面两点:

4.3 MCP 如何工作

4.3.1 MCP 架构

官方给出的MCP架构图

MCP 遵循客户端-服务器架构(client-server),总共分为了下面五个部分:

整个 MCP 协议核心的在于 Server,因为 Host 和 Client 相信熟悉计算机网络的都不会陌生,非常好理解,但是 Server 如何理解呢?

看看 Cursor 的 AI Agent 发展过程,我们会发现整个 AI 自动化的过程发展会是从 Chat 到 Composer 再进化到完整的 AI Agent

AI Chat 只是提供建议,如何将 AI 的 response 转化为行为和最终的结果,全部依靠人类,例如手动复制粘贴,或者进行某些修改。

AI Composer 是可以自动修改代码,但是需要人类参与和确认,并且无法做到除了修改代码之外的其它操作。

AI Agent 是一个完全的自动化程序,未来完全可以做到自动读取 Figma 的图片,自动生产代码,自动读取日志,自动调试代码,自动 push 代码到 GitHub。

而 MCP Server 就是为了实现 AI Agent 的自动化而存在的,它是一个中间层,告诉 AI Agent 目前存在哪些服务,哪些 API,哪些数据源,AI Agent 可以根据 Server 提供的信息来决定是否调用某个服务,然后通过 Function Calling 来执行函数。

MCP Client

MCP client 充当 LLM 和 MCP server 之间的桥梁,MCP client 的工作流程如下:

Claude Desktop 和Cursor都支持了MCP Server接入能力,它们就是作为 MCP client来连接某个MCP Server感知和实现调用。

MCP Server

MCP server 是 MCP 架构中的关键组件,它可以提供 3 种主要类型的功能:

这些功能使 MCP server 能够为 AI 应用提供丰富的上下文信息和操作能力,从而增强 LLM 的实用性和灵活性。

你可以在 MCP Servers Repository 和 Awesome MCP Servers 这两个 repo 中找到许多由社区实现的 MCP server。使用 TypeScript 编写的 MCP server 可以通过 npx 命令来运行,使用 Python 编写的 MCP server 可以通过 uvx 命令来运行。

4.3.2 MCP Server 的工作原理

我们先看一个简单的例子,假设我们想让 AI Agent 完成自动搜索 GitHub Repository,接着搜索 Issue,然后再判断是否是一个已知的 bug,最后决定是否需要提交一个新的 Issue 的功能。

那么我们就需要创建一个 Github MCP Server,这个 Server 需要提供查找 Repository、搜索 Issues 和创建 Issue 三种能力。

该后台服务进程 核心功能:将一系列GitHub操作封装成工具Tools,并提供给一个外部系统(很可能是一个大型语言模型或AI智能体)来调用。

我们直接来看看代码:

// 服务器初始化,创建一个服务器实例const server = new Server(  {    name: "github-mcp-server",    version: VERSION,  },  {    capabilities: {      tools: {},    },  });// 菜单——注册可用的工具列表。// setRequestHandler 为服务器注册一个请求处理器,ListToolsRequestSchema列出所有可用工具// inputSchema: zodToJsonSchema(...): 每个工具的“使用说明书”。定义调用这个工具需要提供哪些参数,以及这些参数的格式和类型。zod库来做格式校验server.setRequestHandler(ListToolsRequestSchema, async () => {  return {    tools: [      {        name: "search_repositories",        description: "Search for GitHub repositories",        inputSchema: zodToJsonSchema(repository.SearchRepositoriesSchema),      },      {        name: "create_issue",        description: "Create a new issue in a GitHub repository",        inputSchema: zodToJsonSchema(issues.CreateIssueSchema),      },      {        name: "search_issues",        description: "Search for issues and pull requests across GitHub repositories",        inputSchema: zodToJsonSchema(search.SearchIssuesSchema),      }    ],  };});// 处理工具调用请求// CallToolRequestSchema 处理器负责处理“调用某个具体工具”的请求,当外部系统说“帮我执行create_issue”操作时,它会被触发server.setRequestHandler(CallToolRequestSchema, async (request) => {  try {    if (!request.params.arguments) {      throw new Error("Arguments are required");    }    switch (request.params.name) {      case "search_repositories": {        // 使用zod验证传入的参数 是否符合SearchRepositoriesSchema定义的规范        const args = repository.SearchRepositoriesSchema.parse(request.params.arguments);        // 校验通过,调用searchRepositories 实际的业务逻辑函数        const results = await repository.searchRepositories(          args.query,          args.page,          args.perPage        );        return {          content: [{ type: "text", text: JSON.stringify(results, null, 2) }],        };      }      case "create_issue": {        const args = issues.CreateIssueSchema.parse(request.params.arguments);        const { owner, repo, ...options } = args;        const issue = await issues.createIssue(owner, repo, options);        return {          content: [{ type: "text", text: JSON.stringify(issue, null, 2) }],        };      }      case "search_issues": {        const args = search.SearchIssuesSchema.parse(request.params.arguments);        const results = await search.searchIssues(args);        return {          content: [{ type: "text", text: JSON.stringify(results, null, 2) }],        };      }      default:        throw new Error(`Unknown tool: ${request.params.name}`);    }  } catch (error) {}});async function runServer() {  // StdioServerTransport 是理解这个服务运行方式的关键。它没有使用常见的HTTP(网络端口),而使用stdio (Standard Input/Output,标准输入/输出) 作为通信方式  // 这意味着:这个服务作为一个独立的命令行进程运行。它的父进程(比如AI模型的主程序)通过向它的标准输入(stdin)写入请求数据来和它通信,并通过读取它的标准输出(stdout)来接收响应。这是一种高效的进程间通信方式  const transport = new StdioServerTransport();  // 将服务器逻辑和通信方式连接起来,让服务器正式开始监听来自stdio的请求  await server.connect(transport);  console.error("GitHub MCP Server running on stdio");}runServer().catch((error) => {  console.error("Fatal error in main():", error);  process.exit(1);});

上面的代码中,我们通过 server.setRequestHandler 来告诉 Client 端我们提供了哪些能力,通过 description 字段来描述这个能力的作用,通过 inputSchema 来描述完成这个能力需要的输入参数。

一个设计良好、模块化的AI工具集服务,将复杂的GitHub操作简化为AI可以直接理解和调用的标准化工具。核心功能:将一系列GitHub操作封装成工具Tools,并提供给一个外部系统(很可能是一个大型语言模型或AI智能体)来调用。

    启动:作为一个命令行工具启动,通过标准输入/输出与外界通信。广播能力:当被问及时,它会返回一个包含 search_repositories、create_issue 和 search_issues 三个工具的列表,并附上详细的参数说明。执行任务:当收到调用具体工具的请求时,它会:
      验证传入的参数是否合法。调用相应的函数去执行真正的 GitHub API 操作。将操作结果返回给请求方。

我们再来看看具体的实现代码:

// 使用zod库定义调用GitHub API时所需的参数结构// 一个可复用的基础搜索选项export const SearchOptions = z.object({  q: z.string(),                             // 搜索查询,必须是字符串  order: z.enum(["asc", "desc"]).optional(), // 排序方式,可选,且值必须是 'asc' 或 'desc'  page: z.number().min(1).optional(),        // 页码,可选,必须是数字且最小为 1  per_page: z.number().min(1).max(100).optional(), // 每页数量,可选,必须是数字,范围在 1-100});// 扩展基础选项,用于搜索 Issue(Issue有自己独特的排序标准,如按评论数排序)export const SearchIssuesOptions = SearchOptions.extend({  sort: z.enum([  // 排序字段    "comments",    ...  ]).optional(),});// 异步函数,搜索用户// typeof SearchUsersSchema 获取zod schema对象;z.infer<>  从schema中自动推断出TypeScript类型;保证类型安全export async function searchUsers(params: z.infer<typeof SearchUsersSchema>) {  return githubRequest(buildUrl("https://api.github.com/search/users", params));}// 专门为搜索仓库SearchRepositories函数定义的Schema。describe为字段添加描述信息,可以被一些自动化工具(如文档生成器或AI)读取export const SearchRepositoriesSchema = z.object({  query: z.string().describe("Search query (see GitHub search syntax)"),  page: z.number().optional().describe("Page number for pagination (default: 1)"),  perPage: z.number().optional().describe("Number of results per page (default: 30, max: 100)"),});// 搜索仓库的函数export async function searchRepositories(query: string,  page: number = 1,  perPage: number = 30) {  const url = new URL("https://api.github.com/search/repositories");  url.searchParams.append("q", query);  url.searchParams.append("page", page.toString());  url.searchParams.append("per_page", perPage.toString());  const response = await githubRequest(url.toString());  // 使用Zod schema(GitHubSearchResponseSchema),验证返回的数据格式是否符合预期  return GitHubSearchResponseSchema.parse(response);}

这段代码主要由两部分组成:

    Zod Schemas:定义数据结构的“蓝图”或“规则书”。API 调用函数:实际执行与 GitHub API 通信的“执行者”。

可以很清晰的看到,我们最终实现是通过了 https://api.github.com 的 API 来实现和 Github 交互的,我们通过 githubRequest 函数来调用 GitHub 的 API,最后返回结果。

在调用 Github 官方的 API 之前,MCP 的主要工作是描述 Server 提供了哪些能力(给 LLM 提供),需要哪些参数(参数具体的功能是什么),最后返回的结果是什么。

所以 MCP Server 并不是一个新颖的、高深的东西,它只是一个具有共识的协议。

如果我们想要实现一个更强大的 AI Agent,例如我们想让 AI Agent 自动的根据本地错误日志,自动搜索相关的 GitHub Repository,然后搜索 Issue,最后将结果发送到 Slack。

那么我们可能需要创建三个不同的 MCP Server,一个是 Local Log Server,用来查询本地日志;一个是 GitHub Server,用来搜索 Issue;还有一个是 Slack Server,用来发送消息。

AI Agent 在用户输入 我需要查询本地错误日志,将相关的 Issue 发送到 Slack 指令后,自行判断需要调用哪些 MCP Server,并决定调用顺序,最终根据不同 MCP Server 的返回结果来决定是否需要调用下一个 Server,以此来完成整个任务。

4.4 如何使用 MCP

如果你还没有尝试过如何使用 MCP 的话,我们可以考虑用 Cursor(此处以Cursor为例),Claude Desktop 或者 Cline 来体验一下。

当然,我们并不需要自己开发 MCP Servers,MCP 的好处就是通用、标准,所以开发者并不需要重复造轮子(但是学习可以重复造轮子)。

首先推荐的是官方组织的一些 Server:官方的 MCP Server 列表

目前社区的 MCP Server 还是比较混乱,有很多缺少教程和文档,很多的代码功能也有问题,我们可以自行尝试一下 Cursor Directory 的一些例子,具体的配置和实战 可以参考官方文档。

MCP Github地址:github.com/modelcontex…

Smithery平台上的MCP工具与github上的MCP工具对比:

Cursor MCP 使用示例(自定义mcp server)

使用模型上下文协议 (MCP) 插件系统将外部工具和数据源连接到 Cursor

MCP 是一个开放协议,它规范了应用程序向 LLM 提供上下文和工具的方式。MCP 可以理解为 Cursor 的插件系统,它允许您通过标准化接口将 Agent 连接到各种数据源和工具,从而扩展 Agent 的功能。

用途:MCP 允许您将 Cursor 连接到外部系统和数据源。这意味着您可以将 Cursor 与现有的工具和基础架构集成,而无需在代码本身之外告知 Cursor 项目的结构。

Cursor工具中集成mcp server功能对开发增加效率非常明显,配置入口在:File—>Preferences—>Cursor Settings—>MCP—>MCP Servers—>Add new global MCP server

手动配置

MCP 配置文件采用 JSON 格式,结构如下:

// This example demonstrated an MCP server using the stdio format// Cursor automatically runs this process for you// This uses a Python server, ran with `python`{  "mcpServers": {    "wj-server-name": {      "command": "python",      "args": ["server.py"],      "env": {        "API_KEY": "xxx"      }    }  }}

基于MCP(Model Context Protocol)协议的天气查询插件服务,可以通过 MCP 框架与外部系统集成,实现“查询指定城市实时天气”的功能。

#!/usr/bin/env python3import asyncio     # Python的标准库,用于编写异步代码,适合处理网络请求等I/O密集型任务import osfrom typing import Any, Dictimport aiohttp     # 第三方库,用于执行异步的HTTP请求from mcp.server import Server   # MCP框架相关,用于定义服务、工具和数据类型from mcp.server.stdio import stdio_serverfrom mcp.types import Tool, TextContent# 和风天气API设置API_KEY = os.getenv('WEATHER_API_KEY')  # 需要在mcp.json里配置API_URL = "https://mq564tupt3.re.qweatherapi.com/v7/weather/now"# 服务初始化。创建一个MCP服务实例,服务名为weather-mcp-serverserver = Server("weather-mcp-server")# 异步请求和风天气API,查询指定城市的实时天气async def query_weather(city: str) -> Dict[str, Any]:    """查询天气API"""    if not API_KEY:        return {"error": "WEATHER_API_KEY环境变量未设置"}    params = {        "location": city,        "key": API_KEY    }    try:        # 使用aiohttp的标准模式,创建一个客户端会话,并以aiohttp异步方式发送GET请求        async with aiohttp.ClientSession() as session:            async with session.get(API_URL, params=params) as response:                if response.status == 200:                    return await response.json()                else:                    return {"error": f"API调用失败: {await response.text()}"}    except Exception as e:        return {"error": f"请求失败: {str(e)}"}# 工具列表说明@server.list_tools()     # 装饰器Decorator,将list_tools函数注册到server实例上,作为“列出所有工具”请求的处理器async def list_tools() -> list[Tool]:    return [        Tool(            name="weather_query",            description="查询指定城市的实时天气",            # 输入参数为city            inputSchema={                "type": "object",                "properties": {                    "city": {                        "type": "string",                        "description": "要查询的城市名称(如beijing/shanghai/shenzhen)"                    }                },                "required": ["city"]            }        )    ]# 工具调用实现。根据工具名和参数,执行相应的功能@server.call_tool()async def call_tool(name: str, arguments: Dict[str, Any]) -> list[TextContent]:    # 如果调用weather_query工具,提取城市名、调用API查询天气、返回结果格式化为文本内容返回    if name == "weather_query":        city = arguments.get("city", "")        result = await query_weather(city)        if "error" in result:            return [TextContent(type="text", text=f"Error: {result['error']}")]        if result.get("code") != "200":            return [TextContent(type="text", text=f"API返回错误: {result.get('code')}")]        now = result.get("now", {})        weather_text = (            f"{city} 当前天气:{now.get('text', '未知')}\n"            f"温度:{now.get('temp', '未知')}℃\n"            f"风向:{now.get('windDir', '未知')}\n"            f"风速:{now.get('windSpeed', '未知')} km/h"        )        return [TextContent(type="text", text=weather_text)]    raise ValueError(f"Unknown tool: {name}")async def main():    # stdio_server表示服务器的通信方式是标准输入/输出(stdio),而不是通过网络端口    async with stdio_server() as (read_stream, write_stream):        # 启动服务器的主事件循环。服务器会开始从read_stream(标准输入)监听请求,并将响应写入write_stream(标准输出)        await server.run(            read_stream,            write_stream,            server.create_initialization_options()        )if __name__ == "__main__":    asyncio.run(main())

MCP插件服务:通过和风天气API查询实时天气。对外暴露一个工具weather_query,输入城市名、返回天气信息

使用Python和asyncio,构建一个后台服务进程,将将 Hugging Face 的 BLOOM 模型封装成一个标准化的“工具”,供外部系统(如 AI 大模型)调用。

# Hugging Face API settingsAPI_TOKEN = os.getenv('API_KEY')API_URL = "https://api-inference.huggingface.co/models/bigscience/bloom"# Create MCP serverserver = Server("huggingface-mcp-server")async def query_huggingface(payload: Dict[str, Any]) -> Dict[str, Any]:    """Query Hugging Face API"""    if not API_TOKEN:        return {"error": "API_KEY environment variable not set"}        headers = {"Authorization": f"Bearer {API_TOKEN}"}        try:        # 使用aiohttp的标准模式,创建一个客户端会话,并以异步方式发送一个POST请求,将payload作为JSON数据发送        async with aiohttp.ClientSession() as session:            async with session.post(API_URL, headers=headers, json=payload) as response:                if response.status == 200:                    result = await response.json()                    return result                else:                    error_text = await response.text()                    return {"error": f"API call failed: {error_text}"}    except Exception as e:        return {"error": f"Request failed: {str(e)}"}@server.list_tools()   # 装饰器Decorator,将list_tools函数注册到server实例上,作为“列出所有工具”请求的处理器async def list_tools() -> list[Tool]:    """List available tools"""    return [        Tool(            name="huggingface_generate",            description="Generate text using Hugging Face BLOOM model",            inputSchema={   # 工具的使用说明书,使用JSON Schema格式定义。告诉调用方需要提供哪些参数(prompt是必须的),参数的类型(string,integer,number),以及默认值                           "type": "object",                "properties": {                    "prompt": {                        "type": "string",                        "description": "The text prompt to generate from"                    },                    "max_length": {                        "type": "integer",                        "description": "Maximum length of generated text",                        "default": 100                    },                    "temperature": {                        "type": "number",                        "description": "Temperature for generation",                        "default": 0.7                    }                },                "required": ["prompt"]            }        )    ]@server.call_tool()    # 装饰器Decorator,将call_tool函数注册为“执行具体工具”请求的处理器async def call_tool(name: str, arguments: Dict[str, Any]) -> list[TextContent]:    """Handle tool calls"""    if name == "huggingface_generate":        prompt = arguments.get("prompt", "")        max_length = arguments.get("max_length", 100)        temperature = arguments.get("temperature", 0.7)                # Call Hugging Face API        hf_payload = {            "inputs": prompt,            "parameters": {                "max_length": max_length,                "temperature": temperature,                "return_full_text": False            }        }                # 调用query_huggingface函数来完成实际的 API 请求        result = await query_huggingface(hf_payload)                if "error" in result:            return [TextContent(type="text", text=f"Error: {result['error']}")]        else:            generated_text = result[0].get('generated_text', '') if result else ''            return [TextContent(type="text", text=generated_text)]        raise ValueError(f"Unknown tool: {name}")async def main():    """Main entry point"""    # stdio_server表示服务器的通信方式是标准输入/输出(stdio),而不是通过网络端口    async with stdio_server() as (read_stream, write_stream):        # 启动服务器的主事件循环。服务器会开始从read_stream(标准输入)监听请求,并将响应写入write_stream(标准输出)        await server.run(            read_stream,            write_stream,            server.create_initialization_options()        )if __name__ == "__main__":  # Python 的标准入口点,确保只有当这个文件被直接执行时,asyncio.run(main()) 才会运行,从而启动整个服务    asyncio.run(main())

这是一个非常典型的 AI Agent 工具化 实践,将一个外部服务(Hugging Face API)包装成了一个可以让 AI 模型方便、安全调用的标准化工具。

完成 server.py、requirements.txt,并在Cursor的config.json添加MCP服务器配置后,可以在Cursor中使用这个自定义模型,操作步骤如下:

步骤 1: 启动你的本地服务器

运行 server.py 文件。这个服务器会作为一个“中间人”,接收来自 Cursor 的请求,请求和风天气的API/转发给 Hugging Face API。

重要提示: 在你使用自定义模型的整个过程中,这个终端窗口必须保持打开状态。关闭它就会中断服务器,Cursor 将无法连接。

步骤 2: 在 Cursor 中选择并使用你的模型、开始聊天

选择 wj-server-name 后,你就可以像平常一样使用 Cursor 的聊天功能了。

两种方式:

    Cursor编辑器 选中/激活weather-server,找到weather-server相关的工具。
      选择weather_query工具,输入参数(城市名),工具会自动调用MCP Server,返回天气信息并显示在编辑器侧边栏或弹窗中
    在Cursor的Chat,选择weather-server 作为当前MCP工具,输入weather_query city=beijing

所有这些请求现在都会发送到你的本地 server.py,再由它调用 和风天气 的API(可以用其他各种模型等)进行处理,最后将结果返回到 Cursor 界面。

MCP 的一些资源

MCP 官方资源

社区的 MCP Server 的列表

Agent

2D数字人项目:github.com/wan-h/aweso…

参考:

一文概览人工智能(AI)发展历程

MCP 终极指南

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

MCP 大语言模型 AI Agent 开放协议 Cursor
相关文章