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

打造一个支持MySQL查询的MCP同步插件:Java实现

打造一个支持MySQL查询的MCP同步插件:Java实现

用Java实现一个MCP本地插件,直接通过JDBC操作本地MySQL,并通过STDIO与上层MCP客户端(例如Cursor)通信。插件注册一个名为mysql
的同步工具,接收连接参数及SQL查询,执行后将结果以JSON返回。目录结构、完整代码及在Cursor中的示例配置如下。

摘要

我们基于 Model Context Protocol Java SDK 实现了一个简单的 MCP Server 插件,它:

  1. 在 Server 启动时注册一个名为 mysql 的工具(SyncToolSpecification),其参数定义包括 hostuserpassword
    databasequery 等字段。

  2. 在工具处理器中利用 MySQL 官方 JDBC 驱动(mysql-connector-java)连接数据库,执行查询,并将每行结果封装为 JSON 数组返回。

  3. 打包为可执行 JAR 后,通过命令行启动,Cursor 中配置类似于:

    {"mcpServers": {"mysql": {"command": "java","args": ["-jar", "/Users/changmeng.yuan.o/Desktop/mysql-server-mcp-java-demo/target/mysql-server-mcp-java-demo-1.0.0.jar"],"env": {"MYSQL_HOST": "localhost","MYSQL_USER": "root","MYSQL_PASSWORD": "875213MenG...","MYSQL_DATABASE": "test"}}}
    

}


即可在对话中直接调用 `mysql` 工具执行任意查询并获取结果。## 依赖在 `pom.xml` 中声明以下关键依赖:* **MCP 核心 SDK**(包含 STDIO Server 传输实现)```xml
<dependency><groupId>io.modelcontextprotocol.sdk</groupId><artifactId>mcp</artifactId><version>0.9.0</version>
</dependency>
  • MySQL JDBC 驱动
    可以用新版的 mysql-connector-j

     <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.2.0</version></dependency>
    

    (来自 MySQL 官方 Maven 中心)

  • Jackson 用于 JSON 序列化(可选,STDIO Transport 已自带,但我们手动构造 JSON)

    <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.2</version>
    </dependency>
    

目录结构

mcp-mysql-plugin/
├── pom.xml
└── src└── main├── java│   └── com│       └── example│           └── mcpmysql│               ├── Main.java│               └── MysqlTool.java└── resources└── application.properties

pom.xml


<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.codeyuan.mcpmysql</groupId><artifactId>mysql-server-mcp-java-demo</artifactId><version>1.0.0</version><properties><!-- 指定 Java 版本 --><java.version>17</java.version><mcp.version>0.9.0</mcp.version><jackson.version>2.15.2</jackson.version><mysql.connector.version>8.2.0</mysql.connector.version><!-- 用于 Maven Compiler Plugin 的 release 配置 --><maven.compiler.release>${java.version}</maven.compiler.release></properties><dependencies><!-- MCP core SDK with STDIO transport --><dependency><groupId>io.modelcontextprotocol.sdk</groupId><artifactId>mcp</artifactId><version>${mcp.version}</version></dependency><!-- MySQL JDBC --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>${mysql.connector.version}</version></dependency><!-- Jackson JSON --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.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><!-- 一次性设置 source、target 和标准库版本 --><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><transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>com.codeyuan.mcpmysql.Main</mainClass></transformer></transformers></configuration></execution></executions></plugin></plugins></build>
</project>

Main.java

package com.codeyuan.mcpmysql;import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpSyncServer;
import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;/*** main主函数方法* @author codeyuan*/
public class Main {public static void main(String[] args) throws InterruptedException {// 1) 使用 STDIO 传输层启动服务器var transportProvider = new StdioServerTransportProvider(new ObjectMapper());// 2) 构建并启动同步 MCP Server,启用工具执行能力McpSyncServer server = McpServer.sync(transportProvider)// 配置一下  Server 信息.serverInfo("mysql-plugin", "1.0.0").capabilities(McpSchema.ServerCapabilities.builder()// 开启工具支持.tools(true).build())// build() 方法会立即启动服务器并监听输入:contentReference[oaicite:6]{index=6}.build();// 3) 注册自定义 MySQL 工具// addTool 可在运行时动态添加工具:contentReference[oaicite:7]{index=7}server.addTool(MysqlTool.specification());// 4) 在 JVM 退出时优雅关闭服务器// close() 用于关闭传输并释放资源:contentReference[oaicite:8]{index=8}Runtime.getRuntime().addShutdownHook(new Thread(server::close));// 5) 阻塞主线程,保持进程存活// join() 阻塞主线程,防止 JVM 退出:contentReference[oaicite:9]{index=9}Thread.currentThread().join();}
}

说明:基于文档示例,使用 McpServer.sync(...) 构建同步服务器,开启 tools 功能,并注册我们自定义的工具。

MysqlTool.java

package com.codeyuan.mcpmysql;import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.spec.McpSchema;import java.sql.*;
import java.util.*;/*** 执行连接操作mysql* 支持 SELECT 和非 SELECT 类型语句* @author codeyuan*/
public class MysqlTool {private static final ObjectMapper JSON = new ObjectMapper();// 定义工具规格:name、description、JSON 参数 schemapublic static McpServerFeatures.SyncToolSpecification specification() {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("mysql", "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/%s?useSSL=false&allowMultiQueries=true", host, db);try (Connection conn = DriverManager.getConnection(url, user, pass);Statement stmt = conn.createStatement()) {if (sql.toLowerCase().startsWith("select")) {try (ResultSet rs = stmt.executeQuery(sql)) {List<Map<String, Object>> rows = new ArrayList<>();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("rows", rows);return new McpSchema.CallToolResult(String.valueOf(result), false);}} else {int affected = stmt.executeUpdate(sql);Map<String, Object> result = Map.of("affectedRows", affected);return new McpSchema.CallToolResult(String.valueOf(result), false);}}} catch (Exception e) {// 错误时将异常信息返回return new McpSchema.CallToolResult(String.valueOf(Map.of("error", e.getMessage())), false);}});}
}

application.properties

(可用于默认值配置,示例中未使用;所有参数均从工具调用时传入或环境变量读取。)

# 可在此预置 host, user, password, database 等默认值

打包与发布

# 编译并打包为 fat-jar
mvn clean package
# 生成目标: target/mcp-mysql-plugin-1.0.0.jar

将生成的 JAR 上传或放置在可访问路径,然后在 Cursor 等 MCP 客户端中配置:

{"mcpServers": {"mysql": {"command": "java","args": ["-jar","/absolute/path/to/mcp-mysql-plugin-1.0.0.jar"],"env": {"MYSQL_HOST": "localhost","MYSQL_USER": "root","MYSQL_PASSWORD": "secret","MYSQL_DATABASE": "testdb"}}}
}

调用示例(在对话中):

{"tool": "mysql","arguments": {"host": "localhost","user": "root","password": "secret","database": "testdb","query": "SELECT * FROM users LIMIT 10"}
}

即可返回如下 JSON 结构:

{"rows": [{"id": 1,"name": "Alice","email": "alice@example.com"}]
}

获取直接使用自然语言对话

我是用的数据库版本是8.0,给我创建一个用户表,用户表可能存在,表中有姓名、年纪、性别、地址等字段,模拟插入10条数据

cursor-mysql-mcp-test-1.jpg

cursor-mysql-mcp-test-2.jpg

参考文档:

  1. https://modelcontextprotocol.io/sdk/java/mcp-server “MCP Server - Model Context Protocol”
  2. https://modelcontextprotocol.io/sdk/java/mcp-overview “Overview - Model Context Protocol”

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
下面关注回复【mysql-server-mcp-java-demo】
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

相关文章:

打造一个支持MySQL查询的MCP同步插件:Java实现

打造一个支持MySQL查询的MCP同步插件&#xff1a;Java实现 用Java实现一个MCP本地插件&#xff0c;直接通过JDBC操作本地MySQL&#xff0c;并通过STDIO与上层MCP客户端&#xff08;例如Cursor&#xff09;通信。插件注册一个名为mysql 的同步工具&#xff0c;接收连接参数及SQL…...

黑马k8s(十五)

1.Ingress介绍 2.Ingress使用 环境准备 Http代理 Https代理...

Axure项目实战:智慧运输平台后台管理端-订单管理1(多级交互)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:订单管理 主要内容:条件组合、中继器筛选、表单跟随菜单拖动、审批数据互通等 应用场景…...

解决 cursor 中不能进入 conda 虚拟环境

【问题】 遇到一个小问题&#xff0c;我创建的conda 环境在 cmd、powershell中都可以激活&#xff0c;但在pycharm、cursor中却不能激活&#xff1f; 看图 cmd中正常&#xff1a; cursor中不正常&#xff1a; 【解决方法】 cursor 中&#xff0c;打开终端&#xff0c;输入&a…...

微信小程序请求扣子(coze)api的例子

1. 准备工作 在开始之前&#xff0c;确保已经完成了以下准备工作&#xff1a; 创建并发布了 Coze 智能体。获取了个人访问令牌&#xff08;Personal Access Token&#xff09;&#xff0c;这是用于授权的关键凭证。确认目标智能体的 Bot ID 和其他必要参数已准备就绪。 2. 请…...

C++ 实现二叉树的后序遍历与中序遍历构建及层次遍历输出

C 实现二叉树的后序遍历与中序遍历构建及层次遍历输出 目录 C 实现二叉树的后序遍历与中序遍历构建及层次遍历输出一、实验背景与目标二、实验环境三、实验内容四、数据结构与算法数据结构算法描述1. **构建二叉树函数 buildTree**2. **层次遍历函数 LevelOrder** 关键代码与解…...

基于大模型的髋关节骨关节炎预测与治疗方案研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 1.3 研究方法与技术路线 二、髋关节骨关节炎概述 2.1 疾病定义与分类 2.2 发病机制与病理过程 2.3 流行病学特征 三、大模型技术原理与应用基础 3.1 大模型的基本概念与架构 3.2 大模型在医疗领域的应用进展…...

qiankun解决的问题

qiankun 中的沙箱机制是如何实现的&#xff1f;解决了什么问题&#xff1f; 一、实现方式 qiankun 的沙箱机制主要用于隔离微应用之间的运行环境&#xff0c;避免相互影响。其核心实现基于两种策略&#xff1a; 快照沙箱&#xff08;SnapshotSandbox&#xff09; 适用于不支…...

JavaScript从入门到精通(一)

引言 JavaScript 是一种跨平台、面向对象的脚本语言&#xff0c;最初是为了给网页添加交互性而创建的。如今&#xff0c;JavaScript 不仅是浏览器端开发的核心技术&#xff0c;也广泛应用于服务器端&#xff08;如 Node.js&#xff09;、移动应用开发等多个领域。本教程旨在提…...

快速失败(fail-fast)和安全失败(fail-safe)的区别

在 Java 中&#xff0c;‌快速失败&#xff08;Fail-Fast&#xff09;‌和‌安全失败&#xff08;Fail-Safe&#xff09;‌是集合类&#xff08;Collection&#xff09;在迭代过程中处理并发修改的两种不同策略&#xff0c;二者的核心区别在于 ‌对并发修改的感知机制与容错性‌…...

虚拟环境中的PyQt5 Pycharm设置参考

假如虚拟环境名是p3939 里面安装了pyqt5相关的库 1.QtDesigner Qt Designer 是通过拖拽的方式放置控件&#xff0c;并实时查看控件效果进行快速UI设计 位置 内容 name 可以随便命名&#xff0c;只要便于记忆就可以&#xff0c;本次采取通用…...

AI 笔记 - 模型优化 - 注意力机制在目标检测上的使用

人脸检测添加注意力机制 简介人脸检测的核心挑战与注意力机制的作用人脸检测中的注意力机制作用 选型参考基础选择&#xff08;空间注意力 vs 通道注意力&#xff09;空间注意力&#xff08;关注“哪里”重要&#xff09;通道注意力&#xff08;关注“什么特征”重要&#xff0…...

AUTOSAR图解==>AUTOSAR_SRS_LIN

AUTOSAR LIN模块分析 目录 LIN模块概述LIN模块架构LIN通信状态流程LIN通信序列LIN配置结构总结1. LIN模块概述 本文档基于AUTOSAR规范SRS_LIN文档,对LIN(Local Interconnect Network)相关模块进行详细分析。主要包括以下几个模块: LIN接口 (LinIf)LIN驱动 (Lin)LIN传输层…...

UML 时序图 使用案例

UML 时序图 UML 时序图 (Sequence Diagram)时序图的主要元素消息类型详解时序图示例时序图绘制步骤时序图的应用场景 UML 时序图 (Sequence Diagram) 时序图是UML(统一建模语言)中用于展示对象之间交互行为的动态视图&#xff0c;它特别强调消息的时间顺序。 时序图的主要元素…...

华为昇腾使用ollama本地部署DeepSeek大模型

文章目录 前言一、本次使用的硬件资源二、Ollama介绍三、Ollama在arm64位的芯片的安装及使用方法总结 前言 本次打算在华为昇腾上面使用ollama进行部署DeepSeek大模型。 一、本次使用的硬件资源 存储资源 内存资源 cpu资源 二、Ollama介绍 Ollama 是一个开源的大型语言…...

多态的总结

什么是多态&#xff1f; 答&#xff1a;多态是多种形态&#xff0c;是为了完成某种行为时&#xff0c;不同对象会产生不同的形态&#xff08;结合车票例子解释&#xff09; 2. 什么是重载、重写(覆盖)、重定义(隐藏)&#xff1f; 答&#xff1a;重载的条件是&#xff1a;在同一…...

Windows 高分辨率屏幕适配指南:解决界面过小、模糊错位问题

&#x1f5a5;️ Windows 高分辨率屏幕适配指南&#xff1a;解决界面过小、模糊错位问题 摘要&#xff1a; 在使用高分辨率屏幕时&#xff0c;许多老旧的桌面软件会出现界面显示异常的问题&#xff0c;例如窗口过小、控件错位、文字模糊等。本文提供一套通用解决方案&#xff0…...

tvalid寄存器的理解

if(!out_axis_tvalid_reg || m_axis_tready ) beginend m_axis_tready 是上拍下一级给的ready信号 out_axis_tvalid_reg是上一拍&#xff0c;本级给下级的valid信号 一共有四种组合&#xff0c;然后可以通过这个if语句&#xff0c;在接下来的begin ... end中&#xff0c;用来…...

C++八股 —— 手撕定时器

文章目录 1. 什么是定时器2. 需要考虑的问题吧3. 接口设计4. 完整代码5. 性能优化 来自&#xff1a;腾讯百度C二面&#xff1a;手撕定时器_哔哩哔哩_bilibili 腾讯、网易、百度C&#xff1a; 手撕定时器 相关概念参考&#xff1a; C八股——函数对象、Lambda、bind、functi…...

K8S-statefulset-mysql-ha

需求 实现一个HA mysql&#xff0c;包括1个master&#xff0c;2个slave。在K8S上已statefulset部署。 mysql HA原理 略 K8S环境需要解决的问题 1、由于使用同一个statefulset配置&#xff0c;因此需要考虑master和slave使用不同的cnf文件。 2、不同pod之间文件的传输 3、…...

【方案分享】展厅智能讲解:基于BLE蓝牙Beacon的自动讲解触发技术实现

【方案分享】展厅智能讲解&#xff1a;基于BLE蓝牙Beacon的自动讲解触发技术实现 让观众靠近展品即可自动弹出讲解页面&#xff0c;是智能展厅的核心功能之一。本文将从软硬件技术、BLE Beacon原理、微信小程序实现、优劣对比与拓展方案五个维度&#xff0c;系统讲解“靠近展台…...

web常见的攻击方式有哪些?如何防御?

Web常见攻击方式及防御策略 SQL注入 (SQL Injection) 详细解析: SQL 注入是一种利用应用程序未正确验证用户输入的漏洞&#xff0c;通过向应用传递恶意 SQL 查询来操纵数据库的行为。这种攻击可能导致敏感数据泄露、篡改或删除。 步骤: 攻击者找到可接受动态参数的应用程序…...

力扣:《螺旋矩阵》系列题目

今天做了一下螺旋矩阵主题的一系列题目 即力扣中的相似题目 还是有所感悟的 接下来一一回顾&#xff1a; 第一题&#xff1a; 59. 螺旋矩阵 II - 力扣&#xff08;LeetCode&#xff09; 这题让我们生成一个正方形的矩阵&#xff0c;注意是正方形&#xff0c;不是长方形&a…...

发电厂进阶,modbus TCP转ethernet ip网关如何赋能能源行业

案例分享&#xff1a;稳联技术modbus TCP转ethernet ip网关wl-abc004赋能&#xff0c;发电厂自动化改造&#xff0c;推动能源行业智能化升级 随着全球能源结构转型和“双碳”目标的推进&#xff0c;传统发电厂&#xff08;如火电、水电、生物质发电&#xff09;正面临严峻挑战&…...

深入了解linux系统—— 操作系统的路径缓冲与链接机制

前言 在之前学习当中&#xff0c;我们了解了被打开的文件是如何管理的&#xff1b;磁盘&#xff0c;以及ext2文件系统是如何存储文件的。 那我们要打开一个文件&#xff0c;首先要先找到这个文件&#xff0c;操作系统又是如何去查找的呢&#xff1f; 理解操作系统搜索文件 …...

Ansible快速入门指南

Ansible 是一款基于 Python 开发的开源自动化运维工具&#xff0c;主要用于实现服务器配置管理、应用部署、任务自动化执行等功能。它通过 简单的 YAML 脚本&#xff08;Playbook&#xff09; 定义任务&#xff0c;结合 SSH 协议 对远程主机进行管理&#xff0c;无需在被控节点…...

华为2025年校招笔试真题手撕教程(一)

一、题目 输入&#xff1a; 第一行为记录的版本迭代关系个数N&#xff0c;范围是[1&#xff0c;100000]; 第二行到第N1行&#xff1a;每行包含两个字符串&#xff0c;第一个字符串为当前版本&#xff0c;第二个字符串为前序版本&#xff0c;用空格隔开。字符串包含字符个数为…...

第9.2讲、Tiny Decoder(带 Mask)详解与实战

自己搭建一个 Tiny Decoder&#xff08;带 Mask&#xff09;&#xff0c;参考 Transformer Encoder 的结构&#xff0c;并添加 Masked Multi-Head Self-Attention&#xff0c;它是 Decoder 的核心特征之一。 1. 背景与动机 Transformer 架构已成为自然语言处理&#xff08;NLP…...

postgresql 常用参数配置

#01 - Connection-Authentication 优化点&#xff1a; listen_addresses 0.0.0.0 建议&#xff1a;生产环境应限制为具体IP&#xff08;如 192.168.1.0/24,127.0.0.1&#xff09;&#xff0c;避免暴露到公网。 ssl off 建议&#xff1a;启用SSL&#xff08;ssl on&#xf…...

Python模块中的私有命名与命名空间管理:深入解析与实践指南

文章大纲 引言 在Python开发中,模块是代码组织和复用的重要方式,而私有命名和命名空间管理则是确保代码清晰和避免冲突的关键机制。私有命名通过特定的命名约定限制了模块中某些内容的访问,有效保护了内部实现细节;命名空间管理则帮助开发者理解标识符的作用域和查找规则…...