摘要:本文主要介绍用spring-ai开发一个ssh的mcp工具,公司研发人员可以用这个mcp处理服务器的问题和自动化更新。
实操代码
pom.xml
xml
<?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 https://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.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>sp3-mcp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sp3-mcp</name>
<description>sp3-mcp</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>21</java.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.1.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
SshToolService
less
@Service
public class SshToolService {
@McpTool(description = "执行MySQL查询语句(SELECT)")
public String executeSshCommand(
@McpToolParam(description = "远程服务器 IP") String host,
@McpToolParam(description = "SSH 端口,通常是 22") Integer port,
@McpToolParam(description = "用户名") String username,
@McpToolParam(description = "登录密码") String password,
@McpToolParam(description = "要执行的命令") String command) {
Session session = null;
ChannelExec channel = null;
try {
JSch jsch = new JSch();
// 1. 获取 Session
session = jsch.getSession(username, host, port != null ? port : 22);
// 2. 设置密码 (关键修改点)
session.setPassword(password);
// 3. 关闭 HostKey 检查 (避免 UnknownHostKey 异常,避免交互式确认)
session.setConfig("StrictHostKeyChecking", "no");
// 可选:设置超时时间 (毫秒)
session.connect(10000);
// 4. 打开执行通道
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
channel.setInputStream(null);
// 5. 获取输入流(读取命令结果)和错误流
InputStream in = channel.getInputStream();
InputStream err = channel.getErrStream();
channel.connect();
// 6. 读取输出数据
StringBuilder outputBuffer = new StringBuilder();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) break;
outputBuffer.append(new String(tmp, 0, i, StandardCharsets.UTF_8));
}
// 同时也读取错误流,防止缓冲区满导致挂起
while (err.available() > 0) {
int i = err.read(tmp, 0, 1024);
if (i < 0) break;
outputBuffer.append("STDERR: ").append(new String(tmp, 0, i, StandardCharsets.UTF_8));
}
if (channel.isClosed()) {
if (in.available() > 0) continue;
break;
}
try { Thread.sleep(100); } catch (Exception ee) {}
}
return outputBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return "SSH 连接或执行失败: " + e.getMessage();
} finally {
if (channel != null) channel.disconnect();
if (session != null) session.disconnect();
}
}
}
application.properties
ini
# spring.main.web-application-type=none
# NOTE: You must disable the banner and the console logging
# to allow the STDIO transport to work !!!
spring.main.banner-mode=off
# logging.pattern.console=
# spring.ai.mcp.server.stdio=false
spring.ai.mcp.server.name=mcp-weather-server
spring.ai.mcp.server.request-timeout=1h
spring.ai.mcp.server.protocol=sse
logging.file.name=./mcp-weather-server/target/server.log
客户端配置
mcp_config.json
json
{
"mcpServers": {
"天气服务": {
"disabledTools": [],
"serverUrl": "http://localhost:8080/sse"
}
}
}