Codestyle Server MCP 是一个基于 Spring AI 实现的 Model Context Protocol (MCP) 服务器,为 IDE 和 AI 代理提供代码模板搜索和检索工具。该服务从本地缓存查找模板,并在缺失时自动从远程仓库下载元数据和文件进行修复。
- 原生 MCP 工具:
CodestyleService通过spring-ai-starter-mcp-server注册codestyleSearch和getTemplateByPath工具,STDIO 客户端(Cherry Studio、Cursor 等)可直接调用 - Lucene 本地全文检索:集成 Apache Lucene ,支持中文分词(SmartChineseAnalyzer),离线环境下也能高效检索模板
- 双模式检索:支持本地 Lucene 检索(默认)和远程 API 检索两种模式,通过配置一键切换
- 增量更新机制:通过 SHA256 哈希值比对判断模板是否需要更新,避免重复下载
- 自修复模板缓存:本地未找到模板时自动触发远程下载,支持按需获取
- 精确路径定位:从请求路径解析
groupId/artifactId,直接定位meta.json - 提示词模板化:
PromptService使用content-result.txt和search-result.txt渲染响应,确保变量和文件内容遵循统一布局 - 多版本共存:采用
groupId/artifactId/version/Maven 风格目录结构,支持同一模板的多版本管理
- Java 17, Maven 3.9+
- Spring Boot 3.2.5
- Spring AI MCP Server 1.1.0
- Apache Lucene 9.12.3(本地全文检索引擎,支持中文分词)
- Hutool 5.8.42(HTTP、文件、JSON、ZIP 工具)
┌───────────────────────────────────────────────────────────────────┐
│ MCP 客户端 (Cursor/Cherry Studio) │
└───────────────────────────────────────────────────────────────────┘
│
│ STDIO
▼
┌───────────────────────────────────────────────────────────────────┐
│ CodestyleService (@McpTool) │
│ ├── codestyleSearch(keyword) → 目录树 + 模板组介绍 │
│ └── getTemplateByPath(path) → 变量说明 + 模板内容 │
└───────────────────────────────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌───────────────────────────────┐ ┌───────────────────────────────┐
│ LuceneIndexService │ │ TemplateService │
│ ├── rebuildIndex() │ │ ├── searchLocalRepository() │
│ ├── updateIndex() │ │ ├── searchByPath() │
│ └── fetchLocalMetaConfig() │ │ ├── fetchRemoteMetaConfig() │
└───────────────────────────────┘ │ └── smartDownloadTemplate() │
│ └───────────────────────────────┘
│ │
▼ ▼
┌───────────────────────────────┐ ┌───────────────────────────────┐
│ Lucene 索引 │ │ SDKUtils (核心工具层) │
│ (lucene-index/) │ │ ├── searchLocalRepository() │
│ ├── 中文分词 (SmartCN) │ │ ├── searchByPath() │
│ └── 全文检索 │ │ ├── fetchRemoteMetaConfig() │
└───────────────────────────────┘ │ ├── smartDownloadTemplate() │
│ └── downloadAndExtract...() │
└───────────────────────────────┘
│
▼
┌───────────────────────────────────┐
│ 本地缓存 (codestyle-cache/) │
│ └── {groupId}/{artifactId}/ │
│ ├── meta.json │
│ └── {version}/... │
└───────────────────────────────────┘
mcp-codestyle-server
├── pom.xml
├── src/main
│ ├── java/top/codestyle/mcp
│ │ ├── McpServerApplication.java # 应用入口
│ │ ├── config
│ │ │ └── RepositoryConfig.java # 仓库路径配置(支持远程检索开关)
│ │ ├── model
│ │ │ ├── meta/ # 本地缓存模型
│ │ │ │ ├── LocalMetaConfig.java # 本地 meta.json 结构(多版本)
│ │ │ │ ├── LocalMetaInfo.java # 本地模板元信息
│ │ │ │ └── LocalMetaVariable.java # 本地变量(预留扩展)
│ │ │ ├── sdk/ # SDK 模型
│ │ │ │ ├── MetaInfo.java # 通用模板元信息
│ │ │ │ ├── MetaVariable.java # 模板变量
│ │ │ │ └── RemoteMetaConfig.java # 远程 API 响应结构(单版本)
│ │ │ └── tree/ # 目录树模型
│ │ │ ├── Node.java # 节点接口
│ │ │ └── TreeNode.java # 树节点实现
│ │ ├── service
│ │ │ ├── CodestyleService.java # MCP 工具实现(@McpTool)
│ │ │ ├── LuceneIndexService.java # Lucene 本地索引服务(全文检索)
│ │ │ ├── TemplateService.java # 模板业务编排
│ │ │ └── PromptService.java # 提示词模板加载(懒加载)
│ │ └── util
│ │ ├── SDKUtils.java # 核心工具(搜索/下载/SHA256)
│ │ ├── MetaInfoConvertUtil.java # 元信息转换
│ │ └── PromptUtils.java # 目录树和变量格式化
│ └── resources
│ ├── application.yml # 配置文件
│ ├── content-result.txt # 模板内容提示词模板
│ └── search-result.txt # 搜索结果提示词模板
└── examples/ # 示例模板
└── continew/ # ContiNew 框架模板组
├── CRUD/ # 增删改查模板
│ ├── meta.json # 模板元数据
│ └── 1.0.0/ # 版本目录
│ ├── README.md # 模板说明文档
│ ├── backend/ # 后端模板
│ └── frontend/ # 前端模板
└── Logo/ # Logo 模板组
└── 1.0.0/
核心配置位于 src/main/resources/application.yml,可通过 JVM 系统属性覆盖。
spring:
application:
name: mcp-codestyle-server
main:
web-application-type: none # 关闭Web服务器
banner-mode: off # 关闭启动横幅
ai:
mcp:
server:
name: mcp-codestyle-server # MCP服务器名称
version: 1.0.0 # 版本号
type: SYNC # 服务器类型: SYNC(同步) 或 ASYNC(异步)
stdio: true # 启用STDIO模式
annotation-scanner:
enabled: true # 启用注解扫描
repository:
local-path: /var/cache/codestyle # 本地基础路径
remote-path: http://localhost # 远程仓库地址(需配置)
dir: # 可选,不配置则使用local-path/codestyle-cache
remote-search-enabled: false # 是否启用远程检索(默认false,使用本地Lucene检索)repository.local-path:本地缓存基础目录(可通过-Dcache.base-path覆盖)repository.dir:具体缓存文件夹,默认为<local-path>/codestyle-cacherepository.remote-path:远程仓库基础 URL(仅在启用远程检索时需要配置)repository.remote-search-enabled:检索模式开关false(默认):使用本地 Lucene 全文检索,无需网络连接true:使用远程 API 检索,需配置远程仓库地址
远程服务提供以下两个接口:
-
获取模板元数据
GET {remoteBaseUrl}/api/mcp/search?templateKeyword=CRUD返回
RemoteMetaConfigJSON 格式:{ "groupId": "backend", "artifactId": "CRUD", "description": "完整的CRUD操作模板", "config": { "version": "1.0.0", "files": [ { "filePath": "/src/main/java/com/air/controller", "filename": "Controller.ftl", "description": "控制器模板", "sha256": "abc123...", "inputVariables": [ { "variableName": "className", "variableType": "String", "variableComment": "类名", "example": "UserController" } ] } ] } } -
下载模板 ZIP
GET {remoteBaseUrl}/api/file/load?paths=/groupId/artifactId返回包含模板文件的 ZIP 压缩包,解压后目录结构应为:
src/ main/ java/ com/ air/ controller/ Controller.ftl
- JDK 17+
- Maven 3.9+(或使用项目自带的
mvnw/mvnw.cmd)
git clone https://github.com/itxaiohanglover/mcp-codestyle-server.git
cd mcp-codestyle-server
./mvnw clean package -DskipTests编辑 src/main/resources/application.yml,将 repository.remote-path 修改为实际的远程服务器地址:
repository:
remote-path: http://your-server.com # 替换为实际地址# Windows
java ^
-Dspring.ai.mcp.server.stdio=true ^
-Dspring.main.web-application-type=none ^
-Dlogging.pattern.console= ^
-Dcache.base-path=C:/mcp-cache ^
-Dfile.encoding=UTF-8 ^
-Drepository.remote-path=http://your-server.com ^
-jar target/mcp-codestyle-server-1.0.2.jar
# Linux/macOS
java \
-Dspring.ai.mcp.server.stdio=true \
-Dspring.main.web-application-type=none \
-Dlogging.pattern.console= \
-Dcache.base-path=/mcp-cache \
-Dfile.encoding=UTF-8 \
-Drepository.remote-path=http://your-server.com \
-jar target/mcp-codestyle-server-1.0.2.jar在设置 -> MCP Servers 中添加:
{
"mcpServers": {
"codestyleServer": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dspring.main.web-application-type=none",
"-Dlogging.pattern.console=",
"-Dfile.encoding=UTF-8"
"-jar",
"C:/path/to/mcp-codestyle-server/target/mcp-codestyle-server-0.0.1.jar"
],
"env": {}
}
}
}
注意实际 jar 路径和参数配置一致
添加成功
通过配置按钮可以查看到两个工具已注册

在 ~/.cursor/mcp_settings.json 中添加:
{
"mcpServers": {
"codestyleServer": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dspring.main.web-application-type=none",
"-Dlogging.pattern.console=",
"-Dfile.encoding=UTF-8",
"-jar",
"/path/to/mcp-codestyle-server/target/mcp-codestyle-server-0.0.1.jar"
]
}
}
}参数:
templateKeyword(String): 模板关键词- 示例:
CRUD、backend、frontend
- 示例:
响应示例:
找到模板组: CRUD
目录树:
backend/
CRUD/
1.0.0/
src/
main/
java/
com/
air/
controller/
└── Controller.ftl
service/
└── Service.ftl
模板组介绍:
完整的CRUD操作模板,包含控制器、服务层、数据访问层等
执行流程:
# 本地Lucene检索模式(默认)
1. luceneIndexService.fetchLocalMetaConfig(keyword) → 本地全文检索
2. searchLocalRepository(groupId, artifactId) → 从本地 meta.json 读取文件列表
3. PromptUtils.buildTree(metaInfos) → 构建目录树结构
4. promptService.buildSearchResult() → 格式化输出
# 远程检索模式(remote-search-enabled=true)
1. fetchRemoteMetaConfig(keyword) → 调用远程 API 获取模板配置
2. smartDownloadTemplate(config) → SHA256 比对,按需下载
3. searchLocalRepository(groupId, artifactId) → 从本地 meta.json 读取文件列表
4. PromptUtils.buildTree(metaInfos) → 构建目录树结构
5. promptService.buildSearchResult() → 格式化输出
参数:
templatePath(String): 完整模板路径- 格式:
groupId/artifactId/version/filePath/filename - 示例:
backend/CRUD/1.0.0/src/main/java/com/air/controller/Controller.ftl
- 格式:
响应示例:
#文件名:backend/CRUD/1.0.0/src/main/java/com/air/controller/Controller.ftl
#文件变量:
- className: 类名(示例:UserController)[String]
- packageName: 包名(示例:com.air.controller)[String]
#文件内容:
package ${packageName};
public class ${className} {
// CRUD方法
}
执行流程:
1. searchByPath(path) → 从路径解析 groupId/artifactId,直接定位 meta.json
2. 如未找到 → fetchRemoteMetaConfig() + smartDownloadTemplate() → 自动修复
3. readTemplateContent() → 读取模板文件内容
4. promptService.buildPrompt() → 格式化输出(变量 + 内容)
codestyle-cache/
├── lucene-index/ # Lucene 全文索引目录
│ ├── _1.cfe
│ ├── _1.cfs
│ ├── _1.si
│ └── segments_2
└── continew/ # groupId
└── CRUD/ # artifactId
├── meta.json # 元数据配置
├── preview.png # 预览图(可选)
└── 1.0.0/ # version
├── README.md # 模板说明文档
├── backend/ # 后端模板
│ ├── sql/
│ └── src/
└── frontend/ # 前端模板
└── src/
{
"groupId": "backend",
"artifactId": "CRUD",
"configs": [
{
"version": "1.0.0",
"files": [
{
"filePath": "/src/main/java/com/air/controller",
"filename": "Controller.ftl",
"description": "控制器模板",
"sha256": "abc123...",
"inputVariables": [
{
"variableName": "className",
"variableType": "String",
"variableComment": "类名",
"example": "UserController"
}
]
}
]
}
]
}特点:
- 支持多版本共存(
configs数组) - SHA256 校验保证文件完整性
- 精确的文件路径和变量描述
#文件名:%{s}
#文件变量:
%{s}
#文件内容:
%{s}
- 3 个占位符:文件名、变量列表、模板内容
找到模板组: %{s}
目录树:
%{s}
模板组介绍:
%{s}
- 3 个占位符:groupId/artifactId、目录树、描述
可编辑这些文件以适配不同 MCP 客户端的响应风格。
v1.0.2 版本引入了 Apache Lucene 全文检索引擎,实现离线模板检索能力:
┌─────────────────────────────────────────────────────────────┐
│ LuceneIndexService │
├─────────────────────────────────────────────────────────────┤
│ 初始化流程 (@PostConstruct) │
│ 1. 创建 lucene-index 目录 │
│ 2. 初始化 SmartChineseAnalyzer (中文分词器) │
│ 3. 扫描本地仓库所有 meta.json │
│ 4. 为每个模板建立索引文档 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 索引文档结构 │
│ ├── groupId (StringField) → 精确匹配 │
│ ├── artifactId (StringField) → 精确匹配 │
│ ├── metaPath (StringField) → meta.json 路径 │
│ ├── description (TextField) → 全文检索 (README.md内容) │
│ └── content (TextField) → 组合检索字段 │
└─────────────────────────────────────────────────────────────┘
索引特性:
| 特性 | 说明 |
|---|---|
| 中文分词 | 使用 SmartChineseAnalyzer,支持中文关键词检索 |
| 自动重建 | 启动时自动扫描并重建索引 |
| 增量更新 | 下载新模板后自动更新对应索引 |
| 离线检索 | 无需网络连接,本地即可完成模板搜索 |
用户搜索模板 (codestyleSearch)
│
▼
┌───────────────────────┐
│ 1. 获取远程配置 │ fetchRemoteMetaConfig(keyword)
│ (远程API返回) │ → 返回 groupId, artifactId, version, 文件列表+SHA256
└───────────────────────┘
│
▼
┌───────────────────────┐
│ 2. 智能下载判断 │ smartDownloadTemplate(remoteConfig)
└───────────────────────┘
│
▼
本地 meta.json 存在?
│
┌────┴────┐
│ 否 │ 是
▼ ▼
需要下载 ┌─────────────────────┐
│ 3. 检查是否需要更新 │ checkIfNeedsUpdate()
└─────────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
版本不存在? 文件不存在? SHA256变化?
│ │ │
└─────┬─────┴───────────┘
▼
需要更新?
┌────┴────┐
│ 否 │ 是
▼ ▼
跳过 ┌─────────────────────┐
│ 4. 下载并解压 │ downloadAndExtractTemplate()
│ - 备份本地meta │
│ - 请求远程ZIP │
│ - 解压到本地仓库 │
│ - 合并更新meta │
└─────────────────────┘
| 条件 | 触发更新 |
|---|---|
| 本地 meta.json 不存在 | ✅ |
| 远程版本在本地不存在 | ✅ |
| 远程文件在本地不存在 | ✅ |
| 文件 SHA256 不一致 | ✅ |
| 所有文件 SHA256 一致 | ❌ 跳过下载 |
下载新版本时会保留本地已有版本:
场景:本地已有 v0.9.0,远程推送了 v1.0.0
1. 备份本地 meta.json(包含 v0.9.0 配置)
2. 下载并解压远程 ZIP
3. 删除远程带来的 meta.json(只含单版本)
4. 从备份恢复,追加 v1.0.0 配置
5. 最终 meta.json 包含:v0.9.0 + v1.0.0
mvn test或运行 CodestyleServiceTest.main() 方法:
// 通过 STDIO 启动 JAR 并调用 MCP 工具
CodestyleServiceTest.main(new String[]{});- 在远程仓库添加新的模板 ZIP 和对应的 JSON 配置
- 确保
meta.json中的sha256与实际文件哈希一致 - 运行测试验证端到端流程
- 查看日志:移除
-Dlogging.pattern.console=参数 - 检查缓存:查看
repository.dir配置的目录 - 验证远程接口:使用
curl或 Postman 测试远程 API
A: 删除 repository.dir 配置的目录,下次运行时会自动重新下载。
A: 为每个用户配置不同的 cache.base-path,或在 groupId 前添加用户标识。
A: 系统会继续使用本地缓存,并返回友好的错误提示。
A: 本地 meta.json 使用 configs 数组支持多版本共存,而远程返回的是单版本的 config 对象。下载时会自动转换并合并。
A: 删除对应模板目录(如 codestyle-cache/continew/CRUD/),系统会重新下载完整模板。
A: 在 application.yml 中设置 repository.remote-search-enabled:
false(默认):本地 Lucene 检索,启动快、无需网络true:远程 API 检索,始终获取最新模板信息
A: 删除 codestyle-cache/lucene-index/ 目录,重启服务后会自动重建索引。
基于 MIT License 发布。
- artboy (itxaiohanglover)
- Kanttha
- movclantian
- v1.0 (2025-12-03)
- 集成 Apache Lucene 全文检索引擎
- 支持 SmartChineseAnalyzer 中文分词
- 实现离线模板检索,无需网络连接
- 启动时自动扫描本地仓库并建立索引
- 默认使用本地 Lucene 检索(false)
- 可切换为远程 API 检索模式(true)
- 拉取远程模板后自动更新 Lucene 索引
- 保证本地索引与模板文件同步
- 初始版本
- 支持
codestyleSearch和getTemplateByPath工具 - Maven 风格目录结构
- SHA256 增量更新机制
- 自动修复机制(本地缺失时触发下载)
- 多版本共存支持
- 精确路径定位优化
