From c6c6e1d5eff0be762e73d7382b036440ccae300a Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Wed, 19 Aug 2026 13:41:38 +0200 Subject: [PATCH] Improve: Add optional max_width to get_screenshot The get_screenshot tool inherited the MFC thumbnail-preview profile, capping the frame at 1024px wide (1280 on 4K source), which is too small for AI vision/OCR of dense UI. Add an optional max_width argument that overrides the width (clamped to the client's 64..1920 limit) while keeping the RTT-adaptive jpegQuality. Omitted or 0 keeps the existing thumbnail profile; 1920 yields near-native resolution (full 1080p on a 1080p source, 1920 wide on 4K). Sync the design doc. Co-Authored-By: deepseek-v4-pro --- docs/Mcp_Phase2_Design.md | 1 + server/2015Remote/McpServer.cpp | 37 ++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/Mcp_Phase2_Design.md b/docs/Mcp_Phase2_Design.md index 8ae40ba..d30b21b 100644 --- a/docs/Mcp_Phase2_Design.md +++ b/docs/Mcp_Phase2_Design.md @@ -271,6 +271,7 @@ Web 是长连接,子链接可长驻;MCP 是**一次性 request/response**。 - 复用现有双击预览机制 `COMMAND_SCREEN_PREVIEW_REQ`(247)→`TOKEN_SCREEN_PREVIEW_RSP`(248)(`common/commands.h:416-455`,单帧 JPEG,`ScreenPreviewReq`/`ScreenPreviewRspHeader`),`ctx->Send2Client` 发请求、主连接回响应,**不建子链接、不弹框**。 - 复用 MFC 预览的 RTT/FRP 自适应参数挑选 `ChooseScreenPreviewParams` + `SendScreenPreviewRequest`,不重复实现 `GetTargetQualityLevel`。 +- **可选 `max_width` 参数**:缺省/0 沿用缩略图档位(最大 1024,4K 源屏高档 1280);`max_width`>0 覆盖宽度并钳制到客户端上限 `[64,1920]`(客户端 `CaptureAndEncodePreview` 硬钳制),供 AI 视觉/OCR 场景请求接近原分辨率(1080p 源屏传 1920 即原分辨率,4K 源屏最多 1920)。`jpegQuality` 仍沿用档位自适应值。 - **请求关联**:`ScreenPreviewReq.reqId` 提供关联;MCP 用独立 16 位 reqId 发生器(`NextPreviewReqId`,跳过 0)+ `SetPendingReqId` 登记期望值,`TakePreviewResponse` 只接受「挂起命中 + reqId 一致」的响应,过期/他途(MFC 预览并发)响应原样回落到 MFC 路径。 - 客户端能力位 `CLIENT_CAP_SCREEN_PREVIEW`(0x0004,仅 Windows 客户端声明):非 Windows 主机返回 `-32005`「不支持」。 - 返回结构:`content[0] = {type:"image", data: base64(JPEG), mimeType:"image/jpeg"}` + `structuredContent.image = {mimeType,width,height,bytes}`(元数据,不含 base64,避免二次膨胀)。 diff --git a/server/2015Remote/McpServer.cpp b/server/2015Remote/McpServer.cpp index 1a6ad53..fa19548 100644 --- a/server/2015Remote/McpServer.cpp +++ b/server/2015Remote/McpServer.cpp @@ -587,6 +587,29 @@ Json::Value BuildScreenshotOutputSchema() { return schema; } +// get_screenshot 的 inputSchema(id 必填,max_width 可选) +Json::Value BuildGetScreenshotInputSchema() { + Json::Value props(Json::objectValue); + + Json::Value idProp(Json::objectValue); + idProp["type"] = "string"; + idProp["description"] = u8"主机 id,取 list_online_hosts / search_hosts 返回的 id 字段"; + props["id"] = idProp; + + Json::Value mwProp(Json::objectValue); + mwProp["type"] = "integer"; + mwProp["description"] = u8"期望图片最大宽度(像素,钳制到 64~1920)。省略或传 0 时沿用 RTT 自适应缩略图档位(最大 1024);传 1920 可拿到接近原分辨率(1080p 源屏即原分辨率,4K 源屏最多 1920),供 AI 视觉/OCR 场景提升清晰度。"; + props["max_width"] = mwProp; + + Json::Value schema(Json::objectValue); + schema["type"] = "object"; + schema["properties"] = props; + Json::Value required(Json::arrayValue); + required.append("id"); + schema["required"] = required; + return schema; +} + // list_files 的 inputSchema(id 必填,path 可选;path 缺省/空 = 列盘) Json::Value BuildListFilesInputSchema() { Json::Value props(Json::objectValue); @@ -752,7 +775,7 @@ std::string BuildToolsListResult(const Json::Value& id) { tool["name"] = "get_screenshot"; tool["description"] = u8"截取指定在线主机的一帧屏幕,返回 base64 编码的 JPEG 图片(image 对象含 mimeType/data/width/height)。仅 Windows 客户端支持(能力位 CLIENT_CAP_SCREEN_PREVIEW),主连接 RPC、一次性返回。"; - tool["inputSchema"] = BuildGetHostDetailInputSchema(); // 复用 { id } 必填 schema + tool["inputSchema"] = BuildGetScreenshotInputSchema(); // { id } 必填 + max_width 可选 tool["outputSchema"] = BuildScreenshotOutputSchema(); tools.append(tool); @@ -1061,6 +1084,18 @@ std::string BuildGetScreenshot(const Json::Value& id, const Json::Value& args, C WORD maxWidth = 0; BYTE quality = 0; parent->ChooseScreenPreviewParams(ctx, maxWidth, quality); + + // 可选 max_width:缺省/0 沿用缩略图档位;>0 覆盖宽度(钳制到客户端上限 [64,1920]), + // 供 AI 视觉/OCR 场景请求接近原分辨率的大图。jpegQuality 仍沿用档位自适应值。 + if (args.isMember("max_width") && args["max_width"].isInt()) { + int mw = args["max_width"].asInt(); + if (mw > 0) { + if (mw < 64) mw = 64; + if (mw > 1920) mw = 1920; + maxWidth = (WORD)mw; + } + } + parent->SendScreenPreviewRequest(ctx, reqId, maxWidth, quality); std::vector data;