- aitools 共用 runtime:list/describe/schema/query/redis(纯只读,无写确认) - 白名单 ~/.opsxdb/mcp.json;审计 mcp-audit.jsonl;复用 danger.go - 桌面 connections 双写 ~/.opsxdb/connections.json(ox1. 解码) - Cursor 配置示例与任务书验收勾选更新;写操作与 Agent UI 留 P1
57 lines
1.2 KiB
Go
57 lines
1.2 KiB
Go
package aitools
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// AuditEntry MCP/Agent 工具审计;不含密码与大结果全文。 // Logan.Li
|
|
type AuditEntry struct {
|
|
Time string `json:"time"`
|
|
Tool string `json:"tool"`
|
|
ConnectionID string `json:"connection_id,omitempty"`
|
|
Mode string `json:"mode"`
|
|
OK bool `json:"ok"`
|
|
Summary string `json:"summary,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
var auditMu sync.Mutex
|
|
|
|
func AuditPath() (string, error) {
|
|
dir, err := opsxdbDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return filepath.Join(dir, "logs", "mcp-audit.jsonl"), nil
|
|
}
|
|
|
|
// AppendAudit 追加一行 JSONL;失败静默(不影响工具主路径)。
|
|
func AppendAudit(e AuditEntry) {
|
|
if e.Time == "" {
|
|
e.Time = time.Now().Format(time.RFC3339)
|
|
}
|
|
path, err := AuditPath()
|
|
if err != nil {
|
|
return
|
|
}
|
|
auditMu.Lock()
|
|
defer auditMu.Unlock()
|
|
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
|
|
return
|
|
}
|
|
b, err := json.Marshal(e)
|
|
if err != nil {
|
|
return
|
|
}
|
|
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer f.Close()
|
|
_, _ = f.Write(append(b, '\n'))
|
|
}
|