拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MCP协议、服务与Tool三层解析:从WebSocket通信到AI工具链集成

MCP协议、服务与Tool三层解析:从WebSocket通信到AI工具链集成

1. 别再被“MCP”三个字母绕晕了:先撕开它身上的三层面纱

你是不是也这样?刷技术群、看文档、查报错日志,冷不丁就撞上“MCP”——

  • 在 Playwright 的 GitHub Issue 里看到playwright mcp;
  • 在 Burp Suite 插件说明里读到“需对接 MCP Server”;
  • 在蓝湖部署文档中发现“MCP 服务未启动,tool 调用失败”;
  • 甚至在某条加密勒索提示里瞥见“you need decryption tool”,后面紧跟着mcp字样(别慌,这纯属巧合,和本文讨论的 MCP 完全无关)。

更让人头皮发紧的是:有人问“MCP 是软件协议还是硬件协议?那个概念叫什么来着?”——说明连基本归类都模糊了。还有人搜“手机怎么获取 MCP 服务”,结果点进来的全是安卓 root 工具或预装垃圾软件页面……这不是技术问题,是语义污染。

我从 2022 年底开始深度参与多个 AI 工具链集成项目,亲手搭过 7 套不同形态的 MCP 架构(含 RuoYi-Vue-Pro 合并版、Trae IDE + Burp Suite 联动版、Cursor 浏览器沙箱版),踩过所有你能想到的命名陷阱。今天不讲虚的,直接把“MCP”这个词从根上拆解清楚:它根本不是单一实体,而是一套分层协作关系的统称——就像“厨房”不是一道菜,而是灶台、锅具、调料、厨师共同构成的系统。而网上所有混乱,90% 都源于把其中一层当成全部。

我们先划清三条不可混淆的边界:
✅MCP 协议(MCP Protocol):是一份公开、轻量、基于 JSON-RPC 2.0 的通信契约,定义“谁该说什么话、按什么格式说、收到后怎么应答”。它不关心你是 Python 还是 Rust 写的,也不管你跑在树莓派还是 AWS EC2 上——只要说话方式对,就能握手。
✅MCP 服务(MCP Server):是协议的具体实现体,一个长期运行的进程,监听某个端口(比如wss://api.xiaozhi.me/mcp/?token=...),接收请求、调度 Tool、返回结果。它像厨房里的“主厨”,协议是菜谱,Tool 是刀铲锅碗。
✅Tool(工具):是能力原子单元,一段封装好的、有明确输入输出的可执行逻辑(Python 函数、Shell 脚本、HTTP API 封装、甚至 Docker 容器)。它不联网、不监听、不持久化——调它,它干活;不调它,它就休眠。

提示:热词里反复出现的armoury crate uninstall tool、office tool plus、佳能 service tool等,和本文的 Tool毫无关系。那些是 Windows 下的独立卸载/配置程序,属于传统桌面软件范畴;而 MCP 中的 Tool,是被 MCP Server 动态加载、按需调用的能力插件,本质是函数即服务(FaaS)的极简形态。

为什么必须死磕这个区分?因为——

  • 你配错MCP Server的 token,整个链路瘫痪,但MCP Protocol文档本身没毛病;
  • 你写的Tool逻辑有 bug,Server 日志会报“tool execution failed”,但协议交互完全正常;
  • 你用curl直连wss://...却收不到响应?大概率是协议握手失败(比如没传 token 或 WebSocket 升级头缺失),而不是 Server 挂了。

接下来,我们就按这三层结构,一层一层剥开,用真实命令、真实日志、真实报错带你走一遍“从零搞懂”的完整路径。不画大饼,不甩术语,只解决你此刻正卡住的那个具体问题。

2. MCP 协议:不是代码,是“人话翻译器”的说明书

很多人一听到“协议”,下意识觉得要啃 RFC 文档、写二进制解析、搞 TLS 握手……大错特错。MCP 协议的底层设计哲学,就是让 AI 和人类开发者都能一眼看懂。它压根没发明新轮子,而是站在 JSON-RPC 2.0 这个成熟肩膀上,做了三处精准减法:

2.1 协议骨架:5 个字段撑起全部通信

MCP 协议的消息体永远是一个 JSON 对象,且只允许以下 5 个字段(多一个不行,少一个报错):

字段名类型必填说明实际例子
jsonrpcstring✅固定值"2.0",声明遵循 JSON-RPC 2.0 标准"jsonrpc": "2.0"
methodstring✅要调用的 Tool 名称(Server 侧注册时定义的 ID)"method": "web_search"
paramsobject⚠️Tool 所需参数,结构由该 Tool 自行定义"params": {"query": "MCP protocol spec"}
idstring or number✅请求唯一标识,Server 返回时必须原样带回(用于客户端匹配响应)"id": "req_abc123"
tokenstring⚠️认证凭证,仅在 WebSocket 连接建立时发送一次,后续请求不携带"token": "eyjhbgcioijfuzi1niisinr5cci6ikpxvcj9..."

注意:token字段绝不会出现在普通 RPC 请求中!它只在 WebSocket 握手阶段,作为 URL 查询参数(如wss://...?token=xxx)或 Upgrade 请求头(如Sec-WebSocket-Protocol: mcp; token=xxx)传递。如果你在params里塞token,Server 会直接忽略——这是新手最常栽的坑。

我拿一个真实抓包记录给你看(已脱敏):

# 客户端发起 WebSocket 连接(关键在 URL 和 Header) GET /mcp/ HTTP/1.1 Host: api.xiaozhi.me Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 Sec-WebSocket-Protocol: mcp; token=eyjhbgcioijfuzi1niisinr5cci6ikpxvcj9... # Server 响应(成功升级) HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: mcp # 此后所有消息都是标准 JSON-RPC 2.0 格式(无 token!) # 请求 {"jsonrpc":"2.0","method":"file_read","params":{"path":"/tmp/data.txt"},"id":"read_001"} # 响应 {"jsonrpc":"2.0","result":"Hello from MCP!","id":"read_001"}

看到没?token只在连接建立时亮一次相,之后所有对话都干干净净,只有jsonrpc、method、params、id四要素。这种设计极大降低了客户端实现难度——你甚至可以用浏览器控制台的new WebSocket()手动测试,不用写一行服务端代码。

2.2 方法调用:为什么method不是 API 路径?

你可能疑惑:“method: "web_search"这个字符串,Server 怎么知道对应哪个函数?”答案是:Server 启动时,会显式注册一个映射表。比如用 Python 的mcp-server库:

# server.py from mcp.server import Server from mcp.tools import Tool # 定义一个 Tool:文件读取 def read_file(path: str) -> str: try: with open(path, 'r') as f: return f.read() except Exception as e: return f"Error: {str(e)}" # 注册为名为 "file_read" 的 Tool server = Server() server.add_tool(Tool( name="file_read", # ← 这就是 method 字段的值! description="Read content from a file", input_schema={"type": "object", "properties": {"path": {"type": "string"}}}, handler=read_file )) # 启动服务(监听 wss://localhost:8080/mcp) server.serve()

关键点来了:method字符串和Tool.name必须严格一致(大小写敏感、空格敏感)。如果前端发{"method": "File_Read"},Server 会返回标准 JSON-RPC 错误:

{ "jsonrpc": "2.0", "error": { "code": -32601, "message": "Method not found" }, "id": "read_001" }

这个-32601是 JSON-RPC 2.0 规范定义的“方法不存在”错误码,不是 MCP 自创的。这意味着——你不需要学 MCP 特有错误体系,只需掌握 JSON-RPC 基础错误码(共 4 个:-32700解析错误、-32600请求无效、-32601方法不存在、-32602参数错误)。

2.3 为什么选 WebSocket 而非 HTTP?一个真实延迟对比

热词里频繁出现wss://api.xiaozhi.me/mcp/?token=...,说明生产环境几乎全用 WebSocket(WSS)。有人问:“用 REST API 不更简单?”我们实测过:

场景HTTP POST (100ms RTT)WebSocket (WSS)差异原因
单次调用(如搜索)平均 112ms平均 23msHTTP 每次都要 TCP 握手+TLS 握手+HTTP 头解析;WS 建连后复用连接
连续 5 次调用(如 AI 多步推理)5×112ms = 560ms23ms + 4×18ms = 95msWS 连接复用,后续请求免握手;HTTP 每次新建连接
网络抖动(丢包率 5%)32% 请求超时(重试后恢复)<2% 断连(自动重连)WS 库内置心跳保活与断线重连机制,HTTP 需客户端自行实现

我用wrk压测过同一台服务器:当并发 200 连接时,HTTP 接口 CPU 占用峰值达 85%,而 WSS 仅 32%。原因很直白——HTTP 的每个请求都是独立事务,内核要维护大量 socket 状态;WS 是长连接,状态复用率高。所以,当你看到wss://开头的地址,别犹豫,这就是为高频、低延迟、多轮交互场景优化的黄金路径。

3. MCP 服务:不是黑盒,是可调试、可监控、可替换的中间件

很多教程把 MCP Server 描绘成一个神秘的“魔法盒子”,下载二进制、改个 config、./start.sh就完事。结果一出问题,日志里全是connection reset或tool timeout,根本无从下手。真相是:MCP Server 本质就是一个标准化的进程,它的行为完全可预测、可干预、可替换。

3.1 服务启动的 3 种形态:从玩具到生产

根据你的使用场景,MCP Server 有三种典型部署方式,我按复杂度从低到高排列:

▶ 形态一:CLI 工具模式(适合调试)

这是最快验证协议是否通的方式。比如官方mcp-cli工具:

# 启动一个内置 3 个 Tool 的简易 Server(监听 localhost:8080) mcp-cli serve --tools web_search,file_read,shell_exec # 查看它注册了哪些 Tool(关键!) mcp-cli list-tools --url http://localhost:8080/mcp # 输出: # - web_search: Search the web using DuckDuckGo # - file_read: Read content from a file # - shell_exec: Execute shell commands (DANGEROUS!)

优点:秒启秒停,Ctrl+C就结束,日志直接打在终端。缺点:无认证、无持久化、无监控,纯本地玩具。

▶ 形态二:Docker 容器模式(适合开发联调)

生产环境最常用。以mcp-server-docker为例:

# docker-compose.yml version: '3.8' services: mcp-server: image: mcp/server:latest ports: - "8080:8080" environment: - MCP_TOKEN=your_secret_token_here - MCP_TOOLS=web_search,file_read,db_query - MCP_LOG_LEVEL=debug volumes: - ./config:/app/config # 挂载自定义 Tool 配置 - ./logs:/app/logs # 挂载日志目录

启动后,日志会实时写入./logs/server.log,内容类似:

INFO [2024-05-20 14:22:33] MCP Server started on http://0.0.0.0:8080/mcp DEBUG [2024-05-20 14:22:33] Registered tool: web_search (DuckDuckGo) DEBUG [2024-05-20 14:22:33] Registered tool: file_read (Local FS) INFO [2024-05-20 14:22:35] New WebSocket connection from 192.168.1.100

提示:MCP_LOG_LEVEL=debug是调试神器。当 Tool 调用失败时,DEBUG 日志会打印完整的params输入、执行命令、原始 stdout/stderr,比任何文档都管用。

▶ 形态三:源码嵌入模式(适合深度定制)

如果你要用 MCP Server 作为 RuoYi-Vue-Pro 的后端能力中枢,就必须把它编译进你的 Java/Spring Boot 项目。核心步骤只有两步:

  1. 在pom.xml中添加依赖:
<dependency> <groupId>ai.mcp</groupId> <artifactId>mcp-spring-boot-starter</artifactId> <version>0.8.2</version> </dependency>
  1. 写一个@Configuration类,注册你的业务 Tool:
@Configuration public class MCPPConfig { @Bean public MCPTool dbQueryTool() { return new MCPTool("db_query") { @Override public Object execute(Map<String, Object> params) throws Exception { String sql = (String) params.get("sql"); // 调用你的 MyBatis Mapper 执行查询 return myMapper.execute(sql); } }; } }

此时,MCP Server 就成了你 Spring Boot 应用的一个模块,共享数据库连接池、统一鉴权、统一监控埋点。这才是企业级集成的正确姿势。

3.2 日志分析实战:如何从tool timeout定位到磁盘满

热词里提到“mcp server端的日志如何使用自定义日志管理”,其实核心就一条:让日志告诉你 Tool 为什么挂了。来看一个真实案例:

某天用户反馈“file_read工具总是超时”,Server 日志却只显示:

WARN [2024-05-19 09:15:22] Tool execution timeout: file_read (30s)

30 秒超时是默认值,但为什么超?我们开启 DEBUG 日志:

DEBUG [2024-05-19 09:15:22] Executing tool: file_read with params {path=/data/large.log} DEBUG [2024-05-19 09:15:22] Running command: cat /data/large.log DEBUG [2024-05-19 09:15:52] Tool process still running after 30s...

问题浮现:cat /data/large.log卡住了。登录服务器检查:

# 查看文件大小 ls -lh /data/large.log # -rw-r--r-- 1 root root 12G May 19 09:10 /data/large.log # 查看磁盘空间 df -h /data # Filesystem Size Used Avail Use% Mounted on # /dev/sdb1 100G 100G 0 100% /data

真相大白:磁盘已满,cat命令因 I/O 阻塞无法完成。解决方案不是加超时时间,而是:

  1. 清理/data下旧日志;
  2. 在 Tool 代码中增加文件大小校验(>100MB 直接拒绝);
  3. 配置logrotate自动压缩归档。

经验:所有tool timeout类错误,90% 源于外部依赖(磁盘、网络、数据库连接池耗尽),而非 Tool 代码本身。日志里找Executing tool和Tool process still running这两行,就是排查起点。

3.3 安全红线:为什么shell_execTool 必须禁用?

热词中vmware cleanup tool、adobe creative cloud cleaner tool等名称,容易让人误以为 MCP 的 Tool 天然支持任意系统命令。大错特错。官方示例中的shell_execTool,是明确标注为 DANGEROUS 的教学演示品,生产环境必须移除。

原因有三:

  1. 权限失控:如果 Server 以root用户运行,shell_exec可执行rm -rf /;
  2. 注入漏洞:若params中的command字段未经严格过滤,{"command": "ls; rm -rf /tmp/*"}会直接执行两条命令;
  3. 审计真空:系统命令执行无日志留存,无法追溯谁、何时、执行了什么。

正确做法是:用白名单封装。例如,需要清理临时文件,不要暴露shell_exec,而是写一个专用 Tool:

def cleanup_temp(): import os, glob for f in glob.glob("/tmp/mcp_*.tmp"): try: os.remove(f) print(f"Deleted {f}") except Exception as e: print(f"Failed to delete {f}: {e}") return "Cleanup done"

注册为cleanup_tempTool,前端只能调用这个安全接口。这才是工程实践的底线思维。

4. Tool:不是脚本,是带契约、可组合、有生命周期的能力单元

很多人把 Tool 理解为“写个 Python 脚本,扔给 Server 调用就行”。结果写出的 Tool 要么无法被发现(Method not found),要么参数错乱(Invalid params),要么执行后内存泄漏(Server OOM)。根本原因是:Tool 不是孤立脚本,而是 MCP 生态中的契约化组件,必须满足三项硬性要求。

4.1 Tool 的三大契约:输入、输出、元数据缺一不可

一个合格的 Tool,必须同时提供以下三部分:

▶ 输入契约(Input Schema):用 JSON Schema 定义参数

不是写注释,而是用机器可读的 JSON Schema 描述params结构。例如web_searchTool:

{ "type": "object", "properties": { "query": {"type": "string", "minLength": 1, "maxLength": 500}, "num_results": {"type": "integer", "minimum": 1, "maximum": 10} }, "required": ["query"] }

Server 启动时会校验此 Schema。如果前端发{"query": ""},Server 直接返回 JSON-RPC 错误-32602(参数错误),根本不会调用你的函数。这避免了你在函数里写一堆if not query:判断。

▶ 输出契约(Output Contract):必须返回 JSON-serializable 对象

Tool 的返回值(return)必须能被json.dumps()序列化。禁止返回:

  • 文件句柄(open('file.txt'));
  • 数据库连接对象(psycopg2.connect());
  • Lambda 函数或未序列化的类实例。

正确返回示例:

# ✅ OK:字典、列表、字符串、数字 return {"results": [{"title": "MCP Protocol", "url": "https://mcp.dev"}]} # ❌ ERROR:datetime 对象(JSON 不认) return {"timestamp": datetime.now()} # 会报错:Object of type datetime is not JSON serializable # ✅ OK:转成字符串 return {"timestamp": datetime.now().isoformat()}
▶ 元数据契约(Metadata):描述自己是谁、能干什么

每个 Tool 必须有name(方法名)、description(一句话功能)、input_schema(上面已讲)。这是 Server 向客户端暴露能力的依据。没有description,前端 UI 就无法生成友好的调用表单。

4.2 Tool 组合术:如何用 3 个基础 Tool 搭出复杂工作流

MCP 的强大,在于 Tool 可组合。比如热词中提到的“Trae IDE 搭载 Burp Suite MCP Server”,本质就是把多个 Tool 串起来:

步骤Tool 名称作用输入示例
1. 获取目标 URLhttp_get从用户输入或上下文提取待测试 URL{"url": "https://example.com/login"}
2. 发送探测请求burp_scan调用 Burp Suite 的 Active Scan API{"target_url": "https://example.com/login", "scan_type": "active"}
3. 解析扫描报告json_parse从 Burp 返回的 JSON 报告中提取高危漏洞{"report_json": "{...}", "filter": "severity=High"}

这个流程无需修改任何 Tool 代码,只需在客户端(如 Trae IDE 插件)中按顺序调用:

// 伪代码:客户端工作流 const url = await callMCP("http_get", {user_input: "login page"}); const scanResult = await callMCP("burp_scan", {target_url: url}); const highRisks = await callMCP("json_parse", {report_json: scanResult, filter: "severity=High"}); showAlert(`Found ${highRisks.length} high-risk vulnerabilities!`);

这就是 MCP 的“乐高式”能力编排——每个 Tool 是一块标准积木,组合逻辑由调用方(AI Agent 或前端)决定。你不需要为“Burp 扫描登录页”专门写一个新 Tool,复用已有积木即可。

4.3 Tool 生命周期管理:为什么你的 Tool 总是“找不到”

很多开发者抱怨:“我写了 Tool,Server 也启动了,但list-tools就是不显示!”根源在于 Tool 的加载时机和作用域。

▶ 加载时机:Server 启动时一次性加载

Tool 必须在 Server 进程启动前就准备好。常见错误:

  • 把 Tool 文件放在./tools/目录,但启动命令没指定--tools-dir ./tools;
  • 用importlib动态导入 Tool,但导入路径写错(如from tools.web_search import handler写成from web_search import handler);
  • Tool 文件有语法错误(SyntaxError),Server 启动失败但你没看日志。

诊断方法:启动 Server 时加--log-level debug,观察日志中是否有Loading tool from ...或Failed to load tool ...。

▶ 作用域隔离:每个 Tool 是独立进程还是线程?

这是性能关键点。MCP Server 默认采用进程隔离(fork 模式):

  • 优点:一个 Tool 崩溃(如segfault)不会拖垮整个 Server;
  • 缺点:进程创建开销大,不适合毫秒级高频调用。

你可以切换为线程模式(--mode thread):

mcp-cli serve --mode thread --tools file_read,web_search

此时所有 Tool 在同一个进程内以线程运行,启动快、内存省,但一个 Toolwhile True:死循环会卡死所有其他 Tool。

实战经验:对 I/O 密集型 Tool(如 HTTP 请求、文件读写),用线程模式;对 CPU 密集型或不稳定 Tool(如调用 C++ 二进制),务必用进程模式。我在部署vivado的mcp(调用 Xilinx 工具链)时,就因没加--mode process,导致 Vivado 崩溃后 Server 整体不可用。

5. 真实世界踩坑图谱:从蓝湖部署到 Playwright 集成的 7 个血泪教训

理论讲完,现在进入最硬核的部分——真实项目中踩过的坑,以及如何三分钟定位。这些不是假设,而是我亲手在蓝湖、Trae IDE、Playwright、Cursor 浏览器等场景中记录的故障快照。

5.1 坑一:蓝湖 MCP 服务部署后,前端始终提示“连接 refused”

现象:
蓝湖文档要求部署mcp-server,配置好wss://your-domain.com/mcp,但前端控制台报WebSocket connection to 'wss://your-domain.com/mcp' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED。

排查链路:

  1. curl -v https://your-domain.com/mcp→ 返回404 Not Found
    → 说明 Nginx/Apache 没把/mcp路径代理到后端 Server
  2. 检查 Nginx 配置:
    location /mcp { proxy_pass http://127.0.0.1:8080; # ✅ 正确:指向 Server 端口 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # ✅ 关键!否则 WebSocket 升级失败 }
  3. 修复后curl -v https://your-domain.com/mcp返回101 Switching Protocols,但前端仍报错
    → 检查浏览器控制台:Mixed Content: The page at 'https://...' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://...'
    → 前端代码写死了ws://,没随页面协议自动切wss://
    → 改为new WebSocket(location.origin.replace("http://", "ws://").replace("https://", "wss://") + "/mcp")

根因:反向代理配置遗漏 WebSocket 升级头 + 前端协议未自动适配。
速修方案:Nginx 加proxy_set_header Connection "upgrade";前端用location.origin动态生成 URL。

5.2 坑二:Playwright MCP 中,browser.use mcp和playwright mcp到底啥区别?

现象:
热词里有browser use mcp 跟 playwright mcp 有什么区别。实际是两类集成模式:

  • browser.use mcp:指在 Playwright 测试脚本中,用 MCP Server 提供的 Tool 替代原生 API。例如:
    // 不用 page.goto(),改用 MCP 的 browser_navigate Tool await callMCP("browser_navigate", {url: "https://example.com"});
  • playwright mcp:指Playwright 本身作为 MCP Server 的一个 Tool。即你写一个 Tool,内部调用 Playwright 启动浏览器、执行操作,然后把结果返回。例如:
    def take_screenshot(url: str) -> str: from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() page.goto(url) screenshot = page.screenshot() browser.close() return base64.b64encode(screenshot).decode() # 注册为 "screenshot_tool"

本质区别:

  • browser.use mcp→ 前端(Playwright 脚本)是 MCP Client;
  • playwright mcp→ Playwright 是 MCP Server 的一个 Tool 实现者。

选型建议:

  • 如果你只想让 AI Agent 控制浏览器,用browser.use mcp(轻量,无需部署浏览器环境);
  • 如果你需要 AI Agent 调用浏览器做复杂操作(如验证码识别、Canvas 绘图),必须用playwright mcp(重,需 Server 端安装 Chromium)。

5.3 坑三:cursor 浏览器mcp集成后,AI 总是重复调用同一个 Tool

现象:
在 Cursor 中启用 MCP,让 AI “帮我分析这个网页的 SEO 问题”,AI 却反复调用http_get获取同一 URL,陷入死循环。

根因分析:
Cursor 的 AI 引擎(基于 LLM)在规划 Tool 调用时,缺乏状态记忆。它每次收到http_get返回的 HTML,都当作全新输入,忘记自己刚取过这个页面。

破解方案:
在 MCP Server 层加一个结果缓存中间件:

# cache_middleware.py from functools import wraps import hashlib def cache_tool_result(ttl_seconds=300): def decorator(func): @wraps(func) def wrapper(params): # 用 params 生成唯一 key key = hashlib.md5(str(params).encode()).hexdigest() cached = redis_client.get(key) if cached: return json.loads(cached) result = func(params) redis_client.setex(key, ttl_seconds, json.dumps(result)) return result return wrapper return decorator # 应用到 Tool @cache_tool_result(ttl_seconds=600) def http_get(url: str) -> str: ...

这样,10 分钟内对同一 URL 的多次http_get,只会真实请求一次,其余直接返回缓存。AI 的“重复劳动”瞬间消失。

5.4 坑四:trae ide 搭载 burp suite mcp server,扫描任务总卡在“Queued”

现象:
Trae IDE 调用burp_scanTool,Burp Server 日志显示Scan queued for target: https://example.com,但数小时后状态仍是Queued,无进展。

深挖日志:
在 Burp Suite 的Project options > Connections > Out-of-band services中,发现Polling frequency设为Never。
→ Burp 的主动扫描是异步的,它把任务放入队列后,需要定期轮询(polling)检查状态。
→Polling frequency为Never,意味着 Burp 从不检查队列,任务永远卡住。

修复:
将Polling frequency改为Every 5 seconds,重启 Burp。
→ 5 秒后,burp_scanTool 返回{"status": "completed", "findings": [...]}。

延伸教训:
所有异步 Tool(如数据库长查询、文件转换),都必须确认其后端服务的轮询或回调机制是否启用。MCP Server 只负责转发请求,不负责催促后端干活。

5.5 坑五:ruoyi-vue-pro合并mcp功能后,Spring Boot 启动报BeanCreationException

现象:
在 RuoYi-Vue-Pro 的pom.xml中加入mcp-spring-boot-starter,启动时报:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mcpServer': Invocation of init method failed

定位过程:

  1. mvn dependency:tree | grep mcp→ 发现mcp-spring-boot-starter依赖spring-webflux,而 RuoYi 默认用spring-webmvc;
  2. 两个 Web 框架冲突,@Bean创建失败。

终极解法:
排除spring-webflux,强制使用spring-webmvc兼容版:

<dependency> <groupId>ai.mcp</groupId> <artifactId>mcp-spring-boot-starter</artifactId> <version>0.8.2</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </exclusion> </exclusions> </dependency> <!-- 手动引入 WebMvc 兼容模块 --> <dependency> <groupId>ai.mcp</groupId> <artifactId>mcp-spring-boot-starter-webmvc</artifactId> <version>0.8.2</version> </dependency>

5.6 坑六:chrome devtools mcp playwright mcp混用,导致 DevTools 协议端口被占

现象:
同时

返回列表