MCP协议:AI应用开发的标准化通信桥梁与万能插座 1. 项目概述为什么我们需要一个“万能插座”如果你在AI应用开发领域摸爬滚打过一段时间大概率会遇到一个让人头疼的场景你的应用需要调用多个不同厂商、不同接口、不同认证方式的AI模型或服务。比如用户输入一个问题你可能需要先用OpenAI的GPT-4进行理解然后调用Anthropic的Claude生成草稿最后再用Google的Gemini进行润色和风格检查。每个服务都有自己的SDK、API密钥格式、请求参数和响应结构。光是写适配代码、处理错误和统一日志就足以让开发效率大打折扣更别提后续维护和扩展新模型了。这感觉就像你家里的电器有欧标、美标、英标各种插头而你只有一个固定制式的插座。每次想用新设备都得找个转换头甚至重新布线。混乱、低效且脆弱。MCPModel Context Protocol正是为了解决这个“插头不兼容”的问题而诞生的。你可以把它理解为AI世界的“万能插座”协议。它由Anthropic公司牵头提出并开源目标是为AI应用尤其是智能体Agent与外部工具、数据源之间建立一个标准化、统一化的通信桥梁。简单说它定义了一套清晰的规则让任何AI模型都能以同样的方式“发现”、“描述”和“调用”外部能力无论这个能力是查询数据库、执行代码、搜索网络还是控制智能家居。这个协议的出现直接切中了当前AI应用开发的核心痛点——碎片化。它让开发者从“写胶水代码”的泥潭中解放出来专注于构建更强大的AI智能体逻辑本身。接下来我们就深入这个“插座”的内部看看它的设计思路、核心组件以及你该如何上手使用它来“通电”。2. MCP协议的核心设计思路与架构拆解MCP的设计哲学非常清晰关注点分离和协议中立。它不关心你底层用的是什么传输方式HTTP、SSE、Stdio也不强制你使用特定的AI模型或框架。它只定义一套双方都能理解的“语言”消息格式确保“工具提供方”和“工具使用方”通常是AI智能体能顺畅对话。2.1 核心角色与交互模型理解MCP首先要搞清楚三个核心角色客户端Client通常是AI智能体或应用程序。它是工具的“使用者”负责发起请求。比如一个代码助手智能体就是一个客户端。服务器Server是工具的“提供者”。它封装了一个或多个具体的功能并将其通过MCP协议暴露出来。一个服务器可以提供“执行SQL查询”、“读取文件系统”、“调用天气API”等多种工具。传输层Transport连接客户端和服务器的通信通道。MCP协议本身与传输层解耦目前主要支持三种方式标准输入输出Stdio最简单的方式服务器作为一个独立的进程启动通过stdin/stdout与客户端交换JSON-RPC消息。适合本地集成。HTTP/SSEServer-Sent Events服务器作为一个HTTP服务运行客户端通过HTTP请求建立连接并通过SSE接收服务器推送的消息。适合远程服务。WebSocket全双工通信适用于需要实时双向交互的复杂场景。交互的基本流程可以类比为点餐客户端顾客向服务器餐厅发送请求“你们有什么菜工具”服务器回复一份菜单工具列表详细描述了每道菜工具的名字、原料输入参数和样子输出格式。客户端根据菜单点菜“我要这个菜这是我的要求参数。”服务器收到后开始烹饪执行工具完成后将菜品结果端上来。整个过程中传输层就是服务员和传菜通道。2.2 协议基石JSON-RPC 2.0MCP的所有通信都构建在JSON-RPC 2.0这个轻量级远程过程调用协议之上。这意味着所有的请求和响应都是结构化的JSON对象包含jsonrpc: “2.0”、method方法名、params参数和id请求ID等标准字段。选择JSON-RPC是因为它简单、通用、语言无关。几乎所有的编程语言都有成熟的JSON-RPC库这极大地降低了实现MCP服务器或客户端的门槛。协议中定义了一系列标准的method例如tools/list列出工具、tools/call调用工具、resources/list列出资源等。2.3 核心概念工具Tools与资源Resources这是MCP协议中两个最重要的抽象概念理解了它们就理解了MCP能力的核心。工具Tools代表一个可执行的操作。每个工具都有名称name唯一标识符如search_web。描述description用自然语言描述这个工具是做什么的。这部分描述对于AI智能体至关重要因为它依赖这些描述来理解何时以及如何使用该工具。输入模式inputSchema一个遵循JSON Schema规范的定义严格规定了调用此工具时需要提供的参数及其类型、格式、是否必填等。例如一个搜索工具可能需要query字符串类型和limit数字类型参数。资源Resources代表可读取的静态或动态内容。与工具“执行动作”不同资源是“提供数据”。每个资源都有URIuri统一资源标识符如file:///path/to/doc.md或dynamic://news/latest。MIME类型mimeType如text/plaintext/markdownapplication/json 告诉客户端如何解析内容。名称和描述便于AI理解资源内容。资源的概念非常强大。它允许服务器将数据库表、API文档、系统状态等信息以结构化的方式“喂”给AI智能体作为其思考的上下文Context。这正是“Model Context Protocol”中“Context”一词的体现——它不仅提供可调用的工具Actions更提供了丰富的背景信息Data。3. 核心细节解析与实操要点了解了宏观架构我们深入到协议定义的细节中看看一个标准的MCP交互到底包含哪些具体步骤和消息。这里我们以最常见的Stdio 传输方式为例因为它最直观也最适合本地开发和调试。3.1 连接初始化与能力协商任何通信开始前客户端和服务器需要“握手”确认双方的能力和配置。这个过程通过交换initialize和initialized消息完成。客户端发送initialize请求这个消息是客户端发起的第一个请求。它包含了客户端的元信息比如它支持的协议版本、它的身份等。最关键的是它通过capabilities字段声明自己支持哪些MCP特性例如是否支持“资源”特性。// 客户端 - 服务器 { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2024-11-05, capabilities: { tools: {}, resources: {} }, clientInfo: { name: MyAwesomeAIAssistant } } }服务器回复initialize响应服务器收到后会回复一个响应同样包含自己的元信息和capabilities。服务器会列出它真正提供的能力。比如如果客户端声明支持resources但服务器只提供了tools那么服务器在响应中可能只包含tools的能力描述。// 服务器 - 客户端 { jsonrpc: 2.0, id: 1, result: { protocolVersion: 2024-11-05, capabilities: { tools: {} }, serverInfo: { name: FileSystemServer } } }客户端发送initialized通知收到服务器的成功响应后客户端发送一个没有返回值的initialized通知告知服务器初始化完成可以开始正式工作了。// 客户端 - 服务器 { jsonrpc: 2.0, method: initialized, params: {} }实操心得能力协商是关键。在实现自己的MCP服务器时务必根据initialize请求中客户端的能力来调整你的响应。如果客户端不支持resources你就不要在后继消息中发送任何资源相关的通知否则客户端可能无法处理而导致连接错误。这是一种优雅的退化机制。3.2 工具与资源的发现与通知握手完成后服务器需要主动告诉客户端“我这儿有什么”。这不是通过客户端轮询而是通过服务器主动发送通知实现的。工具列表通知tools/list服务器发送一个notifications/tools/list通知包含一个工具列表。每个工具对象都包含详细的description和inputSchema。// 服务器 - 客户端 { jsonrpc: 2.0, method: notifications/tools/list, params: { tools: [ { name: read_file, description: 读取指定路径文件的内容。, inputSchema: { type: object, properties: { path: { type: string, description: 文件的绝对路径。 } }, required: [path] } } ] } }资源列表通知resources/list如果服务器支持资源它同样会发送一个notifications/resources/list通知列出所有可用的资源URI和描述。// 服务器 - 客户端 { jsonrpc: 2.0, method: notifications/resources/list, params: { resources: [ { uri: file:///etc/hosts, name: 系统Hosts文件, description: 本地系统的hosts配置文件内容。, mimeType: text/plain } ] } }注意事项动态更新。工具和资源的列表不是一成不变的。服务器可以在运行时随时发送新的tools/list或resources/list通知来更新列表。例如一个服务器在用户登录后才动态添加访问用户个人数据的工具。客户端需要能够处理这种动态变化。3.3 工具调用与资源读取这是最核心的交互环节。工具调用流程客户端请求客户端通过tools/call请求调用一个工具必须提供工具名和符合inputSchema的参数。// 客户端 - 服务器 { jsonrpc: 2.0, id: 100, method: tools/call, params: { name: read_file, arguments: { path: /home/user/document.txt } } }服务器执行并响应服务器执行对应的逻辑如读取文件然后将结果或错误通过tools/call的响应返回。// 成功响应 { jsonrpc: 2.0, id: 100, result: { content: [ { type: text, text: 这是文件的内容... } ] } } // 错误响应 { jsonrpc: 2.0, id: 100, error: { code: -32603, message: 文件不存在 } }注意结果中的content是一个数组支持多种类型textimage等这是为了未来扩展性设计的。资源读取流程客户端请求客户端通过resources/read请求读取一个资源只需提供资源的URI。// 客户端 - 服务器 { jsonrpc: 2.0, id: 101, method: resources/read, params: { uri: file:///etc/hosts } }服务器响应服务器返回资源的内容和MIME类型。// 服务器 - 客户端 { jsonrpc: 2.0, id: 101, result: { contents: [ { uri: file:///etc/hosts, mimeType: text/plain, text: 127.0.0.1 localhost } ] } }3.4 采样Sampling与日志Logging除了核心的工具和资源MCP还定义了一些辅助性消息用于增强开发体验和智能体能力。采样sampling/create这是一个非常有趣且强大的功能。它允许客户端请求服务器“基于给定的上下文和提示词生成一些示例内容”。这不同于调用一个确定性的工具而是请求服务器背后的模型如果服务器连接了AI模型进行创造性生成。例如一个连接了Claude的服务器客户端可以请求它“给定这个数据库表结构生成5条符合逻辑的测试数据。” 服务器会调用模型来完成这个任务。用途为AI智能体生成训练数据、创建测试用例、辅助内容创作等。流程客户端发送sampling/create请求包含prompt提示词和可选context上下文资源。服务器返回生成的内容。日志notifications/logging/log服务器可以通过此通知向客户端发送日志消息用于调试或信息展示。客户端可以选择在UI中显示这些日志。这对于开发者理解服务器内部正在发生什么非常有帮助。// 服务器 - 客户端 { jsonrpc: 2.0, method: notifications/logging/log, params: { level: info, data: 正在处理文件读取请求路径/home/user/doc.txt } }4. 实操过程从零构建一个MCP服务器理论说得再多不如动手实践。让我们用Python快速构建一个最简单的MCP服务器它提供一个工具计算两个数的和。我们将使用官方推荐的mcpPython SDK这能省去我们手动处理JSON-RPC消息的麻烦。4.1 环境准备与依赖安装首先确保你的Python环境在3.8以上。然后创建一个新的项目目录并安装必要的包。# 创建项目目录 mkdir mcp-demo-server cd mcp-demo-server # 创建虚拟环境推荐 python -m venv .venv # 激活虚拟环境 # Windows: .venv\Scripts\activate # Linux/Mac: source .venv/bin/activate # 安装MCP SDK pip install mcpmcp这个包是Anthropic官方维护的Python SDK它封装了协议通信、消息序列化/反序列化、服务器生命周期管理等底层细节让我们可以像写普通Python函数一样定义工具。4.2 编写服务器核心代码创建一个名为server.py的文件写入以下内容#!/usr/bin/env python3 一个简单的MCP服务器示例提供加法计算工具。 import asyncio from mcp.server import Server, NotificationOptions from mcp.server.models import InitializationOptions import mcp.server.stdio from mcp.types import Tool, TextContent # 创建Server实例 server Server(demo-math-server) # 使用装饰器注册一个工具 server.list_tools() async def handle_list_tools() - list[Tool]: 返回服务器提供的工具列表。 # 定义一个名为 add 的工具 add_tool Tool( nameadd, description计算两个数字的和。, inputSchema{ type: object, properties: { a: { type: number, description: 第一个加数 }, b: { type: number, description: 第二个加数 } }, required: [a, b] } ) return [add_tool] # 注册工具执行函数 server.call_tool() async def handle_call_tool(name: str, arguments: dict) - list[TextContent]: 执行指定的工具。 if name add: # 从参数中取出 a 和 b a arguments.get(a) b arguments.get(b) if a is None or b is None: raise ValueError(参数 a 和 b 是必需的) result a b # 返回结果包装在 TextContent 中 return [TextContent(typetext, textf{a} {b} {result})] else: # 如果工具名未知抛出错误 raise ValueError(f未知的工具: {name}) async def main(): 主函数启动服务器。 # 使用Stdio传输层运行服务器 async with mcp.server.stdio.stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, InitializationOptions( server_namedemo-math-server, server_version0.1.0 ), NotificationOptions() # 使用默认通知选项 ) if __name__ __main__: asyncio.run(main())代码逐行解析导入与初始化导入必要的模块创建Server实例。Server类是SDK的核心它管理工具注册和请求路由。server.list_tools()这是一个装饰器用于注册一个处理“列出工具”请求的函数。当客户端初始化后请求工具列表时这个函数会被调用。我们在这里定义并返回了add工具包括其名称、描述和严格的输入模式JSON Schema。server.call_tool()这个装饰器注册了处理“调用工具”请求的函数。当客户端发起tools/call请求时SDK会根据工具名name路由到这里。我们检查name是否为add然后从arguments字典中提取参数a和b执行加法运算最后将结果包装成TextContent列表返回。MCP协议要求结果必须是Content数组。main()函数这是服务器的启动入口。mcp.server.stdio.stdio_server()创建了标准输入输出的传输通道。server.run()方法会启动服务器主循环开始监听read_stream上的请求并通过write_stream发送响应。4.3 运行与测试服务器保存文件后在终端直接运行它python server.py此时服务器进程会启动并等待来自标准输入stdin的请求。它自己不会做任何事情因为还没有客户端连接。为了测试我们需要一个MCP客户端。最快速的方法是使用MCP CLI命令行工具。首先安装它需要Node.js环境npm install -g modelcontextprotocol/inspector然后在另一个终端窗口使用CLI连接我们的服务器# 假设 server.py 正在运行 mcp-inspector python server.pymcp-inspector是一个官方提供的调试客户端它会启动指定的服务器命令这里是python server.py并与之建立Stdio连接然后提供一个简单的交互式界面。连接成功后你应该能在mcp-inspector的界面中看到连接状态显示为 “Connected”。在 “Tools” 标签页下能看到我们定义的add工具及其描述、参数Schema。在 “Resources” 标签页下是空的因为我们没定义资源。现在我们可以在 “Tools” 标签页找到add工具点击它在参数输入框里填入{ a: 5, b: 3 }点击 “Call”你会在右侧结果窗口看到返回5 3 8。恭喜你已经成功创建并运行了你的第一个MCP服务器。mcp-inspector充当了客户端它完成了初始化、获取工具列表、调用工具的全过程。4.4 进阶添加资源与动态更新让我们增强这个服务器添加一个资源和动态更新工具列表的能力。修改server.py增加以下部分# ... 前面的导入和server初始化不变 ... from mcp.types import Resource, TextContent # 模拟一个动态的计数器 call_count 0 server.list_resources() async def handle_list_resources() - list[Resource]: 返回服务器提供的资源列表。 global call_count resource Resource( uridynamic://server/stats, name服务器统计信息, description显示服务器工具被调用的次数。, mimeTypeapplication/json ) return [resource] server.read_resource() async def handle_read_resource(uri: str) - list[TextContent]: 读取指定URI的资源内容。 global call_count if uri dynamic://server/stats: content { tool_calls: call_count, status: running } import json return [TextContent(typetext, textjson.dumps(content, indent2))] else: raise ValueError(f未知的资源URI: {uri}) server.call_tool() async def handle_call_tool(name: str, arguments: dict) - list[TextContent]: 执行指定的工具。 global call_count if name add: call_count 1 # 调用计数1 # 动态更新工具列表添加一个“获取计数”的工具仅作演示实际需更复杂逻辑 # 注意实际动态更新需要通过 server.request_context 发送通知此处简化。 a arguments.get(a) b arguments.get(b) if a is None or b is None: raise ValueError(参数 a 和 b 是必需的) result a b return [TextContent(typetext, textf{a} {b} {result}\n(工具已被调用 {call_count} 次))] elif name get_stats: # 新增一个工具直接返回统计信息 import json stats {tool_calls: call_count} return [TextContent(typetext, textjson.dumps(stats, indent2))] else: raise ValueError(f未知的工具: {name}) # 在 main 函数之前我们需要一个后台任务来模拟动态更新工具列表 async def dynamic_tool_updater(server_instance: Server): 一个后台任务模拟在运行一段时间后动态添加新工具。 await asyncio.sleep(10) # 等待10秒 print([Server] 准备动态添加新工具 get_stats..., filesys.stderr) # 在实际应用中这里应该通过 server_instance 的方法触发一个 tools/list 通知。 # 由于SDK高级封装动态更新通常需要在 handle_list_tools 中根据状态返回不同列表 # 并通过 server_instance.request_context 发送通知。本例为演示概念简化处理。 # 更正确的做法是维护一个内部工具列表并在 handle_list_tools 中返回它。 # 当需要更新时修改这个列表然后主动调用相关方法通知客户端。 # 修改 main 函数启动后台任务 async def main(): 主函数启动服务器。 # 启动动态更新后台任务 updater_task asyncio.create_task(dynamic_tool_updater(server)) async with mcp.server.stdio.stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, InitializationOptions( server_namedemo-math-server, server_version0.1.0 ), NotificationOptions() ) # 取消后台任务虽然通常run不会返回 updater_task.cancel() # ... 文件末尾不变 ...这段代码的要点添加资源我们通过server.list_resources()和server.read_resource()装饰器定义并实现了一个资源。这个资源的URI是dynamic://server/stats内容是JSON格式的服务器统计信息调用次数。客户端可以通过resources/read请求来获取这个动态信息。状态管理我们使用了一个全局变量call_count来记录工具调用次数并在每次调用add工具时递增。动态更新的概念我们在dynamic_tool_updater函数中演示了“动态更新”的概念。在实际生产环境中动态更新工具列表需要更严谨的机制通常服务器内部维护一个工具列表当列表变化时主动向所有连接的客户端发送一个新的notifications/tools/list通知。Python SDK提供了更高级的抽象来处理这种状态管理。重启服务器并用mcp-inspector重新连接你现在应该能在 “Resources” 标签页看到dynamic://server/stats资源点击 “Read” 可以获取当前的调用统计。调用几次add工具后再读取资源可以看到计数器的变化。5. 常见问题与排查技巧实录在实际开发和集成MCP的过程中你肯定会遇到各种问题。下面是我在多个项目中总结的一些典型问题和解决方法。5.1 连接与初始化失败问题现象可能原因排查步骤与解决方案客户端无法启动服务器进程1. 服务器命令路径错误。2. 依赖未安装。3. 脚本无执行权限。1.手动测试在终端直接运行python server.py看是否能正常启动并等待不退出。2.检查路径确保mcp-inspector或客户端使用的命令是绝对路径或已在PATH中。3.检查依赖确认pip install mcp已成功执行。连接建立但立即断开或报错1. 服务器未按MCP协议发送/接收消息。2.initialize响应格式错误。3. 传输层不匹配如客户端用HTTP服务器开Stdio。1.查看日志使用mcp-inspector或客户端详细日志看错误信息。通常第一行错误信息很关键。2.协议验证确保服务器发送的第一个消息是对客户端initialize请求的响应且格式完全符合JSON-RPC 2.0和MCP规范。3.使用调试工具可以用nc(netcat) 或写一个最简单的echo客户端来拦截和查看最初的几条JSON消息对比协议规范。客户端收不到工具/资源列表服务器没有在初始化后发送notifications/tools/list或notifications/resources/list通知。1.确认SDK使用如果使用官方SDK如Pythonmcp确保使用了NotificationOptions()并正确注册了server.list_tools()函数。SDK通常会帮你发送通知。2.手动实现检查如果是手动实现必须在initialized通知之后主动发送列表通知。5.2 工具调用与资源读取错误问题现象可能原因排查步骤与解决方案调用工具时返回“未知工具”错误1. 工具名拼写不一致。2. 工具列表通知中的工具名与call_tool处理函数中判断的名字不匹配。1.严格对照检查server.list_tools()返回的Tool对象的name字段必须与server.call_tool()函数中if name “...”判断的字符串完全一致包括大小写。2.使用常量建议将工具名定义为模块级常量避免硬编码字符串导致的不一致。参数验证失败客户端发送的参数不符合inputSchema的定义。1.强化Schema在inputSchema中尽可能详细地定义参数的type,description,required等。好的Schema本身就是文档。2.服务器端验证即使在Schema中定义了在call_tool函数内部也应该对参数进行二次验证和类型转换提供更友好的错误信息。3.客户端提示在客户端AI智能体侧可以利用Schema生成更准确的参数提示引导用户或AI提供正确的输入。资源读取返回404或空内容1. 资源URI错误或不存在。2.read_resource函数没有正确处理请求的URI。3. 资源内容是动态生成的但生成逻辑有误。1.URI匹配在handle_read_resource函数中使用精确匹配或前缀匹配来路由URI请求。打印收到的URI有助于调试。2.内容格式确保返回的TextContent中的text字段是字符串并且mimeType与声明的一致。对于非文本资源如图片需要使用ImageContent或其他对应的类型。工具执行超时或阻塞工具执行的操作耗时过长如网络请求、复杂计算未及时返回响应。1.异步编程确保你的call_tool处理函数是async的并且内部耗时的操作也使用异步库如aiohttp用于网络请求。避免使用同步的阻塞调用。2.设置超时在客户端侧可以为工具调用设置合理的超时时间。在服务器侧对于可能长时间运行的任务考虑返回一个任务ID然后通过其他通知或资源来提供进度和结果。5.3 高级问题与性能优化问题分析与建议如何管理多个客户端的连接状态MCP服务器尤其是HTTP/SSE或WebSocket传输可能需要同时服务多个客户端。每个客户端连接应有独立的会话状态。PythonmcpSDK的Server实例是与传输层绑定的通常一个服务器进程处理一个连接。对于多连接你需要运行多个进程或使用支持并发的服务器框架如为HTTP传输使用uvicornfastapi。状态共享可以通过外部数据库或内存缓存实现。工具和资源很多列表通知会很大吗会的。如果工具/资源数量庞大例如成百上千一次性发送完整列表可能效率低下。MCP协议目前没有内置的分页或增量更新机制。一个实践方案是1.分类与懒加载初始只发送一个分类或常用工具列表提供“发现更多”的元工具。2.动态按需注册根据客户端请求的上下文动态添加相关的工具到列表并通知更新。这需要更复杂的状态管理。如何保证工具调用的安全性和权限控制MCP协议本身不处理认证和授权。安全需要在传输层或应用层实现1.传输层安全使用HTTPSWSS加密通信。使用API密钥、Token或OAuth在连接建立时进行认证。2.应用层控制在call_tool函数内部根据当前会话的用户身份、上下文等信息判断是否允许执行该操作。可以为每个工具定义所需的权限级别并在执行前检查。如何调试复杂的MCP交互1.用好mcp-inspector这是最直观的调试工具可以查看所有收发的消息。2.启用详细日志在服务器代码中关键位置添加日志输出打印到stderrmcp-inspector会捕获并显示。3.消息抓包对于HTTP传输可以使用curl或 Postman 手动发送JSON-RPC请求或者使用 Wireshark、Charles 等工具抓包分析。5.4 我的踩坑心得Schema是契约务必严谨inputSchema不仅是给AI看的描述更是严格的API契约。一开始我经常偷懒只写“type”: “object”结果AI经常传错参数。后来我学乖了对每个参数都明确type,description, 甚至enum枚举值。这大大提高了工具调用的成功率。异步是必须而非可选尤其是在需要执行I/O操作网络、磁盘的工具中一定要用异步函数async def和异步库。早期我用同步的requests库做HTTP请求在并发调用时直接把服务器卡死了。换成aiohttp后世界都清净了。错误处理要友好在call_tool中不要只抛出原始的Python异常。捕获异常后构造一个包含清晰错误码和信息的JSON-RPC错误响应返回给客户端。这对于AI智能体理解哪里出错了至关重要。例如文件不存在和权限不足应该是不同的错误信息。从Stdio开始再过渡到HTTP开发调试阶段强烈建议先用Stdio传输和mcp-inspector。这能让你快速验证业务逻辑而不用操心网络服务器、CORS、认证等一堆问题。等核心功能稳定后再包装成HTTP服务会顺利得多。“资源”概念被低估了一开始我只关注“工具”觉得“资源”就是读个文件。后来发现用资源来提供“上下文”太有用了。比如我把当前项目的目录结构、最近修改的文件列表、系统环境变量都做成资源。AI智能体在思考“我能在当前目录做什么”时先读取这些资源它的回答会准确和靠谱得多。这真正体现了“Context”的价值。