Feature: Add list_services and get_client_log MCP tools

Add the two P2d read-only MCP tools, both one-shot sub-links (mode A') on
the existing single-flight pending registry.

list_services sends COMMAND_SERVICES; the client's CServicesManager emits
TOKEN_SERVERLIST on sub-link creation, parsed as 5 null-terminated fields per
record (display_name/service_name/binary_path/status/start_type) with
zero-padding termination. Services are Windows-only, so LNX/MAC hosts get
-32005 up front instead of a 20s timeout.

get_client_log sends COMMAND_QUERY_LOG; the client's CClientLogManager dumps
its full in-memory Logger ring buffer once, then pushes deltas every 3s. The
MCP path takes the first (full) TOKEN_REPORT_LOG and cancels the sub-link so
later deltas stop, while the MFC log dialog keeps receiving deltas on the
non-pending branch. Log text is client ANSI on Windows, decoded by clientType
like process/file names. MessageHandle intercepts both with
IsPending -> TakeMainResponse + CancelIO. Sync the design doc (P2d section +
verification notes; Linux get_client_log timeout is a client-version gap).

Co-Authored-By: deepseek-v4-pro
This commit is contained in:
yuanyuanxiang
2026-08-19 14:28:10 +02:00
parent c6c6e1d5ef
commit 5611ba621c
3 changed files with 282 additions and 4 deletions

View File

@@ -5467,6 +5467,15 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
// 【x】对话框相关功能
switch (cmd) {
case TOKEN_REPORT_LOG: {
// P3MCP 挂起时接管。客户端子连接建立即回全量日志、随后每 3s 推增量MCP
// 只取首条全量,取走即 CancelIO 关子链接,停止后续增量推送(与 MFC 日志对话框
// 持续接收增量的路径区分开)。
uint64_t devId = ContextObject->GetClientID();
if (McpServer().IsPending(devId)) {
McpServer().TakeMainResponse(devId, szBuffer, len);
ContextObject->CancelIO();
break;
}
std::string logText((char*)(szBuffer + 1), len > 1 ? len - 1 : 0);
if (!ContextObject->hDlg) {
// 对话框尚未打开:用 SendMessage 同步打开并显示初始全量日志
@@ -6411,6 +6420,14 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
break;
}
case TOKEN_SERVERLIST: { // 服务管理【x】
// P3MCP 挂起时接管。服务列表为一次性子链接回传CServicesManager 构造即发),
// 取走即 CancelIO 关子链接(无 MFC 对话框续用该子链接)。
uint64_t devId = ContextObject->GetClientID();
if (McpServer().IsPending(devId)) {
McpServer().TakeMainResponse(devId, szBuffer, len);
ContextObject->CancelIO();
break;
}
g_2015RemoteDlg->SendMessage(WM_OPENSERVICESDIALOG, 0, (LPARAM)ContextObject);
break;
}