Files
MyGoNavi/internal/mcpserver/backend.go
Syngnat 6c53fb14a6 feat(ai-mcp): 补全跨表字段探针并拆分 MCP 设置区块
- 新增 get_all_columns 内置工具和 MCP server 只读探针
- MCP 服务表单增加实际启动命令预览并补强参数提示
- 抽离 AISettingsMCPSection 并补齐前后端测试
2026-06-08 07:29:52 +08:00

119 lines
4.5 KiB
Go

package mcpserver
import (
"context"
"GoNavi-Wails/internal/ai"
aiservice "GoNavi-Wails/internal/ai/service"
appcore "GoNavi-Wails/internal/app"
"GoNavi-Wails/internal/appdata"
"GoNavi-Wails/internal/connection"
"GoNavi-Wails/internal/logger"
)
// Backend 抽象 GoNavi 后端能力,便于复用真实 App 和单元测试替身。
type Backend interface {
Close(context.Context) error
GetSavedConnections() ([]connection.SavedConnectionView, error)
GetEditableSavedConnection(id string) (connection.SavedConnectionView, error)
DBGetDatabases(config connection.ConnectionConfig) connection.QueryResult
DBGetTables(config connection.ConnectionConfig, dbName string) connection.QueryResult
DBGetAllColumns(config connection.ConnectionConfig, dbName string) connection.QueryResult
DBGetColumns(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult
DBGetIndexes(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult
DBGetForeignKeys(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult
DBGetTriggers(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult
DBShowCreateTable(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult
DBQueryMulti(config connection.ConnectionConfig, dbName string, query string, queryID string) connection.QueryResult
InspectSQL(dbType string, sql string) appcore.SQLInspection
GetSQLSafetyLevel() ai.SQLPermissionLevel
}
// AppBackend 基于现有 internal/app.App 暴露 MCP 所需数据库能力。
type AppBackend struct {
app *appcore.App
}
func NewAppBackend(ctx context.Context) *AppBackend {
if ctx == nil {
ctx = context.Background()
}
a := appcore.NewApp()
appcore.InitializeLifecycle(a, ctx)
return &AppBackend{app: a}
}
func (b *AppBackend) Close(ctx context.Context) error {
if b == nil || b.app == nil {
return nil
}
if ctx == nil {
ctx = context.Background()
}
b.app.Shutdown(ctx)
return nil
}
func (b *AppBackend) GetSavedConnections() ([]connection.SavedConnectionView, error) {
return b.app.GetSavedConnections()
}
func (b *AppBackend) GetEditableSavedConnection(id string) (connection.SavedConnectionView, error) {
return b.app.GetEditableSavedConnection(id)
}
func (b *AppBackend) DBGetDatabases(config connection.ConnectionConfig) connection.QueryResult {
return b.app.DBGetDatabases(config)
}
func (b *AppBackend) DBGetTables(config connection.ConnectionConfig, dbName string) connection.QueryResult {
return b.app.DBGetTables(config, dbName)
}
func (b *AppBackend) DBGetAllColumns(config connection.ConnectionConfig, dbName string) connection.QueryResult {
return b.app.DBGetAllColumns(config, dbName)
}
func (b *AppBackend) DBGetColumns(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
return b.app.DBGetColumns(config, dbName, tableName)
}
func (b *AppBackend) DBGetIndexes(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
return b.app.DBGetIndexes(config, dbName, tableName)
}
func (b *AppBackend) DBGetForeignKeys(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
return b.app.DBGetForeignKeys(config, dbName, tableName)
}
func (b *AppBackend) DBGetTriggers(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
return b.app.DBGetTriggers(config, dbName, tableName)
}
func (b *AppBackend) DBShowCreateTable(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
return b.app.DBShowCreateTable(config, dbName, tableName)
}
func (b *AppBackend) DBQueryMulti(config connection.ConnectionConfig, dbName string, query string, queryID string) connection.QueryResult {
return b.app.DBQueryMulti(config, dbName, query, queryID)
}
func (b *AppBackend) InspectSQL(dbType string, sql string) appcore.SQLInspection {
return appcore.InspectSQL(dbType, sql)
}
func (b *AppBackend) GetSQLSafetyLevel() ai.SQLPermissionLevel {
inspection, err := aiservice.NewProviderConfigStore(appdata.MustResolveActiveRoot(), nil).Inspect()
if err != nil {
logger.Error(err, "加载 MCP SQL 安全控制失败,按只读模式回退")
return ai.PermissionReadOnly
}
switch inspection.Snapshot.SafetyLevel {
case ai.PermissionReadOnly, ai.PermissionReadWrite, ai.PermissionFull:
return inspection.Snapshot.SafetyLevel
default:
return ai.PermissionReadOnly
}
}