package aitools // ToolSpec 工具元数据:MCP stdio 与侧栏 Agent(OpenAI tools)共用同一份契约。 // Logan.Li type ToolSpec struct { Name string Description string Properties map[string]any Required []string } // ToolSpecs P0 七工具 schema(顺序与 ToolNames 一致)。 func ToolSpecs() []ToolSpec { connID := map[string]any{"type": "string", "description": "Saved connection id from opsxdb_list_connections"} database := map[string]any{"type": "string", "description": "Database / schema / Redis DB index"} return []ToolSpec{ { Name: ToolListConnections, Description: "List whitelisted OpsxDB connections (id/name/driver/host/port/database; never passwords).", Properties: map[string]any{}, }, { Name: ToolListDatabases, Description: "List databases for a connection.", Properties: map[string]any{"connection_id": connID}, Required: []string{"connection_id"}, }, { Name: ToolListTables, Description: "List tables/views (or engine equivalents) in a database.", Properties: map[string]any{"connection_id": connID, "database": database}, Required: []string{"connection_id"}, }, { Name: ToolDescribeTable, Description: "Describe columns and metadata for a table.", Properties: map[string]any{ "connection_id": connID, "database": database, "table": map[string]any{"type": "string", "description": "Table name"}, }, Required: []string{"connection_id", "table"}, }, { Name: ToolGetSchemaContext, Description: "Compact schema text for LLM context (capped ~4k chars).", Properties: map[string]any{ "connection_id": connID, "database": database, "max_tables": map[string]any{"type": "integer", "description": "Max tables to include (default 40)"}, }, Required: []string{"connection_id"}, }, { Name: ToolExecuteQuery, Description: "Execute SQL. Default read-only (SELECT/SHOW/EXPLAIN/WITH…SELECT). Writes require mcp.json mode=read_write AND confirm_danger=true (never auto). Default limit 100, max 500.", Properties: map[string]any{ "connection_id": connID, "sql": map[string]any{"type": "string", "description": "SQL statement"}, "database": database, "limit": map[string]any{"type": "integer", "description": "Row limit (default 100, max 500)"}, "confirm_danger": map[string]any{"type": "boolean", "description": "Required for writes when mode=read_write; Agent UI sets this only after user confirms"}, }, Required: []string{"connection_id", "sql"}, }, { Name: ToolExecuteRedisCommand, Description: "Execute Redis command. Default read-only whitelist. Writes require mode=read_write AND confirm_danger=true. FLUSH*/KEYS/CONFIG always denied.", Properties: map[string]any{ "connection_id": connID, "command": map[string]any{"type": "string", "description": "Single Redis command line"}, "database": database, "confirm_danger": map[string]any{"type": "boolean", "description": "Required for writes when mode=read_write"}, }, Required: []string{"connection_id", "command"}, }, } } // InputSchema 返回 JSON Schema object(MCP raw schema / OpenAI parameters)。 func (t ToolSpec) InputSchema() map[string]any { schema := map[string]any{ "type": "object", "properties": t.Properties, } if len(t.Required) > 0 { schema["required"] = t.Required } if t.Properties == nil { schema["properties"] = map[string]any{} } return schema } // OpenAITool OpenAI chat.completions tools[] 一项。 type OpenAITool struct { Type string `json:"type"` Function struct { Name string `json:"name"` Description string `json:"description"` Parameters map[string]any `json:"parameters"` } `json:"function"` } // OpenAITools 供 Agent / DeepSeek 等 openai-chat 兼容协议挂载。 func OpenAITools() []OpenAITool { specs := ToolSpecs() out := make([]OpenAITool, 0, len(specs)) for _, s := range specs { var t OpenAITool t.Type = "function" t.Function.Name = s.Name t.Function.Description = s.Description t.Function.Parameters = s.InputSchema() out = append(out, t) } return out }