当前位置: 首页 > news >正文

深入浅出MCP:从零开始的完整学习指南(保姆级教程)

手把手带你理解MCP是什么、怎么用、如何开发,每个步骤都有详细说明

写在前面

很多朋友看完MCP的介绍还是一头雾水:“这到底是什么?跟我有什么关系?我该怎么用?”

别急,这篇文章我会用最通俗的方式一步一步带你搞懂MCP。每个概念都会配上生活化的例子,每个操作都有完整的代码


第一部分:先搞懂“为什么” - 需求分析

问题1:现在的AI有什么痛点?

假设你有一个AI助手,你想让它帮你:

  • 读取你电脑上的Excel文件

  • 搜索网络上的图片

  • 调用公司内部的API

现在的问题是:每个AI模型都要单独适配,ChatGPT写一套代码,Claude写另一套,本地模型又不一样。太麻烦了!

问题2:MCP怎么解决?

MCP就像一个万能插座

text

之前:每个电器都要自己的专属插座 → 混乱 现在:统一标准,什么电器都能插 → 方便

MCP就是AI界的USB-C接口,让所有AI模型都能用统一的方式调用工具、获取数据。


第二部分:彻底搞懂MCP - 必知必会

什么是MCP?(用大白话说)

官方定义:MCP(Model Context Protocol)是一个开放协议,用于标准化应用程序向大型语言模型提供上下文的方式。

大白话解释:MCP是一套通用规则,规定了:

  • AI怎么“伸手要东西”(请求格式)

  • 工具怎么“把东西给AI”(响应格式)

  • 双方怎么“对话”(通信方式)

MCP架构(用餐厅比喻)

1. 宏观架构

把MCP想象成餐厅点餐

角色餐厅例子MCP世界
顾客AI模型
服务员服务员MCP客户端
厨房厨房MCP服务端
菜单菜单工具列表

流程

  1. 顾客(AI)说要吃什么 →

  2. 服务员(MCP客户端)记录并传给厨房 →

  3. 厨房(MCP服务端)做菜并返回

2. SDK 3层架构(通俗版)

text

┌─────────────────────────────────────┐ │ 应用层(你写代码的地方) │ ← 你只需要关心这层 │ @McpTool、@McpResource │ ├─────────────────────────────────────┤ │ 协议层(MCP自己处理) │ ← 不用你操心 │ 消息格式、交互规则 │ ├─────────────────────────────────────┤ │ 传输层(MCP自己处理) │ ← 不用你操心 │ stdio、SSE、HTTP │ └─────────────────────────────────────┘
3. MCP客户端(谁在用?)

客户端 = “请求发起方”

实际例子:

  • Cursor编辑器

  • Claude Desktop

  • 你自己写的Java程序

  • VS Code插件

4. MCP服务端(谁提供工具?)

服务端 = “提供能力的一方”

实际例子:

  • 文件系统服务(让AI读写文件)

  • 数据库服务(让AI查询数据)

  • 图片搜索服务(让AI搜图)

MCP核心概念(图解)

text

┌─────────────────────────────────────────────┐ │ MCP服务端 │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ Tool │ │Resource │ │ Prompt │ │ │ │ 工具 │ │ 资源 │ │ 提示词 │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ ↓ ↓ ↓ │ │ 可执行操作 可读取数据 可用的模板 │ │ (动词) (名词) (配方) │ └─────────────────────────────────────────────┘

详细解释

概念通俗理解代码示例
Tool(工具)AI能“做”的事情searchImages(),sendEmail()
Resource(资源)AI能“看”的数据文件、数据库记录、API响应
Prompt(提示词)预设的“对话模板”“你是一个图片搜索专家...”

第三部分:开始使用MCP(实操从这开始)

第一步:环境准备(5分钟搞定)

1.1 安装Node.js(MCP工具依赖)

bash

# Windows: 去官网下载安装包 https://nodejs.org/ # Mac: brew install node # Linux: sudo apt install nodejs npm # 验证安装 node -v # 应该显示 v18.0.0 或更高 npm -v # 显示版本号
1.2 安装MCP命令行工具

bash

# 全局安装MCP CLI npm install -g @modelcontextprotocol/cli # 验证安装 mcp --version

第二步:在Cursor编辑器中使用MCP

Cursor是什么?一个集成了AI的代码编辑器,类似VS Code。

详细步骤

  1. 下载Cursor:访问 https://cursor.sh/ 下载安装

  2. 打开设置

    • Windows/Linux:Ctrl + ,

    • Mac:Cmd + ,

  3. 找到MCP配置

    • 在设置搜索框输入 "MCP"

    • 找到 "MCP Servers" 配置项

  4. 添加服务

json

{ "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/folder"] } } }
  1. 重启Cursor,就可以在AI对话中使用MCP工具了!

第三步:测试MCP是否工作

bash

# 1. 测试MCP连接 mcp ping # 成功返回: pong # 2. 启动一个简单的MCP服务(作为测试) npx -y @modelcontextprotocol/server-filesystem /tmp # 3. 在另一个终端列出工具 mcp tools list --server http://localhost:3000

第四步:在程序中使用MCP(Python示例)

python

# 1. 安装Python SDK pip install mcp # 2. 创建测试脚本 test_mcp.py import asyncio from mcp import ClientSession, StdioServerParameters async def main(): # 连接到MCP服务 server_params = StdioServerParameters( command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] ) async with ClientSession(server_params) as session: # 初始化连接 await session.initialize() # 列出所有可用工具 tools = await session.list_tools() print("可用工具:", [tool.name for tool in tools]) # 调用一个工具 result = await session.call_tool( "read_file", arguments={"path": "/tmp/test.txt"} ) print("结果:", result) # 运行 asyncio.run(main())

bash

# 执行脚本 python test_mcp.py

第四部分:Spring AI MCP开发(Java/Spring Boot)

如果你用的是Java技术栈,这部分是你的重点

MCP客户端开发(调用别人的服务)

步骤1:创建Spring Boot项目

在 start.spring.io 创建项目,选择:

  • Spring Web

  • 添加MCP依赖

步骤2:添加依赖(pom.xml)

xml

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.0</version> </parent> <dependencies> <!-- Spring Boot基础 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MCP客户端 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId> <version>1.0.0-M1</version> </dependency> </dependencies>
步骤3:配置文件(application.yml)

yaml

spring: ai: mcp: client: enabled: true # 要连接的MCP服务地址 server-url: http://localhost:8080 # 连接超时(毫秒) connect-timeout: 30000 # 请求超时(毫秒) request-timeout: 60000 logging: level: org.springframework.ai: DEBUG
步骤4:编写客户端代码

java

package com.example.mcpclient; import org.springframework.ai.mcp.McpClient; import org.springframework.ai.mcp.model.McpCallToolRequest; import org.springframework.ai.mcp.model.McpCallToolResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/api/mcp") public class McpClientController { @Autowired private McpClient mcpClient; @GetMapping("/search") public String searchImages(@RequestParam String keyword) { // 1. 构造请求 McpCallToolRequest request = new McpCallToolRequest(); request.setName("image-search"); // 要调用的工具名 Map<String, Object> args = new HashMap<>(); args.put("keyword", keyword); args.put("limit", 5); request.setArguments(args); // 2. 发送请求 McpCallToolResult result = mcpClient.callTool(request); // 3. 返回结果 return result.getContent().toString(); } @GetMapping("/tools") public List<String> listAvailableTools() { // 获取所有可用工具 return mcpClient.listTools() .stream() .map(tool -> tool.getName()) .collect(Collectors.toList()); } }

MCP服务端开发(提供给别人调用)

步骤1:创建服务端项目

同样的方式创建Spring Boot项目,添加服务端依赖:

xml

<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId> <version>1.0.0-M1</version> </dependency>
步骤2:配置文件

yaml

spring: ai: mcp: server: name: my-image-search-service version: 1.0.0 # 传输方式:stdio(标准输入输出)或 sse(HTTP) transport-type: sse # HTTP端口(使用SSE时) port: 8080 server: port: 8080
步骤3:启用MCP服务

java

package com.example.mcpserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.ai.mcp.server.annotation.EnableMcpServer; @SpringBootApplication @EnableMcpServer // 这个注解启用MCP服务能力 public class McpServerApplication { public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); System.out.println("MCP服务已启动,地址: http://localhost:8080"); } }
步骤4:开发MCP工具

java

package com.example.mcpserver; import org.springframework.ai.mcp.server.annotation.McpTool; import org.springframework.ai.mcp.server.annotation.McpToolParam; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; import java.util.List; import java.util.ArrayList; @Service @Slf4j public class ImageSearchService { /** * 搜索图片的工具 * @McpTool 注解把这个方法暴露为MCP工具 */ @McpTool( name = "image-search", description = "根据关键词搜索图片,返回图片URL列表" ) public List<ImageInfo> searchImages( @McpToolParam(description = "搜索关键词,比如:风景、猫、汽车") String keyword, @McpToolParam(description = "返回图片数量,默认10张,最大50") Integer limit ) { log.info("收到图片搜索请求: keyword={}, limit={}", keyword, limit); // 限制最大数量 if (limit == null || limit > 50) { limit = 10; } // 这里是示例数据,实际可以调用Unsplash、Pexels等API List<ImageInfo> results = new ArrayList<>(); for (int i = 0; i < limit; i++) { ImageInfo image = new ImageInfo(); image.setId(String.valueOf(i)); image.setTitle(keyword + " - 图片" + (i+1)); image.setUrl("https://example.com/images/" + keyword + "_" + i + ".jpg"); image.setThumbnail("https://example.com/thumbnails/" + keyword + "_" + i + ".jpg"); results.add(image); } return results; } /** * 获取最近上传的图片 * @McpResource 注解暴露资源 */ @McpResource(uri = "image://recent/{count}") public List<ImageInfo> getRecentImages(@McpResourcePath String count) { int num = Integer.parseInt(count); return searchImages("recent", num); } } // 数据类 class ImageInfo { private String id; private String title; private String url; private String thumbnail; // getter/setter 省略 }
步骤5:运行服务

bash

# 打包 mvn clean package # 运行 java -jar target/mcp-server-1.0.0.jar

服务启动后,访问http://localhost:8080可以看到MCP服务信息。


第五部分:完整实战 - 图片搜索服务(复制就能用)

服务端完整代码

ImageSearchService.java

java

package com.example.imagesearch; import org.springframework.ai.mcp.server.annotation.McpTool; import org.springframework.ai.mcp.server.annotation.McpToolParam; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.JsonNode; import java.util.*; @Service public class ImageSearchService { private final RestTemplate restTemplate = new RestTemplate(); @McpTool(name = "search-images", description = "从Unsplash搜索免费图片") public List<Map<String, String>> searchImages( @McpToolParam(description = "搜索关键词,如:mountain, cat, car") String keyword, @McpToolParam(description = "返回数量,默认5") Integer limit ) { // 调用Unsplash API(免费图片API) String url = "https://api.unsplash.com/search/photos?query=" + keyword + "&per_page=" + (limit == null ? 5 : limit) + "&client_id=YOUR_UNSPLASH_ACCESS_KEY"; try { JsonNode response = restTemplate.getForObject(url, JsonNode.class); List<Map<String, String>> results = new ArrayList<>(); for (JsonNode photo : response.get("results")) { Map<String, String> image = new HashMap<>(); image.put("id", photo.get("id").asText()); image.put("description", photo.get("description") != null ? photo.get("description").asText() : keyword); image.put("url", photo.get("urls").get("regular").asText()); image.put("thumbnail", photo.get("urls").get("thumb").asText()); image.put("author", photo.get("user").get("name").asText()); results.add(image); } return results; } catch (Exception e) { // 返回模拟数据 return getMockData(keyword, limit); } } private List<Map<String, String>> getMockData(String keyword, Integer limit) { List<Map<String, String>> results = new ArrayList<>(); for (int i = 0; i < (limit == null ? 5 : limit); i++) { Map<String, String> image = new HashMap<>(); image.put("id", "mock_" + i); image.put("description", keyword + " 图片 " + (i+1)); image.put("url", "https://picsum.photos/id/" + (i+10) + "/800/600"); image.put("thumbnail", "https://picsum.photos/id/" + (i+10) + "/200/150"); results.add(image); } return results; } }

客户端完整代码

ImageSearchController.java

java

package com.example.imageclient; import org.springframework.ai.mcp.McpClient; import org.springframework.ai.mcp.model.McpCallToolRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.*; @RestController @RequestMapping("/api/images") public class ImageSearchController { @Autowired private McpClient mcpClient; @GetMapping("/search") public Map<String, Object> search(@RequestParam String q, @RequestParam(defaultValue = "5") int limit) { Map<String, Object> response = new HashMap<>(); response.put("keyword", q); response.put("limit", limit); try { // 调用MCP服务 McpCallToolRequest request = new McpCallToolRequest(); request.setName("search-images"); Map<String, Object> args = new HashMap<>(); args.put("keyword", q); args.put("limit", limit); request.setArguments(args); Object result = mcpClient.callTool(request); response.put("success", true); response.put("data", result); response.put("message", "搜索成功"); } catch (Exception e) { response.put("success", false); response.put("message", "搜索失败: " + e.getMessage()); } return response; } }

第六部分:最佳实践(避坑指南)

1. 工具设计原则

java

// ❌ 错误:一个工具做太多事 @McpTool(name = "doEverything") public String doEverything(String action, String param1, String param2, ...) // ✅ 正确:每个工具职责单一 @McpTool(name = "searchImages") public List<Image> searchImages(String keyword) @McpTool(name = "downloadImage") public String downloadImage(String imageId) @McpTool(name = "getImageInfo") public ImageInfo getImageInfo(String imageId)

2. 参数设计

java

// ❌ 错误:参数含义模糊 @McpTool(name = "process") public String process(String p1, String p2) // ✅ 正确:参数清晰且有描述 @McpTool(name = "searchImages", description = "搜索图片") public List<Image> searchImages( @McpToolParam(description = "搜索关键词,如:风景、猫") String keyword, @McpToolParam(description = "返回数量,1-50,默认10") Integer limit, @McpToolParam(description = "排序方式:relevance/popularity/latest") String sortBy )

3. 错误处理

java

@McpTool(name = "searchImages") public List<Image> searchImages(String keyword, Integer limit) { // 参数校验 if (keyword == null || keyword.trim().isEmpty()) { throw new IllegalArgumentException("关键词不能为空"); } if (limit != null && (limit < 1 || limit > 100)) { throw new IllegalArgumentException("数量必须在1-100之间"); } try { // 业务逻辑 return doSearch(keyword, limit); } catch (Exception e) { log.error("搜索失败", e); // 返回空列表而不是抛异常,让AI能继续工作 return Collections.emptyList(); } }

第七部分:部署方案

方案1:本地运行(开发调试)

bash

# 直接运行JAR java -jar mcp-server-1.0.0.jar # 或使用Maven mvn spring-boot:run

方案2:Docker部署

创建Dockerfile

dockerfile

FROM openjdk:17-jdk-slim COPY target/mcp-server-1.0.0.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app.jar"]

构建和运行:

bash

# 构建镜像 docker build -t mcp-image-search . # 运行容器 docker run -d -p 8080:8080 --name mcp-service mcp-image-search # 查看日志 docker logs mcp-service

方案3:云平台部署(Railway示例)

  1. 注册 Railway.app

  2. 连接你的GitHub仓库

  3. Railway会自动检测Spring Boot项目并部署

  4. 获得公网URL:https://your-service.up.railway.app


第八部分:安全和常见问题

安全问题及解决方案

风险说明解决方案
命令注入恶意参数执行危险命令严格校验输入,白名单限制
越权访问访问不该访问的资源实现权限校验
信息泄露返回敏感数据数据脱敏,最小化返回
DoS攻击大量请求消耗资源限流,熔断

安全配置示例

java

@Configuration public class McpSecurityConfig { @Bean public McpSecurityInterceptor securityInterceptor() { return new McpSecurityInterceptor() { @Override public boolean preHandle(String toolName, Map<String, Object> args) { // 1. 参数长度限制 String keyword = (String) args.get("keyword"); if (keyword != null && keyword.length() > 100) { throw new SecurityException("参数过长"); } // 2. 敏感词过滤 if (containsSensitiveWords(keyword)) { throw new SecurityException("包含敏感词"); } // 3. 频率限制 if (isRateLimitExceeded()) { throw new SecurityException("请求过于频繁"); } return true; } }; } }
http://www.jsqmd.com/news/804989/

相关文章:

  • Jsxer:解密Adobe ExtendScript二进制格式的专业反编译器
  • Termius v7.0.1汉化踩坑实录:从修改entry.js到完美中文界面的完整流程
  • 3D生物打印骨骼:从生物墨水到临床应用的技术解析与挑战
  • MinIO临时凭证与预签名URL的实战应用:从生成到安全管控(代码详解)
  • 厚街音响租赁哪家值得推荐:秒杀音响租赁金牌 - 13724980961
  • RimSort终极指南:3步解决环世界MOD加载混乱,新手也能轻松管理200+模组
  • Sketch Find And Replace插件终极指南:如何3分钟掌握批量文本替换技巧
  • Atlas机器人:人形设计、液压驱动与救灾场景下的技术权衡
  • 高海拔环境下的硬件设计挑战与GPS定位故障分析
  • MiGPT深度解析:如何将小爱音箱升级为AI语音助手
  • 厚街租车哪家值得推荐:秒杀租车商务首选 - 17322238651
  • 资本可以复制流量,却复制不了《凰标》的天命@凤凰标志
  • PolyGPT-Alpha:基于智能体工厂模式的AI DAO框架设计与实践
  • 詹姆斯·韦伯望远镜:344个单点故障背后的航天工程极限挑战
  • Starter计划账户被限流却不通知?资深开发者逆向追踪请求链路,定位第3层CDN级限频策略
  • 低电感电源总线设计:应对高频大电流挑战的平面电容方案
  • 可穿戴设备安全设计:从架构到实现的全方位防御指南
  • 2026年水族水泵选购指南:泵内杀菌技术与静音性能对比 - 观域传媒
  • ARM架构中断优先级与ID寄存器深度解析
  • 《凰标》:写给所有被资本轻视的创作者@凤凰标志
  • 别再复制粘贴了!手把手教你封装一个可复用的Qt文本编辑器核心组件类
  • LangChain4j 万字教程从零到一:Java开发者的大模型入门完全指南
  • 从server.xml到Nginx:实战iServer访问路径重构与代理配置
  • 2026年中小微破局关键:GEO代理贴牌是不是好生意? - GrowthUME
  • 厚街小程序开发哪家值得推荐:秒杀小程序开发稳如泰山 - 13425704091
  • 如何在 Docker 容器中优化 Node.js 异步网络请求的 DNS 缓存配置
  • 合资企业全流程指南:从战略共识到IP管理的实战避坑
  • 20252220 2025-2026-2 《Python程序设计》实验四报告
  • 北京小红书代运营服务商实力排行:全域能力对比 - 奔跑123
  • 独立开发者如何借助Taotoken快速验证不同大模型的创意应用