一、 核心背景:什么是 MCP?它的核心场景是什么?
1. MCP 的定义与痛点解决
MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 推出的一项开源标准协议。
- 背景: 在此之前,如果想让大模型(如 GitHub Copilot、Claude)读取本地文件、搜索网页或操作数据库,开发者必须为每一个具体的 AI 工具编写定制化的对接代码。
- 定义: MCP 本质上是 AI 时代的“通用 USB 接口”。它定义了一套标准化的 JSON-RPC 通信规范,将“AI 模型”与“数据/工具”彻底解耦。
2. VS Code 中的核心场景与生态位
在 VS Code 环境中,MCP 并不是一个独立运行的程序,而是作为 AI 编程助手(如 GitHub Copilot、Cline、Roo Code 等)的“外挂感知器官与执行手脚” 存在的。
- 协同关系: VS Code 中的 AI 插件充当**客户端 (Client),而我们在
mcp.json 中配置的工具(如 markitdown 或自定义的 test_mcp.py)充当服务端 (Server)**。 - 工作流: 1. 你在聊天框向 AI 提问(例如:“帮我总结这个 PDF 的内容”)。
- AI 插件通过 MCP 协议,向本地的
markitdown 服务器发送指令。
二、 MCP 服务器的连接模式与环境构建
在 .vscode/mcp.json 中,服务器主要分为两种物理隔离的通信模式:
| | | |
|---|
| 本地进程 | "stdio" | 算力在本地。 VS Code 在后台静默启动一个本地终端进程,通过标准输入输出与 AI 传递 JSON 数据。由于需要消耗本地算力与存储,往往需要构建独立的运行环境(如使用 uvx 自动拉取依赖)。 | microsoft/markitdown |
| 远程 API | "http" | 算力在云端。 VS Code 不运行本地代码,而是将请求打包发往指定的 URL。由于涉及调用商业服务器算力,通常需要配置 Token 进行身份鉴权(如配置中的 "inputs" 字段)。 | github-mcp |
拓展原理:uvx 与运行环境像 markitdown 这样强大的多模态工具,底层依赖极多(涵盖图片、PDF、表格解析)。配置中的 uvx 命令会按需在后台构建一个极速的隔离环境并缓存依赖。如果需要解析音视频,还需要在系统层面补充安装 ffmpeg 引擎。
三、 开发避坑指南:卡死、报错与接口规范
在自主开发 MCP 脚本(如 test_mcp.py)时,常会遇到以下逻辑陷阱:
1. 现象:“持续等待初始化”卡死
- 背景与原因: 早期的简陋教程仅仅使用
json.load() 接收数据。然而,MCP 严格遵循 JSON-RPC 2.0 规范,客户端在启动时会发送携带 ID 和版本号的初始化握手请求。如果服务端只是随意回复一个普通的 JSON 字符串(暗号对不上),客户端就会陷入无尽的等待(Waiting for server to respond to initialize request...)。 - 标准解决方案: 摒弃手动拼接 JSON 的做法,直接引入官方 SDK
FastMCP 框架。该框架会自动接管底层握手、心跳检测和错误路由。
2. 现象:手动运行 Python 脚本无响应/抛出异常
- 背景与原因:
stdio 类型的服务器一旦启动,就会挂起并死死监听控制台的 stdin(标准输入)。如果在常规终端手动运行 python test_mcp.py,程序并没有死机,只是在等待机器指令。 - 解惑: 人为使用
Ctrl+C 强行终止时,Python 抛出的 KeyboardInterrupt 及异步清理报错是标准的“断电反应”,并不代表代码存在 Bug。测试的正确姿势是直接在 VS Code 的 AI 面板中观察其是否显示 "Discovered X tools"。
3. 核心规范:为什么必须写 Docstring 而不能用普通注释?
这是 AI 工具接口设计中最容易被忽视的细节,这相当于给实验室的光电探测器贴上标准化标签。
- 工具注册机制:
@mcp.tool() 装饰器负责将 Python 函数暴露给大模型。 - AI 决策依据: AI 是通过读取函数的
description(描述)来决定何时调用它的。 - 普通注释 (
#): 是留给人类开发者的,程序在运行时会将其彻底丢弃,AI 看不到。 - 文档字符串 (
"""..."""): 必须紧跟在函数定义下方。Python 会将其编译并存入函数的 __doc__ 属性中。FastMCP 框架正是通过提取 __doc__ 将其转化为协议中的 description。如果缺失,VS Code 会触发 Warning,导致 AI 无法调用该工具。
四、 CodeLens:UI 交互的本质
在 mcp.json 文件中悬浮的“运行/重启”等按钮(CodeLens),并非 JSON 语法的原生功能。
- 来源: 它们是由支持 MCP 的 VS Code AI 插件(如 Cline、Roo Code)在扫描到有效配置后动态注入的 UI 交互入口。
- 功能: 大多数情况下,MCP 服务器会在你与 AI 交互时静默自动启动。这些按钮主要提供调试便利(例如修改工具代码后,快速点击重启以重新加载环境)。
五、 解决方案与工程实现
针对上述问题,提供以下标准操作流程(SOP)与工程化代码实现。
5.1 跨平台命令调用与第三方工具链配置 (以 markitdown 为例)
在 .vscode/mcp.json 中配置基于 uvx 的第三方工具包,需确保底层包管理器及多媒体引擎就绪。
- 环境初始化:使用系统包管理器全局安装高性能 Python 包管理器
uv,并执行编辑器重启逻辑。 - 多媒体解析引擎补充:若需解析音视频数据,需在 Windows 环境下通过包管理器安装
ffmpeg,并确保其 bin 目录写入系统 PATH 环境变量。
5.2 规范化 MCP 本地服务器开发
摒弃手动构建 JSON-RPC 消息体的方案,采用官方 mcp SDK (FastMCP) 构建底层通信层。
Python 服务端代码 (test_mcp.py):
# 导入官方 SDK 提供的高层级抽象类
from mcp.server.fastmcp import FastMCP
# 实例化 MCP 服务器,参数为服务器的唯一标识符
mcp = FastMCP("HelloWorldServer")
# 使用工具注册装饰器,将函数暴露为 AI 可调用的工具
@mcp.tool()
defsay_hello() -> str:
"""
这是一个向用户致意的工具。
功能:返回标准的问候字符串,用于验证 MCP 客户端与服务端的端到端通信链路是否连通。
输入:无
输出:包含问候信息的字符串
"""
return"Hello World from MCP! 握手成功!"
# 入口函数,启动事件循环并接管 stdio 通信流
if __name__ == "__main__":
mcp.run()
客户端配置文件 (.vscode/mcp.json):
{
"servers": {
"HelloWorldServer": {
"type": "stdio",
"command": "python",
"args": [
"test_mcp.py"
]
},
"microsoft/markitdown": {
"type": "stdio",
"command": "uvx",
"args": [
"markitdown-mcp@0.0.1a4"
]
}
}
}