Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mcp添加Hologres #995

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions jcommon/mcp/mcp-hologres/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
使用Druid链接池连接Hologres数据库, 查询数据后给大模型可进行数据分析
```json
{
"mcpServers": {
"hologres_mcp":{
"command": "D:\\software\\jdk21\\bin\\java.exe",
"args": [
"-jar",
"-Dhologres.url=hgprecn-cn-5yd3l8m6l002-cn-beijing-vpc-st.hologres.aliyuncs.com:80/proretail_car_pre?currentSchema=proretail_car_pre_view&autoReconnect=true&rewriteBatchedStatements=true&characterEncoding=utf8",
"-Dhologres.userName=",
"-Dhologres.password=",
"D:\\workspace\\xiaomiMone\\jcommon\\mcp\\mcp-hologres\\target\\app.jar"
]
}
}
}
```

```properties
帮我查看一下2024年3月2号到3月4号那些省创建了门店

查询结果已完成。以下是2024年3月2日至4日创建门店的省份:
1. 福建省
2. 山西省
3. 河北省
```
86 changes: 86 additions & 0 deletions jcommon/mcp/mcp-hologres/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?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>run.mone</groupId>
<artifactId>mcp</artifactId>
<version>1.6.1-jdk21-SNAPSHOT</version>
</parent>

<groupId>run.mone.mcp</groupId>
<artifactId>mcp-hologres</artifactId>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<logback.version>1.5.12</logback.version>
</properties>

<dependencies>
<dependency>
<artifactId>druid</artifactId>
<groupId>com.alibaba</groupId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.25</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.42.0.0</version>
</dependency>
<dependency>
<groupId>com.blinkfox</groupId>
<artifactId>zealot</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>


<build>

<plugins>

<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<verbose>true</verbose>
<encoding>UTF-8</encoding>
<compilerArguments>
<sourcepath>${project.basedir}/src/main/java</sourcepath>
</compilerArguments>
</configuration>
</plugin>

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.14</version>
<configuration>
<mainClass>run.mone.mcp.hologres.HoloBootstrap</mainClass>
<finalName>app</finalName>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>


</plugins>

</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package run.mone.mcp.hologres;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages = {"run.mone.mcp.hologres"})
public class HoloBootstrap {
public static void main(String[] args) {
SpringApplication.run(HoloBootstrap.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package run.mone.mcp.hologres.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import run.mone.hive.mcp.server.transport.StdioServerTransport;

@Configuration
@ConditionalOnProperty(name = "stdio.enabled", havingValue = "true")
public class McpStdioTransportConfig {
/**
* stdio 通信
* @param mapper
* @return
*/
@Bean
StdioServerTransport stdioServerTransport(ObjectMapper mapper) {
return new StdioServerTransport(mapper);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package run.mone.mcp.hologres.function;

import com.blinkfox.zealot.bean.SqlInfo;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import run.mone.hive.mcp.spec.McpSchema;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.*;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

@Data
@Slf4j
public class HoloFunction implements Function<Map<String, Object>, McpSchema.CallToolResult> {

private String name = "hologres_executor";

private String desc = "Execute Hologres query operations";

private String sqlToolSchema = """
{
"type": "object",
"properties": {
"tableName": {
"type": "string",
"enum": ["dim_org"],
"description": "the name of execute table"
},
"startTime": {
"type": "string",
"description": "the start time of where condition"
},
"endTime": {
"type": "string",
"description": "the start time of where condition"
},
"count": {
"type": "Integer",
"description": "the number of query row"
}
},
"required": ["tableName", "startTime", "endTime"]
}
""";
private DataSource dataSource;


public HoloFunction(DataSource dataSource) {
this.dataSource = dataSource;
}

@SneakyThrows
@Override
public McpSchema.CallToolResult apply(Map<String, Object> args) {
String tableName = (String) args.get("tableName");
String startTime = (String) args.get("startTime");
Integer count = (Integer) args.get("count");
String endTime = (String) args.get("endTime");
if (tableName == null || tableName.trim().isEmpty()) {
log.error("没有指明表明");
throw new IllegalArgumentException("tableName is required");
}
log.info("tableName: {}, startTime: {}, endTime: {}", tableName, startTime, endTime);

// 获取连接
Connection conn = dataSource.getConnection();

try {
SqlInfo sql = SQLGenerator.generateSQLQuery(tableName, startTime, endTime, count);
log.info("sql : {}", sql);
return executeQuery(conn, sql);
} catch (Throwable ex) {
throw new RuntimeException(ex.getMessage());
}
}


private McpSchema.CallToolResult executeQuery(Connection conn, SqlInfo sqlInfo) throws SQLException {

// 创建 PreparedStatement 执行 SQL 语句
try (PreparedStatement ps = conn.prepareStatement(sqlInfo.getSql())) {
if (sqlInfo.getParams() != null && sqlInfo.getParams().size() > 0) {
for (int i = 0; i < sqlInfo.getParams().size(); i++) {
ps.setObject(i + 1, sqlInfo.getParams().get(i));
}

}

ResultSet rs = ps.executeQuery();

StringBuilder result = new StringBuilder();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();

// Add column names
for (int i = 1; i <= columnCount; i++) {
result.append(metaData.getColumnName(i)).append("\t");
}
result.append("\n");

// Add data rows
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
result.append(rs.getString(i)).append("\t");
}
result.append("\n");
}

log.info("Successfully executed query");
return new McpSchema.CallToolResult(
List.of(new McpSchema.TextContent(result.toString())),
false
);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package run.mone.mcp.hologres.function;

import com.blinkfox.zealot.bean.SqlInfo;
import com.blinkfox.zealot.core.ZealotKhala;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Data
@Slf4j
public class SQLGenerator {

/**
* 根据表名和时间生成 SQL 查询语句
* https://github.com/blinkfox/zealot
* @param tableName 表名
* @param startTime 开始时间(格式:yyyy-MM-dd HH:mm:ss)
* @param endTime 结束时间(格式:yyyy-MM-dd HH:mm:ss)
* @return 生成的 SQL 查询语句
*/
public static SqlInfo generateSQLQuery(String tableName, String startTime, String endTime, Integer count) {
// 验证时间格式
// 验证时间格式
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
// String startDate = LocalDate.parse(startTime).format(formatter);
// String endDate = LocalDate.parse(endTime).format(formatter);
int num = count == null ? 5 : count;
return ZealotKhala.start()
.select("*")
.from(tableName)
.where("1=1")
.andBetween("create_date", startTime, endTime)
.limit(String.valueOf(num))
.end();
}

public static void main(String[] args) {
generateSQLQuery("dig_org", "2019-01-01", "2019-01-01", null);
}

}
Loading