diff --git a/units/zh_CN/_toctree.yml b/units/zh_CN/_toctree.yml new file mode 100644 index 0000000..a1a151b --- /dev/null +++ b/units/zh_CN/_toctree.yml @@ -0,0 +1,46 @@ +- title: "0. MCP 课程欢迎页" + sections: + - local: unit0/introduction + title: 欢迎来到 MCP 课程 + +- title: "1. Model Context Protocol 介绍" + sections: + - local: unit1/introduction + title: Model Context Protocol (MCP) 介绍 + - local: unit1/key-concepts + title: 关键概念与术语 + - local: unit1/architectural-components + title: 架构组件 + - local: unit1/communication-protocol + title: 通信协议 + - local: unit1/capabilities + title: MCP 能力解析 + - local: unit1/sdk + title: MCP SDK + - local: unit1/mcp-clients + title: MCP 客户端 + - local: unit1/gradio-mcp + title: Gradio MCP 集成 + +- title: "2. 用例:端到端 MCP 应用" + sections: + - local: unit2/introduction + title: MCP 应用构建入门 + - local: unit2/gradio-server + title: 构建 Gradio MCP 服务端 + - local: unit2/clients + title: 在应用中使用 MCP 客户端 + - local: unit2/gradio-client + title: 使用 Gradio 构建 MCP 客户端 + - local: unit2/tiny-agents + title: 使用 TypeScript 构建微型智能体 + +- title: "3. 用例:高级 MCP 开发" + sections: + - local: unit3/introduction + title: 即将推出 + +- title: "附加单元" + sections: + - local: unit4/introduction + title: 即将推出 \ No newline at end of file diff --git a/units/zh_CN/unit0/introduction.mdx b/units/zh_CN/unit0/introduction.mdx new file mode 100644 index 0000000..c6e56bc --- /dev/null +++ b/units/zh_CN/unit0/introduction.mdx @@ -0,0 +1,104 @@ +# 欢迎来到 🤗 模型上下文协议 (MCP) 课程 + +![MCP 课程封面](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit0/1.png) + +欢迎来到当今 AI 领域最激动人心的主题:**模型上下文协议(Model Context Protocol,MCP)**! + +本免费课程将带你从零基础到精通,全面掌握 MCP 的理解、使用和应用开发。 + +本单元将帮助你快速入门: +* 查看**课程大纲** +* **获取证书获取流程与时间表**的详细信息 +* 认识课程开发团队 +* 创建你的**账户** +* **加入我们的 Discord 服务器**,与同学和导师互动 + +让我们开始吧! + +## 课程内容概览 + +在本课程中你将: +* 📖 学习 MCP 的**理论、设计与实践** +* 🧑‍💻 掌握**使用主流 MCP SDK 和框架** +* 💾 **分享你的项目**并探索社区作品 +* 🏆 参与挑战赛,**与其他学员的 MCP 实现方案同台竞技** +* 🎓 完成作业**获取结业证书** + +课程结束后,你将掌握**如何运用 MCP 标准构建接入外部数据和工具的 AI 应用**。 + +别忘了[**立即报名课程!**](https://huggingface.co/mcp-course) + +## 课程结构 +课程包含: +* _基础单元_:学习 MCP **核心理论** +* _实践环节_:使用**预配置环境**和主流 MCP SDK 构建应用 +* _案例作业_:应用所学知识解决真实场景问题 +* _合作项目_:与 Hugging Face 合作伙伴共同探索最新 MCP 工具 + +**本课程将持续演进,期待你的反馈与贡献!** 欢迎在 GitHub 提交 issue/PR,或在 Discord 参与讨论。 + +课程结束后可通过[反馈表](LINK TO FEEDBACK FORM)提交建议 👈 + +## 课程大纲 +以下是课程总体大纲,各单元详细主题将随课程发布: + +| 章节 | 主题 | 描述 | +| ---- | ----------------------------------------- | --------------------------------------------------------------------------------------- | +| 0 | 入门指南 | 配置开发环境与学习平台 | +| 1 | MCP 基础、架构与核心概念 | 解析 MCP 核心概念与架构组件,演示基础用例 | +| 2 | 端到端案例:MCP 实战 | 构建可分享的完整 MCP 应用 | +| 3 | 部署案例:MCP 实战 | 使用 Hugging Face 生态与合作伙伴服务部署 MCP 应用 | +| 4 | 附加单元 | 与合作伙伴共同打造的拓展内容 | + +## 先修要求 +建议具备: +* AI 和 LLM 基础概念理解 +* 软件开发与 API 基础认知 +* 至少掌握一门编程语言(课程示例使用 Python/TypeScript) + +如需补充知识: +* [LLM 课程](https://huggingface.co/learn/llm-course/):LLM 基础与应用 +* [智能体课程](https://huggingface.co/learn/agents-course/):LLM 智能体开发 + + +以上课程非强制先修,只要理解 LLM 和智能体概念即可立即开始! + + +## 所需工具 +仅需: +* 可联网的_电脑_ +* Hugging Face _账户_([免费注册](https://huggingface.co/join)) + +## 证书获取 +两种学习模式: +* _旁听模式_:可参与所有活动(无需证书) +* _认证模式_(完全免费): + - **基础证书**:完成单元 1(适合了解 MCP 最新趋势) + - **结业证书**:完成单元 2-3(需构建完整应用) + +## 学习进度建议 +每周投入 3-4 小时,1 周完成 1 个章节: + +![推荐进度](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit0/2.png) + +## 高效学习建议 +1. 加入 Discord 学习小组 +2. **完成测验与作业** +3. **制定学习计划** + +![学习建议](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit0/3.png) + +## 课程团队 +### Ben Burtenshaw +Hugging Face 机器学习工程师,专注于 LLM 应用开发与智能体技术 + +## 问题反馈 +欢迎贡献 🤗 +* 提交 bug:GitHub 创建 issue +* 改进课程:提交 Pull Request +* 新增内容:先创建 issue 讨论方案 + +## 其他问题 +请至 Discord 的 #mcp-course-questions 频道提问 + +准备好启航了吗?⛵ \ No newline at end of file diff --git a/units/zh_CN/unit1/architectural-components.mdx b/units/zh_CN/unit1/architectural-components.mdx new file mode 100644 index 0000000..4c3f754 --- /dev/null +++ b/units/zh_CN/unit1/architectural-components.mdx @@ -0,0 +1,85 @@ +# MCP 的架构组件 + +在上一节中,我们讨论了 MCP 的核心概念和术语。现在让我们深入探讨构成 MCP 生态系统的架构组件。 + +## Host、Client 和 Server + +模型上下文协议(Model Context Protocol,MCP)基于客户端-服务端架构构建,实现 AI 模型与外部系统的结构化通信。 + +![MCP 架构示意图](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/4.png) + +MCP 架构包含三个主要组件,每个组件都有明确的职责划分: + +### Host(宿主) + +**Host** 是直接面向用户的 AI 应用程序。典型示例包括: +- AI 聊天应用(如 OpenAI ChatGPT 或 Anthropic 的 Claude Desktop) +- 增强型 IDE(如 Cursor)或工具集成(如 Continue.dev) +- 使用 LangChain 或 smolagents 构建的自定义智能体 + +Host 的核心职责: +- 管理用户交互与权限控制 +- 通过 MCP Client 建立与 Server 的连接 +- 协调用户请求、LLM 处理与外部工具的整体流程 +- 以可理解格式呈现结果 + +开发者可能选择 Cursor 作为开发工具,而领域专家可能使用 smolagents 构建定制应用。 + +### Client(客户端) + +**Client** 是 Host 应用中负责与特定 Server 通信的组件,特点包括: +- 与单个 Server 保持 1:1 连接 +- 处理 MCP 协议层通信细节 +- 作为 Host 逻辑与外部 Server 的中介 + +### Server(服务端) + +**Server** 是通过 MCP 协议对外提供能力的程序/服务,特点包括: +- 封装特定外部工具、数据源或服务 +- 可作为现有功能的轻量级封装层 +- 支持本地或远程部署 +- 以标准化格式暴露可发现的能力 + +## 通信流程 + +典型 MCP 工作流包含以下步骤: + + +下一节将通过实际案例深入解析通信协议细节 + + +1. **用户交互**:用户与 Host 应用进行交互 +2. **请求处理**:Host 解析用户输入(可能使用 LLM) +3. **建立连接**:Host 指示 Client 连接目标 Server +4. **能力发现**:Client 查询 Server 可用能力(工具/资源/提示词) +5. **调用能力**:根据需求调用 Server 特定能力 +6. **执行返回**:Server 执行操作并返回结果 +7. **结果整合**:Client 将结果传回 Host 进行后续处理 + +架构优势在于模块化设计: +- 单个 Host 可通过多个 Client 连接不同 Server +- 新增 Server 无需修改现有 Host +- 跨 Server 能力可自由组合 + + +这种设计将传统的 M×N 集成问题转化为 M+N 问题,各组件只需实现一次 MCP 标准 + + +## 架构优势 + +该架构的核心价值在于: +- **协议标准化**:统一通信规范 +- **职责分离**:明确组件边界 +- **生态扩展性**:支持无缝接入新工具和数据源 + +## 设计原则 + +MCP 遵循以下核心原则: +- **标准化**:提供通用 AI 连接协议 +- **简洁性**:保持核心协议简单直观 +- **安全性**:敏感操作需显式用户授权 +- **可发现性**:支持动态能力探测 +- **可扩展性**:通过版本协商支持演进 +- **互操作性**:确保跨实现环境的兼容性 + +下一节我们将深入解析实现这些组件协作的通信协议细节。 \ No newline at end of file diff --git a/units/zh_CN/unit1/capabilities.mdx b/units/zh_CN/unit1/capabilities.mdx new file mode 100644 index 0000000..1b9dee8 --- /dev/null +++ b/units/zh_CN/unit1/capabilities.mdx @@ -0,0 +1,251 @@ +# 理解 MCP 能力 + +MCP 服务器通过通信协议向客户端暴露多种能力。这些能力分为四大主要类别,每个类别都有独特的特性和用例。让我们探索构成 MCP 功能基础的核心要素。 + + + +在本节中,我们将以框架无关的函数形式展示不同语言的示例。这样做是为了聚焦概念及其协作方式,而非具体框架的复杂性。 + +在后续单元中,我们将展示这些概念如何通过 MCP 专用代码实现。 + + + +## 工具(Tools) + +工具是 AI 模型可以通过 MCP 协议调用的可执行函数或操作。 + +- **控制**:工具通常是**模型控制**的,即 AI 模型(LLM)根据用户请求和上下文决定何时调用 +- **安全性**:由于可能产生副作用,工具执行可能存在风险,因此通常需要用户明确批准 +- **用例**:发送消息、创建工单、查询 API、执行计算 + +**示例**:获取指定位置天气数据的工具: + + + + +```python +def get_weather(location: str) -> dict: + """Get the current weather for a specified location.""" + # Connect to weather API and fetch data + return { + "temperature": 72, + "conditions": "Sunny", + "humidity": 45 + } +``` + + + + +```javascript +function getWeather(location) { + // Connect to weather API and fetch data + return { + temperature: 72, + conditions: 'Sunny', + humidity: 45 + }; +} +``` + + + + +## 资源(Resources) + +资源提供对数据源的只读访问,使 AI 模型能够检索上下文而无需执行复杂逻辑。 + +- **控制**: 资源是**应用控制**的,通常由宿主应用决定访问时机 +- **特性**: 设计用于最小化计算的数据检索,类似 REST API 的 GET 端点 +- **安全性**: 只读特性使其安全风险低于工具 +- **用例**: 访问文件内容、检索数据库记录、读取配置信息 + +**示例**: 提供文件内容访问的资源: + + + + +```python +def read_file(file_path: str) -> str: + """Read the contents of a file at the specified path.""" + with open(file_path, 'r') as f: + return f.read() +``` + + + + +```javascript +function readFile(filePath) { + // Using fs.readFile to read file contents + const fs = require('fs'); + return new Promise((resolve, reject) => { + fs.readFile(filePath, 'utf8', (err, data) => { + if (err) { + reject(err); + return; + } + resolve(data); + }); + }); +} +``` + + + + +## 提示词(Prompts) + +提示词是预定义的模板或工作流,用于引导用户、AI 模型和服务器能力之间的交互。 + +- **控制权**:提示词由**用户控制**,通常以选项形式呈现在宿主应用的用户界面中 +- **目的**:优化工具和资源的使用结构 +- **选择时机**:用户通常在 AI 模型开始处理前选择提示词,设定交互的上下文 +- **应用场景**:通用工作流程、专项任务模板、引导式交互 + +**示例**:生成代码审查的提示模板: + + + + +```python +def code_review(code: str, language: str) -> list: + """Generate a code review for the provided code snippet.""" + return [ + { + "role": "system", + "content": f"You are a code reviewer examining {language} code. Provide a detailed review highlighting best practices, potential issues, and suggestions for improvement." + }, + { + "role": "user", + "content": f"Please review this {language} code:\n\n```{language}\n{code}\n```" + } + ] +``` + + + + +```javascript +function codeReview(code, language) { + return [ + { + role: 'system', + content: `You are a code reviewer examining ${language} code. Provide a detailed review highlighting best practices, potential issues, and suggestions for improvement.` + }, + { + role: 'user', + content: `Please review this ${language} code:\n\n\`\`\`${language}\n${code}\n\`\`\`` + } + ]; +} +``` + + + + +## 采样(Sampling) + +采样允许服务端请求客户端(具体指宿主应用)执行 LLM 交互。 + +- **控制权**:采样由**服务端发起**,但需要客户端/宿主配合 +- **目的**:支持服务端驱动的智能体行为和递归多步骤交互 +- **安全性**:类似工具操作,通常需要用户授权 +- **应用场景**:复杂多步骤任务、自主智能体工作流、交互式流程 + +**示例**:服务端请求客户端分析已处理数据: + + + + +```python +def request_sampling(messages, system_prompt=None, include_context="none"): + """Request LLM sampling from the client.""" + # In a real implementation, this would send a request to the client + return { + "role": "assistant", + "content": "Analysis of the provided data..." + } +``` + + + + +```javascript +function requestSampling(messages, systemPrompt = null, includeContext = 'none') { + // In a real implementation, this would send a request to the client + return { + role: 'assistant', + content: 'Analysis of the provided data...' + }; +} + +function handleSamplingRequest(request) { + const { messages, systemPrompt, includeContext } = request; + // In a real implementation, this would process the request and return a response + return { + role: 'assistant', + content: 'Response to the sampling request...' + }; +} +``` + + + + +采样流程包含以下步骤: +1. 服务端向客户端发送 `sampling/createMessage` 请求 +2. 客户端审核并可能修改请求 +3. 客户端执行 LLM 采样 +4. 客户端审核生成结果 +5. 客户端返回结果至服务端 + + +这种人机协同设计确保用户对 LLM 的输入输出保持控制权。实现采样时需注意: +- 提供结构清晰、内容明确的提示词 +- 包含相关上下文信息 + + +## 能力协作机制 + +| 能力类型 | 控制方 | 通信方向 | 副作用 | 需授权 | 典型应用场景 | +|------------|----------------|------------------------|----------|--------|----------------------| +| 工具 | 模型 (LLM) | Client → Server | 可能有 | 是 | API 调用、数据操作 | +| 资源 | 应用 | Client → Server | 无 | 通常否 | 数据检索 | +| 提示词 | 用户 | Server → Client | 无 | 否 | 引导式工作流 | +| 采样 | 服务端 | Server → Client → Server | 间接有 | 是 | 多步骤智能体任务 | + +能力协作范例: +1. 用户选择**提示词**启动专项流程 +2. 提示词整合**资源**提供的上下文 +3. AI 模型调用**工具**执行操作 +4. 复杂任务中服务端使用**采样**请求额外 LLM 处理 + +这种分层设计为 MCP 交互提供了清晰结构,使 AI 模型能够: +- 安全访问信息 +- 执行具体操作 +- 处理复杂工作流 +同时保持合理的控制边界 + +## 动态发现机制 + +MCP 的关键特性之一是能力动态发现机制: +- `tools/list`: 发现可用工具 +- `resources/list`: 发现可用资源 +- `prompts/list`: 发现可用提示词 + +该机制使客户端无需硬编码即可适配不同服务端的能力组合 + +## 核心价值 + +理解这些核心要素对于有效使用 MCP 至关重要: +- **明确的能力边界**:区分不同类型的能力及其控制权 +- **安全机制**:通过授权机制保障敏感操作的安全性 +- **灵活扩展**:支持动态发现新接入的服务端能力 + +这些设计原则使 MCP 能够: +- 实现 AI 模型与外部系统的高效交互 +- 保持生态系统的可扩展性 +- 确保复杂场景下的可控性 + +下一节我们将探索如何通过 Gradio 为这些能力构建易用接口 \ No newline at end of file diff --git a/units/zh_CN/unit1/certificate.mdx b/units/zh_CN/unit1/certificate.mdx new file mode 100644 index 0000000..fead643 --- /dev/null +++ b/units/zh_CN/unit1/certificate.mdx @@ -0,0 +1,19 @@ +# 获取你的证书! + +干得漂亮!你已经完成了 MCP 课程的第一个单元。现在该参加考试获取证书了。 + +以下是一个测验,用于检查你对该单元的理解。 + + + + + +如果无法正常使用上方测验,可以直接访问 [Hugging Face Hub](https://huggingface.co/spaces/mcp-course/unit_1_quiz) 上的空间。如果发现错误,可以在该空间的 [Community 标签页](https://huggingface.co/spaces/mcp-course/unit_1_quiz/discussions) 中报告。 + + + diff --git a/units/zh_CN/unit1/communication-protocol.mdx b/units/zh_CN/unit1/communication-protocol.mdx new file mode 100644 index 0000000..b27293e --- /dev/null +++ b/units/zh_CN/unit1/communication-protocol.mdx @@ -0,0 +1,221 @@ +# 通信协议 + +MCP 定义了一套标准化的通信协议,使客户端和服务端能够以一致、可预测的方式进行消息交换。这种标准化对于实现跨平台的互操作性至关重要。本节我们将深入解析 MCP 的协议结构和传输机制。 + + + +虽然实际开发中不需要掌握所有协议细节,但了解其工作原理对构建 MCP 应用很有帮助。 + + + +## JSON-RPC:协议基础 + +MCP 使用 **JSON-RPC 2.0** 作为客户端与服务端通信的核心消息格式。这种轻量级远程过程调用协议具有以下优势: + +- 人类可读,易于调试 +- 语言无关,支持任意编程环境 +- 规范明确,社区广泛采用 + +![消息类型示意图](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/5.png) + +协议定义了三种消息类型: + +### 1. 请求(Requests) + +由客户端发往服务端以发起操作,包含: +- 唯一标识符 ([id](file://e:\githubProjects\incubator-shenyu\shenyu-common\src\main\java\org\apache\shenyu\common\dto\RuleData.java#L29-L29)) +- 调用方法名(如 `tools/call`) +- 方法参数(可选) + +请求示例: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "tools/call", + "params": { + "name": "weather", + "arguments": { + "location": "San Francisco" + } + } +} +``` + +### 2. 响应 + +服务器发送响应给客户端,以回复请求。响应消息包含: +- 与相应请求相同的 `id` +- 成功时返回 `result`,失败时返回 `error` + +成功响应示例: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "temperature": 62, + "conditions": "Partly cloudy" + } +} +``` + +错误响应示例: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32602, + "message": "Invalid location parameter" + } +} +``` + +### 3. 通知 + +无需响应的单向消息。通常由服务器发送到客户端,用于提供事件更新或通知。 + +通知示例: +```json +{ + "jsonrpc": "2.0", + "method": "progress", + "params": { + "message": "Processing data...", + "percent": 50 + } +} +``` + +## 传输机制 + +JSON-RPC 定义了消息格式,但 MCP 还规定了这些消息在客户端和服务器之间的传输方式。主要支持两种传输机制: + +### stdio(标准输入/输出) + +stdio 传输用于本地通信,当客户端和服务器运行在同一台机器时: + +宿主应用将服务器作为子进程启动,通过写入其标准输入(stdin)和读取标准输出(stdout)进行通信。 + + + +**典型用例**:文件系统访问或运行本地脚本等本地工具。 + + + +主要**优势**:简单无需网络配置,受操作系统安全沙盒保护。 + +### HTTP + SSE(服务器发送事件)/ 可流式 HTTP + +HTTP+SSE 传输用于远程通信,当客户端和服务器可能位于不同机器时: + +通过 HTTP 进行通信,服务器使用服务器发送事件(SSE)通过持久连接向客户端推送更新。 + + + +**典型用例**:连接远程 API、云服务或共享资源。 + + + +主要**优势**:支持跨网络工作,可与 Web 服务集成,兼容无服务器环境。 + +MCP 标准的最新更新引入并改进了"可流式 HTTP",允许服务器在需要时动态升级到 SSE 进行流传输,同时保持与无服务器环境的兼容性。 + +## 交互生命周期 + +MCP 协议定义了客户端与服务器之间结构化的交互生命周期: + +### 初始化 + +客户端连接服务器并交换协议版本和能力信息,服务器响应其支持的协议版本和功能。 + + + + + + + + + + + + + + + + + +
💻
initialize
🌐
💻
response
🌐
💻
initialized
🌐
+ +客户端通过通知消息确认初始化完成。 + +### 发现 + +客户端请求可用能力信息,服务器响应可用工具列表。 + + + + + + + + + + + + +
💻
tools/list
🌐
💻
response
🌐
+ +此过程可针对每种工具、资源或提示类型重复执行。 + +### 执行 + +客户端根据宿主需求调用能力: + + + + + + + + + + + + + + + + + +
💻
tools/call
🌐
💻
notification (optional progress)
🌐
💻
response
🌐
+ +### 终止 + +当不再需要连接时优雅关闭,服务器确认关闭请求: + + + + + + + + + + + + + + + + + +
💻
shutdown
🌐
💻
response
🌐
💻
exit
🌐
+ +客户端发送最终 exit 消息完成终止流程。 + +## 协议演进 + +MCP 协议设计具备可扩展性和适应性。初始化阶段包含版本协商机制,支持协议演进时的向后兼容。能力发现机制使客户端能适配不同服务器的特性,实现在同一生态系统中基础服务器和高级服务器的共存。 diff --git a/units/zh_CN/unit1/gradio-mcp.mdx b/units/zh_CN/unit1/gradio-mcp.mdx new file mode 100644 index 0000000..2c29244 --- /dev/null +++ b/units/zh_CN/unit1/gradio-mcp.mdx @@ -0,0 +1,155 @@ +# Gradio MCP 集成 + +我们已经探索了 MCP 协议的核心概念及如何实现 MCP 服务器和客户端。本节我们将使用 Gradio 简化 MCP 服务器的创建! + + + +Gradio 是流行的 Python 库,可快速为机器学习模型创建可定制 Web 界面。 + + + +## Gradio 简介 + +Gradio 允许开发者用几行 Python 代码为模型创建 UI,特别适用于: +- 创建演示和原型 +- 与非技术用户共享模型 +- 测试和调试模型行为 + +通过新增的 MCP 支持,Gradio 现在能够通过标准化 MCP 协议暴露 AI 模型能力。 + +Gradio 与 MCP 的结合让你能用最少代码同时创建人性化界面和 AI 可访问工具。最重要的是,Gradio 已被 AI 社区广泛使用,便于分享你的 MCP 服务器。 + +## 前提条件 + +使用 Gradio 的 MCP 支持需要安装额外依赖: +```bash +pip install "gradio[mcp]" +``` + +同时需要支持 MCP 协议工具调用的 LLM 应用,例如 Cursor(即 "MCP Hosts")。 + +## 使用 Gradio 创建 MCP 服务器 + +以下是通过 Gradio 创建 MCP 服务器的基础示例: + +```python +import gradio as gr + +def letter_counter(word: str, letter: str) -> int: + """ + Count the number of occurrences of a letter in a word or text. + + Args: + word (str): The input text to search through + letter (str): The letter to search for + + Returns: + int: The number of times the letter appears in the text + """ + word = word.lower() + letter = letter.lower() + count = word.count(letter) + return count + +# Create a standard Gradio interface +demo = gr.Interface( + fn=letter_counter, + inputs=["textbox", "textbox"], + outputs="number", + title="Letter Counter", + description="Enter text and a letter to count how many times the letter appears in the text." +) + +# Launch both the Gradio web interface and the MCP server +if __name__ == "__main__": + demo.launch(mcp_server=True) +``` + +通过这种设置,你的字母计数功能现在可以通过以下两种方式访问: + +1. 传统的 Gradio 网页界面,供用户直接交互 +2. 可连接兼容客户端的 MCP 服务器 + +MCP 服务器可通过以下地址访问: +``` +http://your-server:port/gradio_api/mcp/sse +``` + +应用本身仍然保持可访问,界面如下所示: + +![Gradio MCP Server](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/7.png) + +## 幕后工作原理 + +当你在 `launch()` 中设置 `mcp_server=True` 时,会发生以下变化: + +1. Gradio 函数会自动转换为 MCP 工具 +2. 输入组件映射到工具参数模式 +3. 输出组件决定响应格式 +4. Gradio 服务器现在同时监听 MCP 协议消息 +5. 建立基于 HTTP+SSE 的 JSON-RPC 协议用于客户端-服务器通信 + +## Gradio <> MCP 集成的关键特性 + +1. **工具转换**:你的 Gradio 应用中的每个 API 端点都会自动转换为具有对应名称、描述和输入模式的 MCP 工具。要查看工具和模式,请访问 `http://your-server:port/gradio_api/mcp/schema` 或点击 Gradio 应用页脚的 "View API" 链接,然后选择 "MCP"。 + +2. **环境变量支持**:有两种方式可以启用 MCP 服务器功能: +- 在 `launch()` 中使用 `mcp_server` 参数: + ```python + demo.launch(mcp_server=True) + ``` +- Using environment variables: + ```bash + export GRADIO_MCP_SERVER=True + ``` + +3. **文件处理**:服务器会自动处理文件数据转换,包括: + - 将 base64 编码字符串转换为文件数据 + - 处理图像文件并以正确格式返回 + - 管理临时文件存储 + + **强烈** 建议输入图像和文件使用完整 URL("http://..." 或 "https://...")传递,因为 MCP 客户端并不总是能正确处理本地文件。 + +4. **在 🤗 Spaces 上托管 MCP 服务器**:你可以将 Gradio 应用免费发布到 Hugging Face Spaces,从而获得免费的托管 MCP 服务器。以下是一个示例 Space:https://huggingface.co/spaces/abidlabs/mcp-tools + +## 故障排除提示 + +1. **类型提示与文档字符串**:确保为函数提供类型提示和有效的文档字符串。文档字符串应包含带缩进参数名的 "Args:" 代码块。 + +2. **字符串输入**:当不确定时,请将输入参数接受为 [str](file://e:\githubProjects\nacos\naming\src\test\java\com\alibaba\nacos\naming\consistency\persistent\impl\NamingKvStorageTest.java#L45-L45) 类型,并在函数内部将其转换为所需类型。 + +3. **SSE 支持**:部分 MCP Hosts 不支持基于 SSE 的 MCP 服务器。这种情况下可以使用 `mcp-remote`: + ```json + { + "mcpServers": { + "gradio": { + "command": "npx", + "args": [ + "mcp-remote", + "http://your-server:port/gradio_api/mcp/sse" + ] + } + } + } + ``` + +4. **重启建议**:如果遇到连接问题,请尝试同时重启你的 MCP 客户端和 MCP 服务器。 + +## 分享你的 MCP 服务器 + +你可以通过将 Gradio 应用发布到 Hugging Face Spaces 来分享 MCP 服务器。以下视频演示了如何创建 Hugging Face Space: + + + +现在,你可以通过分享你的 Hugging Face Space 来与他人共享 MCP 服务器。 + +## 结论 + +Gradio 与 MCP 的集成为 MCP 生态系统提供了便捷的入口。通过结合 Gradio 的简易性和 MCP 的标准化,开发者可以用最少代码快速创建人性化界面和 AI 可访问工具。 + +随着课程深入,我们将探索更复杂的 MCP 实现方案,但 Gradio 为协议的理解和实验提供了绝佳的起点。 + +下一单元我们将深入探讨 MCP 应用开发,重点包括: +- 开发环境搭建 +- SDK 探索 +- 高级 MCP 服务器和客户端的实现 \ No newline at end of file diff --git a/units/zh_CN/unit1/introduction.mdx b/units/zh_CN/unit1/introduction.mdx new file mode 100644 index 0000000..67a71aa --- /dev/null +++ b/units/zh_CN/unit1/introduction.mdx @@ -0,0 +1,33 @@ +# Model Context Protocol (MCP) 简介 + +欢迎来到 MCP 课程的第一单元!本单元我们将探索 Model Context Protocol 的基础知识。 + +## 你将学到什么 + +在本单元中,你将: + +* 理解 Model Context Protocol 是什么及其重要性 +* 学习与 MCP 相关的关键概念和术语 +* 探索 MCP 解决的集成挑战 +* 了解 MCP 的核心优势与目标 +* 通过简单示例观察 MCP 集成的实际应用 + +完成本单元后,你将牢固掌握 MCP 的基础概念,为后续单元深入学习其架构与实现做好准备。 + +## MCP 的重要性 + +AI 生态系统正在快速发展,大型语言模型(LLMs)和其他 AI 系统日益强大。然而,这些模型常受限于训练数据,缺乏实时信息或专用工具的访问能力。这种限制阻碍了 AI 系统在许多场景中提供真正相关、准确且有价值的响应。 + +这正是 Model Context Protocol (MCP) 的用武之地。MCP 使 AI 模型能够连接外部数据源、工具和环境,实现 AI 系统与数字世界之间信息和能力的无缝传输。这种互操作性对于实用 AI 应用的发展和普及至关重要。 + +## 第一单元概览 + +以下是本单元内容概览: + +1. **什么是 Model Context Protocol?** - 从定义 MCP 及其在 AI 生态系统中的作用开始 +2. **关键概念** - 探索 MCP 的核心概念与术语体系 +3. **集成挑战** - 分析 MCP 旨在解决的 "M×N 集成问题" +4. **优势与目标** - 讨论标准化、增强 AI 能力和互操作性等核心优势 +5. **简单示例** - 通过实际案例观察 MCP 集成机制 + +现在让我们正式开启 Model Context Protocol 的探索之旅! \ No newline at end of file diff --git a/units/zh_CN/unit1/key-concepts.mdx b/units/zh_CN/unit1/key-concepts.mdx new file mode 100644 index 0000000..075b3f8 --- /dev/null +++ b/units/zh_CN/unit1/key-concepts.mdx @@ -0,0 +1,88 @@ +# 关键概念与术语 + +在深入探讨模型上下文协议(Model Context Protocol,MCP)之前,理解构成 MCP 基础的关键概念和术语非常重要。本节将介绍支撑该协议的基本概念,并为整个课程中讨论 MCP 实现提供通用术语。 + +MCP 常被描述为 "AI 应用的 USB-C"。正如 USB-C 为连接各种外设到计算设备提供了标准化物理和逻辑接口,MCP 为连接 AI 模型与外部能力提供了一致的协议。这种标准化使整个生态系统受益: + +- **用户** 能在不同 AI 应用中获得更简单一致的体验 +- **AI 应用开发者** 可轻松集成日益增长的工具和数据源生态系统 +- **工具和数据提供者** 只需创建单个实现即可与多个 AI 应用协同工作 +- **整个生态系统** 通过增强互操作性、创新和减少碎片化而受益 + +## 集成问题 + +**M×N 集成问题** 指的是在没有标准化方法的情况下,连接 M 个不同 AI 应用到 N 个不同外部工具或数据源所面临的挑战。 + +### 无 MCP 方案(M×N 问题) + +没有 MCP 这样的协议时,开发者需要创建 M×N 个定制集成——每个 AI 应用与外部能力的配对都需要单独实现。 + +![无 MCP 方案](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/1.png) + +每个 AI 应用都需要单独与每个工具/数据源集成。这是个非常复杂且昂贵的过程,给开发者带来巨大阻力,并产生高昂维护成本。 + +### 使用 MCP 方案(M+N 解决方案) + +MCP 通过提供标准接口将此问题转化为 M+N 问题:每个 AI 应用只需实现一次 MCP 客户端,每个工具/数据源只需实现一次 MCP 服务端。这显著降低了集成复杂度和维护负担。 + +![使用 MCP 方案](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/2.png) + +每个 AI 应用实现一次 MCP 客户端,每个工具/数据源实现一次 MCP 服务端。 + +## MCP 核心术语 + +现在我们已经理解 MCP 解决的问题,让我们深入了解构成 MCP 协议的核心术语和概念。 + + + +MCP 是类似 HTTP 或 USB-C 的标准协议,用于连接 AI 应用到外部工具和数据源。因此,使用标准术语对 MCP 有效运作至关重要。 + +在编写应用文档和社区交流时,我们应该使用以下标准术语。 + + + +### 核心组件 + +正如 HTTP 中的客户端-服务器关系,MCP 也有客户端和服务器。 + +![MCP 组件](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/3.png) + +- **宿主应用(Host)**:直接面向用户的 AI 应用,终端用户直接与之交互。例如 Anthropic 的 Claude Desktop、Cursor 等 AI 增强 IDE、Hugging Face Python SDK 等推理库,或基于 LangChain/smolagents 构建的定制应用。宿主应用负责发起与 MCP 服务器的连接,并协调用户请求、LLM 处理和外部工具之间的整体流程。 + +- **客户端组件(Client)**:宿主应用中管理与特定 MCP 服务器通信的组件。每个客户端维护与单个服务器的 1:1 连接,处理 MCP 通信的协议细节,并充当宿主应用逻辑与外部服务器之间的中介。 + +- **服务器(Server)**:通过 MCP 协议暴露能力(工具、资源、提示)的外部程序或服务。 + + + +许多内容将 'Client' 和 'Host' 混用。严格来说,宿主应用是面向用户的应用程序,客户端是宿主应用中管理与特定 MCP 服务器通信的组件。 + + + +### 核心能力 + +当然,应用程序的价值取决于其提供的能力总和。因此能力是应用程序最重要的组成部分。MCP 可以连接任何软件服务,但许多 AI 应用会使用以下常见能力: + +| 能力类型 | 描述 | 示例 | +|---------------|----------------------------------------------------------------------|----------------------------------------------------------------------| +| **工具** | AI 模型可调用的可执行函数,用于执行操作或获取计算数据,通常与应用用例相关 | 天气应用中的工具可能是返回特定位置天气的函数 | +| **资源** | 提供上下文只读数据源,无需复杂计算 | 研究助手可能包含科学论文资源 | +| **提示** | 预定义模板或工作流,指导用户、AI 模型与可用能力之间的交互 | 摘要生成提示 | +| **采样** | 服务器发起的请求,要求客户端/宿主执行 LLM 交互,支持 LLM 审查生成内容并做出后续决策的递归操作 | 写作应用审查自身输出并决定进一步优化的场景 | + +在下图中,我们可以看到这些能力在代码智能体用例中的综合应用: + +![能力综合示意图](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/8.png) + +该应用可能以下列方式使用其 MCP 实体: + +| 实体类型 | 名称 | 描述 | +|------------|--------------|----------------------------------| +| 工具 | 代码解释器 | 可执行 LLM 编写代码的工具 | +| 资源 | 文档库 | 包含应用程序文档的资源 | +| 提示 | 代码风格 | 指导 LLM 生成代码的提示模板 | +| 采样 | 代码审查 | 允许 LLM 审查代码并决策的采样机制 | + +### 结语 + +理解这些关键概念和术语为有效使用 MCP 奠定了基础。在后续章节中,我们将基于此基础,探索构成模型上下文协议的架构组件、通信协议和能力体系。 \ No newline at end of file diff --git a/units/zh_CN/unit1/mcp-clients.mdx b/units/zh_CN/unit1/mcp-clients.mdx new file mode 100644 index 0000000..4a672d0 --- /dev/null +++ b/units/zh_CN/unit1/mcp-clients.mdx @@ -0,0 +1,342 @@ +# MCP Clients + +现在我们已经对模型上下文协议(Model Context Protocol)有了基本了解,接下来可以探索 MCP 客户端在 MCP 生态系统中的关键作用。 + +在本单元的第一部分,我们将探讨 MCP 客户端在模型上下文协议生态系统中的核心角色。 + +在本节中,您将: + +* 理解 MCP 客户端的定义及其在 MCP 架构中的角色 +* 了解 MCP 客户端的主要职责 +* 探索主流的 MCP 客户端实现方案 +* 学习如何使用 Hugging Face 的 MCP 客户端实现 +* 查看 MCP 客户端的实际使用示例 + +## 理解 MCP 客户端 + +MCP 客户端是连接 AI 应用(宿主)与 MCP 服务器提供的外部能力之间的关键桥梁。可以将宿主视为您的主应用程序(如 AI 助手或 IDE),而客户端则是宿主中专门处理 MCP 通信的模块。 + +## 用户界面客户端 + +让我们从探索 MCP 可用的用户界面客户端开始。 + +### 聊天界面客户端 + +Anthropic 的 Claude Desktop 是最突出的 MCP 客户端之一,提供与各种 MCP 服务器的集成。 + +### 交互式开发客户端 + +Cursor 的 MCP 客户端实现通过直接集成代码编辑能力,提供 AI 驱动的编码辅助。它支持多个 MCP 服务器连接,并在编码过程中提供实时工具调用,是开发者的强大工具。 + +Continue.dev 是另一个支持 MCP 的交互式开发客户端示例,可以从 VS Code 连接到 MCP 服务器。 + +## 配置 MCP 客户端 + +现在我们已经介绍了 MCP 协议的核心内容,接下来看看如何配置您的 MCP 服务器和客户端。 + +要成功部署 MCP 服务器和客户端,需要进行正确的配置。 + + + +由于 MCP 规范仍在演进中,配置方法可能会随之变化。我们将重点介绍当前的最佳配置实践。 + + + +### MCP 配置文件 + +MCP 宿主使用配置文件来管理服务器连接。这些文件定义了可用的服务器及其连接方式。 + +幸运的是,这些配置文件非常简洁易懂,且在主流 MCP 宿主中保持统一。 + +#### `mcp.json` 结构 + +标准的 MCP 配置文件名为 `mcp.json`,其基本结构如下: + +```json +{ + "servers": [ + { + "name": "Server Name", + "transport": { + "type": "stdio|sse", + // Transport-specific configuration + } + } + ] +} +``` + +在此示例中,我们有一个服务器,它具有名称和传输类型。传输类型可以是 `stdio` 或 `sse`。 + +#### stdio 传输配置 + +对于使用 stdio 传输的本地服务器,配置包含启动服务器进程的命令和参数: + +```json +{ + "servers": [ + { + "name": "File Explorer", + "transport": { + "type": "stdio", + "command": "python", + "args": ["/path/to/file_explorer_server.py"] + } + } + ] +} +``` + +这里,我们有一个名为“文件资源管理器”的服务器,它是一个本地脚本。 + +#### HTTP+SSE 传输配置 + +对于使用 HTTP+SSE 传输的远程服务器,配置包含服务器 URL: + +```json +{ + "servers": [ + { + "name": "Remote API Server", + "transport": { + "type": "sse", + "url": "https://example.com/mcp-server" + } + } + ] +} +``` + +#### 配置中的环境变量 + +可以使用 `env` 字段将环境变量传递给服务器进程。以下是在服务器代码中访问它们的方法: + + + + +在 Python 中,我们使用 `os` 模块来访问环境变量: + +```python +import os + +# Access environment variables +github_token = os.environ.get("GITHUB_TOKEN") +if not github_token: + raise ValueError("GITHUB_TOKEN environment variable is required") + +# Use the token in your server code +def make_github_request(): + headers = {"Authorization": f"Bearer {github_token}"} + # ... rest of your code +``` + + + + +在 JavaScript 中,我们使用 `process.env` 对象来访问环境变量: + +```javascript +// Access environment variables +const githubToken = process.env.GITHUB_TOKEN; +if (!githubToken) { + throw new Error("GITHUB_TOKEN environment variable is required"); +} + +// Use the token in your server code +function makeGithubRequest() { + const headers = { "Authorization": `Bearer ${githubToken}` }; + // ... rest of your code +} +``` + + + + +`mcp.json` 中相应的配置如下: + +```json +{ + "servers": [ + { + "name": "GitHub API", + "transport": { + "type": "stdio", + "command": "python", + "args": ["/path/to/github_server.py"], + "env": { + "GITHUB_TOKEN": "your_github_token" + } + } + } + ] +} +``` + +### 配置示例 + +让我们来看一些实际的配置场景: + +#### 场景 1:本地服务器配置 + +在此场景中,我们有一个本地服务器,它是一个 Python 脚本,可以是文件资源管理器或代码编辑器。 + +```json +{ + "servers": [ + { + "name": "File Explorer", + "transport": { + "type": "stdio", + "command": "python", + "args": ["/path/to/file_explorer_server.py"] + } + } + ] +} +``` + +#### 场景 2:远程服务器配置 + +在此场景中,我们有一个作为天气 API 的远程服务器。 + +```json +{ + "servers": [ + { + "name": "Weather API", + "transport": { + "type": "sse", + "url": "https://example.com/mcp-server" + } + } + ] +} +``` + +正确的配置对于成功部署 MCP 集成至关重要。通过了解这些方面,您可以在 AI 应用程序和外部功能之间建立稳健可靠的连接。 + +在下一节中,我们将探索 Hugging Face Hub 上可用的 MCP 服务器生态系统,以及如何在那里发布您自己的服务器。 + +## 代码客户端 + +您还可以在代码中使用 MCP 客户端,以便 LLM 可以使用这些工具。让我们在 `smolagents` 中探索一些示例。 + +首先,让我们探索上一页中的天气服务器。在 `smolagents` 中,我们可以使用 `ToolCollection` 类自动从 MCP 服务器发现并注册工具。这可以通过将 `StdioServerParameters` 或 `SSEServerParameters` 传递给 `ToolCollection.from_mcp` 方法来实现。然后,我们可以将工具打印到控制台。 + +```python +from smolagents import ToolCollection, CodeAgent +from mcp.client.stdio import StdioServerParameters + +server_parameters = StdioServerParameters(command="uv", args=["run", "server.py"]) + +with ToolCollection.from_mcp( + server_parameters, trust_remote_code=True +) as tools: + print("\n".join(f"{t.name}: {t.description}" for t in tools)) + +``` + +
+ +Output + + +```sh +Weather API: Get the weather in a specific location + +``` + +
+ +我们也可以连接到托管在远程计算机上的 MCP 服务器。在这种情况下,我们需要将 `SSEServerParameters` 传递给 `ToolCollection.from_mcp` 方法。 + +```python +from smolagents.mcp_client import MCPClient + +with MCPClient( + {"url": "https://abidlabs-mcp-tools.hf.space/gradio_api/mcp/sse"} +) as tools: + # Tools from the remote server are available + print("\n".join(f"{t.name}: {t.description}" for t in tools)) +``` + +
+ +Output + + +```sh +prime_factors: Compute the prime factorization of a positive integer. +generate_cheetah_image: Generate a cheetah image. +image_orientation: Returns whether image is portrait or landscape. +sepia: Apply a sepia filter to the input image. +``` + +
+ +现在,让我们看看如何在代码智能体中使用 MCP 客户端。 + +```python +from smolagents import ToolCollection, CodeAgent +from mcp.client.stdio import StdioServerParameters +from smolagents import CodeAgent, InferenceClientModel + +model = InferenceClientModel() + +server_parameters = StdioServerParameters(command="uv", args=["run", "server.py"]) + +with ToolCollection.from_mcp( + server_parameters, trust_remote_code=True +) as tool_collection: + agent = CodeAgent(tools=[*tool_collection.tools], model=model) + agent.run("What's the weather in Tokyo?") + +``` + +
+ +Output + + +```sh +The weather in Tokyo is sunny with a temperature of 20 degrees Celsius. +``` + +
+ +我们还可以连接到 MCP 包。以下是连接到 `pubmedmcp` 包的示例。 + +```python +from smolagents import ToolCollection, CodeAgent +from mcp import StdioServerParameters + +server_parameters = StdioServerParameters( + command="uv", + args=["--quiet", "pubmedmcp@0.1.3"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +with ToolCollection.from_mcp(server_parameters, trust_remote_code=True) as tool_collection: + agent = CodeAgent(tools=[*tool_collection.tools], add_base_tools=True) + agent.run("Please find a remedy for hangover.") +``` + +
+ +Output + + +```sh +The remedy for hangover is to drink water. +``` + +
+ +## 后续步骤 + +现在您已经了解了 MCP 客户端,接下来可以: +* 探索具体的 MCP 服务器实现 +* 了解如何创建自定义 MCP 客户端 +* 深入研究高级 MCP 集成模式 + +让我们继续探索模型上下文协议 (MCP) 的世界! diff --git a/units/zh_CN/unit1/quiz1.mdx b/units/zh_CN/unit1/quiz1.mdx new file mode 100644 index 0000000..0b80ae7 --- /dev/null +++ b/units/zh_CN/unit1/quiz1.mdx @@ -0,0 +1,125 @@ +# Quiz 1: MCP 基础测试 + +测试你对 Model Context Protocol 核心概念的理解 + +### Q1: Model Context Protocol (MCP) 的主要目的是什么? + + + +### Q2: MCP 主要解决什么问题? + + + +### Q3: MCP 的关键优势是什么? + + + +### Q4: 在 MCP 术语中,什么是 Host? + + + +### Q5: M×N 集成问题在 AI 应用中指什么? + + + +恭喜完成测试 🥳!如需复习任何内容,建议重新学习本章节巩固知识。 \ No newline at end of file diff --git a/units/zh_CN/unit1/quiz2.mdx b/units/zh_CN/unit1/quiz2.mdx new file mode 100644 index 0000000..59f920a --- /dev/null +++ b/units/zh_CN/unit1/quiz2.mdx @@ -0,0 +1,125 @@ +# 测验 2: MCP SDK + +测试你对 MCP SDK 及其功能的理解 + +### Q1: MCP SDK 的主要目的是什么? + + + +### Q2: MCP SDK 通常处理哪些功能? + + + +### Q3: 根据课程内容,哪个公司维护官方的 Python SDK? + + + +### Q4: 使用名为 server.py 的 Python 文件启动开发 MCP 服务器的命令是什么? + + + +### Q5: JSON-RPC 2.0 在 MCP 中扮演什么角色? + + + +恭喜完成测验 🥳!如需复习任何内容,建议重新学习本章节巩固知识。 \ No newline at end of file diff --git a/units/zh_CN/unit1/sdk.mdx b/units/zh_CN/unit1/sdk.mdx new file mode 100644 index 0000000..662189c --- /dev/null +++ b/units/zh_CN/unit1/sdk.mdx @@ -0,0 +1,168 @@ +# MCP SDK + +模型上下文协议(Model Context Protocol)为 JavaScript、Python 及其他语言提供了官方 SDK。这使得在应用程序中实现 MCP 客户端和服务器变得非常简单。这些 SDK 负责处理底层协议细节,让开发者可以专注于构建应用的核心能力。 + +## SDK 概览 + +各语言 SDK 均提供相似的核心功能,遵循我们之前讨论的 MCP 协议规范。它们处理: + +- 协议级通信 +- 能力注册与发现 +- 消息序列化/反序列化 +- 连接管理 +- 错误处理 + +## 核心原语实现 + +让我们探索如何使用两种 SDK 实现核心原语(工具、资源和提示)。 + + + + + + +```python +from mcp.server.fastmcp import FastMCP + +# Create an MCP server +mcp = FastMCP("Weather Service") + + +@mcp.tool() +def get_weather(location: str) -> str: + """Get the current weather for a specified location.""" + return f"Weather in {location}: Sunny, 72°F" + + +@mcp.resource("weather://{location}") +def weather_resource(location: str) -> str: + """Provide weather data as a resource.""" + return f"Weather data for {location}: Sunny, 72°F" + + +@mcp.prompt() +def weather_report(location: str) -> str: + """Create a weather report prompt.""" + return f"""You are a weather reporter. Weather report for {location}?""" + + +# Run the server +if __name__ == "__main__": + mcp.run() + +``` + + + + +```javascript +import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { z } from "zod"; + +// Create an MCP server +const server = new McpServer({ + name: "Weather Service", + version: "1.0.0" +}); + +// Tool implementation +server.tool("get_weather", + { location: z.string() }, + async ({ location }) => ({ + content: [{ + type: "text", + text: `Weather in ${location}: Sunny, 72°F` + }] + }) +); + +// Resource implementation +server.resource( + "weather", + new ResourceTemplate("weather://{location}", { list: undefined }), + async (uri, { location }) => ({ + contents: [{ + uri: uri.href, + text: `Weather data for ${location}: Sunny, 72°F` + }] + }) +); + +// Prompt implementation +server.prompt( + "weather_report", + { location: z.string() }, + async ({ location }) => ({ + messages: [ + { + role: "assistant", + content: { + type: "text", + text: "You are a weather reporter." + } + }, + { + role: "user", + content: { + type: "text", + text: `Weather report for ${location}?` + } + } + ] + }) +); + +// Run the server +const transport = new StdioServerTransport(); +await server.connect(transport); +``` + + + + +一旦实现了服务器,就可以通过运行服务器脚本来启动它。 + +```bash +mcp dev server.py +``` + +这将初始化一个运行文件“server.py”的开发服务器。并记录以下输出: + +```bash +Starting MCP inspector... +⚙️ Proxy server listening on port 6277 +Spawned stdio transport +Connected MCP client to backing server transport +Created web app transport +Set up MCP proxy +🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀 +``` + +您可以通过访问 [http://127.0.0.1:6274](http://127.0.0.1:6274) 打开 MCP 检查器,查看服务器的能力并与之交互。 + +您将看到服务器提供的各项能力,并可通过 UI 界面直接调用这些功能。 + +![MCP Inspector](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit1/6.png) + +## MCP SDK 支持 + +MCP 设计为语言无关协议,目前为多种主流编程语言提供了官方 SDK: + +| 语言 | 仓库地址 | 维护方 | 状态 | +|------------|--------------------------------------------------------------------------------------------|-----------------------|-----------------| +| TypeScript | [github.com/modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk) | Anthropic | Active | +| Python | [github.com/modelcontextprotocol/python-sdk](https://github.com/modelcontextprotocol/python-sdk) | Anthropic | Active | +| Java | [github.com/modelcontextprotocol/java-sdk](https://github.com/modelcontextprotocol/java-sdk) | Spring AI (VMware) | Active | +| Kotlin | [github.com/modelcontextprotocol/kotlin-sdk](https://github.com/modelcontextprotocol/kotlin-sdk) | JetBrains | Active | +| C# | [github.com/modelcontextprotocol/csharp-sdk](https://github.com/modelcontextprotocol/csharp-sdk) | Microsoft | Active (Preview)| +| Swift | [github.com/modelcontextprotocol/swift-sdk](https://github.com/modelcontextprotocol/swift-sdk) | loopwork-ai | Active | +| Rust | [github.com/modelcontextprotocol/rust-sdk](https://github.com/modelcontextprotocol/rust-sdk) | Anthropic/Community| Active | + +这些 SDK 提供各语言特定的抽象层,简化了 MCP 协议的使用流程,使开发者能够专注于实现服务器或客户端的核心逻辑,而无需处理底层协议细节。 + +## 后续步骤 + +虽然我们只是浅尝辄止地体验了 MCP 的功能,但您已经成功运行了一个基础服务器。实际上,您还通过浏览器中的 MCP 客户端完成了与服务器的连接。 + +在下一章节,我们将探讨如何从大型语言模型(LLM)连接到您的服务器。 diff --git a/units/zh_CN/unit1/unit1-recap.mdx b/units/zh_CN/unit1/unit1-recap.mdx new file mode 100644 index 0000000..f07afb1 --- /dev/null +++ b/units/zh_CN/unit1/unit1-recap.mdx @@ -0,0 +1,45 @@ +# 第一单元回顾 + +## 模型上下文协议 (MCP) + +MCP 是一个标准化协议,旨在将 AI 模型与外部工具、数据源和环境相连接。它通过实现互操作性和实时信息访问,解决现有 AI 系统的局限性。 + +## 核心概念 + +### 客户端-服务端架构 +MCP 采用客户端-服务端模型,客户端负责管理用户与服务端之间的通信。这种架构支持模块化设计,允许轻松添加新服务端而无需修改现有宿主。 + +### 组件 +#### 宿主 (Host) +面向用户的 AI 应用程序,作为最终用户的交互接口。 + +##### 客户端 (Client) +宿主应用中的组件,负责管理与特定 MCP 服务端的通信。客户端与服务端保持 1:1 连接,并处理协议层面的细节。 + +#### 服务端 (Server) +通过 MCP 协议提供工具、数据源或服务的外部程序。服务端作为现有功能的轻量级封装层。 + +### 能力类型 +#### 工具 (Tools) +可执行的功能函数(如发送消息、查询 API)。工具通常由模型控制,因具有副作用操作能力需要用户批准。 + +#### 资源 (Resources) +用于上下文检索的只读数据源,无需复杂计算。资源由应用控制,设计目标类似于 REST API 中的 GET 端点。 + +#### 提示模板 (Prompts) +预定义的模板或工作流,用于引导用户、AI 模型与可用能力之间的交互。提示由用户控制,用于设定交互上下文。 + +#### 采样 (Sampling) +服务端发起的 LLM 处理请求,支持服务端驱动的智能体行为和潜在递归/多步交互。采样操作通常需要用户批准。 + +### 通信协议 +MCP 协议使用 JSON-RPC 2.0 作为客户端与服务端间的消息格式。支持两种主要传输机制:stdio(本地通信)和 HTTP+SSE(远程通信)。消息类型包含请求、响应和通知。 + +### 发现机制 +MCP 允许客户端通过列表方法(如 `tools/list`)动态发现可用工具、资源和提示模板。这种动态发现机制使客户端无需硬编码服务端功能知识即可适配不同服务端的能力。 + +### MCP SDK +官方提供多种编程语言的 SDK 用于实现 MCP 客户端和服务端。这些 SDK 处理协议通信、能力注册和错误处理,简化开发流程。 + +### Gradio 集成 +Gradio 支持快速创建 Web 界面,将能力通过 MCP 协议暴露,使其同时可供人类和 AI 模型访问。该集成以最小代码量提供人机友好的双界面支持。 \ No newline at end of file diff --git a/units/zh_CN/unit2/clients.mdx b/units/zh_CN/unit2/clients.mdx new file mode 100644 index 0000000..cf67347 --- /dev/null +++ b/units/zh_CN/unit2/clients.mdx @@ -0,0 +1,80 @@ +# 构建 MCP 客户端 + +在本章节中,我们将使用不同编程语言创建能与 MCP 服务器交互的客户端。我们将实现基于 HuggingFace.js 的 JavaScript 客户端和基于 smolagents 的 Python 客户端。 + +## 配置 MCP 客户端 + +要成功部署 MCP 服务器和客户端,需要进行正确配置。由于 MCP 规范仍在演进中,配置方法可能随之变化。我们将重点介绍当前的最佳配置实践。 + +### MCP 配置文件 + +MCP 宿主使用配置文件管理服务器连接。这些文件定义了可用服务器及其连接方式。 + +配置文件设计简洁易懂,且在主流 MCP 宿主中保持格式统一。 + +#### `mcp.json` 结构 + +标准 MCP 配置文件名为 `mcp.json`,其基本结构如下: + +```json +{ + "servers": [ + { + "name": "MCP Server", + "transport": { + "type": "sse", + "url": "http://localhost:7860/gradio_api/mcp/sse" + } + } + ] +} +``` + +此示例配置了使用 SSE 传输的服务器,连接本地 7860 端口运行的 Gradio 服务器。 + + + +我们通过 SSE 传输连接 Gradio 应用是假设其运行在远程服务器。如需连接本地脚本,建议使用 `stdio` 传输而非 `sse` 传输。 + + + +#### HTTP+SSE 传输配置 + +对于使用 HTTP+SSE 传输的远程服务器,配置需包含服务器 URL: + +```json +{ + "servers": [ + { + "name": "Remote MCP Server", + "transport": { + "type": "sse", + "url": "https://example.com/gradio_api/mcp/sse" + } + } + ] +} +``` + +该配置使 UI 客户端能通过 MCP 协议与 Gradio 服务器通信,实现前端与 MCP 服务的无缝集成。 + +## 配置 UI MCP 客户端 + +使用 Gradio MCP 服务器时,可通过以下方式配置 UI 客户端连接: + +### 基础配置 + +创建名为 `config.json` 的配置文件: + +```json +{ + "mcpServers": { + "mcp": { + "url": "http://localhost:7860/gradio_api/mcp/sse" + } + } +} +``` + +该配置使 UI 客户端能通过 MCP 协议与 Gradio 服务器通信,实现前端与 MCP 服务的无缝集成。 + diff --git a/units/zh_CN/unit2/gradio-client.mdx b/units/zh_CN/unit2/gradio-client.mdx new file mode 100644 index 0000000..4a36483 --- /dev/null +++ b/units/zh_CN/unit2/gradio-client.mdx @@ -0,0 +1,146 @@ +# 将 Gradio 作为 MCP 客户端 + +在前一章节中,我们探索了如何使用 Gradio 创建 MCP 服务器并通过 MCP 客户端进行连接。本节我们将重点介绍如何将 Gradio 作为 MCP 客户端来连接 MCP 服务器。 + + + +虽然 Gradio 最擅长创建 UI 客户端和 MCP 服务器,但它同样可以配置为 MCP 客户端并将功能通过 UI 界面暴露。 + + + +我们将连接前一章节创建的 MCP 服务器,并使用其功能来回答问题。 + +## 在 Gradio 中实现 MCP 客户端 + +首先需要安装必要的依赖库(如未安装): + +```bash +pip install smolagents[mcp] gradio[mcp] mcp +``` + +现在,我们可以导入必要的库并创建一个使用 MCP 客户端连接到 MCP 服务器的简单 Gradio 界面。 + +```python +import gradio as gr + +from mcp.client.stdio import StdioServerParameters +from smolagents import ToolCollection, CodeAgent +from smolagents import CodeAgent, InferenceClientModel +from smolagents.mcp_client import MCPClient +``` + +接下来,我们将连接到 MCP 服务器并获取可用于回答问题的工具。 + +```python +mcp_client = MCPClient( + {"url": "http://localhost:7860/gradio_api/mcp/sse"} +) +tools = mcp_client.get_tools() +``` + +现在我们有了这些工具,可以创建一个简单的代理来使用它们来回答问题。目前我们只使用一个简单的 `InferenceClientModel` 和 `smolagents` 中的默认模型。 + +```python +model = InferenceClientModel() +agent = CodeAgent(tools=[*tools], model=model) +``` + +现在,我们可以创建一个简单的 Gradio 界面,使用代理来回答问题。 + +```python +demo = gr.ChatInterface( + fn=lambda message, history: str(agent.run(message)), + type="messages", + examples=["Prime factorization of 68"], + title="Agent with MCP Tools", + description="This is a simple agent that uses MCP tools to answer questions.", + messages=[], +) + +demo.launch() +``` + +就这样!我们创建了一个简单的 Gradio 界面,它使用 MCP 客户端连接到 MCP 服务器并回答问题。 + + + + +## 完整示例 + +以下是 Gradio 中 MCP 客户端的完整示例: + +```python +import gradio as gr + +from mcp.client.stdio import StdioServerParameters +from smolagents import ToolCollection, CodeAgent +from smolagents import CodeAgent, InferenceClientModel +from smolagents.mcp_client import MCPClient + + +try: + mcp_client = MCPClient( + # {"url": "https://abidlabs-mcp-tools.hf.space/gradio_api/mcp/sse"} + {"url": "http://localhost:7860/gradio_api/mcp/sse"} + ) + tools = mcp_client.get_tools() + + model = InferenceClientModel() + agent = CodeAgent(tools=[*tools], model=model) + + def call_agent(message, history): + return str(agent.run(message)) + + + demo = gr.ChatInterface( + fn=lambda message, history: str(agent.run(message)), + type="messages", + examples=["Prime factorization of 68"], + title="Agent with MCP Tools", + description="This is a simple agent that uses MCP tools to answer questions.", + messages=[], + ) + + demo.launch() +finally: + mcp_client.close() +``` + +你会注意到我们在 `finally` 代码块中关闭了 MCP 客户端。这一点很重要,因为 MCP 客户端是一个长期存在的对象,需要在程序退出时关闭。 + +## 部署到 Hugging Face 空间 + +为了让您的服务器可供其他人使用,您可以像上一节中一样将其部署到 Hugging Face 空间。 +要将您的 Gradio MCP 客户端部署到 Hugging Face 空间: + +1. 在 Hugging Face 上创建一个新空间: +- 前往 huggingface.co/spaces +- 点击“创建新空间” +- 选择 “Gradio” 作为 SDK +- 为您的空间命名(例如“mcp-client”) + +2. 创建 `requirements.txt` 文件: +```txt +gradio[mcp] +smolagents[mcp] +``` + +3. Push your code to the Space: +```bash +git init +git add server.py requirements.txt +git commit -m "Initial commit" +git remote add origin https://huggingface.co/spaces/YOUR_USERNAME/mcp-client +git push -u origin main +``` + +## 总结 + +在本节中,我们探索了如何使用 Gradio 作为 MCP 客户端连接到 MCP 服务器。我们还了解了如何在 Hugging Face Spaces 中部署 MCP 客户端。 + + diff --git a/units/zh_CN/unit2/gradio-server.mdx b/units/zh_CN/unit2/gradio-server.mdx new file mode 100644 index 0000000..9f57534 --- /dev/null +++ b/units/zh_CN/unit2/gradio-server.mdx @@ -0,0 +1,188 @@ +# 构建基于 Gradio 的 MCP 服务器 + +在本章节中,我们将使用 Gradio 构建情感分析 MCP 服务器。该服务器将对外提供情感分析工具,既可通过网页界面供人工用户使用,也可通过 MCP 协议为 AI 模型提供服务。 + +## Gradio MCP 集成原理 + +Gradio 通过自动将 Python 函数转换为 MCP 工具,提供了创建 MCP 服务器的便捷方式。当在 `launch()` 中设置 `mcp_server=True` 时,Gradio 会执行以下操作: + +1. 自动将函数转换为 MCP 工具 +2. 将输入组件映射为工具参数模式 +3. 根据输出组件确定响应格式 +4. 建立基于 HTTP+SSE 的 JSON-RPC 客户端-服务器通信 +5. 同时创建网页界面和 MCP 服务端点 + +## 项目初始化 + +首先创建项目目录并安装所需依赖: + +```bash +mkdir mcp-sentiment +cd mcp-sentiment +python -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate +pip install "gradio[mcp]" textblob +``` + +## 创建服务器 + +创建一个名为 `server.py` 的新文件,并写入以下代码: + +```python +import gradio as gr +from textblob import TextBlob + +def sentiment_analysis(text: str) -> dict: + """ + Analyze the sentiment of the given text. + + Args: + text (str): The text to analyze + + Returns: + dict: A dictionary containing polarity, subjectivity, and assessment + """ + blob = TextBlob(text) + sentiment = blob.sentiment + + return { + "polarity": round(sentiment.polarity, 2), # -1 (negative) to 1 (positive) + "subjectivity": round(sentiment.subjectivity, 2), # 0 (objective) to 1 (subjective) + "assessment": "positive" if sentiment.polarity > 0 else "negative" if sentiment.polarity < 0 else "neutral" + } + +# Create the Gradio interface +demo = gr.Interface( + fn=sentiment_analysis, + inputs=gr.Textbox(placeholder="Enter text to analyze..."), + outputs=gr.JSON(), + title="Text Sentiment Analysis", + description="Analyze the sentiment of text using TextBlob" +) + +# Launch the interface and MCP server +if __name__ == "__main__": + demo.launch(mcp_server=True) +``` + +## 理解代码 + +让我们分解关键组件: + +1. **函数定义**: + - `sentiment_analysis` 函数接收文本输入并返回字典 + - 使用 TextBlob 进行情感分析 + - 文档字符串(docstring)至关重要,可帮助 Gradio 生成 MCP 工具模式 + - 类型提示(`str` 和 `dict`)帮助定义输入/输出模式 + +2. **Gradio 界面**: + - `gr.Interface` 同时创建网页界面和 MCP 服务器 + - 函数自动暴露为 MCP 工具 + - 输入和输出组件定义了工具的模式 + - JSON 输出组件确保正确的序列化 + +3. **MCP 服务器**: + - 设置 `mcp_server=True` 启用 MCP 服务器 + - 服务器将运行在 `http://localhost:7860/gradio_api/mcp/sse` + - 也可以通过环境变量启用: + ```bash + export GRADIO_MCP_SERVER=True + ``` + +## 运行服务器 + +通过以下命令启动服务器: + +```bash +python server.py +``` + +你应该看到表示网页界面和 MCP 服务器均已运行的输出。网页界面可通过 `http://localhost:7860` 访问,MCP 服务器位于 `http://localhost:7860/gradio_api/mcp/sse`。 + +## 测试服务器 + +你可以通过两种方式测试服务器: + +1. **网页界面**: + - 在浏览器中打开 `http://localhost:7860` + - 输入文本并点击 "Submit" + - 你将看到情感分析结果 + +2. **MCP 模式**: + - 访问 `http://localhost:7860/gradio_api/mcp/schema` + - 这里显示客户端将使用的 MCP 工具模式 + - 你也可以在 Gradio 应用的页脚 "View API" 链接中找到此模式 + +## 故障排除提示 + +1. **类型提示与文档字符串**: + - 始终为函数参数和返回值提供类型提示 + - 包含带有 "Args:" 块的文档字符串说明每个参数 + - 这有助于 Gradio 生成准确的 MCP 工具模式 + +2. **字符串输入**: + - 当不确定时,将输入参数接受为 [str](file://e:\githubProjects\nacos\naming\src\test\java\com\alibaba\nacos\naming\consistency\persistent\impl\NamingKvStorageTest.java#L45-L45) + - 在函数内部将其转换为所需类型 + - 这能提供更好的 MCP 客户端兼容性 + +3. **SSE 支持**: + - 某些 MCP 客户端不支持基于 SSE 的 MCP 服务器 + - 这种情况下请使用 `mcp-remote`: + ```json + { + "mcpServers": { + "gradio": { + "command": "npx", + "args": [ + "mcp-remote", + "http://localhost:7860/gradio_api/mcp/sse" + ] + } + } + } + ``` + +4. **连接问题**: + - 如果遇到连接问题,请尝试重启客户端和服务器 + - 检查服务器是否正在运行且可访问 + - 验证 MCP 模式是否在预期 URL 地址可用 + +## 部署到 Hugging Face Spaces + +要使你的服务器可供他人使用,可以将其部署到 Hugging Face Spaces: + +1. 在 Hugging Face 上创建新 Space: + - 访问 huggingface.co/spaces + - 点击 "Create new Space" + - 选择 "Gradio" 作为 SDK + - 为你的 Space 命名(例如 "mcp-sentiment") + +2. 创建 `requirements.txt` 文件: +```txt +gradio[mcp] +textblob +``` + +3. 将您的代码推送到空间: +```bash +git init +git add server.py requirements.txt +git commit -m "Initial commit" +git remote add origin https://huggingface.co/spaces/YOUR_USERNAME/mcp-sentiment +git push -u origin main +``` + +您的 MCP 服务器现在可在以下位置访问: +``` +https://YOUR_USERNAME-mcp-sentiment.hf.space/gradio_api/mcp/sse +``` + +## 后续步骤 + +现在我们的 MCP 服务器已经运行,我们将创建客户端来与其交互。在接下来的部分中,我们将: + +1. 创建一个基于 HuggingFace.js 的客户端,灵感来自 Tiny Agents +2. 实现一个基于 SmolAgents 的 Python 客户端 +3. 使用我们部署的服务器测试这两个客户端 + +让我们继续构建我们的第一个客户端! \ No newline at end of file diff --git a/units/zh_CN/unit2/introduction.mdx b/units/zh_CN/unit2/introduction.mdx new file mode 100644 index 0000000..27d3f7d --- /dev/null +++ b/units/zh_CN/unit2/introduction.mdx @@ -0,0 +1,64 @@ +# 构建端到端 MCP 应用 + +欢迎来到 MCP 课程的第二个单元! + +在本单元中,我们将从零开始构建一个完整的 MCP 应用,重点是通过 Gradio 创建服务器并连接多个客户端。这种实践方法将帮助您获得整个 MCP 生态系统的实战经验。 + + + +本单元我们将使用 Gradio 和 HuggingFace hub 构建一个简单的 MCP 服务器和客户端。下一单元我们将构建处理真实场景的更复杂服务器。 + + + +## 学习目标 + +在本单元中,您将: + +- 使用 Gradio 内置的 MCP 支持创建 MCP 服务器 +- 构建可供 AI 模型使用的情感分析工具 +- 通过不同客户端实现连接服务器: + - 基于 HuggingFace.js 的客户端 + - 基于 SmolAgents 的 Python 客户端 +- 将 MCP 服务器部署到 Hugging Face Spaces +- 测试和调试完整系统 + +完成本单元后,您将拥有一个可运行的 MCP 应用,充分展示该协议的强大功能和灵活性。 + +## 前置要求 + +开始本单元前请确保: + +- 已完成单元 1 或具备 MCP 基础概念知识 +- 熟悉 Python 和 JavaScript/TypeScript +- 了解 API 和客户端-服务器架构基础知识 +- 已配置开发环境: + - Python 3.10+ + - Node.js 18+ + - Hugging Face 账户(用于部署) + +## 端到端项目 + +我们将构建包含三个主要部分的情感分析应用:服务器、客户端和部署。 + +![情感分析应用](https://huggingface.co/datasets/mcp-course/images/resolve/main/unit2/1.png) + +### 服务端 + +- 使用 Gradio 通过 `gr.Interface` 创建 Web 界面和 MCP 服务器 +- 使用 TextBlob 实现情感分析工具 +- 通过 HTTP 和 MCP 协议暴露工具接口 + +### 客户端 + +- 实现基于 HuggingFace.js 的客户端 +- 或创建基于 SmolAgents 的 Python 客户端 +- 演示如何使用不同客户端实现连接同一服务器 + +### 部署 + +- 将服务器部署到 Hugging Face Spaces +- 配置客户端以适配已部署的服务器 + +## 立即开始 + +准备好构建您的第一个端到端 MCP 应用了吗?让我们从设置开发环境和创建 Gradio MCP 服务器开始! \ No newline at end of file diff --git a/units/zh_CN/unit2/tiny-agents.mdx b/units/zh_CN/unit2/tiny-agents.mdx new file mode 100644 index 0000000..bef689d --- /dev/null +++ b/units/zh_CN/unit2/tiny-agents.mdx @@ -0,0 +1,451 @@ +# Tiny 智能体:50 行代码实现的 MCP 驱动智能体 + +现在我们已经用 Gradio 构建了 MCP 服务器,接下来让我们深入探索 MCP 客户端。本节基于实验性项目 [Tiny Agents](https://huggingface.co/blog/tiny-agents),该项目展示了如何极简地部署可连接服务(如我们的 Gradio 情感分析服务器)的 MCP 客户端。 + +在这个简短练习中,我们将指导您实现一个 TypeScript (JS) MCP 客户端,该客户端可与任何 MCP 服务器通信(包括我们在上一节构建的基于 Gradio 的情感分析服务器)。您将看到 MCP 如何标准化智能体与工具的交互方式,从而显著简化 Agentic AI 的开发。 + +![meme](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/tiny-agents/thumbnail.jpg) +
图片致谢 https://x.com/adamdotdev
+ +我们将展示如何将您的微型智能体连接到基于 Gradio 的 MCP 服务器,使其能够同时使用您自定义的情感分析工具和其他预构建工具。 + +## 如何运行完整演示 + +如果您已安装 NodeJS(包含 `pnpm` 或 `npm`),只需在终端运行: + +```bash +npx @huggingface/mcp-client +``` + +或者使用 `pnpm`: + +```bash +pnpx @huggingface/mcp-client +``` + +该命令会将包安装到临时目录并执行其命令。 + +您将看到您的简易智能体连接到多个本地运行的 MCP 服务器,加载它们的工具(类似于加载 Gradio 情感分析工具的方式),然后进入对话提示模式。 + + + +默认情况下,示例智能体会连接以下两个 MCP 服务器: +- 标准[文件系统服务器](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem),可访问您的桌面 +- [Playwright MCP](https://github.com/microsoft/playwright-mcp) 服务器,提供沙盒化 Chromium 浏览器支持 + +您可以轻松将 Gradio 情感分析服务器添加到列表中(本节后续将演示)。 + +> [!NOTE] +> 注意:当前所有微型智能体中的 MCP 服务器实际上都是本地进程(远程服务器支持即将推出),这不包括运行在 localhost:7860 的 Gradio 服务器。 + +第一个视频的输入示例: +> 写一首关于 Hugging Face 社区的俳句,并保存到桌面名为 "hf.txt" 的文件 + +现在尝试涉及网页浏览的提示: +> 在 Brave Search 上搜索 HF 推理服务提供商并打开前 3 个结果 + + + +当连接 Gradio 情感分析工具后,可以类似地询问: +> 分析这条评论的情感:"我完全爱上了这个产品,它超出了我所有的预期!" + +### 默认模型与提供商 + +示例智能体默认使用以下模型/提供商组合: +- ["Qwen/Qwen2.5-72B-Instruct"](https://huggingface.co/Qwen/Qwen2.5-72B-Instruct) +- 运行于 [Nebius](https://huggingface.co/docs/inference-providers/providers/nebius) 平台 + +这些配置均可通过环境变量修改!以下示例展示如何添加 Gradio MCP 服务器: + +```ts +const agent = new Agent({ + provider: process.env.PROVIDER ?? "nebius", + model: process.env.MODEL_ID ?? "Qwen/Qwen2.5-72B-Instruct", + apiKey: process.env.HF_TOKEN, + servers: [ + // Default servers + { + command: "npx", + args: ["@modelcontextprotocol/servers", "filesystem"] + }, + { + command: "npx", + args: ["playwright-mcp"] + }, + // Our Gradio sentiment analysis server + { + command: "npx", + args: [ + "mcp-remote", + "http://localhost:7860/gradio_api/mcp/sse" + ] + } + ], +}); +``` + + + +我们通过 [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) 包连接到基于 Gradio 的 MCP 服务器。 + + + + +## 实现这一目标的基础:LLM 原生支持工具调用。 + +之所以能够将 Gradio MCP 服务器连接到我们的 Tiny Agent,是因为最近的 LLM(包括封闭式和开放式)都经过了函数调用(也就是工具使用)的训练。同样的功能也支持我们与使用 Gradio 构建的情绪分析工具的集成。 + +工具由其名称、描述以及其参数的 JSONSchema 表示形式定义——这与我们在 Gradio 服务器中定义情绪分析函数的方式完全相同。让我们看一个简单的例子: + +```ts +const weatherTool = { + type: "function", + function: { + name: "get_weather", + description: "Get current temperature for a given location.", + parameters: { + type: "object", + properties: { + location: { + type: "string", + description: "City and country e.g. Bogotá, Colombia", + }, + }, + }, + }, +}; +``` + +我们的 Gradio 情感分析工具结构类似,但输入参数使用 `text` 替代 `location`。 + +这里引用的权威文档是 [OpenAI 的函数调用文档](https://platform.openai.com/docs/guides/function-calling?api-mode=chat)。(是的... OpenAI 几乎为整个社区定义了 LLM 的标准 😅) + +推理引擎允许您在调用 LLM 时传递工具列表,LLM 可以自由选择调用零个、一个或多个工具。 +作为开发者,您需要执行这些工具并将结果反馈给 LLM 以继续生成。 + +> 注意:在后端(推理引擎层面),工具会以特殊格式的 [chat_template](file://e:\githubProjects\transformers\src\transformers\models\llava_onevision\convert_llava_onevision_weights_to_hf.py#L58-L58) 传递给模型(如同其他消息),然后从响应中解析出来(使用模型特定的特殊标记)以暴露为工具调用。 + +## 在 InferenceClient 上实现 MCP 客户端 + +现在我们已经了解现代 LLM 中工具的定义,接下来让我们实现真正的 MCP 客户端,用于与 Gradio 服务器和其他 MCP 服务器通信。 + +[官方文档](https://modelcontextprotocol.io/quickstart/client) 编写得相当完善。您只需将 Anthropic 客户端 SDK 的引用替换为其他 OpenAI 兼容的 SDK 即可(这里还提供了可输入 LLM 的 [llms.txt](https://modelcontextprotocol.io/llms-full.txt) 来辅助编码)。 + +需要说明的是,我们使用 HF 的 `InferenceClient` 作为推理客户端。 + +> [!TIP] +> 完整的 `McpClient.ts` 代码文件可在[此处](https://github.com/huggingface/huggingface.js/blob/main/packages/mcp-client/src/McpClient.ts)查阅 🤓 + +我们的 `McpClient` 类包含: +- 推理客户端(支持任意推理提供商,`huggingface/inference` 同时支持远程和本地端点) +- 一组 MCP 客户端会话(每个连接的 MCP 服务器对应一个会话,支持连接多个服务器包括 Gradio 服务器) +- 可用工具列表(从连接的服务器获取并稍作格式化) + +```ts +export class McpClient { + protected client: InferenceClient; + protected provider: string; + protected model: string; + private clients: Map = new Map(); + public readonly availableTools: ChatCompletionInputTool[] = []; + + constructor({ provider, model, apiKey }: { provider: InferenceProvider; model: string; apiKey: string }) { + this.client = new InferenceClient(apiKey); + this.provider = provider; + this.model = model; + } + + // [...] +} +``` + +为了连接到 MCP 服务器(例如我们的 Gradio 情绪分析服务器),官方的 `@modelcontextprotocol/sdk/client` TypeScript SDK 提供了一个带有 `listTools()` 方法的 `Client` 类: + +```ts +async addMcpServer(server: StdioServerParameters): Promise { + const transport = new StdioClientTransport({ + ...server, + env: { ...server.env, PATH: process.env.PATH ?? "" }, + }); + const mcp = new Client({ name: "@huggingface/mcp-client", version: packageVersion }); + await mcp.connect(transport); + + const toolsResult = await mcp.listTools(); + debug( + "Connected to server with tools:", + toolsResult.tools.map(({ name }) => name) + ); + + for (const tool of toolsResult.tools) { + this.clients.set(tool.name, mcp); + } + + this.availableTools.push( + ...toolsResult.tools.map((tool) => { + return { + type: "function", + function: { + name: tool.name, + description: tool.description, + parameters: tool.inputSchema, + }, + } satisfies ChatCompletionInputTool; + }) + ); +} +``` + +`StdioServerParameters` 是 MCP SDK 中的一个接口,可让您轻松创建本地进程:如前所述,目前所有 MCP 服务器实际上都是本地进程,包括我们的 Gradio 服务器(尽管我们通过 HTTP 访问它)。 + +对于我们连接的每个 MCP 服务器(包括我们的 Gradio 情绪分析服务器),我们都会稍微重新格式化其工具列表,并将其添加到 `this.availableTools` 中。 + +### 如何使用工具 + +使用我们的情绪分析工具(或任何其他 MCP 工具)非常简单。您只需将 `this.availableTools` 传递给您的 LLM 聊天完成函数,以及您常用的消息数组即可: + +```ts +const stream = this.client.chatCompletionStream({ + provider: this.provider, + model: this.model, + messages, + tools: this.availableTools, + tool_choice: "auto", +}); +``` + +`tool_choice: "auto"` 是您传递给 LLM 的参数,用于生成零个、一个或多个工具调用。 + +在解析或流式传输输出时,LLM 会生成一些工具调用(例如函数名称和一些 JSON 编码的参数),您(作为开发者)需要计算这些调用。MCP 客户端 SDK 再次简化了计算过程;它有一个 `client.callTool()` 方法: + +```ts +const toolName = toolCall.function.name; +const toolArgs = JSON.parse(toolCall.function.arguments); + +const toolMessage: ChatCompletionInputMessageTool = { + role: "tool", + tool_call_id: toolCall.id, + content: "", + name: toolName, +}; + +/// Get the appropriate session for this tool +const client = this.clients.get(toolName); +if (client) { + const result = await client.callTool({ name: toolName, arguments: toolArgs }); + toolMessage.content = result.content[0].text; +} else { + toolMessage.content = `Error: No session found for tool: ${toolName}`; +} +``` + +如果 LLM 选择使用我们的情感分析工具,这段代码会自动将调用路由到 Gradio 服务器,执行分析并将结果返回给 LLM。 + +最后您需要将工具消息结果添加到 `messages` 数组并传回 LLM。 + +## 50 行代码实现的智能体 🤯 + +现在我们已经有了能连接任意 MCP 服务器(包括 Gradio 情感分析服务器)获取工具列表,并能将工具注入 LLM 推理流程的 MCP 客户端,那么... 究竟什么是智能体? + +> 当您拥有带工具集的推理客户端后,智能体本质上只是一个 while 循环。 + +更具体地说,智能体由以下要素构成: +- 系统提示 +- LLM 推理客户端 +- 连接多个 MCP 服务器(包括 Gradio 服务器)工具的 MCP 客户端 +- 基础控制流(见下方 while 循环) + +> [!TIP] +> 完整 `Agent.ts` 代码文件可[在此处](https://github.com/huggingface/huggingface.js/blob/main/packages/mcp-client/src/Agent.ts)查看。 + +我们的智能体类直接继承自 McpClient: + +```ts +export class Agent extends McpClient { + private readonly servers: StdioServerParameters[]; + protected messages: ChatCompletionInputMessage[]; + + constructor({ + provider, + model, + apiKey, + servers, + prompt, + }: { + provider: InferenceProvider; + model: string; + apiKey: string; + servers: StdioServerParameters[]; + prompt?: string; + }) { + super({ provider, model, apiKey }); + this.servers = servers; + this.messages = [ + { + role: "system", + content: prompt ?? DEFAULT_SYSTEM_PROMPT, + }, + ]; + } +} +``` + +默认情况下,我们使用受 [GPT-4.1 提示指南](https://cookbook.openai.com/examples/gpt4-1_prompting_guide) 启发的极简系统提示。 + +尽管这来自 OpenAI 😈,但以下声明越来越适用于闭源和开源模型: +> 我们建议开发者仅通过 tools 字段传递工具,而非像过去某些做法那样手动在提示中注入工具描述并编写独立的工具调用解析器。 + +这意味着我们无需在系统提示中精心编排工具使用示例。`tools: this.availableTools` 参数已足够,LLM 将自动掌握文件系统工具和 Gradio 情感分析工具的使用方法。 + +加载智能体工具的操作本质上就是连接所需的 MCP 服务器(借助 JS 的并行特性可轻松实现): + +```ts +async loadTools(): Promise { + await Promise.all(this.servers.map((s) => this.addMcpServer(s))); +} +``` + +我们添加了两个额外的工具(MCP 之外),可供 LLM 用于我们的智能体的控制流: + +```ts +const taskCompletionTool: ChatCompletionInputTool = { + type: "function", + function: { + name: "task_complete", + description: "Call this tool when the task given by the user is complete", + parameters: { + type: "object", + properties: {}, + }, + }, +}; +const askQuestionTool: ChatCompletionInputTool = { + type: "function", + function: { + name: "ask_question", + description: "Ask a question to the user to get more info required to solve or clarify their problem.", + parameters: { + type: "object", + properties: {}, + }, + }, +}; +const exitLoopTools = [taskCompletionTool, askQuestionTool]; +``` + +当调用任何这些工具时,智能体都会中断循环,并将控制权交还给用户,以便用户输入新的输入。 + +### 完整的 while 循环 + +看看我们完整的 while 循环。🎉 + +智能体主 while 循环的要点是,我们简单地迭代 LLM,交替调用工具并向其提供工具结果,**直到 LLM 开始连续响应两条非工具消息**。 + +这是完整的 while 循环: + +```ts +let numOfTurns = 0; +let nextTurnShouldCallTools = true; +while (true) { + try { + yield* this.processSingleTurnWithTools(this.messages, { + exitLoopTools, + exitIfFirstChunkNoTool: numOfTurns > 0 && nextTurnShouldCallTools, + abortSignal: opts.abortSignal, + }); + } catch (err) { + if (err instanceof Error && err.message === "AbortError") { + return; + } + throw err; + } + numOfTurns++; + const currentLast = this.messages.at(-1)!; + if ( + currentLast.role === "tool" && + currentLast.name && + exitLoopTools.map((t) => t.function.name).includes(currentLast.name) + ) { + return; + } + if (currentLast.role !== "tool" && numOfTurns > MAX_NUM_TURNS) { + return; + } + if (currentLast.role !== "tool" && nextTurnShouldCallTools) { + return; + } + if (currentLast.role === "tool") { + nextTurnShouldCallTools = false; + } else { + nextTurnShouldCallTools = true; + } +} +``` + +## 将 Tiny Agent 与 Gradio MCP 服务器连接 + +现在我们了解了 Tiny Agent 和 Gradio MCP 服务器,让我们看看它们是如何协同工作的!MCP 的优点在于它为智能体提供了一种标准化的方式,使其能够与任何兼容 MCP 的服务器(包括我们基于 Gradio 的情绪分析服务器)进行交互。 + +### 将 Gradio 服务器与 Tiny Agent 配合使用 + +要将 Tiny Agent 连接到我们之前构建的 Gradio 情绪分析服务器,我们只需将其添加到服务器列表中即可。以下是修改智能体配置的方法: + +```ts +const agent = new Agent({ + provider: process.env.PROVIDER ?? "nebius", + model: process.env.MODEL_ID ?? "Qwen/Qwen2.5-72B-Instruct", + apiKey: process.env.HF_TOKEN, + servers: [ + // ... existing servers ... + { + command: "npx", + args: [ + "mcp-remote", + "http://localhost:7860/gradio_api/mcp/sse" // Your Gradio MCP server + ] + } + ], +}); +``` + +现在我们的智能体可以同时使用情感分析工具和其他工具!例如,它可以: +1. 使用文件系统服务器从文件中读取文本 +2. 使用我们的 Gradio 服务器分析其情感 +3. 将结果写回到新文件中 + +### 示例交互 + +以下是与我们的智能体进行对话的示例: + +``` +用户:读取我桌面上的 "feedback.txt" 文件并分析其情感 + +智能体:我将帮助您分析反馈文件的情感。以下是具体步骤: + +首先,我会使用文件系统工具读取文件 +然后,使用情感分析工具分析其情感 +最后,将结果写入新文件 +[智能体继续使用工具并提供分析结果] +``` + +### 部署注意事项 + +当将 Gradio MCP 服务器部署到 Hugging Face Spaces 时,您需要更新智能体配置中的服务器 URL 以指向已部署的空间: + +```ts +{ + command: "npx", + args: [ + "mcp-remote", + "https://YOUR_USERNAME-mcp-sentiment.hf.space/gradio_api/mcp/sse" + ] +} +``` + +这使得您的智能体可以从任何地方使用情绪分析工具,而不仅仅是在本地! + + + diff --git a/units/zh_CN/unit3/introduction.mdx b/units/zh_CN/unit3/introduction.mdx new file mode 100644 index 0000000..1a335d7 --- /dev/null +++ b/units/zh_CN/unit3/introduction.mdx @@ -0,0 +1,3 @@ +# 即将推出 + +这将是另一个深入探讨 MCP 协议以及如何以更复杂的方式使用它的用例。 \ No newline at end of file diff --git a/units/zh_CN/unit4/introduction.mdx b/units/zh_CN/unit4/introduction.mdx new file mode 100644 index 0000000..c9c17a7 --- /dev/null +++ b/units/zh_CN/unit4/introduction.mdx @@ -0,0 +1,5 @@ +# 即将推出 + +本单元将与人工智能社区的合作伙伴合作。 + +如果您正在为 MCP 构建工具,请联系我们,我们会将您添加到本单元。请在中心组织中创建[讨论](https://huggingface.co/spaces/mcp-course/README/discussions)。 \ No newline at end of file