前言
MCP(Model Context Protocol)这个概念,近期在人工智能开发者圈子里被频繁讨论。它由Anthropic于2024年底正式提出,是一套开放标准,核心理念在于让AI应用程序能够通过统一、标准化的方式与外部工具及数据源进行高效对接,从而大幅降低集成成本。

什么是MCP
你可以把MCP直观地理解为AI世界里的"USB-C接口"。在过去,如果想为AI系统添加一项新能力,比如查询天气、检索数据库或发送邮件,每个系统都需要单独编写一套对接代码。面对M个模型×N个工具的场景,维护成本会呈指数级增长,令人头疼。
MCP要解决的核心痛点正是标准化。采用MCP之后,复杂的M×N问题被简化为M+N。任何一个MCP客户端都能无缝连接任何一个MCP服务器,就像USB-C接口统一了充电和数据传输标准一样,实现了真正的互联互通。
MCP的三个核心概念
根据官方规范,MCP明确了服务器能够提供的几类功能。具体来说,有三个最核心的概念需要掌握:
- Tools(工具):AI能够主动调用的函数,例如"查天气""读文件"。这是最核心的能力,AI会根据实际需要自主决定何时调用。
- Resources(资源):被动提供的数据,比如文件内容或API返回的数据。AI不能主动调用,只能在需要时按需读取。
- Prompts(提示词模板):预定义好的提示词模板,用户可以一键调用,快速复用常见场景。
举个例子:一个MCP Server可以同时提供"搜索文档"(Tool)和"项目说明文档"(Resource),AI既能自主判断何时需要执行搜索,也能在用户提问时直接读取文档内容给出回答。
架构:Host → Client → Server
MCP采用的是清晰的三层架构:
- Host:用户直接打交道的AI应用,比如Claude Desktop、Cursor,或者mini-cc。
- Client:Host内部维护的模块,每个MCP Server对应一个Client,负责具体的JSON-RPC通信细节。
- Server:真正执行任务的后台服务,可以用任何语言编写——Python、Node.js、Go、Rust都完全支持。
通信协议走的是JSON-RPC,传输方式支持stdio(本地进程间通信)和HTTP/SSE(远程服务),灵活适配不同部署场景。
mini-cc中的MCP实现
那么mini-cc里这套MCP机制具体是怎么实现的?查看源码会发现,其实并没有想象中那么复杂。
预加载策略
mini-cc采用的是预加载策略,而非按需加载。启动时,它会将所有已配置的MCP Server连接好,并把工具直接注册到全局工具注册中心。
设计时面临一个关键选择:是每次需要工具时再临时连接,还是一启动就全部连接?最终团队选择了预加载策略。原因是mini-cc运行过程中子Agent会频繁创建,如果每次创建时都去重新连接MCP Server,延迟会明显变高,影响用户体验。启动时慢一点点完全可以接受,只要子Agent创建过程足够顺畅,那就值了。
当然,预加载也有代价——如果某个MCP Server挂了,启动可能会变慢甚至整个挂掉。因此mini-cc做了完善的容错处理:某个Server连不上就打出警告继续启动,不影响核心功能正常运行。
启动流程大致如下:
启动 mini-cc↓扫描 MCP Server 配置↓全部连接,获取工具列表↓注册到全局 ToolRegistry↓Agent 循环可以直接使用
配置文件的优先级
MCP Server的配置存放在.minicc/mcp.json文件里。配置文件的查找遵循明确的优先级:先找当前工作目录下的.minicc/mcp.json,找不到再找用户的~/.minicc/mcp.json,都找不到就当没有配置MCP Server。
环境变量的优先级更高,整体顺序为:环境变量 > 项目配置 > 全局配置。这样设计的好处是,可以在某个特定项目里配置专用的MCP Server,而不会影响其他项目,实现了灵活隔离。
两种Server连接方式
mini-cc支持两种MCP Server连接方式:
stdio模式:本地进程,通过标准输入输出进行通信,是最常用的方式。配置示例如下:
{"mcpServers": {"filesystem": {"command": "npx","args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/Desktop"],"env": { "DEBUG": "true" }}}}
HTTP/SSE模式:远程服务,通过HTTP加Server-Sent Events进行通信,适合需要中心化部署或跨网络调用的场景。
配置里还支持环境变量自动展开,格式为${ENV_VAR},或者带默认值的${ENV_VAR:-default},使用起来更加灵活。
工具适配器
mini-cc里有一个MCPToolAdapter,它的工作方式非常直接:把MCP Server返回的工具定义拿过来,包装成mini-cc自己的Tool接口格式,然后在execute方法里把调用转发给MCP Client并等待结果返回。
class MCPToolAdapter implements Tool {name: string;description: string;inputSchema: JSONSchema;async execute(args: any, context: ToolUseContext): Promise<ToolResult> {const result = await this.client.callTool(this.name, args);return result;}}
这样一来,Agent在调用工具时,完全不需要知道这个工具是内置的还是来自MCP插件——接口层把一切差异都抹平了,开发者体验非常统一。
MCP客户端的核心逻辑
MCP客户端的核心其实并不复杂,本质就是通过stdio与Server进程通信,使用JSON-RPC发送请求并解析响应。
不过,编写客户端时需要对ChildProcess的标准输入输出做正确处理。数据粘包(多个响应拼在一起)或解析卡死的问题很容易碰到。好在官方MCP SDK(@modelcontextprotocol/sdk)已经把这些底层细节封装好了,直接拿来用就行。mini-cc里也引用了这个包。如果你自己编写MCP客户端,强烈建议直接使用SDK,不要重复造轮子。
MCP的安全特性
需要明确指出的是,MCP协议本身并不负责安全,安全机制需要上层自行实现。MCP的角色是运输层,而非安全层。不过,mini-cc仍然做了几层防护来保障安全性:
1. 进程隔离
每个MCP Server都运行在独立进程中,崩溃不会影响主程序。同时还做了资源限制:
const process = spawn(serverPath, [], {stdio: ['pipe', 'pipe', 'pipe'],resourceLimits: {maxCPU: 1000, // 最多跑1秒CPU时间maxMemory: 512 * 1024 * 1024// 限制512MB内存}});
2. 严格模式
如果希望某个环境"必须"有MCP Server才能运行,可以通过MINICC_MCP_STRICT=1环境变量让启动失败:
| 场景 | 普通模式 | 严格模式 |
|---|---|---|
| 缺少MCP依赖 | 警告 + 跳过 | 启动失败 |
| MCP配置文件格式错误 | 警告 + 跳过 | 启动失败 |
| MCP Server连不上 | 警告 + 跳过 | 启动失败 |
| 没有MCP配置文件 | 正常运行 | 正常运行 |
这个设计非常实用:本地开发时MCP不是必需品,连不上就跳过;但在CI/CD流水线上,如果没有配置好MCP测试环境,就应该提前报错,避免把问题带到生产环境。
3. 用户审批
敏感操作需要用户明确授权,这一点在之前工具系统的文章里已经详细讲解过。
MCP官方网站对安全有三条核心建议:
- 用户同意:涉及数据访问和操作必须获得用户明确同意
- 数据隐私:不能未经用户同意就把数据传给第三方
- 工具安全:工具本质上可以执行任意代码,调用前必须由用户确认
这些原则在mini-cc设计时基本都已经被充分考虑和落地。
测试你的MCP Server
开发MCP Server时如何进行调试?官方提供了一个非常实用的MCP Inspector工具:
npx @modelcontextprotocol/inspector node your-server.js
打开浏览器后,你可以直观地看到Server暴露了哪些Tools和Resources,还可以交互式地测试调用。编写第一个MCP Server时,这个工具能帮助你一步步验证功能,节省大量排查时间。
一个简单的MCP Server示例
一个最简单的Node.js天气插件代码如下:
const { Server } = require('@modelcontextprotocol/sdk/server');const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio');const server = new Server({name: 'weather-server',version: '1.0.0'});server.setRequestHandler('list_tools', async () => ({tools: [{name: 'get_weather',description: '获取城市天气',inputSchema: {type: 'object',properties: {city: { type: 'string', description: '城市名称' }},required: ['city']}}]}));server.setRequestHandler('call_tool', async (request) => {if (request.params.name === 'get_weather') {const city = request.params.arguments.city;const weather = cities[city] || { temp: '未知', condition: '未知' };return { content: `${city} 天气: ${weather.temp}°C ${weather.condition}` };}});const transport = new StdioServerTransport();server.connect(transport);
配置好之后重启mini-cc,get_weather工具就会出现在Agent的工具列表里。当用户在聊天中提及天气时,Agent会自动决定调用这个工具来获取实时信息。
总结
MCP协议是mini-cc插件生态的基石,其核心价值体现在以下几个方面:
- 标准化接口:统一的工具定义和调用方式,无需再为每个AI单独编写对接代码,开发效率大幅提升
- 语言无关:插件可以用任何语言编写——Python、Node.js、Go、Rust都完全支持,灵活适配不同技术栈
- 安全隔离:插件运行在独立进程中,即使崩溃也不会影响主程序,保障系统稳定性
- 预加载策略:启动时全部加载并缓存,子Agent创建时零延迟,用户体验更流畅
如果你觉得mini-cc自带工具不够用,随时可以自行开发MCP插件来扩展功能,满足个性化需求。
关于安全方面,需要再次强调:MCP协议本身只定义了消息如何发送,安全防护还得靠上层Host自行实现。mini-cc编写了一套完整的审批流程,敏感工具调用前会弹出确认窗口,让用户有充分知情权。如果要在生产环境中使用MCP,建议额外加一个网关来做权限控制、审计和限流,否则日志和审计追踪可能会比较棘手。
```