# Directory Structure
```
├── .gitignore
├── img
│ ├── 1.png
│ ├── 2.png
│ └── 3.png
├── pom.xml
├── README.md
└── src
└── main
├── java
│ └── cn
│ └── bigcoder
│ └── mcp
│ └── excel
│ └── mcpexcelserver
│ ├── dto
│ │ ├── BaseResponse.java
│ │ ├── ExcelReadRequest.java
│ │ ├── ExcelReadResponse.java
│ │ ├── ExcelWriteRequest.java
│ │ └── ExcelWriteResponse.java
│ ├── McpExcelServerApplication.java
│ └── servive
│ ├── ExcelReadService.java
│ └── ExcelWriteService.java
└── resources
├── application.yml
└── log4j2.xml
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/ExcelReadRequest.java:
--------------------------------------------------------------------------------
```java
package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
import lombok.Data;
import org.springframework.ai.tool.annotation.ToolParam;
/**
* @author: bigcoder84
* @date: 2025-04-12
**/
@Data
public class ExcelReadRequest {
@ToolParam(description = "文件绝对路径")
private String filePath;
}
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/ExcelReadResponse.java:
--------------------------------------------------------------------------------
```java
package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
import java.util.List;
import java.util.Map;
import lombok.Builder;
import lombok.Data;
/**
* @author: bigcoder84
* @date: 2025-04-12
**/
@Builder
@Data
public class ExcelReadResponse {
private List<Map<String, String>> dataList;
}
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/ExcelWriteResponse.java:
--------------------------------------------------------------------------------
```java
package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
import lombok.Builder;
import lombok.Data;
import org.springframework.ai.tool.annotation.ToolParam;
/**
* @author: bigcoder84
* @date: 2025-04-12
**/
@Builder
@Data
public class ExcelWriteResponse {
@ToolParam(description = "文件绝对路径")
private String filePath;
}
```
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
```yaml
#server:
# port: 8090
spring:
application:
name: mcp-excel-server
main:
web-application-type: none
banner-mode: off
# 默认 dev 环境
# profiles:
# active: dev
ai:
mcp:
server:
stdio: true # 启用stdio模式
name: mcp-server
version: 0.0.1
type: SYNC
logging:
config: classpath:log4j2.xml
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/BaseResponse.java:
--------------------------------------------------------------------------------
```java
package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
import lombok.Data;
/**
* @author: bigcoder84
* @date: 2025-04-12
**/
@Data
public class BaseResponse<T> {
private boolean success;
private String message;
private T data;
private BaseResponse(boolean success, String message, T data) {
this.success = success;
this.message = message;
this.data = data;
}
public static <T> BaseResponse<T> success(T data) {
return new BaseResponse<>(true, null, data);
}
public static <T> BaseResponse<T> failed(String message) {
return new BaseResponse<>(false, message, null);
}
}
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/McpExcelServerApplication.java:
--------------------------------------------------------------------------------
```java
package cn.bigcoder.mcp.excel.mcpexcelserver;
import cn.bigcoder.mcp.excel.mcpexcelserver.servive.ExcelReadService;
import cn.bigcoder.mcp.excel.mcpexcelserver.servive.ExcelWriteService;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class McpExcelServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpExcelServerApplication.class, args);
}
@Bean
public ToolCallbackProvider serverTools(ExcelWriteService excelWriteService,
ExcelReadService excelReadService) {
return MethodToolCallbackProvider
.builder()
.toolObjects(excelWriteService, excelReadService)
.build();
}
}
```
--------------------------------------------------------------------------------
/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
```
<?xml version="1.0" encoding="UTF-8" ?>
<configuration status="warn" monitorInterval="5">
<properties>
<property name="LOG_HOME" value="logs"/>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] [%-5level] %c{36}:%L --- %m%n"/>
</Console>
<File name="File" fileName="${LOG_HOME}/file-log4j2.log">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %m%n"/>
</File>
<RandomAccessFile name="AccessFile" fileName="${LOG_HOME}/info.log"
immediateFlush="true">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %m%n"/>
</RandomAccessFile>
<RollingFile name="RollingFile" fileName="${LOG_HOME}/log4j2.log"
filePattern="logs/log4j2.%d{yyyy-MM-dd-HH-mm}.%i.log">
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %msg%n"/>
<Policies>
<OnStartupTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="10 KB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
<AppenderRef ref="AccessFile"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</configuration>
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/servive/ExcelReadService.java:
--------------------------------------------------------------------------------
```java
package cn.bigcoder.mcp.excel.mcpexcelserver.servive;
import cn.bigcoder.mcp.excel.mcpexcelserver.dto.BaseResponse;
import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelReadRequest;
import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelReadResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;
/**
* @author bigcoder84
* @Description
* @date 2025-03-26 11:35
*/
@Slf4j
@Service
public class ExcelReadService {
/**
* 根据搜索词搜索面试鸭面试题目
*
* @return 返回解析的JSON数据
*/
@Tool(description = "用于读取本地excel中的内容,传入文件路径,返回JSON格式的数据")
public BaseResponse<ExcelReadResponse> readExcel(ExcelReadRequest request) {
log.info("开始读取Excel文件: {}", request);
String filePath = request.getFilePath();
try (FileInputStream fis = new FileInputStream(filePath)) {
Workbook workbook;
if (filePath.toLowerCase().endsWith(".xlsx")) {
workbook = new XSSFWorkbook(fis);
} else if (filePath.toLowerCase().endsWith(".xls")) {
workbook = new HSSFWorkbook(fis);
} else {
throw new IllegalArgumentException("不支持的文件格式,仅支持.xlsx或.xls格式");
}
List<Map<String, String>> result = new ArrayList<>();
Sheet sheet = workbook.getSheetAt(0);
Row headerRow = sheet.getRow(0);
int columnCount = headerRow.getLastCellNum();
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) {
continue;
}
Map<String, String> rowData = new HashMap<>();
for (int j = 0; j < columnCount; j++) {
Cell headerCell = headerRow.getCell(j);
Cell cell = row.getCell(j);
String header = headerCell != null ? headerCell.toString() : "Column" + j;
String value = cell != null ? cell.toString() : "";
rowData.put(header, value);
}
result.add(rowData);
}
workbook.close();
log.info("Excel文件读取完成,共处理{}行数据", result.size());
return BaseResponse.success(ExcelReadResponse.builder().dataList(result).build());
} catch (IOException e) {
log.error("读取Excel文件失败: {}", e.getMessage(), e);
return BaseResponse.failed("读取Excel文件失败,error:" + e.getMessage());
}
}
}
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/servive/ExcelWriteService.java:
--------------------------------------------------------------------------------
```java
package cn.bigcoder.mcp.excel.mcpexcelserver.servive;
import cn.bigcoder.mcp.excel.mcpexcelserver.dto.BaseResponse;
import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelWriteRequest;
import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelWriteResponse;
import java.io.FileOutputStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* @author bigcoder84
* @Description
* @date 2025-03-26 11:35
*/
@Slf4j
@Service
public class ExcelWriteService {
/**
* 将JSON数据写入Excel文件
*/
@Tool(description = "用于将JSON数据写入Excel文件,")
public BaseResponse<ExcelWriteResponse> writeToExcel(ExcelWriteRequest request) {
log.info("开始写入Excel文件: {}", request);
if (request.getDataList() == null || request.getDataList().isEmpty()) {
log.warn("没有数据需要写入Excel");
return BaseResponse.failed("没有数据需要写入的数据");
}
try (Workbook workbook = new XSSFWorkbook()) {
Sheet sheet = workbook.createSheet("Sheet1");
// 创建标题行样式
CellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerStyle.setAlignment(HorizontalAlignment.CENTER);
//先设置表中的编码
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerStyle.setFont(headerFont);
// 创建表头
List<String> headers = request.getHeaders();
Row headerRow = sheet.createRow(0);
int colNum = 0;
for (String header : headers) {
Cell cell = headerRow.createCell(colNum++);
cell.setCellValue(header);
cell.setCellStyle(headerStyle);
//先设置表中的编码
}
// 写入数据
int rowNum = 1;
for (Map<String, String> rowData : request.getDataList()) {
Row row = sheet.createRow(rowNum++);
colNum = 0;
for (String header : headers) {
Cell cell = row.createCell(colNum++);
Object value = rowData.get(header);
if (value != null) {
cell.setCellValue(value.toString());
}
}
}
// 自动调整列宽
for (int i = 0; i < headers.size(); i++) {
sheet.autoSizeColumn(i);
}
// 设置 JVM 默认字符编码
System.setProperty("file.encoding", "UTF-8");
// 保存文件
try (FileOutputStream fileOut = new FileOutputStream(request.getFilePath())) {
workbook.write(fileOut);
}
return BaseResponse.success(ExcelWriteResponse.builder().filePath(request.getFilePath()).build());
} catch (Exception e) {
log.error("写入Excel文件失败: {}", e.getMessage(), e);
return BaseResponse.failed("导出失败,error:" + e.getMessage());
}
}
}
```
--------------------------------------------------------------------------------
/pom.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>
<groupId>cn.bigcoder.grpc.demo.mcpexcel</groupId>
<artifactId>mcp-excel-server</artifactId>
<version>0.0.1</version>
<name>mcp-excel-server</name>
<description>mcp-excel-server</description>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.2.5</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- Apache POI for Excel processing -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.43</version>
</dependency>
<!-- 使用 log4j2 的适配器进行绑定 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.19.0</version>
</dependency>
<!-- log4j2 日志门面 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.19.0</version>
</dependency>
<!-- log4j2 日志实面 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
```