MCP协议深度解析:从设计思路到实战落地,智能体工具集成不再难
1. 为什么这一讲值得单独拿出来精讲MCP全称 Model Context Protocol是近两年在智能体工程圈子里被反复讨论的一个协议规范。如果你正在做 AI 应用开发尤其是涉及工具调用、多智能体协作、外部数据源接入这类场景那 MCP 基本是绕不开的一环。斯坦福 CS329Z 这门课把 MCP 规范列为第四讲的必读材料本身就说明了一个信号它不再只是某个团队的内部约定而是正在成为智能体与外部世界交互的一套通用语言。我最初接触 MCP 的时候第一反应是这不就是又一个插件协议吗。但真正把规范文档啃完、又动手写了几个 Server 和 Client 之后才发现它解决的问题比想象中要根本得多。传统的函数调用方案每接一个新工具就要写一套适配代码工具描述、参数格式、错误处理全都要自己定义项目一大就变成维护噩梦。MCP 的思路是把模型需要什么能力和这个能力由谁提供、怎么提供彻底解耦用一套标准化的协议把两边粘起来。这篇文章适合三类人看一是正在做智能体应用、被工具集成搞得焦头烂额的开发者二是想理解 MCP 设计哲学、为后续技术选型做准备的技术负责人三是对协议规范本身感兴趣、想搞清楚它和传统方案本质区别的学习者。我会从设计思路、核心概念、实操落地、常见坑四个维度展开尽量把规范里那些抽象的描述翻译成能直接上手的东西。需要提前说明的是MCP 规范本身还在演进不同版本之间会有细节差异。我下面讲的内容基于我实际用过的版本如果你用的是更新的版本个别字段名或流程可能有调整但核心思想是一致的。2. MCP 到底解决了什么问题从设计思路说起2.1 传统工具集成的三个死结在 MCP 出现之前让大模型调用外部工具主流做法是函数调用Function Calling。模型输出一个结构化的 JSON里面写明要调用哪个函数、传什么参数然后由应用层去执行。这套方案能用但用久了会发现三个绕不开的问题。第一个死结是描述与实现强耦合。每个工具的 schema 都要手写参数类型、必填项、描述文本全在应用代码里。工具一多这份 schema 就变成几百行的配置文件改一个参数要动好几处。更麻烦的是同一个工具在不同项目里要重复定义没法复用。第二个死结是能力发现是静态的。模型在启动时就知道有哪些工具可用运行过程中没法动态发现新能力。如果我想让智能体在运行中接入一个新的数据源只能重启或者重新加载配置。这在需要灵活扩展的场景里很致命。第三个死结是传输层没有统一标准。有的工具走 HTTP有的走本地进程有的走消息队列。每接一种新传输方式就要写一套连接管理、错误重试、超时处理的逻辑。这些逻辑和业务无关却占了大量开发时间。2.2 MCP 的核心思路把能力抽象成资源MCP 的设计者显然是想清楚了上面这些问题它的核心思路可以用一句话概括把模型需要的外部能力抽象成标准化的资源和工具通过统一的协议进行发现、调用和传输。这里的关键词是标准化。MCP 定义了一套完整的消息格式包括请求、响应、通知三种类型每种类型都有固定的字段结构。任何符合这套格式的 Server都能被任何符合这套格式的 Client 调用不需要额外的适配层。这就像 USB 接口一样只要设备符合 USB 标准插上就能用不用管它是鼠标还是键盘。具体来说MCP 把外部能力分成几类Resources代表可读取的数据比如文件内容、数据库记录Tools代表可执行的操作比如发送邮件、查询天气Prompts代表预定义的提示模板方便复用。这种分类不是随便定的而是对应了模型与外部交互的三种基本模式读、写、引导。2.3 为什么是协议而不是框架很多人第一次听到 MCP 会以为它是个开发框架其实它是协议。这个区别很重要。框架是给你一套代码结构你得按它的方式写协议是给你一套通信规则你怎么实现都行。MCP 只规定消息长什么样、怎么传输、怎么握手不规定你用 Python 还是 Go 写 Server不规定你的工具内部怎么实现。这种设计的好处是最大程度的解耦。工具提供方可以用自己最熟悉的技术栈实现 Server调用方可以用自己最顺手的语言写 Client两边只要遵守同一套协议就能互通。我个人的体会是这种协议优先的思路在长期项目里优势明显。框架会过时协议不会。今天用某个框架写的代码两年后可能因为框架停止维护而废弃但基于协议实现的东西只要协议还在就能一直用下去。3. 核心概念拆解Host、Client、Server 三角关系3.1 三个角色的职责边界MCP 的架构里有三个核心角色Host、Client、Server。这三个词容易混淆我用一个生活化的类比来解释。想象你去餐厅吃饭。你是Host也就是发起需求的人你决定要吃什么、什么时候吃。服务员是Client负责把你的需求传达给厨房再把菜端回来。厨房是Server负责实际做菜它不关心你是谁只关心订单内容。对应到技术场景Host 是运行大模型的那个应用比如你的智能体程序Client 是 Host 内部负责与 Server 通信的组件Server 是提供具体能力的服务比如一个查询数据库的工具。Host 可以有多个 Client每个 Client 连接一个 Server这样 Host 就能同时使用多种能力。这个设计的精妙之处在于职责分离。Host 只管业务逻辑不用关心通信细节Client 只管协议通信不用关心业务Server 只管能力实现不用关心谁在调用。三者各司其职任何一方变化都不会影响其他两方。3.2 连接的生命周期MCP 的连接是有状态的这一点和普通的 HTTP 请求不同。一个完整的连接生命周期包括几个阶段初始化、能力协商、正常通信、关闭。初始化阶段Client 和 Server 交换版本信息和能力声明。Client 告诉 Server 自己支持哪些特性Server 告诉 Client 自己提供哪些能力。这个阶段很关键因为它决定了后续通信能用哪些功能。如果 Client 不支持某个特性Server 就不会尝试使用它。能力协商完成后进入正常通信阶段。这个阶段 Client 可以调用 Server 的工具、读取资源、获取提示模板。Server 也可以主动向 Client 发送通知比如告诉 Client 某个资源发生了变化。这种双向通信是 MCP 相比传统方案的一个优势。关闭阶段相对简单一方发送关闭消息另一方确认后断开连接。但实际实现中要注意优雅关闭确保正在进行的请求能完成避免数据丢失。3.3 传输层的两种选择MCP 规范定义了两种标准传输方式stdio和HTTP with SSE。这两种方式各有适用场景选错了会很别扭。stdio 传输通过标准输入输出进行通信适合本地进程之间的交互。比如你的 Host 启动一个 Server 子进程通过管道收发消息。这种方式简单直接不需要网络配置延迟也低。缺点是只能本机通信没法跨机器。HTTP with SSE 传输通过 HTTP 请求发送消息通过 Server-Sent Events 接收服务端推送。这种方式适合远程 Server可以跨网络通信。缺点是配置复杂一些要处理网络异常、重连等问题。我实测下来的经验是本地工具优先用 stdio远程服务用 HTTP。不要为了统一而强行用一种方式那样反而会增加不必要的复杂度。4. 消息格式与交互流程规范里最该细看的部分4.1 JSON-RPC 2.0 作为基础MCP 的消息格式基于 JSON-RPC 2.0这是一个成熟的远程调用协议。选择它而不是自定义格式是因为 JSON-RPC 已经有大量现成的库和工具能省不少事。一条典型的请求消息长这样{ jsonrpc: 2.0, id: 1, method: tools/call, params: { name: query_database, arguments: { sql: SELECT * FROM users LIMIT 10 } } }id字段用于匹配请求和响应method指明要调用的方法params是参数。响应消息会带上同样的id这样 Client 就知道这个响应对应哪个请求。这里有个细节要注意id 必须是唯一的。如果两个请求用了同一个 id响应回来的时候就分不清谁是谁了。我在早期实现里偷懒用了固定 id结果并发请求时数据全乱了排查了半天才发现是这个原因。4.2 核心方法一览MCP 定义了一批核心方法覆盖了能力发现、工具调用、资源读取等场景。下面这张表是我整理的常用方法建议收藏方法名作用调用方向initialize初始化连接交换能力信息Client 到 Servertools/list列出所有可用工具Client 到 Servertools/call调用指定工具Client 到 Serverresources/list列出所有可用资源Client 到 Serverresources/read读取指定资源内容Client 到 Serverprompts/list列出所有提示模板Client 到 Serverprompts/get获取指定提示模板Client 到 Servernotifications/tools/list_changed通知工具列表变化Server 到 Clientnotifications/resources/updated通知资源更新Server 到 Client这张表里的方法不需要全部记住但tools/list和tools/call这两个一定要熟悉因为它们是最常用的。tools/list让 Client 知道 Server 提供了哪些工具tools/call实际执行工具。4.3 一次完整的工具调用流程光看方法列表可能还是抽象我走一遍完整的调用流程你就能理解各个方法是怎么串起来的。假设你的 Host 是一个智能助手用户问帮我查一下数据库里有多少用户。Host 内部的 Client 连接到数据库 Server流程是这样的第一步Client 发送initialize请求Server 返回自己支持的能力包括提供哪些工具。第二步Client 发送tools/listServer 返回工具列表里面有query_database这个工具附带参数说明。第三步Host 把工具列表和用户问题一起交给大模型模型决定调用query_database参数是SELECT COUNT(*) FROM users。第四步Client 发送tools/callServer 执行查询返回结果。第五步Host 把结果交给模型模型生成自然语言回复给用户。整个流程里Client 和 Server 之间的通信完全遵循 MCP 规范Host 的业务逻辑和 Server 的能力实现互不干扰。这就是协议化的价值。5. 动手实现一个最小可用的 MCP Server5.1 环境准备与依赖选择理论讲完了该动手了。我下面用一个最小化的例子带你实现一个能查询本地文件的 MCP Server。这个例子足够简单能跑通又能体现 MCP 的核心机制。语言选择上Python 是最容易上手的官方也有 SDK 可用。我用的版本是 Python 3.10 以上SDK 用的是官方提供的mcp包。安装很简单pip install mcp如果你不想用官方 SDK也可以自己实现 JSON-RPC 的收发逻辑但那样工作量会大很多。我的建议是先用 SDK 跑通理解流程后再考虑自己实现。SDK 帮你处理了消息序列化、连接管理这些琐事让你能专注在业务逻辑上。5.2 定义工具与资源先定义我们要提供的工具。这个 Server 提供两个工具一个是列出目录下的文件一个是读取指定文件的内容。代码如下from mcp.server import Server from mcp.types import Tool, TextContent import os app Server(file-server) app.list_tools() async def list_tools(): return [ Tool( namelist_files, description列出指定目录下的所有文件, inputSchema{ type: object, properties: { directory: { type: string, description: 要列出的目录路径 } }, required: [directory] } ), Tool( nameread_file, description读取指定文件的内容, inputSchema{ type: object, properties: { path: { type: string, description: 要读取的文件路径 } }, required: [path] } ) ]这段代码里inputSchema用的是 JSON Schema 格式描述了工具接受什么参数。这个 schema 很重要因为模型会根据它来决定怎么调用工具。schema 写得越清楚模型调用得越准确。5.3 实现工具调用逻辑定义完工具接下来实现实际的调用逻辑app.call_tool() async def call_tool(name: str, arguments: dict): if name list_files: directory arguments[directory] try: files os.listdir(directory) return [TextContent( typetext, text\n.join(files) )] except Exception as e: return [TextContent( typetext, textf错误{str(e)} )] elif name read_file: path arguments[path] try: with open(path, r, encodingutf-8) as f: content f.read() return [TextContent( typetext, textcontent )] except Exception as e: return [TextContent( typetext, textf错误{str(e)} )] else: raise ValueError(f未知工具{name})这里有个实操心得错误处理一定要做好。工具执行失败时不要直接抛异常让连接断掉而是把错误信息作为正常结果返回。这样模型能知道发生了什么可以决定是重试还是换一种方式。我早期实现里没注意这点一个文件读不到就导致整个连接崩溃体验很差。5.4 启动 Server 并测试最后加上启动代码if __name__ __main__: import asyncio from mcp.server.stdio import stdio_server async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) asyncio.run(main())运行这个脚本Server 就启动了通过 stdio 等待 Client 连接。测试的时候你可以写一个简单的 Client或者用官方提供的调试工具。我一般用调试工具先验证工具列表能不能正常返回再测试实际调用。测试时要注意stdio 传输下 Server 不能往标准输出打印任何非协议内容。我踩过这个坑在代码里加了个 print 调试结果 Client 收到一堆乱码排查了好久才想起来是 print 惹的祸。调试信息要打到标准错误或者用日志文件。6. 常见问题与排查技巧实录6.1 连接建立失败最常见的问题是连接根本建立不起来。表现是 Client 发送 initialize 后收不到响应或者直接报连接错误。排查思路是这样的先确认 Server 进程有没有正常启动。如果是 stdio 传输检查启动命令对不对有没有依赖缺失。如果是 HTTP 传输检查端口有没有被占用防火墙有没有拦截。然后确认协议版本是否匹配Client 和 Server 用的 MCP 版本差太多会握手失败。我遇到过一次很隐蔽的情况Server 启动时加载了一个大文件耗时超过 Client 的超时时间Client 以为连接失败就断开了。解决办法是把耗时操作放到 initialize 之后或者延长 Client 的超时时间。6.2 工具调用返回异常工具能列出来但调用时出错这也是高频问题。原因通常有几类参数格式不对、工具内部逻辑报错、返回值格式不符合规范。参数格式问题最好排查把 Client 发送的 arguments 打印出来和 inputSchema 对比一下就能发现。工具内部报错要看 Server 的日志定位到具体哪一行。返回值格式问题容易被忽略MCP 要求返回的是 content 数组每项有 type 和 text 字段格式不对 Client 解析会失败。下面这张表是我整理的常见错误对照可以快速定位现象可能原因排查方法工具列表为空Server 未正确注册工具检查 list_tools 返回值调用返回未知工具工具名拼写不一致对比 list 和 call 的名称返回内容解析失败content 格式不对检查是否符合规范连接频繁断开心跳或超时配置问题检查超时设置并发调用结果错乱id 不唯一确保每次请求 id 唯一6.3 性能与并发问题单次调用没问题并发一上来就出问题这是很多人在生产环境才会遇到的坑。MCP 的连接是有状态的同一个连接上的请求要按顺序处理不能并行。如果 Server 处理一个请求要很久后面的请求就会排队。解决办法是用多个连接分担负载或者把耗时操作异步化。还有一个坑是资源泄漏。Server 如果打开了文件、数据库连接却没关闭跑久了就会耗尽资源。我建议在工具实现里用上下文管理器确保资源用完就释放。6.4 版本兼容性陷阱MCP 规范还在演进不同版本之间有 breaking change。我升级 SDK 的时候就遇到过原来能用的代码突然报错查了半天发现是某个字段改名了。应对策略是锁定版本。生产环境不要用 latest 标签明确指定版本号。升级前先看 changelog确认有哪些变化。如果必须跨版本兼容可以在 initialize 阶段做版本协商根据对方版本调整行为。7. 从规范到落地一些个人体会把 MCP 用在实际项目里一段时间后我最大的感受是它的价值不在于技术多先进而在于把混乱的东西标准化了。以前每个项目都要重新造轮子现在有了统一规范工具可以跨项目复用开发效率提升很明显。但也要清醒地看到MCP 不是银弹。它解决的是通信标准化问题不解决工具本身的质量问题。一个设计糟糕的工具用 MCP 包装一下还是糟糕。所以重点还是要放在工具的设计上参数要清晰、错误要友好、边界要明确。另外MCP 的学习曲线不算平缓。规范文档写得比较抽象第一次看容易懵。我的建议是先跑通一个最小例子再回头读规范这样理解起来会快很多。光看文档不动手很难真正掌握。最后分享一个小技巧调试 MCP 的时候把消息日志打开完整记录 Client 和 Server 之间的每一条消息。出问题的时候对着日志一条条看基本都能定位到。这个习惯帮我省了大量排查时间。

相关新闻

OpenClaw requireApproval 插件:生产环境 AI 代理的人工审批闸门

OpenClaw requireApproval 插件:生产环境 AI 代理的人工审批闸门

OpenClaw 跑得越顺,我心里反而越没底。这句话听起来有点反直觉,但凡是把 OpenClaw 从个人实验搬到团队生产环境的人,多半能对上这个感觉:代理的执行力越强,越没人敢给它在生产环境里完全放开手脚。OpenClaw v2026.3.28…

2026/10/19 5:38:26 阅读更多 →
Agent上下文管理选型:流水式与汉堡式架构对比及混合方案实践

Agent上下文管理选型:流水式与汉堡式架构对比及混合方案实践

1. 从一次上下文溢出事故说起去年冬天,我接手了一个内部知识库问答助手的调优工作。上线第一周就出了状况:用户连续追问七八轮之后,Agent 开始答非所问,甚至把三轮之前已经确认过的订单编号又当成新信息重新询问。日志里最扎眼的一…

2026/10/19 5:38:26 阅读更多 →
PSO-BiLSTM与SHAP可解释性分析:多步时序回归的完整实践

PSO-BiLSTM与SHAP可解释性分析:多步时序回归的完整实践

上个月我手头有一个多步超前回归需求:一段工业设备运行监测数据,十几个连续采集的变量,要用过去24个时刻的观测预报未来三个时刻的一项关键质量指标。业务方提出三个硬性要求——预报要准,模型结果要能解释“到底哪些变量在起作用…

2026/10/19 5:38:26 阅读更多 →

最新新闻

Dify工作流实现双模型分栏流式对比:从原理到实践

Dify工作流实现双模型分栏流式对比:从原理到实践

最开始我对比两个模型的回答质量,用的还是最笨的办法:开两个浏览器标签页,把同一个问题分别粘进去,再左右来回切。遇到长回答还得自己对对齐位置,效率低到让人怀疑人生。直到我把这套动作搬进 Dify,用可视化…

2026/10/19 6:51:01 阅读更多 →
击剑赛事编排引擎:离线优先、规则可配置的本地化工具

击剑赛事编排引擎:离线优先、规则可配置的本地化工具

简介:Engarde816是一款面向击剑赛事组织者、裁判团队及体育信息化管理者的专业编排软件,专为解决中小型至大型击剑比赛中的分组抽签、赛制设定(单/双败淘汰、循环赛)、对阵生成、实时成绩追踪与多场地日程协同等核心难题而设计。资…

2026/10/19 6:51:01 阅读更多 →
TaskExplorer 完整指南:跨平台深度进程监控工具

TaskExplorer 完整指南:跨平台深度进程监控工具

TaskExplorer 完整指南:跨平台深度进程监控工具 【免费下载链接】TaskExplorer Power full Task Manager for Windows and Linux 项目地址: https://gitcode.com/GitHub_Trending/ta/TaskExplorer TaskExplorer 是一款功能强大的跨平台任务管理器&#xff0c…

2026/10/19 6:51:01 阅读更多 →
DeepSeek-V4-Flash-Vision-Exp-MLX生产部署指南:OpenAI兼容API与本地服务搭建

DeepSeek-V4-Flash-Vision-Exp-MLX生产部署指南:OpenAI兼容API与本地服务搭建

【免费下载链接】DeepSeek-V4-Flash-Vision-Exp-MLX 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/DeepSeek-V4-Flash-Vision-Exp-MLX 点击查看 免费下载 DeepSeek-V4-Flash-Vision-Exp-MLX 是 DeepSeek V4 系列的实验性多模态模型(支持…

2026/10/19 6:51:01 阅读更多 →
VideoMamba开发者指南:如何将它作为Backbone无缝替换ViT接入你的视频项目

VideoMamba开发者指南:如何将它作为Backbone无缝替换ViT接入你的视频项目

【免费下载链接】VideoMamba 项目地址: https://ai.gitcode.com/OpenGVLab/VideoMamba 点击查看 免费下载 VideoMamba 是一个基于双向状态空间模型(Bidirectional SSM)的轻量级视频理解模型,由 OpenGVLab 开发,核心定…

2026/10/19 6:51:01 阅读更多 →
LTX-2 在 ComfyUI 中如何落地:ComfyUI-LTXVideo 节点安装、首跑与显存配置指南

LTX-2 在 ComfyUI 中如何落地:ComfyUI-LTXVideo 节点安装、首跑与显存配置指南

LTX-2 在 ComfyUI 中如何落地:ComfyUI-LTXVideo 节点安装、首跑与显存配置指南 【免费下载链接】ComfyUI-LTXVideo LTX-Video Support for ComfyUI 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-LTXVideo 本文面向刚接触 AI 视频生成的读者&am…

2026/10/19 6:50:01 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →