苏森AI

  • AI资讯
  • AI应用
  • AI工具
  • AI工作流
  • AI智能体
  • AI提示词
苏森AI
从这里开启你的AI学习旅程!
  1. 首页
  2. AI应用
  3. 正文

MCP(2)开发:如何通过mcp把私域数据库接入到大模型

2025-06-09 43点热度 0人点赞 0条评论
MCP(2)开发:如何通过mcp把私域数据库接入到大模型

从MCP(1)应用:通过mcp在大模型中关联应用私域数据库已可直观地感受到效果,现在来瞅瞅这个MCP工具的源代码——如何开发自己的MCP工具。简直太......请观后自品😄

回想一下,在没有 MCP 之前我们是怎么做的呢?我们多半是人工编辑描述好这些可能LLM所需要的信息——即上下文,然后粘贴给到它。

而现在,可由 MCP 这一充当着 AI 模型的"万能转接头"来帮 LLM 能自动获取数据或调用其它工具。

相信我:不久,在某些业务场景功能模块下,我们的后端应用服务中就要多出一份接口——它是MCP协议的(好比xml的webservice、json的RESTful、RPC)!

在MCP官网https://modelcontextprotocol.io有关示例基本是用TypeScript、Python实现的。现分别用MCP原生Java SDK和Spring AI实现。

图片

一、使用MCP原生Java SDK实现

感兴趣可以看看SDK源码,代码量并不大:

https://github.com/modelcontextprotocol/java-sdk

1.1、工程结构如下

MCP(2)开发:如何通过mcp把私域数据库接入到大模型

😄也就两个类,总共代码不足100行。

1.2、具体代码

  • 依赖pom配置:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.ydj</groupId>    <artifactId>ydj-kits-mysql4mcp</artifactId>    <version>1.0-SNAPSHOT</version>    <properties>        <java.version>17</java.version>        <mcp.version>0.10.0</mcp.version>        <jackson.version>2.18.3</jackson.version>        <lombok.version>1.18.36</lombok.version>        <mysql.connector.version>9.1.0</mysql.connector.version>        <maven.compiler.release>${java.version}</maven.compiler.release>    </properties>    <dependencies>        <dependency>            <groupId>io.modelcontextprotocol.sdk</groupId>            <artifactId>mcp</artifactId>            <version>${mcp.version}</version>        </dependency>        <dependency>            <groupId>com.mysql</groupId>            <artifactId>mysql-connector-j</artifactId>            <version>${mysql.connector.version}</version>        </dependency>        <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-databind</artifactId>            <version>${jackson.version}</version>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>${lombok.version}</version>        </dependency>    </dependencies>    <build>        <plugins>            <!-- 1. Maven Compiler: 指定 Java 版本,支持文本块 -->            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.14.0</version>                <configuration>                    <release>${maven.compiler.release}</release>                </configuration>            </plugin>            <!-- 2. Maven Shade: 打包为 fat-jar -->            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-shade-plugin</artifactId>                <version>3.5.0</version>                <executions>                    <execution>                        <phase>package</phase>                        <goals>                            <goal>shade</goal>                        </goals>                        <configuration>                            <!-- 去除依赖中的签名文件等,避免冲突 -->                            <filters>                                <filter>                                    <artifact>*:*</artifact>                                    <excludes>                                        <exclude>META-INF/*.SF</exclude>                                        <exclude>META-INF/*.DSA</exclude>                                        <exclude>META-INF/*.RSA</exclude>                                    </excludes>                                </filter>                            </filters>                            <!-- 指定主类 -->                            <transformers>                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">                                    <mainClass>com.ydj.kits.mcp.mysql.kits.mcp.mysql.MySqlMcpServerApplication</mainClass>                                </transformer>                            </transformers>                        </configuration>                    </execution>                </executions>            </plugin>        </plugins>    </build></project>

重点注意:打包方式以及要指定主类入口。

  • 入口main方法类:
/** * @Desc : 注册工具&启动监听服务 * @Author : ydj * @Date : 2025/5/12 */public class MySqlMcpServerApplication {    public static void main(String[] args) throws InterruptedException {        //1) 使用 STDIO 传输层启动服务器        var transportProvider = new StdioServerTransportProvider(new ObjectMapper());        //2) 构建并启动同步 MCP Server,启用工具执行能力        var server = McpServer.sync(transportProvider)                .serverInfo("ydj-kits-mysql4mcp", "1.0.0")                .capabilities(McpSchema.ServerCapabilities.builder()                        .tools(true)                        .build())                .build();        //3) 注册自定义 MySQL 工具:addTool 可在运行时动态添加工具        server.addTool(ExeSqlOnMysqlService.exeMysqlDB());        //4) 在 JVM 退出时优雅关闭服务器:close() 用于关闭传输并释放资源        Runtime.getRuntime().addShutdownHook(new Thread(server::close));        //5) 阻塞主线程,保持进程存活:join() 阻塞主线程,防止 JVM 退出        Thread.currentThread().join();    }}
  •  MySql工具能力服务实现类:
/** * @Desc : 执行连接操作mysql * @Author : ydj * @Date : 2025/5/12 */@Slf4jpublic class ExeSqlOnMysqlService {    public static McpServerFeatures.SyncToolSpecification exeMysqlDB() {        String schema = """                    {                      "type": "object",                      "properties": {                        "host":     { "type": "string" },                        "user":     { "type": "string" },                        "password": { "type": "string" },                        "database": { "type": "string" },                        "query":    { "type": "string" }                      },                      "required": ["host","user","password","database","query"]                    }                """;        McpSchema.Tool tool = new McpSchema.Tool("ydj-kits-mysql4mcp", "Execute SQL on MySQL", schema);        return new McpServerFeatures.SyncToolSpecification(tool, (exchange, arguments) -> {            try {                String host = arguments.get("host").toString();                String user = arguments.get("user").toString();                String pass = arguments.get("password").toString();                String db   = arguments.get("database").toString();                String sql  = arguments.get("query").toString().trim();                String url  = String.format("jdbc:mysql://%s:3306/%s?useSSL=false&allowMultiQueries=true", host, db);                log.info("host:{},user:{},db:{},sql:{}", host, user, db, sql);                try (Connection conn = DriverManager.getConnection(url, user, pass);                     Statement stmt = conn.createStatement()) {                    if (sql.toLowerCase().startsWith("select")) {                        List<Map<String, Object>> rows = new ArrayList<>();                        try (ResultSet rs = stmt.executeQuery(sql)) {                            ResultSetMetaData meta = rs.getMetaData();                            int colCount = meta.getColumnCount();                            while (rs.next()) {                                Map<String, Object> row = new LinkedHashMap<>();                                for (int i = 1; i <= colCount; i++) {                                    row.put(meta.getColumnLabel(i), rs.getObject(i));                                }                                rows.add(row);                            }                        }                        Map<String, Object> result = Map.of("Result Rows", rows);                        log.info("result:{}", result);                        return new McpSchema.CallToolResult(String.valueOf(result), false);                    }                    int affected = stmt.executeUpdate(sql);                    Map<String, Object> result = Map.of("Affected Rows", affected);                    log.info("result:{}", result);                    return new McpSchema.CallToolResult(String.valueOf(result), false);                }            } catch (Exception e) {                log.error("error:{}", e.getMessage());                return new McpSchema.CallToolResult(String.valueOf(Map.of("Error", e.getMessage())), true);            }        });    }}

主要是定义工具规格:name、description、JSON参数schema(即与LLM进行沟通的Prompt,很重要)。至于Mysql具体处理那块就没什么特殊的了。

如上,代码实际很简单!然后正常打出的jar包即可在支持MCP的LLM工具中配置使用,具体如何配置请参见第一篇MCP(1)应用:通过mcp在大模型中关联应用私域数据库。

图片

二、使用Spring AI实现

Spring在其SDK的基础之上进行了封装,因此开发起来更简单,自然毋庸置疑最后打出来jar包也会大很多。

2.1、工程结构如下

MCP(2)开发:如何通过mcp把私域数据库接入到大模型

😄同样也就两个类,代码更少更简单(DateTimeService是用来测试发布多tool能力)。

2.2、具体代码

  • 依赖pom配置:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>3.4.4</version>    </parent>    <groupId>com.ydj</groupId>    <artifactId>mcp-demo-mysql-springai</artifactId>    <version>1.0-SNAPSHOT</version>    <properties>        <java.version>17</java.version><spring-ai.version>1.0.0</spring-ai.version>        <main.class>com.ydj.kits.mcp.mysql.StdioServerApplication</main.class>        <maven.compiler.release>${java.version}</maven.compiler.release>    </properties>    <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.ai</groupId>                <artifactId>spring-ai-bom</artifactId>                <version>${spring-ai.version}</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement>    <dependencies>        <dependency>            <groupId>org.springframework.ai</groupId>            <artifactId>spring-ai-starter-mcp-server</artifactId>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-web</artifactId>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter</artifactId>        </dependency>        <!-- MySQL JDBC -->        <dependency>            <groupId>com.mysql</groupId>            <artifactId>mysql-connector-j</artifactId>        </dependency>        <!-- Jackson JSON -->        <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-databind</artifactId>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>                <executions>                    <execution>                        <goals>                            <goal>repackage</goal>                        </goals>                    </execution>                </executions>            </plugin>        </plugins>    </build></project>

如临时版本可能Maven中央私服仓库中下载不下来,则可以在Maven settings文件中添加阿里镜像仓库:

<mirrors>    <mirror>  	<id>aliyunmaven</id>  	<mirrorOf>*,!spring-milestones</mirrorOf>  	<name>阿里云公共仓库</name>  	<url>https://maven.aliyun.com/repository/public</url>    </mirror></mirrors><repositories>        <repository>            <id>spring-milestones</id>            <name>Spring Milestones</name>            <url>https://repo.spring.io/milestone</url>            <snapshots>                <enabled>false</enabled>            </snapshots>        </repository>        <repository>            <id>spring-snapshots</id>            <name>Spring Snapshots</name>            <url>https://repo.spring.io/snapshot</url>            <releases>                <enabled>false</enabled>            </releases>        </repository>        <repository>            <id>central-portal-snapshots</id>            <name>Central Portal Snapshots</name>            <url>https://central.sonatype.com/repository/maven-snapshots/</url>            <releases>                <enabled>false</enabled>            </releases>            <snapshots>                <enabled>true</enabled>            </snapshots>        </repository></repositories>
  • Spring配置信息application.yml:
spring:  main:    web-application-type: none    banner-mode: off  ai:    mcp:      server:        name: ydj-mysql-mcp-server        version: 0.0.1
  • 入口main方法类:
/** * @Desc : 启动类 * @Author : ydj * @Date : 2025/5/12 */@SpringBootApplicationpublic class StdioServerApplication {public static void main(String[] args) {SpringApplication.run(StdioServerApplication.class, args);	}}
  • StdioServer工具装配类:
@Configurationpublic class StdioServerConfig {    @Bean    public ToolCallbackProvider tools(DateTimeService dateTimeService, ExeSqlOnMysqlService exeSqlOnMysqlService) {        return MethodToolCallbackProvider.builder().toolObjects(dateTimeService, exeSqlOnMysqlService).build();    }}
  • MySql工具能力服务实现类:
@Slf4j@Servicepublic class ExeSqlOnMysqlService {    @Tool(description = "执行Mysql数据库操作")    public String exeMysqlDB(            @ToolParam(description = "mysql服务主机") String host,            @ToolParam(description = "用户名") String user,            @ToolParam(description = "密码") String password,            @ToolParam(description = "数据库") String database,            @ToolParam(description = "SQL语句") String query    ) {        log.info("host:{},user:{},db:{},sql:{}", host, user, database, query);        String url = String.format("jdbc:mysql://%s:3306/%s?useSSL=false&allowMultiQueries=true", host, database);        try (Connection conn = DriverManager.getConnection(url, user, password);             Statement stmt = conn.createStatement()) {            if (query.toLowerCase().startsWith("select")) {                List<Map<String, Object>> rows = new ArrayList<>();                try (ResultSet rs = stmt.executeQuery(query)) {                    ResultSetMetaData meta = rs.getMetaData();                    int colCount = meta.getColumnCount();                    while (rs.next()) {                        Map<String, Object> row = new LinkedHashMap<>();                        for (int i = 1; i <= colCount; i++) {                            row.put(meta.getColumnLabel(i), rs.getObject(i));                        }                        rows.add(row);                    }                }                Map<String, Object> result = Map.of("Result Rows", rows);                log.info("result:{}", result);                return result.toString();            }            int affected = stmt.executeUpdate(query);            Map<String, Object> result = Map.of("Affected Rows", affected);            log.info("result:{}", result);            return result.toString();        } catch (Exception e) {            log.error("error:{}", e.getMessage());            return Map.of("Error", e.getMessage()).toString();        }    }}
  • 附加多Tool能力测试类:
@Servicepublic class DateTimeService {    @Tool(description = "获取用户所在时区的当前时间")    String getCurrentDateTime() {        return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();    }    @Tool(description = "为用户设置一个闹铃,返回的时间格式为ISO-DATE-TIME")    String setAlarm(String time) {        LocalDateTime alarmTime = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME);        return alarmTime + "的闹铃已经设置完成";    }}

如上,代码更简单!然后正常打出的jar包即可在支持MCP的LLM工具中配置使用,具体如何配置请参见第一篇MCP(1)应用:通过mcp在大模型中关联应用私域数据库。

图片

三、思考总结

3.1、模拟测试验证

整体来说,两种实现方式都很简单。如上两种方式均可以使用如下代码进行本地验证测试:

public class ClientStdioTest {    public static void main(String[] args) {        var stdioParams = ServerParameters.builder("D:/Program Files/Java/jdk-17.0.4.1/bin/java")                .args("-jar",                        "-Dspring.ai.mcp.server.stdio=true",                        "-Dspring.main.web-application-type=none",                        "-Dlogging.pattern.console=",                        "D:\IdeaProjects\LLM\mcp-demo-mysql-springai\target\mcp-demo-mysql-springai-1.0-SNAPSHOT.jar")                .build();        var transport = new StdioClientTransport(stdioParams);        var client = McpClient.sync(transport).build();        client.initialize();        // 列出并展示可用的工具        ListToolsResult toolsList = client.listTools();        System.out.println("可用工具 = " + toolsList);        // getCurrentDateTime        CallToolResult res = client.callTool(new CallToolRequest("getCurrentDateTime", Map.of()));        System.out.println("获取用户所在时区的当前时间: " + res);        // setAlarm        res = client.callTool(new CallToolRequest("setAlarm",Map.of("time", "2025-05-13 21:10")));        System.out.println("设置闹钟: " + res);        // exeMysqlDB        String sql = "select id,dep_name,dep_code from ydj_dep";        res = client.callTool(new CallToolRequest("exeMysqlDB",                Map.of(                        "host", "192.1.2.5",                        "user", "xxxx",                        "password", "xxxxxxxx",                        "database", "ydj_test",                        "query", sql                )        ));        System.out.printf("执行SQL = [%s]结果: %s%n", sql, res);        client.closeGracefully();    }}

如上使用stdio传输,MCP服务器由客户端自动启动,注意需要先构建服务器jar(即上述代码中位置jar包需先打包好)。

3.2、基本运作流程&原理

MCP(2)开发:如何通过mcp把私域数据库接入到大模型
  1. MCP Client首先从MCP Server获取可用的工具列表;
  2. 将用户的Query连同工具描述通过Function Calling一起发送给 LLM;
  3. LLM 决定是否需要使用工具以及使用哪些工具;
  4. 如果需要使用工具,MCP Client会通过 MCP Server执行相应的工具调用;
  5. 工具调用的结果会被发送回LLM;
  6. LLM基于所有信息生成自然语言响应;
  7. 最后将响应展示给用户。

MCP Server 是由 LLM 主动选择并调用的。有意思的是 LLM 具体是如何确定该使用哪些工具呢?以及是否会使用一些不存在的工具呢(幻觉)?

参见官网:

https://modelcontextprotocol.io/quickstart/server#what%E2%80%99s-happening-under-the-hood

3.3、对MCP发展的展望

  • 新协议服务能力——MCP将成为软件对外开放和集成的新协议,SaaS、应用服务将会以MCP方式提供对外服务(如百度已提供MCP协议地图接口)。
  • 产品交互重构——重构应用形态,智能助手将以“搜索框”的形式成为各个应用的交互入口,支持语音及自然语言交换形式,完成复杂任务的执行。

多出一份协议接口,业务核心能力复用,分分钟把原应用服务通过MCP接入到大模型。赶紧动起手来😄

 图片

本篇文章来源于微信公众号: 梦语路

标签: mcp 大模型 私域数据库
最后更新:2025-07-26

苏森

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复
最新 热点 随机
最新 热点 随机
AI智能体扣子(Coze)工作流实战,1分钟生成100篇阅读量10万+AI漫画公众号文章,保姆级教程 17个作品涨粉超110万!用AI制作人生哲理视频,百万点赞火的一塌糊涂(保姆级实战教程) 独家首发!挑战用Coze做治愈系动态视频(风景/动漫/乡村),核心工作流搭建思路拆解(附体验链接) Coze+剪映视频工作流,1分钟制作治愈老爷爷/老奶奶视频,每条都是10w+(附提示词和体验链接) 打造10万+爆文的新法宝:Coze+DeepSeek工作流全攻略,手把手教你搭建 Coze+剪映视频工作流,一分钟打造爆款养生视频,干货分享,价值4位数 Coze+DeepSeek+剪映打造爆款国学文化视频工作流,进阶版保姆级教程,助力自媒体运营一路开挂 重磅发布 | 挑战用Coze做“如果书籍会说话”读书视频,20天涨粉10万,书单赛道新型玩法,附核心工作流搭建思路拆解
基于扣子 (Coze):AI 智能体搭建【作业批改复习助手】工作流企业新基建:MCP + LLM + Agent 8大架构,将打通AI Agent的“神经中枢”落地实操!2025年,建议你一定要用AI搭建自媒体全自动工作流值得收藏!3个黄金提示词公式,让 AI 从 “答非所问” 变 “超级助理”AI智能体扣子(Coze)工作流搭建,3分钟自动生成100篇知识图文,保姆级教程基于Dify动态解析异构银行流水:架构拆解→风控报告生成别卷了!用 Dify 搭建你的专属 AI 数据分析报告助手AI智能体:一键生成爆款历史人物短视频,66万粉丝
新品首发 | Coze视频工作流打造爆款英文版心理知识视频,附核心工作流搭建思路拆解 AI智能体:一键生成爆款历史人物短视频,66万粉丝 扣子(Coze)工作流:头条新闻链接生成热点时事点评视频 AI智能体平台大比拼:Coze、Dify、FastGPT深度对比分析 全自动生成高质量有声书!能克隆任意音色!完全免费的AI工作流! AI智能体扣子(Coze)工作流搭建,试卷出题系统,涵盖所有学科、所有年级,保姆级教程 全自动AI短视频工厂:一个让你实现躺赚的n8n工作流 7 天爆涨10 万粉!治愈系中年大叔这样做(附制作思路)
标签聚合
工作流 智能体 豆包 coze 扣子 n8n 小红书 Agent 提示词 Prompt DeepSeek Dify mcp ChatGPT 飞书 FastGPT

COPYRIGHT © 2025 苏森AI SOOSON.COM. ALL RIGHTS RESERVED.

站点地图