通过 MCP 实现 AI Agent 目前有哪些最佳实践?

工具、框架、设计模式等
收藏者
0
被浏览
174

5 个回答

kevinnest LV

发表于 2025-4-9 18:04:28

嘿,各位!你们是不是也在捣鼓AI智能体呢?是不是跟我一样,每次想给智能体加点新技能,就得头疼地啃那些又臭又长的文档,然后对着代码改来改去,简直生无可恋?真是太痛苦了!不过,我发现了个超棒的东西——MCP服务器,简直就像游戏的“作弊码”一样!你只需要简单地把它们接入你的智能体,你的智能体立马就学会新本事了,再也不用费劲巴拉地搞代码了,简直不要太爽!这次和大家分享五款“神器”,赶紧一起来看看吧!
1. Firecrawl MCP 服务器: 网页数据抓取
有没有那么一瞬间,你特别希望你的AI智能体能够自己上网“冲浪”,帮你抓取各种有用的信息?  Firecrawl MCP 就是为此而生的!  它是由 Firecrawl 公司开发的,而且在 GitHub 上也能找到它哦。  把它和像 Claude 或者 Cursor 这样的工具连接起来,你的智能体就能像个专业的网络高手一样,轻松抓取网页内容,爬遍整个网站,或者深入挖掘各种你想要的信息。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-1.jpg

它能干啥?

  • 轻轻松松抓取网页上的文字、图片各种内容。
  • 像模像样地在各个网站之间“溜达”。
  • 帮你把乱七八糟的数据整理干净,变成像 JSON 这样方便使用的格式。
我为什么喜欢它?
比如说,你想让你的智能体做点市场调研啥的。有了 Firecrawl,你就不用费劲自己写代码去抓网页了,直接用它就行,省时省力!给你看个例子,你就明白了:
  1. // 完整的网页抓取功能示例,使用了假设的 firecrawl-mcp 库
  2. const firecrawl = require('firecrawl-mcp'); // 假设的 MCP 客户端库
  3. // 默认配置
  4. const DEFAULT_CONFIG = {
  5.     TIMEOUT: 30000,          // 默认超时时间:30秒
  6.     MAX_RETRIES: 2,          // 最大重试次数
  7.     RETRY_DELAY: 1000,       // 重试间隔:1秒 (毫秒)
  8.     USER_AGENT: 'WebScraper/1.0' // 默认用户代理
  9. };
  10. /**
  11. * 抓取网站数据并返回结构化数据
  12. * @param {string} url - 要抓取的网址
  13. * @param {Object} [options] - 配置选项
  14. * @returns {Promise<Object>} 抓取到的数据
  15. */
  16. async function scrapeWebsite(url, options = {}) {
  17.     // 合并默认配置和用户自定义配置
  18.     const config = {
  19.         timeout: options.timeout || DEFAULT_CONFIG.TIMEOUT,
  20.         maxRetries: options.maxRetries || DEFAULT_CONFIG.MAX_RETRIES,
  21.         retryDelay: options.retryDelay || DEFAULT_CONFIG.RETRY_DELAY,
  22.         headers: {
  23.             'User-Agent': options.userAgent || DEFAULT_CONFIG.USER_AGENT,
  24.             ...options.headers
  25.         },
  26.         format: options.format || 'json'
  27.     };
  28.     // 输入验证
  29.     if (!url || typeof url !== 'string' || !isValidUrl(url)) {
  30.         throw new Error('提供的URL无效');
  31.     }
  32.     let attempts = 0;
  33.     let lastError;
  34.     // 重试逻辑
  35.     while (attempts <= config.maxRetries) {
  36.         try {
  37.             // 配置抓取选项
  38.             const scrapeOptions = {
  39.                 url: url,
  40.                 format: config.format,
  41.                 timeout: config.timeout,
  42.                 headers: config.headers
  43.             };
  44.             // 执行抓取
  45.             const result = await firecrawl.scrape(scrapeOptions);
  46.             // 验证响应
  47.             if (!result || !result.data) {
  48.                 throw new Error('抓取操作未返回任何数据');
  49.             }
  50.             console.log(`第 ${attempts + 1} 次尝试,成功抓取 ${url}`);
  51.             return processScrapedData(result.data);
  52.         } catch (error) {
  53.             attempts++;
  54.             lastError = error;
  55.             // 处理特定错误情况
  56.             if (error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT') {
  57.                 console.warn(`第 ${attempts} 次尝试,网络错误: ${error.message}`);
  58.             } else if (error.status === 429) {
  59.                 console.warn('请求频率超限,正在重试...');
  60.             }
  61.             // 如果不是最后一次尝试,则等待后重试
  62.             if (attempts <= config.maxRetries) {
  63.                 await new Promise(resolve => setTimeout(resolve, config.retryDelay));
  64.                 console.log(`正在重试 (第 ${attempts}/${config.maxRetries} 次)...`);
  65.                 continue;
  66.             }
  67.         }
  68.     }
  69.     throw new Error(`经过 ${config.maxRetries + 1} 次尝试后,抓取 ${url} 失败: ${lastError.message}`);
  70. }
  71. /**
  72. * 验证URL格式是否有效
  73. * @param {string} url - 要验证的URL
  74. * @returns {boolean}
  75. */
  76. function isValidUrl(url) {
  77.     try {
  78.         new URL(url);
  79.         return true;
  80.     } catch {
  81.         return false;
  82.     }
  83. }
  84. /**
  85. * 处理和标准化抓取到的数据
  86. * @param {Object} data - 原始抓取数据
  87. * @returns {Object} 处理后的数据
  88. */
  89. function processScrapedData(data) {
  90.     // 可以根据需要添加数据标准化或转换步骤
  91.     return {
  92.         ...data,
  93.         timestamp: new Date().toISOString(),
  94.         sourceUrl: data.url || 'unknown'
  95.     };
  96. }
  97. /**
  98. * 主执行函数,包含使用示例
  99. */
  100. async function main() {
  101.     const targetUrl = 'https://example.com';
  102.     // 自定义配置
  103.     const scrapeOptions = {
  104.         timeout: 60000,           // 超时时间:60秒
  105.         maxRetries: 3,           // 最大重试次数:3次
  106.         retryDelay: 2000,        // 重试间隔:2秒
  107.         userAgent: 'CustomScraper/1.0',
  108.         headers: {
  109.             'Accept': 'application/json'
  110.         }
  111.     };
  112.     try {
  113.         console.log(`开始抓取 ${targetUrl}`);
  114.         const scrapedData = await scrapeWebsite(targetUrl, scrapeOptions);
  115.         // 打印抓取结果
  116.         console.log('抓取到的内容:', JSON.stringify(scrapedData, null, 2));
  117.         // 示例:访问特定数据
  118.         if (scrapedData.title) {
  119.             console.log('页面标题:', scrapedData.title);
  120.         }
  121.     } catch (error) {
  122.         console.error('抓取失败:', {
  123.             message: error.message,
  124.             stack: error.stack,
  125.             url: targetUrl
  126.         });
  127.         process.exit(1); // 以错误代码退出
  128.     }
  129. }
  130. // 如果直接运行此脚本
  131. if (require.main === module) {
  132.     main().then(() => {
  133.         console.log('网页抓取成功完成');
  134.         process.exit(0);
  135.     });
  136. }
  137. // 导出模块,方便其他地方使用
  138. module.exports = {
  139.     scrapeWebsite,
  140.     isValidUrl,
  141.     DEFAULT_CONFIG
  142. };
复制代码
怎么样,你的智能体是不是瞬间变得超能了?  简直不要太轻松!
2. Browserbase MCP 服务器:  浏览器,随叫随到!
想象一下:你的AI智能体,它竟然能自己打开浏览器,像模像样地点击各种链接,甚至还能给你截个网页的屏幕快照!  没错,Browserbase MCP 就能帮你实现这个神奇的功能!有了它,就好像给你的智能体配了个超贴心的“网上冲浪”小助手一样。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-2.jpg

它能做些啥?

  • 一键启动一个真正的浏览器。
  • 想去哪个网站,随便你定。
  • 网页截图。
它牛在哪儿?
比如说,你想监控某个网站的内容有没有更新。  有了 Browserbase MCP,你的智能体就能自己“溜”进浏览器,到处看看,然后把网页截图给你发回来,是不是很方便?
  1. // 完整的基于浏览器的页面捕获功能示例,使用了假设的 browserbase-mcp 库
  2. const browserbase = require('browserbase-mcp'); // 假设的 MCP 客户端库
  3. // 默认配置
  4. const DEFAULT_CONFIG = {
  5.     TIMEOUT: 30000,          // 默认超时时间:30秒
  6.     MAX_RETRIES: 2,          // 最大重试次数
  7.     RETRY_DELAY: 1000,       // 重试间隔:1秒 (毫秒)
  8.     SCREENSHOT_FORMAT: 'png', // 默认截图格式
  9.     VIEWPORT: {              // 默认视窗大小
  10.         width: 1280,
  11.         height: 720
  12.     }
  13. };
  14. /**
  15. * 捕获网页并返回截图信息
  16. * @param {string} url - 要捕获的网址
  17. * @param {Object} [options] - 配置选项
  18. * @returns {Promise<Object>} 截图详细信息
  19. */
  20. async function capturePage(url, options = {}) {
  21.     // 合并默认配置和用户自定义配置
  22.     const config = {
  23.         timeout: options.timeout || DEFAULT_CONFIG.TIMEOUT,
  24.         maxRetries: options.maxRetries || DEFAULT_CONFIG.MAX_RETRIES,
  25.         retryDelay: options.retryDelay || DEFAULT_CONFIG.RETRY_DELAY,
  26.         format: options.format || DEFAULT_CONFIG.SCREENSHOT_FORMAT,
  27.         viewport: options.viewport || DEFAULT_CONFIG.VIEWPORT,
  28.         headless: options.headless !== false // 默认为无头模式
  29.     };
  30.     // 输入验证
  31.     if (!url || typeof url !== 'string' || !isValidUrl(url)) {
  32.         throw new Error('提供的URL无效');
  33.     }
  34.     let session;
  35.     let attempts = 0;
  36.     let lastError;
  37.     // 重试逻辑
  38.     while (attempts <= config.maxRetries) {
  39.         try {
  40.             // 创建浏览器会话
  41.             session = await browserbase.createSession({
  42.                 timeout: config.timeout,
  43.                 headless: config.headless,
  44.                 viewport: config.viewport
  45.             });
  46.             if (!session) {
  47.                 throw new Error('创建浏览器会话失败');
  48.             }
  49.             console.log(`第 ${attempts + 1} 次尝试,正在访问 ${url}`);
  50.             await browserbase.navigate(session, url, { timeout: config.timeout });
  51.             // 等待页面加载完成 (可选,根据需要调整)
  52.             await new Promise(resolve => setTimeout(resolve, 1000));
  53.             // 截取屏幕截图
  54.             const screenshot = await browserbase.takeScreenshot(session, {
  55.                 format: config.format,
  56.                 fullPage: options.fullPage || false
  57.             });
  58.             if (!screenshot || !screenshot.filePath) {
  59.                 throw new Error('截图失败');
  60.             }
  61.             const result = processScreenshotData(screenshot);
  62.             console.log('截图已保存至:', result.filePath);
  63.             return result;
  64.         } catch (error) {
  65.             attempts++;
  66.             lastError = error;
  67.             // 处理特定错误情况
  68.             if (error.code === 'TIMEOUT' || error.code === 'NETWORK_ERROR') {
  69.                 console.warn(`第 ${attempts} 次尝试,浏览器错误: ${error.message}`);
  70.             } else if (error.message.includes('session')) {
  71.                 console.warn('会话创建失败');
  72.             }
  73.             // 清理会话(如果已创建)
  74.             if (session) {
  75.                 await cleanupSession(session).catch(cleanupError => {
  76.                     console.warn('会话清理失败:', cleanupError.message);
  77.                 });
  78.             }
  79.             // 如果不是最后一次尝试,则等待后重试
  80.             if (attempts <= config.maxRetries) {
  81.                 await new Promise(resolve => setTimeout(resolve, config.retryDelay));
  82.                 console.log(`正在重试 (第 ${attempts}/${config.maxRetries} 次)...`);
  83.                 continue;
  84.             }
  85.         }
  86.     }
  87.     throw new Error(`经过 ${config.maxRetries + 1} 次尝试后,捕获 ${url} 失败: ${lastError.message}`);
  88. }
  89. /**
  90. * 清理浏览器会话
  91. * @param {Object} session - 要清理的浏览器会话
  92. */
  93. async function cleanupSession(session) {
  94.     if (session) {
  95.         await browserbase.closeSession(session);
  96.     }
  97. }
  98. /**
  99. * 验证URL格式是否有效
  100. * @param {string} url - 要验证的URL
  101. * @returns {boolean}
  102. */
  103. function isValidUrl(url) {
  104.     try {
  105.         new URL(url);
  106.         return true;
  107.     } catch {
  108.         return false;
  109.     }
  110. }
  111. /**
  112. * 处理和标准化截图数据
  113. * @param {Object} screenshot - 原始截图数据
  114. * @returns {Object} 处理后的截图数据
  115. */
  116. function processScreenshotData(screenshot) {
  117.     return {
  118.         filePath: screenshot.filePath,
  119.         format: screenshot.format,
  120.         timestamp: new Date().toISOString(),
  121.         size: screenshot.size || null,
  122.         url: screenshot.url || 'unknown'
  123.     };
  124. }
  125. /**
  126. * 主执行函数,包含使用示例
  127. */
  128. async function main() {
  129.     const targetUrl = 'https://example.com';
  130.     // 自定义配置
  131.     const captureOptions = {
  132.         timeout: 60000,           // 超时时间:60秒
  133.         maxRetries: 3,           // 最大重试次数:3次
  134.         retryDelay: 2000,        // 重试间隔:2秒
  135.         format: 'jpeg',          // 自定义格式:jpeg
  136.         viewport: {              // 自定义视窗大小
  137.             width: 1920,
  138.             height: 1080
  139.         },
  140.         fullPage: true,          // 捕获完整页面
  141.         headless: true           // 运行在无头模式
  142.     };
  143.     try {
  144.         console.log(`开始捕获 ${targetUrl}`);
  145.         const screenshotData = await capturePage(targetUrl, captureOptions);
  146.         // 打印截图详细信息
  147.         console.log('截图详细信息:', JSON.stringify(screenshotData, null, 2));
  148.         // 示例:访问特定数据
  149.         console.log('文件位置:', screenshotData.filePath);
  150.         console.log('捕获时间:', screenshotData.timestamp);
  151.     } catch (error) {
  152.         console.error('页面捕获失败:', {
  153.             message: error.message,
  154.             stack: error.stack,
  155.             url: targetUrl
  156.         });
  157.         process.exit(1); // 以错误代码退出
  158.     }
  159. }
  160. // 如果直接运行此脚本
  161. if (require.main === module) {
  162.     main().then(() => {
  163.         console.log('页面捕获成功完成');
  164.         process.exit(0);
  165.     });
  166. }
  167. // 导出模块,方便其他地方使用
  168. module.exports = {
  169.     capturePage,
  170.     isValidUrl,
  171.     DEFAULT_CONFIG
  172. };
复制代码
使用代码方法:
  1. // 作为脚本运行
  2. node capture.js
  3. // 作为模块导入
  4. const { capturePage } = require('./capture');
  5. await capturePage('https://example.com');
复制代码
温馨提示:

  • 请根据你实际使用的库调整API调用。
  • 根据你的具体需求修改 processScreenshotData 函数。
你的智能体现在基本上可以像人一样浏览网页了,是不是很神奇?
3. Opik MCP 服务器:  给你的AI智能体装上“监控”
有没有好奇过,你的AI智能体平时都在干些啥?  Opik MCP,就像一个“追踪器”一样。  它可以密切关注你的AI智能体的一举一动,然后把“一手情报”都告诉你。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-3.jpg

它有啥本事?

  • 帮你创建项目,方便管理。
  • 追踪你的智能体的每一个操作步骤。
  • 给你展示各种统计数据,让你对智能体的表现一目了然。
它为啥实用?
如果你的智能体突然“抽风”,表现得不太正常,Opik 就能帮你找出问题所在。  用起来大概是这个样子:
  1. #!/usr/bin/env python3
  2. """
  3. 完整的追踪功能示例,使用了假设的 Opik MCP 客户端库
  4. """
  5. import os
  6. import time
  7. import logging
  8. from typing import Optional, Dict, Any
  9. from opik_mcp import OpikClient  # 假设的 MCP 客户端库
  10. from datetime import datetime
  11. # 配置日志
  12. logging.basicConfig(
  13.     level=logging.INFO,
  14.     format='%(asctime)s - %(levelname)s - %(message)s'
  15. )
  16. logger = logging.getLogger(__name__)
  17. # 默认配置常量
  18. class Config:
  19.     DEFAULT_API_KEY = os.getenv('OPIK_API_KEY', 'your-api-key')
  20.     DEFAULT_TIMEOUT = 30  # 秒
  21.     RETRY_ATTEMPTS = 2
  22.     RETRY_DELAY = 1  # 秒
  23. class OpikTracer:
  24.     """Opik MCP 操作的封装类"""
  25.     def __init__(self, api_key: str = Config.DEFAULT_API_KEY, timeout: int = Config.DEFAULT_TIMEOUT):
  26.         """使用配置初始化 Opik 客户端"""
  27.         if not api_key or api_key == 'your-api-key':
  28.             raise ValueError("必须提供有效的 API 密钥")
  29.         self.client = OpikClient(api_key=api_key, timeout=timeout)
  30.         self.projects = {}
  31.         self.timeout = timeout
  32.     def create_project(self, project_name: str) -> Any:
  33.         """创建项目或获取现有项目,带重试逻辑"""
  34.         if project_name in self.projects:
  35.             return self.projects[project_name]
  36.         attempts = 0
  37.         while attempts <= Config.RETRY_ATTEMPTS:
  38.             try:
  39.                 project = self.client.create_project(project_name)
  40.                 if not project:
  41.                     raise ValueError(f"创建项目失败: {project_name}")
  42.                 self.projects[project_name] = project
  43.                 logger.info(f"已创建项目: {project_name}")
  44.                 return project
  45.             except Exception as e:
  46.                 attempts += 1
  47.                 if attempts > Config.RETRY_ATTEMPTS:
  48.                     logger.error(f"经过 {Config.RETRY_ATTEMPTS + 1} 次尝试后,创建项目失败: {str(e)}")
  49.                     raise
  50.                 logger.warning(f"第 {attempts} 次项目创建尝试失败: {str(e)}")
  51.                 time.sleep(Config.RETRY_DELAY)
  52.     def trace_action(self, project_name: str, trace_name: str, metadata: Optional[Dict] = None) -> None:
  53.         """追踪一个动作,包含错误处理和元数据"""
  54.         project = self.create_project(project_name)
  55.         try:
  56.             trace = self.client.start_trace(project, trace_name)
  57.             if not trace:
  58.                 raise ValueError(f"启动追踪失败: {trace_name}")
  59.             start_time = time.time()
  60.             trace.log(f"开始 {trace_name},时间: {datetime.now().isoformat()}")
  61.             if metadata:
  62.                 trace.log(f"元数据: {metadata}")
  63.             yield trace  # 允许上下文管理器使用
  64.             duration = time.time() - start_time
  65.             trace.log(f"耗时 {duration:.2f} 秒")
  66.             trace.end()
  67.             logger.info(f"追踪 {trace_name} 成功完成")
  68.         except Exception as e:
  69.             logger.error(f"追踪 {trace_name} 失败: {str(e)}")
  70.             if 'trace' in locals():
  71.                 trace.log(f"错误: {str(e)}")
  72.                 trace.end(status="failed")
  73.             raise
  74.     def get_stats(self, project_name: str) -> Dict:
  75.         """获取项目统计数据,带验证"""
  76.         project = self.create_project(project_name)
  77.         attempts = 0;
  78.         while attempts <= Config.RETRY_ATTEMPTS:
  79.             try:
  80.                 stats = self.client.get_trace_stats(project)
  81.                 if not stats:
  82.                     raise ValueError("未返回任何统计数据")
  83.                 return self._process_stats(stats)
  84.             except Exception as e:
  85.                 attempts += 1
  86.                 if attempts > Config.RETRY_ATTEMPTS:
  87.                     logger.error(f"经过 {Config.RETRY_ATTEMPTS + 1} 次尝试后,获取统计数据失败: {str(e)}")
  88.                     raise
  89.                 logger.warning(f"第 {attempts} 次统计数据获取尝试失败: {str(e)}")
  90.                 time.sleep(Config.RETRY_DELAY)
  91.     def _process_stats(self, stats: Dict) -> Dict:
  92.         """处理和标准化统计数据"""
  93.         return {
  94.             "project": stats.get("project_name", "unknown"),
  95.             "total_traces": stats.get("total_traces", 0),
  96.             "avg_duration": stats.get("avg_duration", 0.0),
  97.             "success_rate": stats.get("success_rate", 0.0),
  98.             "timestamp": datetime.now().isoformat()
  99.         }
  100. def main():
  101.     """主执行函数,包含使用示例"""
  102.     try:
  103.         # 初始化追踪器
  104.         tracer = OpikTracer(
  105.             api_key=Config.DEFAULT_API_KEY,
  106.             timeout=60  # 自定义超时时间
  107.         )
  108.         # 项目设置
  109.         project_name = "MyAIProject"
  110.         # 使用上下文管理器的追踪示例
  111.         with tracer.trace_action(project_name, "DecisionStep", {"input_size": 1024}) as trace:
  112.             trace.log("正在处理输入...")
  113.             time.sleep(1)  # 模拟工作
  114.             trace.log("分析完成")
  115.         # 获取并显示统计数据
  116.         stats = tracer.get_stats(project_name)
  117.         logger.info(f"性能统计数据: {stats}")
  118.     except Exception as e:
  119.         logger.error(f"执行失败: {str(e)}")
  120.         exit(1)
  121. if __name__ == "__main__":
  122.     main()
复制代码
使用代码方法:
  1. # 作为脚本运行
  2. python trace.py
  3. # 作为模块导入
  4. from trace import OpikTracer
  5. tracer = OpikTracer(api_key="your-actual-key")
  6. with tracer.trace_action("MyProject", "TestStep") as trace:
  7.     trace.log("正在工作...")
  8. stats = tracer.get_stats("MyProject")
复制代码
请注意:

  • 把代码里的 'opik_mcp' 替换成你实际用的库的名字。
  • 记得设置 OPIK_API_KEY 环境变量,或者直接把 API 密钥传进去。
  • _process_stats 函数要根据实际的统计数据格式来调整。
现在,你的智能体就像有了“眼睛”,你随时都能掌握它的动态了,是不是超实用?
4. Brave MCP 服务器:  搜索,就是要更聪明!
搜索功能对AI智能体来说,那是相当重要的!  Brave MCP 服务器就能让你的智能体接入 Brave 搜索引擎的 API。  无论是想在网上搜信息,还是想找本地文件,它都能帮你搞定。
它能做啥?

  • 帮你“冲浪”搜索全网信息。
  • 还能在你自己的电脑里“翻箱倒柜”找东西。
我为啥觉得它赞?
是不是有时候你的智能体需要快速查点资料?  用 Brave MCP 服务器就能轻松实现搜索功能,代码大概是这样写的:
  1. // 完整的网页搜索功能示例,使用了假设的 brave-mcp 库
  2. const brave = require('brave-mcp'); // 假设的 MCP 客户端库
  3. // 默认配置
  4. const DEFAULT_CONFIG = {
  5.     TIMEOUT: 10000,          // 默认超时时间:10秒
  6.     MAX_RETRIES: 3,          // 最大重试次数
  7.     RETRY_DELAY: 500,        // 重试间隔:0.5秒 (毫秒)
  8.     MAX_RESULTS: 5,          // 默认最大结果数
  9.     LANGUAGE: 'en'           // 默认语言:英语
  10. };
  11. /**
  12. * 使用 Brave MCP 执行网页搜索
  13. * @param {string} query - 搜索关键词
  14. * @param {Object} [options] - 配置选项
  15. * @returns {Promise<Object[]>} 搜索结果数组
  16. */
  17. async function searchWeb(query, options = {}) {
  18.     // 合并默认配置和用户自定义配置
  19.     const config = {
  20.         timeout: options.timeout || DEFAULT_CONFIG.TIMEOUT,
  21.         maxRetries: options.maxRetries || DEFAULT_CONFIG.MAX_RETRIES,
  22.         retryDelay: options.retryDelay || DEFAULT_CONFIG.RETRY_DELAY,
  23.         maxResults: options.maxResults || DEFAULT_CONFIG.MAX_RESULTS,
  24.         language: options.language || DEFAULT_CONFIG.LANGUAGE,
  25.         safeSearch: options.safeSearch || 'moderate' // 默认安全搜索级别:适中
  26.     };
  27.     // 输入验证
  28.     if (!query || typeof query !== 'string' || query.trim().length === 0) {
  29.         throw new Error('提供的搜索关键词无效或为空');
  30.     }
  31.     let attempts = 0;
  32.     let lastError;
  33.     // 重试逻辑
  34.     while (attempts <= config.maxRetries) {
  35.         try {
  36.             // 配置搜索参数
  37.             const searchParams = {
  38.                 query: query.trim(),
  39.                 maxResults: config.maxResults,
  40.                 timeout: config.timeout,
  41.                 language: config.language,
  42.                 safeSearch: config.safeSearch
  43.             };
  44.             console.log(`正在搜索关键词 "${query}" (第 ${attempts + 1} 次尝试)`);
  45.             const results = await brave.webSearch(searchParams);
  46.             // 验证响应
  47.             if (!results || !Array.isArray(results)) {
  48.                 throw new Error('搜索结果格式无效');
  49.             }
  50.             const processedResults = processSearchResults(results);
  51.             console.log(`找到 ${processedResults.length} 条结果`);
  52.             return processedResults;
  53.         } catch (error) {
  54.             attempts++;
  55.             lastError = error;
  56.             // 处理特定错误情况
  57.             if (error.code === 'ETIMEDOUT' || error.code === 'ENOTFOUND') {
  58.                 console.warn(`第 ${attempts} 次尝试,网络错误: ${error.message}`);
  59.             } else if (error.status === 429) {
  60.                 console.warn('请求频率超限,正在重试...');
  61.             }
  62.             // 如果不是最后一次尝试,则等待后重试
  63.             if (attempts <= config.maxRetries) {
  64.                 await new Promise(resolve => setTimeout(resolve, config.retryDelay));
  65.                 console.log(`正在重试 (第 ${attempts}/${config.maxRetries} 次)...`);
  66.                 continue;
  67.             }
  68.         }
  69.     }
  70.     throw new Error(`经过 ${config.maxRetries + 1} 次尝试后,搜索关键词 "${query}" 失败: ${lastError.message}`);
  71. }
  72. /**
  73. * 处理和标准化搜索结果
  74. * @param {Object[]} results - 原始搜索结果数组
  75. * @returns {Object[]} 处理后的结果数组
  76. */
  77. function processSearchResults(results) {
  78.     return results.map((result, index) => ({
  79.         id: result.id || index,
  80.         title: result.title || '无标题',
  81.         url: result.url || '无URL',
  82.         snippet: result.snippet || result.description || '无描述',
  83.         timestamp: new Date().toISOString(),
  84.         source: result.source || '未知来源'
  85.     }));
  86. }
  87. /**
  88. * 主执行函数,包含使用示例
  89. */
  90. async function main() {
  91.     const searchQuery = '最新AI趋势';
  92.     // 自定义配置
  93.     const searchOptions = {
  94.         timeout: 15000,           // 超时时间:15秒
  95.         maxRetries: 4,           // 最大重试次数:4次
  96.         retryDelay: 1000,        // 重试间隔:1秒
  97.         maxResults: 10,          // 获取10条结果
  98.         language: 'en',          // 结果语言:英语
  99.         safeSearch: 'strict'     // 安全搜索级别:严格
  100.     };
  101.     try {
  102.         console.log(`开始搜索关键词 "${searchQuery}"`);
  103.         const results = await searchWeb(searchQuery, searchOptions);
  104.         // 打印搜索结果 (JSON格式)
  105.         console.log('搜索结果:', JSON.stringify(results, null, 2));
  106.         // 示例:访问特定数据并打印
  107.         results.forEach((result, index) => {
  108.             console.log(`结果 ${index + 1}:`);
  109.             console.log(`- 标题: ${result.title}`);
  110.             console.log(`- URL: ${result.url}`);
  111.             console.log(`- 摘要: ${result.snippet}`);
  112.             console.log('---');
  113.         });
  114.     } catch (error) {
  115.         console.error('搜索失败:', {
  116.             message: error.message,
  117.             stack: error.stack,
  118.             query: searchQuery
  119.         });
  120.         process.exit(1); // 以错误代码退出
  121.     }
  122. }
  123. // 如果直接运行此脚本
  124. if (require.main === module) {
  125.     main().then(() => {
  126.         console.log('搜索成功完成');
  127.         process.exit(0);
  128.     });
  129. }
  130. // 导出模块,方便其他地方使用
  131. module.exports = {
  132.     searchWeb,
  133.     DEFAULT_CONFIG,
  134.     processSearchResults
  135. };
复制代码
使用代码方法:
  1. // 作为脚本运行
  2. node search.js
  3. // 作为模块导入
  4. const { searchWeb } = require('./search');
  5. await searchWeb('最新AI趋势');
复制代码
温馨提示:  记得根据你实际用的 Brave Search API 或者类似的搜索服务来调整代码里的 API 调用。  processSearchResults 函数也要根据你的具体需求和实际返回的数据格式来修改。  可能你还需要先安装一下这个包: npm install brave-mcp。
有了它,你的智能体就好像有了自己的“谷歌”,是不是超值?
5. Sequential Thinking MCP 服务器:  步步为营,让思考更深入
有时候,你的智能体不能光靠“猜”,得学会像人一样思考问题。  Sequential Thinking MCP 服务器就能帮它把复杂的问题拆成一个个小步骤,然后一步一步地想明白。
它是干啥的?

  • 把复杂的大问题拆分成很多小步骤。
  • 让智能体在解决问题的过程中,一步一步地深入思考。
它厉害在哪儿?
就拿解数学题来说吧,你的智能体可以用 Sequential Thinking MCP 服务器,像下面这样一步一步地把题解出来:
  1. #!/usr/bin/env python3
  2. """
  3. 完整的顺序思考功能示例,使用了假设的 sequential_thinking_mcp 库
  4. """
  5. import logging
  6. from typing import List, Optional, Union
  7. from sequential_thinking_mcp import Thinker  # 假设的 MCP 客户端库
  8. from datetime import datetime
  9. # 配置日志
  10. logging.basicConfig(
  11.     level=logging.INFO,
  12.     format='%(asctime)s - %(levelname)s - %(message)s'
  13. )
  14. logger = logging.getLogger(__name__)
  15. # 默认配置常量
  16. class Config:
  17.     MAX_STEPS = 20  # 最大步骤数,防止无限循环
  18.     TIMEOUT = 30    # 每次操作的超时时间,单位:秒
  19.     DEFAULT_FORMAT = 'text'  # 默认输出格式:文本
  20. class SequentialSolver:
  21.     """顺序思考操作的封装类"""
  22.     def __init__(self, timeout: int = Config.TIMEOUT, max_steps: int = Config.MAX_STEPS):
  23.         """使用配置初始化 Thinker"""
  24.         try:
  25.             self.thinker = Thinker(timeout=timeout)
  26.             self.max_steps = max_steps
  27.             self.timeout = timeout
  28.         except Exception as e:
  29.             logger.error(f"初始化 Thinker 失败: {str(e)}")
  30.             raise
  31.     def solve(self, problem: str, steps: bool = True, output_format: str = Config.DEFAULT_FORMAT) -> Union[List[str], str]:
  32.         """
  33.         使用顺序思考步骤解决问题
  34.         Args:
  35.             problem: 要解决的问题
  36.             steps: 是否返回步骤式的解答
  37.             output_format: 输出格式 ('text', 'json' 等)
  38.         Returns:
  39.             根据 steps 参数返回步骤列表或最终答案
  40.         """
  41.         // 输入验证
  42.         if not problem or not isinstance(problem, str):
  43.             raise ValueError("必须提供有效的问题字符串")
  44.         try:
  45.             logger.info(f"开始解决问题: {problem}")
  46.             solution = self.thinker.solve(
  47.                 problem=problem,
  48.                 steps=steps,
  49.                 max_steps=self.max_steps
  50.             )
  51.             if not solution:
  52.                 raise ValueError("未返回任何解答")
  53.             if steps:
  54.                 processed_steps = self._process_steps(solution, output_format)
  55.                 logger.info(f"在 {len(processed_steps)} 步内找到解答")
  56.                 return processed_steps
  57.             else:
  58.                 result = self._process_result(solution, output_format)
  59.                 logger.info(f"找到解答: {result}")
  60.                 return result
  61.         except Exception as e:
  62.             logger.error(f"解决问题 '{problem}' 失败: {str(e)}")
  63.             raise
  64.     def _process_steps(self, steps: List, format: str) -> List[str]:
  65.         """处理和格式化解答步骤"""
  66.         if not isinstance(steps, (list, tuple)):
  67.             raise ValueError("步骤必须是列表或元组类型")
  68.         processed = []
  69.         for i, step in enumerate(steps[:self.max_steps], 1):
  70.             if format == 'json':
  71.                 processed.append({
  72.                     "step": i,
  73.                     "description": str(step),
  74.                     "timestamp": datetime.now().isoformat()
  75.                 })
  76.             else:
  77.                 processed.append(f"步骤 {i}: {str(step)}")
  78.         return processed
  79.     def _process_result(self, result: Any, format: str) -> str:
  80.         """处理和格式化最终结果"""
  81.         if format == 'json':
  82.             return {
  83.                 "result": str(result),
  84.                 "timestamp": datetime.now().isoformat()
  85.             }
  86.         return str(result)
  87.     def validate_solution(self, problem: str, solution: Union[List[str], str]) -> bool:
  88.         """验证解答 (基础实现)"""
  89.         try:
  90.             if isinstance(solution, list):
  91.                 final_step = solution[-1].lower()
  92.                 // 对代数问题进行基本检查
  93.                 if '=' in problem and 'x =' in final_step:
  94.                     return True
  95.             return bool(solution)
  96.         except Exception as e:
  97.             logger.warning(f"解答验证失败: {str(e)}")
  98.             return False
  99. def main():
  100.     """主执行函数,包含使用示例"""
  101.     try:
  102.         # 初始化解题器
  103.         solver = SequentialSolver(
  104.             timeout=60,  # 自定义超时时间
  105.             max_steps=10  # 自定义最大步骤数
  106.         )
  107.         # 示例问题
  108.         problem = "解方程 2x + 3 = 7"
  109.         # 步骤式解题
  110.         logger.info(f"正在解题: {problem}")
  111.         steps = solver.solve(problem, steps=True, output_format='text')
  112.         # 打印解题步骤
  113.         for step in steps:
  114.             print(step)
  115.         # 验证解答
  116.         if solver.validate_solution(problem, steps):
  117.             logger.info("解答似乎有效")
  118.         else:
  119.             logger.warning("解答验证失败")
  120.         # 非步骤式解题示例
  121.         result = solver.solve(problem, steps=False)
  122.         print(f"\n最终答案: {result}")
  123.     except Exception as e:
  124.         logger.error(f"执行失败: {str(e)}")
  125.         exit(1)
  126. if __name__ == "__main__":
  127.     main()
复制代码
使用代码方法:
  1. # 作为脚本运行
  2. python solver.py
  3. # 作为模块导入
  4. from solver import SequentialSolver
  5. solver = SequentialSolver()
  6. steps = solver.solve("Solve 2x + 3 = 7", steps=True)
  7. for step in steps:
  8.     print(step)
复制代码
温馨提示:记得根据你实际用的库来调整代码里的 API 调用。  _process_steps 和 _process_result 这两个函数也要根据你的实际输出需求来改。  如果你想让智能体更智能地验证答案,可以改进 validate_solution 函数。  还有,max_steps 和 timeout 这两个参数,也要根据问题的复杂程度来调整。
有了这个 Sequential Thinking MCP 服务器,你的智能体就好像有了一个“笔记本”,可以用来一步一步地思考问题了,是不是超级给力?
这些 MCP 服务器,简直就是给你的AI智能体开“外挂”!  再也不用为各种功能苦哈哈地写代码了,直接“插”上这些服务器,你的AI智能体就能瞬间拥有网页抓取、浏览器操作、行为追踪、智能搜索、深入思考等等各种超能力,简直是如有神助!
<hr/>我会定期更新干货和学习笔记。喜欢的话,记得点个关注 ,不错过后续精彩内容!

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-4.jpg

超超 LV

发表于 2025-4-9 18:15:44

学习智能体的这段时间,我发现一个比较有意思的现象,就是大多数市面上的智能体只有价值,没有商业价值。

有的智能体功能看起来很炫酷,但就是解决不了一点实际问题,有的智能体却能帮助企业实现 300% 提效。

这是因为大多数人在制作一个普通智能体或运用在商业的智能体上,他们都没有一套系统的方法论。

可以说很多人在制作智能体的时候,都在自嗨,甚至连受众用户群体都没了解过。

因此,我们在制作智能体的时候,不应该急着写代码,梳理工作流,而是坐下来好好规划一下:这个 Agent 到底是谁在用?能解决什么痛点?它的场景是什么?

先把这些问题想清楚,才能少走弯路,释放 Agent 的价值。

今天我就讲述一套我个人搭建 Agent 的方法论。


通过 MCP 实现 AI Agent 目前有哪些最佳实践?-1.jpg





需求与场景定义




需求是指个体或系统在特定条件下为实现某种目标或维持某种状态所必需的资源、条件或服务。

场景定义了用户使用产品或服务时的行为,需求以及互动方式,帮助我们更好的理解用户的体验和期望。

怎么样?是不是说了跟没说一样?哈哈,说点人话。

其实我们在做一个智能体之前,我们就需要调研一些场景,从中寻找一些可能存在的痛点需求。

一个智能体当它能够解决目标用户的需求时,才能留住目标用户,才可能有商业价值。

但需求只有在场景下,才会被体现出来。

举个例子:上周我在面试,发现一些写字楼楼下开有一些什么广告,打印,复印店,我去店里打印自己的简历,发现店里的生意还是很不错的,我都需要等一段时间才轮到我打印。

如果这些打印店开在一些繁华的商业街,它当然也有生意,但大概率不会比写字楼下的生意好。

因为在写字楼下的打印店,它已经有明确的场景,明确的需求,且需求频率较高,同时目标受众基本也确定了。

由此,我们可以知道,在确定需求前,我们应该先确定场景,再确定目标用户,最后再定义需求,而不是直接就定义需求就完事了。

因为你认为的需求,它在某些场景下不一定是真需求,就算它是真需求,它在某些场景下,它也没那么紧急或频繁。

所以,我们在做一个智能体之前,我们需要考虑好它在应用场景中目标用户的需求,需求紧急度怎么样,频率怎么样,如果是一次性的,那么用户用完就走了。

当然,如果是企业内部提效,场景和需求已经确定了,这一步直接跳过。


通过 MCP 实现 AI Agent 目前有哪些最佳实践?-2.jpg





需求分析




当我们确定好场景,目标用户,以及需求之后,我们下一步就要对需求进行梳理,进行分析。

那么我们该分析什么东西?又怎样去做分析?

首先,我们要明确的是,我们做这个 AI Agent 是帮我们解决什么样的问题。

比如我是一位做自媒体的人,我就会做一个来帮我解决重复性工作的 AI Agent ,比如找选题,找热点,做用户分析。

其次,我们要进行工作流的拆解,这一步我们要时刻记住,我们该分析,该梳理的那些步骤,是重复的,机械化的步骤,且越详细越好。

当然,这时候我们也可以使用 AI 进行协助,充分的利用 AI 的思考能力,减少自己的工作时间,但我更希望你能独立思考,这对你来说十分有益。

  1. 作为一位工作流梳理专家,麻烦你帮我梳理一下“自媒体编辑”这个角色在日常工作中需要重复执行的任务,并且标注出哪些任务可以由 AI 来协助,哪些任务需要我亲自完成。请先以表格形式输出,表格包含三列:工作内容、AI 协助、人工来做。当我认为表格内容完整后,我会回复“继续”,随后请你以 Mermaid 流程图的形式输出,每个流程节点需注明是否可由 AI 协助完成,流程图为横向。梳理过程中,请明确可能涉及的工具。
复制代码

最好我们能输出一个需求文档,流程图。


通过 MCP 实现 AI Agent 目前有哪些最佳实践?-3.jpg





选择平台




分析完需求之后,我们就该选择合适的 AI Agent 的平台了,这里只需要根据自己的需求进行选择即可。

Coze,云端 AI Agent 快速搭建,插件类型丰富,多 Agent 协作,拖拽式工作流,但不能在本地。

Dify,开源灵活,通过可视化的界面,极大地简化了开发流程,不仅面向个人开发者,它还提供了企业级的解决方案。

FastGPT,知识问答优化方面强。

新手直接使用 Coze,Dify 无代码平台。


通过 MCP 实现 AI Agent 目前有哪些最佳实践?-4.jpg


选择 LLM




选择完平台以后,我们就该考虑选择大模型了,那么我们该如何选择大模型呢?

答案是根据你的具体使用场景进行选择,如果你的场景比较的复杂,就可以考虑混合使用了。

但我建议你去深入了解一下不同模型的能力,现在海外的 ChatGPT,Claude,Gemini等,国内的也有 Kimi,通义千问,DeepSeek,豆包等。

每个模型有每个模型的优势特点,不要啥啥场景都用一个模型,要最大发挥模型的优点。

比如

  • 该模型的领域专精度怎么样?
  • 该模型的处理上下文的窗口长度怎么样?
  • 该模型的算力,推理能力怎么样?
  • 该模型的价格怎么样?
  • 该模型会不会泄露用户隐私数据?
  • ....


通过 MCP 实现 AI Agent 目前有哪些最佳实践?-5.jpg


如果你选择海外的模型,我建议选择 OpenAI 和 Claude 毕竟是属于头部的大模型,国内的大模型的话,毫无疑问了直接选 DeepSeek 即可,最近 DeepSeek 也是迭代更新了,有兴趣的朋友可以看看。

选择工具




在AI Agent开发中,工具选型是构建智能体能力体系的核心环节。工具作为智能体的"感官与肢体",可分为两大技术实现路径

标准化接口工具(API驱动),有 API 接口的工具,对接就比较的简单,在 Coze,Dify 平台上,已经集成了许多工具,直接配置就行了。

非结构化系统交互(RPA驱动)通过计算机视觉(CV)与操作系统级自动化,模拟人类键鼠操作的自动化工具。


通过 MCP 实现 AI Agent 目前有哪些最佳实践?-6.jpg


写提示词




提示词是 AI Agent 的核心,只有好的的提示词,大模型才能输出好的答案。

之前 DeepSeek 爆火的时候,我一度认为已经不需要提示词了,但后面发现没有好的提示词,DeepSeek 的回答很容易用力过猛。

所以,在我不怎么使用提示词用了一些推理模型一段时间之后,又乖乖回去使用提示词了。

毕竟

  • 好的提示词能帮助 AI Agent 准确地理解任务,提升大模型的回答质量。
  • 好的提示词可以减少 token 的消耗,降低钱的成本。
  • 好的提示词在后续的修改,扩充和调试都很方便。
  • 好的提示词能节约上下文的窗口空间。
  • 好的提示词可以减少大模型的响应延迟,提高回复的速度。
  • ....
除了掌握如何编写有效的提示词以外,我们还要了解提示词和大模型两者之间的交互规则是怎么样的,毕竟知己知彼,百战不殆。

比如

  • 对于模型生成的一些重要信息,尤其是那种涉及专业领域,决策依据等方面的内容。
  • 不要故意输入恶意或诱导的内容,让模型生成有害,不适当或虚假的信息,会导致不良后果。
  • 尽量让交互方式和语言风格适应用户的习惯和偏好,使交流更加流畅。
  • 模拟用户提一些刁钻的问题,拒绝一些完美的话术,迫使其发生错误。

数据存储




在我们使用 AI Agent 的时候,必然会产生一些数据,比如聊天记录,实时采集的信息,这时候我们就要使用数据库将这些重要的数据进行存储。

对于那些敏感的数据,我们就本地存储,对于那些非敏感数据,我们就可以选择云端。

同时,对于搞技术的人,直接使用 MySQL 这种常用的数据库就行,我也用的这个。

对于那些非技术人员的话,我常见的就是使用飞书文档了。

构建 UI




博主还在学,后期该内容再更新一篇,后面再写吧,抱歉。懂得可以联系俺,教一下俺。

测试评估




当 AI Agent 开发完之后,我们就要进行测试了,做软件开发需要测试,这个也是不例外。

测试方面的话,对于我们这种新手,主要考虑以下几个方面。

功能测试:验证任务执行的完整性,防止执行一半,中断没数据了,我就遇到过。

压力测试:模拟高并发的一些请求。

AB测试:对比一些不同模型,不同提示词的一些效果。

在评估方面的话,我们主要关注两个点就够了。

准确性:关键人物完成率,比如我们搭建了一个客服 AI Agent ,这时候我们就要看客服回答的正确率。

成本:这个必须考虑,主要看单次调用 Token 消耗是多少。


通过 MCP 实现 AI Agent 目前有哪些最佳实践?-7.jpg





部署发布




测试你感觉没问题,那我们就要发布使用了,不同的 AI Agent 开发平台有不同的部署方式。

有的是云端部署,有的是本地的部署,看情况操作即可。

在发布完成后,我们还要对日志进行监控分析,追踪存在的一些异常行为。

同时,我们也要持续迭代,比如定期更新知识库与模型版本,要跟上时代,懂吧兄弟。

总结

今天,我们讲了一套搭建 AI Agent 的方法论,这套方法论适用于大多数情况,不能说全部,里面还有很多细节,需要我们去考虑。

主要的步骤分为 需求与场景定义 —> 需求分析 —> 选择平台 —> 选择 LLM —> 选择工具 —> 写提示词 —> 数据存储 —> 构建UI —> 测试评估 —> 部署发布。

方法并非一成不变,将来我会在不断的实践中调整方法,所以这个方法论也会持续更新,一段时间更新一篇吧,文章内容不会使用花里胡哨的词句,只讲大家听得懂的内容!

最近俺也是成为了打工人,但账号会持续更新内容,可能会更新的比较的慢,但只更新大家想看的,能看懂的内容。

感谢你的耐心。

如果看完喜欢,请帮忙转发分享一下,你的点赞转发,就是我更新下去的动力!

那年那月 LV

发表于 2025-4-9 18:25:22

以下回答来自Deepseek R1
通过MCP(Model Context Protocol)实现AI Agent的最佳实践,目前已在工具集成、框架设计、开发模式等方面形成了多种创新方案。以下从工具与框架、设计模式、应用场景三个维度进行系统性总结:

---

一、工具与框架实践

1. **Cursor IDE + MCP的深度集成**  
   - Cursor作为智能开发环境,通过MCP协议连接Slack、GitHub、Google Docs等平台,实现自动化工作流。例如,用户通过Slack提出功能需求后,MCP服务自动解析需求、生成代码并提交Pull Request,全程无需人工干预,效率提升10倍以上。  
   - **关键工具链**:Composio提供的托管MCP服务支持100+应用和15,000+ API操作,无需复杂认证或编码即可接入。

2. **BlenderMCP:3D建模自动化**  
   - 基于MCP的开源项目BlenderMCP允许Claude通过自然语言指令控制Blender完成3D建模任务。例如,用户输入“创建低多边形地牢场景”,MCP服务器自动调用Blender插件执行建模、材质设置等操作,将原本几小时的工作缩短至几分钟。

3. **Cline插件 + MCP的本地化开发**  
   - Cline作为VSCode插件,结合MCP协议支持本地化智能体开发。开发者可通过自然语言快速创建MCP服务,例如生成YouTube视频字幕提取器或军事评论文章生成器,避免数据上传至第三方平台的风险。

---

二、设计模式与开发范式

1. **Tool Use Pattern(工具调用模式)**  
   - **核心机制**:MCP通过动态发现和双向通信能力,使AI Agent能够按需调用外部工具(如数据库、API)。例如,在旅行规划场景中,MCP统一连接日历、邮件和机票API,AI自动完成时间匹配、订票和邮件通知的完整流程。  
   - **优势**:与传统API集成相比,开发者无需为每个工具单独编写代码,只需遵循MCP协议规范即可实现跨平台复用。

2. **Planning Pattern(任务规划模式)**  
   - **应用案例**:通过MCP将复杂任务拆解为子任务。例如,HuggingGPT通过MCP连接多个模型,根据任务需求选择最优模型执行子任务(如文本生成、图像处理),最终汇总结果。  
   - **技术实现**:MCP支持上下文保持和实时交互,允许Agent在任务执行过程中动态调整策略。

3. **Multi-Agent Collaboration Pattern(多智能体协作)**  
   - **实验性应用**:多个MCP客户端协同工作,例如在软件开发中,一个Agent负责需求解析,另一个生成代码,第三个执行测试。尽管当前技术成熟度有限,但ChatDev等项目已初步验证其可行性。

---

三、关键开发优化策略

1. **统一协议与动态发现**  
   - MCP的标准化接口(类似USB-C)允许开发者一次集成即可复用多个服务,例如Composio的MCP服务器可同时支持GitHub、Slack和Google搜索,减少重复开发成本。

2. **安全与权限控制**  
   - MCP服务器内置安全机制,例如通过本地服务器管理敏感数据(如数据库凭证),避免将密钥直接暴露给AI模型,同时支持细粒度权限管理。

3. **低代码/无代码开发**  
   - 使用Cline等工具,开发者可通过自然语言提示快速生成MCP服务。例如,输入“创建下载YouTube字幕的MCP服务器”,系统自动生成服务代码并配置API连接。

---

四、典型应用场景案例

1. **智能IDE自动化**  
   - Cursor通过MCP集成代码库、文档和通讯工具,实现上下文感知的代码建议、自动Bug修复和需求响应。

2. **跨平台数据分析**  
   - MCP连接多个数据库和可视化工具,AI Agent自动完成数据清洗、分析及图表生成,例如金融报告自动化生成。

3. **创意设计增强**  
   - 如BlenderMCP将自然语言指令转化为3D建模操作,或通过MCP+QGIS实现地理信息系统的自动化处理。

---

未来挑战与趋势

-  **标准化与生态扩展**:尽管MCP社区已有超1100个开源服务器,但其能否成为行业标准仍需观察(如LangChain社区对此持谨慎态度)。  
- **技术融合**:结合Planning Pattern和多智能体协作,MCP可能推动更复杂的自动化场景,例如全链路项目管理或跨领域协作。

通过以上实践,开发者可充分利用MCP的灵活性、安全性和高效性,快速构建适应复杂需求的AI Agent系统。

wddp LV

发表于 2025-4-9 18:35:45

今天测试了下Blender + Claude Desktop通过MCP联动的应用,下面视频记录了生成全过程,视频已加速。
通过 MCP 实现 AI Agent 目前有哪些最佳实践?-1.jpg


https://www.zhihu.com/video/1885958030513926783
最后的成品并不复杂,就是一个3D模拟出来的沙滩,但要知道现在只是starting point,随着不断的迭代,最后面AI直接做3D建模是完全可行的。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-2.jpg

总体方法很简单,就三步:
1 软件下载安装
2 软件配置
3 连接并使用
前置软件下载和安装

需要安装四个软件/应用:

  • Blender 3.0及以上版本
  • Python 3.10及以上版本
  • Claude Desktop
  • uv包
前三个官网下载即可,第4个uv包是一个 Python 包安装器和解析器,它被设计成比 pip 和 pip-tools 更快。
简单来说,uv 可以帮助你更快速地安装和管理你的 Python 项目所需要的各种依赖包。
Mac安装,打开terminal输入
  1. brew install uv
复制代码
Windows安装分两步
  1. powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
复制代码
然后
  1. set Path=C:\Users\nntra\.local\bin;%Path%
复制代码
软件配置

Claude Desktop设置

1 打开Desktop,选择Settings设置

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-3.jpg

2 选择Developer开发者模式,然后选择Edit Config

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-4.jpg

3 之后会定位到本地的配置文件,json格式。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-5.jpg

4 修改成如下配置

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-6.jpg

可以直接复制粘贴这个
  1. {
  2.     "mcpServers": {
  3.         "blender": {
  4.             "command": "uvx",
  5.             "args": [
  6.                 "blender-mcp"
  7.             ]
  8.         }
  9.     }
  10. }
复制代码
Blender配置

1 下载addon.py 文件,链接如下
https://github.com/ahujasid/blender-mcp/blob/main/addon.py
2 打开Blender,点击edit,然后preference

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-7.jpg

3 点击向下箭头,然后点击install from disk,也就是从本地文件安装意思。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-8.jpg

4找到你刚下载好的addon.py进行安装
5 确保Blender MCP前面的箭头已打上,表明功能已开启。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-9.jpg

使用方法

连接Blender与Claude Desktop

1 打开Blender的3D视角(快捷键是N)
然后如下顺序BlenderMCP,然后Start MCP Server开始连接

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-10.jpg

⚠️注意:Use Assets From Ploy Haven和User Hyper3D Rodin最好开启,有些场景需要用到
2 查看Claude Desktop是否已连接
如果看到这个锤子标志,就差不多成功了

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-11.jpg

点开看到这些MCP Tools就可以确定成功了。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-12.jpg

在Settings里面也可以看到Blender的MCP server正在运行中。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-13.jpg

Claude Desktop使用

只需要输入最简单的Prompt即可,剩下的几乎是全自动的

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-14.jpg

遇到这种需求权限的时候,直接无脑给给就行。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-15.jpg


Prompt示例[1]

  • "Create a low poly scene in a dungeon, with a dragon guarding a pot of gold"
  • "Create a beach vibe using HDRIs, textures, and models like rocks and vegetation from Poly Haven"
  • Give a reference image, and create a Blender scene out of it
  • "Generate a 3D model of a garden gnome through Hyper3D"
  • "Get information about the current scene, and make a threejs sketch from it"
  • "Make this car red and metallic"
  • "Create a sphere and place it above the cube"
  • "Make the lighting like a studio"
  • "Point the camera at the scene, and make it isometric"

TsMnO LV

发表于 2025-4-9 18:44:26

推荐一个好用的mcp客户端,chatwise。
是个人认为最目前简单易用的mcp客户端(很接近原生claude)。可以帮助大家快速测试各种mcp工具。

通过 MCP 实现 AI Agent 目前有哪些最佳实践?-1.jpg

10M体积塞下cherry studio 100M安装包的功能。模型和mcp的配置非常简单,artificts功能做实时预览。还有实际使用下来体验很丝滑。
下面是使用chatwise简单搭建的一个深度学术搜索agent,以下是测试效果(在专业学术问题上,个人认为比google Deep Research效果更好):
通过 MCP 实现 AI Agent 目前有哪些最佳实践?-2.jpg

基于MCP工具的深度学术搜索
https://www.zhihu.com/video/1891429248285251116
29美元一次性购买,有点小贵。点下面的链接,购买时候输入优惠码GUIZANG,可以打8折:
https://chatwise.app?atp=RQfocH

您需要登录后才可以回帖 登录 | 立即注册