Feature: Add get_audit_log MCP tool
Expose the server main-window audit log (host online/offline, operation results, alerts) as a read-only, no-arg, in-memory MCP tool. The log lives in m_CList_Message, a CListCtrl that is only safe to touch on the UI thread, so add a thread-safe mirror m_MessageLog (guarded by m_cs) and keep it in sync at the four item-mutation sites: ShowMessage, OnShowErrMessage, OnMsglogDelete and OnMsglogClear. The tool reads the mirror directly under m_cs and returns up to MAX_MESSAGE_COUNT (1000) entries, newest first. Co-Authored-By: deepseek-v4-pro
This commit is contained in:
@@ -639,6 +639,34 @@ Json::Value BuildClientLogOutputSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
// get_audit_log 的 outputSchema(服务端消息/审计日志条目数组)
|
||||
Json::Value BuildAuditLogOutputSchema() {
|
||||
Json::Value props(Json::objectValue);
|
||||
|
||||
Json::Value entriesProp(Json::objectValue);
|
||||
entriesProp["type"] = "array";
|
||||
Json::Value items(Json::objectValue);
|
||||
items["type"] = "object";
|
||||
Json::Value itemProps(Json::objectValue);
|
||||
const char* strFields[] = { "type", "time", "msg" };
|
||||
for (const char* f : strFields) {
|
||||
Json::Value s(Json::objectValue);
|
||||
s["type"] = "string";
|
||||
itemProps[f] = s;
|
||||
}
|
||||
items["properties"] = itemProps;
|
||||
entriesProp["items"] = items;
|
||||
props["entries"] = entriesProp;
|
||||
|
||||
Json::Value schema(Json::objectValue);
|
||||
schema["type"] = "object";
|
||||
schema["properties"] = props;
|
||||
Json::Value required(Json::arrayValue);
|
||||
required.append("entries");
|
||||
schema["required"] = required;
|
||||
return schema;
|
||||
}
|
||||
|
||||
// get_screenshot 的 outputSchema(image 元数据;base64 数据在 content 的 image 块中)
|
||||
Json::Value BuildScreenshotOutputSchema() {
|
||||
Json::Value props(Json::objectValue);
|
||||
@@ -897,6 +925,23 @@ std::string BuildToolsListResult(const Json::Value& id) {
|
||||
tools.append(tool);
|
||||
}
|
||||
|
||||
// 11) get_audit_log(服务端本地:主界面消息/审计日志,纯内存,无子链接)
|
||||
{
|
||||
Json::Value tool(Json::objectValue);
|
||||
tool["name"] = "get_audit_log";
|
||||
tool["description"] = u8"获取 YAMA 服务端主界面的消息/审计日志(主机上线/下线、操作结果、告警等)。返回列表内当前全部条目(最多 1000 条,新在前)。只读、纯内存。";
|
||||
|
||||
Json::Value inputSchema(Json::objectValue);
|
||||
inputSchema["type"] = "object";
|
||||
inputSchema["properties"] = Json::Value(Json::objectValue);
|
||||
inputSchema["required"] = Json::Value(Json::arrayValue);
|
||||
tool["inputSchema"] = inputSchema;
|
||||
|
||||
tool["outputSchema"] = BuildAuditLogOutputSchema();
|
||||
|
||||
tools.append(tool);
|
||||
}
|
||||
|
||||
result["tools"] = tools;
|
||||
return BuildResult(id, result);
|
||||
}
|
||||
@@ -1418,6 +1463,41 @@ std::string BuildGetClientLog(const Json::Value& id, const Json::Value& args, CM
|
||||
return BuildResult(id, result);
|
||||
}
|
||||
|
||||
// tools/call:get_audit_log(服务端本地消息日志,读取 UI 日志列表的线程安全镜像)
|
||||
std::string BuildGetAuditLog(const Json::Value& id, CMy2015RemoteDlg* parent) {
|
||||
Json::Value entries(Json::arrayValue);
|
||||
if (parent) {
|
||||
EnterCriticalSection(&parent->m_cs);
|
||||
// m_MessageLog 新在前、旧在后(与界面一致),直接顺序输出。
|
||||
for (const auto& e : parent->m_MessageLog) {
|
||||
Json::Value item(Json::objectValue);
|
||||
item["type"] = ToUtf8(e.type.c_str(), 936);
|
||||
item["time"] = ToUtf8(e.time.c_str(), 936);
|
||||
item["msg"] = ToUtf8(e.msg.c_str(), 936);
|
||||
entries.append(item);
|
||||
}
|
||||
LeaveCriticalSection(&parent->m_cs);
|
||||
}
|
||||
|
||||
int count = (int)entries.size();
|
||||
|
||||
Json::Value result(Json::objectValue);
|
||||
Json::Value structuredContent(Json::objectValue);
|
||||
structuredContent["entries"] = entries;
|
||||
result["structuredContent"] = structuredContent;
|
||||
|
||||
Json::Value content(Json::arrayValue);
|
||||
Json::Value item(Json::objectValue);
|
||||
item["type"] = "text";
|
||||
item["text"] = count > 0 ? std::string(u8"共 ") + std::to_string(count) + std::string(u8" 条日志。")
|
||||
: std::string(u8"当前无日志。");
|
||||
content.append(item);
|
||||
result["content"] = content;
|
||||
result["isError"] = false;
|
||||
|
||||
return BuildResult(id, result);
|
||||
}
|
||||
|
||||
// tools/call 分派
|
||||
std::string BuildToolsCall(const Json::Value& root, CMy2015RemoteDlg* parent) {
|
||||
const Json::Value& id = root["id"];
|
||||
@@ -1440,6 +1520,7 @@ std::string BuildToolsCall(const Json::Value& root, CMy2015RemoteDlg* parent) {
|
||||
if (toolName == "list_files") return BuildListFiles(id, args, parent);
|
||||
if (toolName == "list_services") return BuildListServices(id, args, parent);
|
||||
if (toolName == "get_client_log") return BuildGetClientLog(id, args, parent);
|
||||
if (toolName == "get_audit_log") return BuildGetAuditLog(id, parent);
|
||||
|
||||
return BuildError(id, -32602,
|
||||
"Unknown tool: " + (toolName.empty() ? std::string("(empty)") : toolName));
|
||||
|
||||
Reference in New Issue
Block a user