#
tokens: 4027/50000 11/11 files
lines: off (toggle) GitHub
raw markdown copy
# 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>

```