# 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:
--------------------------------------------------------------------------------
```
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/ExcelReadRequest.java:
--------------------------------------------------------------------------------
```java
1 | package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
2 |
3 | import lombok.Data;
4 | import org.springframework.ai.tool.annotation.ToolParam;
5 |
6 | /**
7 | * @author: bigcoder84
8 | * @date: 2025-04-12
9 | **/
10 | @Data
11 | public class ExcelReadRequest {
12 |
13 | @ToolParam(description = "文件绝对路径")
14 | private String filePath;
15 | }
16 |
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/ExcelReadResponse.java:
--------------------------------------------------------------------------------
```java
1 | package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | import lombok.Builder;
6 | import lombok.Data;
7 |
8 | /**
9 | * @author: bigcoder84
10 | * @date: 2025-04-12
11 | **/
12 | @Builder
13 | @Data
14 | public class ExcelReadResponse {
15 |
16 | private List<Map<String, String>> dataList;
17 | }
18 |
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/ExcelWriteResponse.java:
--------------------------------------------------------------------------------
```java
1 | package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
2 |
3 | import lombok.Builder;
4 | import lombok.Data;
5 | import org.springframework.ai.tool.annotation.ToolParam;
6 |
7 | /**
8 | * @author: bigcoder84
9 | * @date: 2025-04-12
10 | **/
11 | @Builder
12 | @Data
13 | public class ExcelWriteResponse {
14 |
15 | @ToolParam(description = "文件绝对路径")
16 | private String filePath;
17 | }
18 |
```
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
```yaml
1 |
2 | #server:
3 | # port: 8090
4 | spring:
5 | application:
6 | name: mcp-excel-server
7 | main:
8 | web-application-type: none
9 | banner-mode: off
10 |
11 | # 默认 dev 环境
12 | # profiles:
13 | # active: dev
14 | ai:
15 | mcp:
16 | server:
17 | stdio: true # 启用stdio模式
18 | name: mcp-server
19 | version: 0.0.1
20 | type: SYNC
21 | logging:
22 | config: classpath:log4j2.xml
23 |
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/dto/BaseResponse.java:
--------------------------------------------------------------------------------
```java
1 | package cn.bigcoder.mcp.excel.mcpexcelserver.dto;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @author: bigcoder84
7 | * @date: 2025-04-12
8 | **/
9 | @Data
10 | public class BaseResponse<T> {
11 |
12 | private boolean success;
13 | private String message;
14 | private T data;
15 |
16 | private BaseResponse(boolean success, String message, T data) {
17 | this.success = success;
18 | this.message = message;
19 | this.data = data;
20 | }
21 |
22 | public static <T> BaseResponse<T> success(T data) {
23 | return new BaseResponse<>(true, null, data);
24 | }
25 |
26 | public static <T> BaseResponse<T> failed(String message) {
27 | return new BaseResponse<>(false, message, null);
28 | }
29 | }
30 |
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/McpExcelServerApplication.java:
--------------------------------------------------------------------------------
```java
1 | package cn.bigcoder.mcp.excel.mcpexcelserver;
2 |
3 | import cn.bigcoder.mcp.excel.mcpexcelserver.servive.ExcelReadService;
4 | import cn.bigcoder.mcp.excel.mcpexcelserver.servive.ExcelWriteService;
5 | import org.springframework.ai.tool.ToolCallbackProvider;
6 | import org.springframework.ai.tool.method.MethodToolCallbackProvider;
7 | import org.springframework.boot.SpringApplication;
8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
9 | import org.springframework.context.annotation.Bean;
10 |
11 | @SpringBootApplication
12 | public class McpExcelServerApplication {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(McpExcelServerApplication.class, args);
16 | }
17 |
18 | @Bean
19 | public ToolCallbackProvider serverTools(ExcelWriteService excelWriteService,
20 | ExcelReadService excelReadService) {
21 | return MethodToolCallbackProvider
22 | .builder()
23 | .toolObjects(excelWriteService, excelReadService)
24 | .build();
25 | }
26 | }
27 |
```
--------------------------------------------------------------------------------
/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
```
1 | <?xml version="1.0" encoding="UTF-8" ?>
2 | <configuration status="warn" monitorInterval="5">
3 | <properties>
4 | <property name="LOG_HOME" value="logs"/>
5 | </properties>
6 | <Appenders>
7 | <Console name="Console" target="SYSTEM_OUT">
8 | <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] [%-5level] %c{36}:%L --- %m%n"/>
9 | </Console>
10 | <File name="File" fileName="${LOG_HOME}/file-log4j2.log">
11 | <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %m%n"/>
12 | </File>
13 | <RandomAccessFile name="AccessFile" fileName="${LOG_HOME}/info.log"
14 | immediateFlush="true">
15 | <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %m%n"/>
16 | </RandomAccessFile>
17 | <RollingFile name="RollingFile" fileName="${LOG_HOME}/log4j2.log"
18 | filePattern="logs/log4j2.%d{yyyy-MM-dd-HH-mm}.%i.log">
19 | <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
20 | <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %msg%n"/>
21 | <Policies>
22 | <OnStartupTriggeringPolicy/>
23 | <SizeBasedTriggeringPolicy size="10 KB"/>
24 | <TimeBasedTriggeringPolicy/>
25 | </Policies>
26 | <DefaultRolloverStrategy max="30"/>
27 | </RollingFile>
28 | </Appenders>
29 | <Loggers>
30 | <Root level="INFO">
31 | <AppenderRef ref="Console"/>
32 | <AppenderRef ref="File"/>
33 | <AppenderRef ref="AccessFile"/>
34 | <AppenderRef ref="RollingFile"/>
35 | </Root>
36 | </Loggers>
37 | </configuration>
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/servive/ExcelReadService.java:
--------------------------------------------------------------------------------
```java
1 | package cn.bigcoder.mcp.excel.mcpexcelserver.servive;
2 |
3 | import cn.bigcoder.mcp.excel.mcpexcelserver.dto.BaseResponse;
4 | import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelReadRequest;
5 | import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelReadResponse;
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import lombok.extern.slf4j.Slf4j;
13 | import org.apache.poi.hssf.usermodel.HSSFWorkbook;
14 | import org.apache.poi.ss.usermodel.Cell;
15 | import org.apache.poi.ss.usermodel.Row;
16 | import org.apache.poi.ss.usermodel.Sheet;
17 | import org.apache.poi.ss.usermodel.Workbook;
18 | import org.apache.poi.xssf.usermodel.XSSFWorkbook;
19 | import org.springframework.ai.tool.annotation.Tool;
20 | import org.springframework.stereotype.Service;
21 |
22 | /**
23 | * @author bigcoder84
24 | * @Description
25 | * @date 2025-03-26 11:35
26 | */
27 | @Slf4j
28 | @Service
29 | public class ExcelReadService {
30 |
31 |
32 | /**
33 | * 根据搜索词搜索面试鸭面试题目
34 | *
35 | * @return 返回解析的JSON数据
36 | */
37 | @Tool(description = "用于读取本地excel中的内容,传入文件路径,返回JSON格式的数据")
38 | public BaseResponse<ExcelReadResponse> readExcel(ExcelReadRequest request) {
39 | log.info("开始读取Excel文件: {}", request);
40 | String filePath = request.getFilePath();
41 | try (FileInputStream fis = new FileInputStream(filePath)) {
42 | Workbook workbook;
43 | if (filePath.toLowerCase().endsWith(".xlsx")) {
44 | workbook = new XSSFWorkbook(fis);
45 | } else if (filePath.toLowerCase().endsWith(".xls")) {
46 | workbook = new HSSFWorkbook(fis);
47 | } else {
48 | throw new IllegalArgumentException("不支持的文件格式,仅支持.xlsx或.xls格式");
49 | }
50 |
51 | List<Map<String, String>> result = new ArrayList<>();
52 | Sheet sheet = workbook.getSheetAt(0);
53 | Row headerRow = sheet.getRow(0);
54 | int columnCount = headerRow.getLastCellNum();
55 |
56 | for (int i = 1; i <= sheet.getLastRowNum(); i++) {
57 | Row row = sheet.getRow(i);
58 | if (row == null) {
59 | continue;
60 | }
61 |
62 | Map<String, String> rowData = new HashMap<>();
63 | for (int j = 0; j < columnCount; j++) {
64 | Cell headerCell = headerRow.getCell(j);
65 | Cell cell = row.getCell(j);
66 | String header = headerCell != null ? headerCell.toString() : "Column" + j;
67 | String value = cell != null ? cell.toString() : "";
68 | rowData.put(header, value);
69 | }
70 | result.add(rowData);
71 | }
72 |
73 | workbook.close();
74 | log.info("Excel文件读取完成,共处理{}行数据", result.size());
75 | return BaseResponse.success(ExcelReadResponse.builder().dataList(result).build());
76 | } catch (IOException e) {
77 | log.error("读取Excel文件失败: {}", e.getMessage(), e);
78 | return BaseResponse.failed("读取Excel文件失败,error:" + e.getMessage());
79 | }
80 | }
81 | }
```
--------------------------------------------------------------------------------
/src/main/java/cn/bigcoder/mcp/excel/mcpexcelserver/servive/ExcelWriteService.java:
--------------------------------------------------------------------------------
```java
1 | package cn.bigcoder.mcp.excel.mcpexcelserver.servive;
2 |
3 | import cn.bigcoder.mcp.excel.mcpexcelserver.dto.BaseResponse;
4 | import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelWriteRequest;
5 | import cn.bigcoder.mcp.excel.mcpexcelserver.dto.ExcelWriteResponse;
6 | import java.io.FileOutputStream;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.apache.poi.ss.usermodel.*;
9 | import org.apache.poi.xssf.usermodel.XSSFWorkbook;
10 | import org.springframework.ai.tool.annotation.Tool;
11 | import org.springframework.stereotype.Service;
12 |
13 | import java.util.List;
14 | import java.util.Map;
15 |
16 | /**
17 | * @author bigcoder84
18 | * @Description
19 | * @date 2025-03-26 11:35
20 | */
21 | @Slf4j
22 | @Service
23 | public class ExcelWriteService {
24 |
25 | /**
26 | * 将JSON数据写入Excel文件
27 | */
28 | @Tool(description = "用于将JSON数据写入Excel文件,")
29 | public BaseResponse<ExcelWriteResponse> writeToExcel(ExcelWriteRequest request) {
30 | log.info("开始写入Excel文件: {}", request);
31 | if (request.getDataList() == null || request.getDataList().isEmpty()) {
32 | log.warn("没有数据需要写入Excel");
33 | return BaseResponse.failed("没有数据需要写入的数据");
34 | }
35 |
36 | try (Workbook workbook = new XSSFWorkbook()) {
37 | Sheet sheet = workbook.createSheet("Sheet1");
38 |
39 | // 创建标题行样式
40 | CellStyle headerStyle = workbook.createCellStyle();
41 | headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
42 | headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
43 | headerStyle.setAlignment(HorizontalAlignment.CENTER);
44 | //先设置表中的编码
45 | Font headerFont = workbook.createFont();
46 | headerFont.setBold(true);
47 | headerStyle.setFont(headerFont);
48 |
49 | // 创建表头
50 | List<String> headers = request.getHeaders();
51 | Row headerRow = sheet.createRow(0);
52 | int colNum = 0;
53 | for (String header : headers) {
54 | Cell cell = headerRow.createCell(colNum++);
55 | cell.setCellValue(header);
56 | cell.setCellStyle(headerStyle);
57 | //先设置表中的编码
58 | }
59 |
60 | // 写入数据
61 | int rowNum = 1;
62 | for (Map<String, String> rowData : request.getDataList()) {
63 | Row row = sheet.createRow(rowNum++);
64 | colNum = 0;
65 | for (String header : headers) {
66 | Cell cell = row.createCell(colNum++);
67 | Object value = rowData.get(header);
68 | if (value != null) {
69 | cell.setCellValue(value.toString());
70 | }
71 | }
72 | }
73 |
74 | // 自动调整列宽
75 | for (int i = 0; i < headers.size(); i++) {
76 | sheet.autoSizeColumn(i);
77 | }
78 |
79 | // 设置 JVM 默认字符编码
80 | System.setProperty("file.encoding", "UTF-8");
81 | // 保存文件
82 | try (FileOutputStream fileOut = new FileOutputStream(request.getFilePath())) {
83 | workbook.write(fileOut);
84 | }
85 | return BaseResponse.success(ExcelWriteResponse.builder().filePath(request.getFilePath()).build());
86 | } catch (Exception e) {
87 | log.error("写入Excel文件失败: {}", e.getMessage(), e);
88 | return BaseResponse.failed("导出失败,error:" + e.getMessage());
89 | }
90 | }
91 | }
```
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <project xmlns="http://maven.apache.org/POM/4.0.0"
3 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5 | <modelVersion>4.0.0</modelVersion>
6 | <groupId>cn.bigcoder.grpc.demo.mcpexcel</groupId>
7 | <artifactId>mcp-excel-server</artifactId>
8 | <version>0.0.1</version>
9 | <name>mcp-excel-server</name>
10 | <description>mcp-excel-server</description>
11 | <properties>
12 | <java.version>11</java.version>
13 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
14 | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
15 | <spring-boot.version>3.2.5</spring-boot.version>
16 | </properties>
17 | <dependencies>
18 | <dependency>
19 | <groupId>org.springframework.boot</groupId>
20 | <artifactId>spring-boot-starter</artifactId>
21 | </dependency>
22 |
23 | <dependency>
24 | <groupId>org.springframework.boot</groupId>
25 | <artifactId>spring-boot-starter-test</artifactId>
26 | <scope>test</scope>
27 | </dependency>
28 | <dependency>
29 | <groupId>org.springframework.ai</groupId>
30 | <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
31 | <version>1.0.0-M6</version>
32 | </dependency>
33 | <dependency>
34 | <groupId>org.projectlombok</groupId>
35 | <artifactId>lombok</artifactId>
36 | <scope>provided</scope>
37 | </dependency>
38 | <!-- Apache POI for Excel processing -->
39 | <dependency>
40 | <groupId>org.apache.poi</groupId>
41 | <artifactId>poi</artifactId>
42 | <version>5.2.3</version>
43 | </dependency>
44 | <dependency>
45 | <groupId>org.apache.poi</groupId>
46 | <artifactId>poi-ooxml</artifactId>
47 | <version>5.2.3</version>
48 | </dependency>
49 | <dependency>
50 | <groupId>com.alibaba.fastjson2</groupId>
51 | <artifactId>fastjson2</artifactId>
52 | <version>2.0.43</version>
53 | </dependency>
54 | <!-- 使用 log4j2 的适配器进行绑定 -->
55 | <dependency>
56 | <groupId>org.apache.logging.log4j</groupId>
57 | <artifactId>log4j-slf4j-impl</artifactId>
58 | <version>2.19.0</version>
59 | </dependency>
60 |
61 | <!-- log4j2 日志门面 -->
62 | <dependency>
63 | <groupId>org.apache.logging.log4j</groupId>
64 | <artifactId>log4j-api</artifactId>
65 | <version>2.19.0</version>
66 | </dependency>
67 |
68 | <!-- log4j2 日志实面 -->
69 | <dependency>
70 | <groupId>org.apache.logging.log4j</groupId>
71 | <artifactId>log4j-core</artifactId>
72 | <version>2.19.0</version>
73 | </dependency>
74 |
75 | </dependencies>
76 | <dependencyManagement>
77 | <dependencies>
78 | <dependency>
79 | <groupId>org.springframework.boot</groupId>
80 | <artifactId>spring-boot-dependencies</artifactId>
81 | <version>${spring-boot.version}</version>
82 | <type>pom</type>
83 | <scope>import</scope>
84 | </dependency>
85 | </dependencies>
86 | </dependencyManagement>
87 |
88 | <build>
89 | <plugins>
90 | <plugin>
91 | <groupId>org.springframework.boot</groupId>
92 | <artifactId>spring-boot-maven-plugin</artifactId>
93 | <executions>
94 | <execution>
95 | <goals>
96 | <goal>repackage</goal>
97 | </goals>
98 | </execution>
99 | </executions>
100 | </plugin>
101 | </plugins>
102 | </build>
103 |
104 | </project>
105 |
```