同步完整源码至远程:扁平化重构现状 + 未入库源文件
- 补入库:server/internal/db/dump.go、redis 分页/扫描预算测试、opsxdb-mcp main_test、 packages/opsxdb-mcp package-lock、docs 审计与对比文档等 37 个新文件 - 含结构扁平化进行中的 80 处修改与 155 处旧结构删除(server/ src/ src-tauri/ 为当前有效源) - 构建产物(bin/target/dist)与签名私钥仍按规则排除
This commit is contained in:
1 parent
5c0be49217
commit
2c0bfafd8d
269 files changed
+10372
-16435
No files matched your search
@@ -1,7 +1,7 @@
|
||||
// opsxdb-mcp:stdio MCP Server,暴露只读数据库工具(P0)。 // Logan.Li
|
||||
// opsxdb-mcp:stdio MCP Server,按本机策略暴露数据库工具。
|
||||
//
|
||||
// 配置:
|
||||
// ~/.opsxdb/mcp.json — allowed_connection_ids;mode(P0 执行层强制只读)
|
||||
// ~/.opsxdb/mcp.json — allowed_connection_ids;mode;每次工具调用重新读取
|
||||
// ~/.opsxdb/connections.json — 桌面双写的连接列表(密码 ox1. 混淆)
|
||||
// ~/.opsxdb/logs/mcp-audit.jsonl
|
||||
//
|
||||
@@ -21,13 +21,6 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
rt, err := aitools.DefaultRuntime()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "opsxdb-mcp: load policy: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
rt.Source = "mcp"
|
||||
|
||||
s := server.NewMCPServer(
|
||||
"opsxdb",
|
||||
"0.1.0",
|
||||
@@ -39,8 +32,7 @@ func main() {
|
||||
t := mcp.NewToolWithRawSchema(spec.Name, spec.Description, raw)
|
||||
toolName := spec.Name
|
||||
s.AddTool(t, func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
args := req.GetArguments()
|
||||
out, err := rt.Call(ctx, toolName, args)
|
||||
out, err := callTool(ctx, toolName, req.GetArguments(), aitools.DefaultRuntime)
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError(err.Error()), nil
|
||||
}
|
||||
@@ -53,3 +45,13 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// 每次调用使用新的策略快照;读取失败直接拒绝,不继续用上一次的权限。
|
||||
func callTool(ctx context.Context, tool string, args map[string]any, load func() (*aitools.Runtime, error)) (any, error) {
|
||||
rt, err := load()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load policy: %w", err)
|
||||
}
|
||||
rt.Source = "mcp"
|
||||
return rt.Call(ctx, tool, args)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"opsxdb/server/internal/aitools"
|
||||
)
|
||||
|
||||
func TestCallToolReloadsPolicyAndFailsClosed(t *testing.T) {
|
||||
policy := aitools.Policy{Mode: aitools.ModeReadOnly, AllowedConnectionIDs: []string{"c1"}}
|
||||
var loadErr error
|
||||
load := func() (*aitools.Runtime, error) {
|
||||
if loadErr != nil {
|
||||
return nil, loadErr
|
||||
}
|
||||
rt := aitools.NewRuntime(policy)
|
||||
rt.Audit = func(aitools.AuditEntry) {}
|
||||
rt.LoadConns = func() ([]aitools.SavedConnection, error) {
|
||||
return []aitools.SavedConnection{{ID: "c1"}, {ID: "c2"}}, nil
|
||||
}
|
||||
return rt, nil
|
||||
}
|
||||
list := func() ([]aitools.ConnectionSummary, error) {
|
||||
out, err := callTool(context.Background(), aitools.ToolListConnections, nil, load)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.(map[string]any)["connections"].([]aitools.ConnectionSummary), nil
|
||||
}
|
||||
first, err := list()
|
||||
if err != nil || len(first) != 1 || first[0].ID != "c1" {
|
||||
t.Fatalf("initial whitelist: %v, %v", first, err)
|
||||
}
|
||||
policy.AllowedConnectionIDs = []string{"c2"}
|
||||
second, err := list()
|
||||
if err != nil || len(second) != 1 || second[0].ID != "c2" {
|
||||
t.Fatalf("updated whitelist: %v, %v", second, err)
|
||||
}
|
||||
loadErr = errors.New("invalid mcp.json")
|
||||
if _, err := list(); err == nil || !strings.Contains(err.Error(), "invalid mcp.json") {
|
||||
t.Fatalf("broken policy must reject calls, got %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user