From ffe1844ba6b90da1483287664f1d85f7d231d811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?piexlMax=28=E5=A5=87=E6=B7=BC?= Date: Tue, 28 Oct 2025 17:47:29 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix(mcp):=20=E9=80=92=E5=BD=92=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E5=8C=85=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=AD=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=AD=98=E5=9C=A8.go=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/mcp/gva_analyze.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/server/mcp/gva_analyze.go b/server/mcp/gva_analyze.go index e48409bfe..3611b5430 100644 --- a/server/mcp/gva_analyze.go +++ b/server/mcp/gva_analyze.go @@ -282,20 +282,38 @@ func (g *GVAAnalyzer) isPackageFolderEmpty(packageName, template string) (bool, } else if err != nil { return false, err // 其他错误 } + // 递归检查是否有.go文件 + return g.hasGoFilesRecursive(basePath) +} - // 读取文件夹内容 - entries, err := os.ReadDir(basePath) +// hasGoFilesRecursive 递归检查目录及其子目录中是否有.go文件 +func (g *GVAAnalyzer) hasGoFilesRecursive(dirPath string) (bool, error) { + entries, err := os.ReadDir(dirPath) if err != nil { - return false, err + return true, err // 读取失败,返回空 } - // 检查是否有.go文件 + // 检查当前目录下的.go文件 for _, entry := range entries { if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".go") { return false, nil // 找到.go文件,不为空 } } + // 递归检查子目录 + for _, entry := range entries { + if entry.IsDir() { + subDirPath := filepath.Join(dirPath, entry.Name()) + isEmpty, err := g.hasGoFilesRecursive(subDirPath) + if err != nil { + continue // 忽略子目录的错误,继续检查其他目录 + } + if !isEmpty { + return false, nil // 子目录中找到.go文件,不为空 + } + } + } + return true, nil // 没有找到.go文件,为空 } From 89ea284cc64cd629e3895856476991e00c318014 Mon Sep 17 00:00:00 2001 From: frank515 Date: Thu, 30 Oct 2025 21:46:10 +0800 Subject: [PATCH 2/4] =?UTF-8?q?doc:=20=E7=BF=BB=E8=AF=91=E4=BA=86README-en?= =?UTF-8?q?.md=20=E4=B8=AD=E7=9A=84=E4=B8=AD=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-en.md b/README-en.md index 3c5a8178a..0ba961c3d 100644 --- a/README-en.md +++ b/README-en.md @@ -148,7 +148,7 @@ go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct cd server go generate -run "go env -w .*?" -# 使用如下命令下载swag +# Use the following command to download swag go get -u github.com/swaggo/swag/cmd/swag ```` From ca0a1250cdba35cb3370fb782027abac351f0233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?piexlMax=28=E5=A5=87=E6=B7=BC?= Date: Thu, 6 Nov 2025 17:25:36 +0800 Subject: [PATCH 3/4] =?UTF-8?q?refactor(mcp):=20=E4=BF=AE=E6=94=B9execute?= =?UTF-8?q?=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/mcp/gva_execute.go | 144 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 5 deletions(-) diff --git a/server/mcp/gva_execute.go b/server/mcp/gva_execute.go index 62377b850..6443f62a8 100644 --- a/server/mcp/gva_execute.go +++ b/server/mcp/gva_execute.go @@ -57,7 +57,7 @@ type ExecutionPlan struct { // New 创建GVA代码生成执行器工具 func (g *GVAExecutor) New() mcp.Tool { - return mcp.NewTool("gva_execute", + return mcp.NewTool("gva_execute", mcp.WithDescription(`**GVA代码生成执行器:直接执行代码生成,无需确认步骤** **核心功能:** @@ -194,10 +194,144 @@ func (g *GVAExecutor) New() mcp.Tool { - 当字段配置了dataSource且association=2(一对多关联)时,系统会自动将fieldType修改为'array' - 这确保了一对多关联数据的正确存储和处理 - 修正操作会记录在日志中,便于开发者了解变更情况`), - mcp.WithObject("executionPlan", - mcp.Description("执行计划,包含包信息和模块信息"), - mcp.Required(), - ), + mcp.WithObject("executionPlan", + mcp.Description("执行计划,包含包信息、模块与字典信息"), + mcp.Required(), + mcp.Properties(map[string]interface{}{ + "packageName": map[string]interface{}{ + "type": "string", + "description": "包名(小写开头)", + }, + "packageType": map[string]interface{}{ + "type": "string", + "description": "package 或 plugin", + "enum": []string{"package", "plugin"}, + }, + "needCreatedPackage": map[string]interface{}{ + "type": "boolean", + "description": "是否需要创建包", + }, + "needCreatedModules": map[string]interface{}{ + "type": "boolean", + "description": "是否需要创建模块", + }, + "needCreatedDictionaries": map[string]interface{}{ + "type": "boolean", + "description": "是否需要创建字典", + }, + "packageInfo": map[string]interface{}{ + "type": "object", + "description": "包创建信息", + "properties": map[string]interface{}{ + "desc": map[string]interface{}{"type": "string", "description": "包描述"}, + "label": map[string]interface{}{"type": "string", "description": "展示名"}, + "template": map[string]interface{}{"type": "string", "description": "package 或 plugin", "enum": []string{"package", "plugin"}}, + "packageName": map[string]interface{}{"type": "string", "description": "包名"}, + }, + }, + "modulesInfo": map[string]interface{}{ + "type": "array", + "description": "模块配置列表", + "items": map[string]interface{}{ + "type": "object", + "properties": map[string]interface{}{ + "package": map[string]interface{}{"type": "string", "description": "包名(小写开头)"}, + "tableName": map[string]interface{}{"type": "string", "description": "数据库表名(蛇形命名)"}, + "businessDB": map[string]interface{}{"type": "string", "description": "业务数据库(可留空表示默认)"}, + "structName": map[string]interface{}{"type": "string", "description": "结构体名(大驼峰)"}, + "packageName": map[string]interface{}{"type": "string", "description": "文件名称"}, + "description": map[string]interface{}{"type": "string", "description": "中文描述"}, + "abbreviation": map[string]interface{}{"type": "string", "description": "简称"}, + "humpPackageName": map[string]interface{}{"type": "string", "description": "文件名称(小驼峰)"}, + "gvaModel": map[string]interface{}{"type": "boolean", "description": "是否使用GVA模型(固定为true)"}, + "autoMigrate": map[string]interface{}{"type": "boolean"}, + "autoCreateResource": map[string]interface{}{"type": "boolean"}, + "autoCreateApiToSql": map[string]interface{}{"type": "boolean"}, + "autoCreateMenuToSql": map[string]interface{}{"type": "boolean"}, + "autoCreateBtnAuth": map[string]interface{}{"type": "boolean"}, + "onlyTemplate": map[string]interface{}{"type": "boolean"}, + "isTree": map[string]interface{}{"type": "boolean"}, + "treeJson": map[string]interface{}{"type": "string"}, + "isAdd": map[string]interface{}{"type": "boolean"}, + "generateWeb": map[string]interface{}{"type": "boolean"}, + "generateServer": map[string]interface{}{"type": "boolean"}, + "fields": map[string]interface{}{ + "type": "array", + "items": map[string]interface{}{ + "type": "object", + "properties": map[string]interface{}{ + "fieldName": map[string]interface{}{"type": "string"}, + "fieldDesc": map[string]interface{}{"type": "string"}, + "fieldType": map[string]interface{}{"type": "string"}, + "fieldJson": map[string]interface{}{"type": "string"}, + "dataTypeLong": map[string]interface{}{"type": "string"}, + "comment": map[string]interface{}{"type": "string"}, + "columnName": map[string]interface{}{"type": "string"}, + "fieldSearchType": map[string]interface{}{"type": "string"}, + "fieldSearchHide": map[string]interface{}{"type": "boolean"}, + "dictType": map[string]interface{}{"type": "string"}, + "form": map[string]interface{}{"type": "boolean"}, + "table": map[string]interface{}{"type": "boolean"}, + "desc": map[string]interface{}{"type": "boolean"}, + "excel": map[string]interface{}{"type": "boolean"}, + "require": map[string]interface{}{"type": "boolean"}, + "defaultValue": map[string]interface{}{"type": "string"}, + "errorText": map[string]interface{}{"type": "string"}, + "clearable": map[string]interface{}{"type": "boolean"}, + "sort": map[string]interface{}{"type": "boolean"}, + "primaryKey": map[string]interface{}{"type": "boolean"}, + "dataSource": map[string]interface{}{ + "type": "object", + "properties": map[string]interface{}{ + "dbName": map[string]interface{}{"type": "string"}, + "table": map[string]interface{}{"type": "string"}, + "label": map[string]interface{}{"type": "string"}, + "value": map[string]interface{}{"type": "string"}, + "association": map[string]interface{}{"type": "integer"}, + "hasDeletedAt": map[string]interface{}{"type": "boolean"}, + }, + }, + "checkDataSource": map[string]interface{}{"type": "boolean"}, + "fieldIndexType": map[string]interface{}{"type": "string"}, + }, + }, + }, + }, + }, + }, + "paths": map[string]interface{}{ + "type": "object", + "description": "生成的文件路径映射", + "additionalProperties": map[string]interface{}{"type": "string"}, + }, + "dictionariesInfo": map[string]interface{}{ + "type": "array", + "description": "字典创建信息", + "items": map[string]interface{}{ + "type": "object", + "properties": map[string]interface{}{ + "dictType": map[string]interface{}{"type": "string"}, + "dictName": map[string]interface{}{"type": "string"}, + "description": map[string]interface{}{"type": "string"}, + "status": map[string]interface{}{"type": "boolean"}, + "fieldDesc": map[string]interface{}{"type": "string"}, + "options": map[string]interface{}{ + "type": "array", + "items": map[string]interface{}{ + "type": "object", + "properties": map[string]interface{}{ + "label": map[string]interface{}{"type": "string"}, + "value": map[string]interface{}{"type": "string"}, + "sort": map[string]interface{}{"type": "integer"}, + }, + }, + }, + }, + }, + }, + }), + mcp.AdditionalProperties(false), + ), mcp.WithString("requirement", mcp.Description("原始需求描述(可选,用于日志记录)"), ), From 057ad2eeebed0f6dda56e9f3f57e2091fbf02a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?piexlMax=28=E5=A5=87=E6=B7=BC?= Date: Thu, 6 Nov 2025 17:43:09 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E5=8D=A0=E4=BD=8D?= =?UTF-8?q?=E7=AC=A6=E5=AD=97=E6=AE=B5=E9=98=B2=E6=AD=A2json=20schema?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/mcp/api_lister.go | 3 +++ server/mcp/menu_lister.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/server/mcp/api_lister.go b/server/mcp/api_lister.go index d8a87d1f1..ba0a8e169 100644 --- a/server/mcp/api_lister.go +++ b/server/mcp/api_lister.go @@ -52,6 +52,9 @@ func (a *ApiLister) New() mcp.Tool { **返回数据结构:** - databaseApis: 数据库中的API记录(包含ID、描述、分组等完整信息) - ginApis: gin路由中的API(仅包含路径和方法),需要AI根据路径自行揣摩路径的业务含义,例如:/api/user/:id 表示根据用户ID获取用户信息`), + mcp.WithString("_placeholder", + mcp.Description("占位符,防止json schema校验失败"), + ), ) } diff --git a/server/mcp/menu_lister.go b/server/mcp/menu_lister.go index c04c83e92..825ad237c 100644 --- a/server/mcp/menu_lister.go +++ b/server/mcp/menu_lister.go @@ -46,6 +46,9 @@ func (m *MenuLister) New() mcp.Tool { - 菜单权限管理:了解系统中所有可用的菜单项 - 导航组件开发:构建动态导航菜单 - 系统架构分析:了解系统的菜单结构和页面组织`), +mcp.WithString("_placeholder", + mcp.Description("占位符,防止json schema校验失败"), + ), ) }