fix: let agents download Feishu message resources

This commit is contained in:
2026-07-10 12:17:07 +08:00
parent 4ca4afb141
commit 1094ebd651
9 changed files with 332 additions and 27 deletions
+33
View File
@@ -2,6 +2,7 @@ import { createSdkMcpServer, tool, type McpSdkServerConfigWithInstance, type Sdk
import { z } from "zod";
import { sendApprovalCard, sendFile, type FeishuRuntime, type SendMessageOptions } from "./client.js";
import { resolveDeliverableFile } from "./fileDelivery.js";
import { downloadFeishuMessageResource } from "./download.js";
import { readFeishuContext } from "./read.js";
import type { ApprovalManager } from "./approval.js";
import { CPH_HUB_MCP_TOOL_IDS, type CphHubMcpToolId } from "../agent/roleTools.js";
@@ -85,6 +86,33 @@ export function createFileDeliveryMcpServer(options: FileDeliveryToolOptions): M
);
}
if (enabledTools.has("feishu_download_resource")) {
tools.push(
tool(
"feishu_download_resource",
"Download an image or file resource from a Feishu message in the current project's bound chat into the project workspace. Use message_id and file_key returned by feishu_read_context.",
{
message_id: z.string().describe("The Feishu message id containing the resource."),
file_key: z.string().describe("The image_key or file_key from that message's content."),
resource_type: z.enum(["image", "file"]).describe("Use image for image_key and file for file_key."),
},
async (args) => {
const downloaded = await downloadFeishuMessageResource(
{
messageId: args.message_id,
fileKey: args.file_key,
resourceType: args.resource_type,
},
{ boundChatId: options.chatId, workspaceDir: options.workspaceDir },
options.rt,
);
return { content: [{ type: "text", text: JSON.stringify(downloaded) }] };
},
{ alwaysLoad: true },
),
);
}
if (enabledTools.has("request_approval")) {
tools.push(
tool(
@@ -159,6 +187,11 @@ function mcpInstructions(enabledTools: ReadonlySet<CphHubMcpToolId>): string {
if (enabledTools.has("feishu_read_context")) {
instructions.push("Use feishu_read_context when the trigger context contains a reply, thread, or message anchor and more Feishu context is needed.");
}
if (enabledTools.has("feishu_download_resource")) {
instructions.push(
"When feishu_read_context returns an image_key or file_key whose pixels or bytes are needed, call feishu_download_resource and then read the returned local path.",
);
}
if (enabledTools.has("request_approval")) {
instructions.push("Use request_approval when explicit human approval or confirmation is required before continuing.");
}