feat(mcp): P0 只读 MCP tool runtime + opsxdb-mcp stdio

- aitools 共用 runtime:list/describe/schema/query/redis(纯只读,无写确认)
- 白名单 ~/.opsxdb/mcp.json;审计 mcp-audit.jsonl;复用 danger.go
- 桌面 connections 双写 ~/.opsxdb/connections.json(ox1. 解码)
- Cursor 配置示例与任务书验收勾选更新;写操作与 Agent UI 留 P1
This commit is contained in:
logan committed 2026-10-15 11:14:08 +08:00
1 parent 5c17d32647
commit 0b68c8344d
19 files changed
+1989 -79

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
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'))
}