当前位置: 首页 > news >正文

Amazon Quick + MCP 远程服务实战:让 AI 助手直接操作飞书,从设计到落地

Amazon Quick + MCP 远程服务实战:让 AI 助手直接操作飞书,从设计到落地

"帮我在飞书上建一个项目群,把这 5 个人拉进去,然后发一条启动通知。"

这种话以前只能对人说。现在可以对 Amazon Quick 说了——它真的能帮你执行。

但实现起来没那么简单。飞书有 200+ 开放 API,全塞给 AI 作为工具上下文?token 直接爆炸。多步操作的准确率怎么保证?token 泄露了怎么办?

亚马逊云科技官博最近发了一篇实践文章,讲了怎么用 Bedrock AgentCore 构建远程 MCP 服务来解决这些问题。我看完之后照着搭了一套,记录一下关键设计决策和踩的坑。

问题:200+ 工具的上下文膨胀

飞书开放平台的 API 覆盖了消息、群组、文档、日历、审批、多维表格等十几个模块。如果把所有工具描述一股脑塞进 system prompt:

  • 200+ 工具 × 平均 300 token/工具描述 ≈ 60,000 token 上下文
  • Claude 每次请求都要"读"这些描述来决策用哪个
  • 绝大多数工具在当前对话中完全用不上
  • 成本和延迟都往上飙

方案:Meta Tool + 按需加载

核心思路是分层注册。不把 200+ 工具全给 AI,而是给它一个"工具索引"(Meta Tool),让它先查询有哪些能力,再按需加载具体工具。

用户请求↓
AI 调用 Meta Tool → "飞书消息相关能力有哪些?"↓
返回 5 个具体工具描述↓
AI 选择具体工具执行 → send_message / create_group

这样每次对话只加载用得上的工具,上下文从 60K token 降到 3-5K token。

架构设计

整体架构分三层:

Amazon Quick (AI 助手)↓ MCP 协议
Bedrock AgentCore (远程 MCP 服务)↓ REST API
飞书开放平台

Bedrock AgentCore 做了什么

AgentCore 在这里的角色是远程 MCP 服务器。它负责:

  1. 工具注册和发现 — 管理所有飞书 API 的工具描述
  2. 认证和鉴权 — OAuth PKCE + HMAC 签名
  3. 执行代理 — 接收 AI 的工具调用请求,转发到飞书 API
  4. 结果格式化 — 把飞书 API 的原始响应转成 AI 能理解的格式

为什么用远程 MCP 不用本地

本地 MCP(每个用户电脑跑一个 MCP server)有几个问题:

  • 需要用户本地安装和配置
  • 飞书 token 存在用户电脑上,安全风险大
  • 不同用户的权限难以统一管理
  • 无法集中监控和审计

远程 MCP 服务部署在 AWS 上,统一管理认证和权限。Amazon Quick 通过 MCP 协议与之通信。

关键设计:token 安全

飞书 API 调用需要 access_token。这个 token 怎么管理,直接影响系统安全。

方案:OAuth PKCE + HMAC 域分离签名

import hashlib
import hmac
import time
import secretsclass TokenManager:"""飞书 token 安全管理"""def __init__(self, app_id: str, app_secret: str, signing_key: bytes):self.app_id = app_idself.app_secret = app_secretself.signing_key = signing_keydef get_tenant_token(self) -> str:"""获取租户级别的 access_token"""import requestsresp = requests.post("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",json={"app_id": self.app_id, "app_secret": self.app_secret})return resp.json()["tenant_access_token"]def sign_request(self, user_id: str, action: str, timestamp: int) -> str:"""HMAC 域分离签名 — 防止跨用户/跨操作伪造"""message = f"{user_id}|{action}|{timestamp}"return hmac.new(self.signing_key,message.encode(),hashlib.sha256).hexdigest()def verify_request(self, user_id: str, action: str, timestamp: int, signature: str) -> bool:"""验证请求签名,防止重放攻击"""# 检查时间戳(5分钟有效)if abs(time.time() - timestamp) > 300:return Falseexpected = self.sign_request(user_id, action, timestamp)return hmac.compare_digest(expected, signature)

关键点:

  • 域分离 — 签名里包含 user_id 和 action,防止 A 用户的签名被 B 用户复用
  • 时间戳 — 5 分钟有效期,防重放
  • HMAC-SHA256 — 签名密钥存在服务端,客户端拿不到

Meta Tool 实现

Meta Tool 本质上是一个"工具目录"服务:

from typing import Dict, List# 工具分类注册表
TOOL_REGISTRY: Dict[str, List[dict]] = {"messaging": [{"name": "send_message", "description": "发送消息到指定会话"},{"name": "reply_message", "description": "回复指定消息"},{"name": "recall_message", "description": "撤回已发送的消息"},],"group": [{"name": "create_group", "description": "创建群组"},{"name": "add_members", "description": "添加群成员"},{"name": "set_group_name", "description": "修改群名称"},],"calendar": [{"name": "create_event", "description": "创建日历事件"},{"name": "list_events", "description": "查询日历事件列表"},{"name": "update_event", "description": "更新日历事件"},],"docs": [{"name": "create_doc", "description": "创建云文档"},{"name": "update_doc", "description": "更新文档内容"},{"name": "share_doc", "description": "分享文档给指定用户"},]
}def meta_tool_query(category: str = None, keyword: str = None) -> List[dict]:"""Meta Tool: AI 调用此函数发现可用工具Args:category: 按分类筛选 (messaging/group/calendar/docs)keyword: 按关键词搜索工具描述Returns:匹配的工具列表(含完整参数定义)"""results = []for cat, tools in TOOL_REGISTRY.items():if category and cat != category:continuefor tool in tools:if keyword and keyword not in tool["description"]:continueresults.append({"category": cat, **tool})return results

AI 的调用流程变成:

  1. 用户说"帮我建个群" → AI 调用 meta_tool_query(category="group")
  2. 拿到 create_groupadd_members 等工具描述
  3. AI 选择 create_group 并填入参数执行

多步编排的准确性

实际任务往往需要多步操作。比如"建群+拉人+发消息":

async def execute_multi_step(steps: List[dict], context: dict):"""多步操作编排器"""results = {}for step in steps:tool_name = step["tool"]params = step["params"]# 支持步骤间参数传递# 比如 create_group 返回 group_id,add_members 需要用它for key, value in params.items():if isinstance(value, str) and value.startswith("$"):ref = value[1:]  # "$create_group.group_id" → "create_group.group_id"ref_step, ref_field = ref.split(".")params[key] = results[ref_step][ref_field]# 执行当前步骤result = await call_feishu_api(tool_name, params, context)results[step["id"]] = result# 失败则中断(不做半截操作)if not result.get("success"):return {"status": "failed", "failed_step": step["id"], "error": result.get("error"), "completed": results}return {"status": "success", "results": results}

部署到 AgentCore

把整套 MCP 服务部署为 AgentCore 托管的远程服务:

# 打包部署
aws bedrock-agentcore create-mcp-service \--service-name "feishu-mcp" \--description "飞书操作 MCP 服务" \--runtime "python3.12" \--handler "main.handler" \--source-code-path "./feishu_mcp/" \--environment-variables '{"FEISHU_APP_ID": "cli_xxxx","SIGNING_KEY_ARN": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:feishu-signing-key"}' \--region ap-northeast-1

敏感配置(app_secret、signing_key)存在 Secrets Manager 里,运行时通过 IAM Role 获取。

踩坑记录

  1. 飞书 token 有效期 2 小时 — 必须做自动刷新。我用了一个后台 timer 每 90 分钟刷新一次。

  2. 消息格式兼容 — 飞书消息支持富文本、卡片、Markdown 等多种格式。AI 生成的纯文本消息需要包装成飞书消息格式。

  3. 权限粒度 — 不是所有用户都能操作所有群。Meta Tool 返回工具列表时要根据当前用户的权限过滤。

参考链接

  • Amazon Quick 官方文档:https://docs.aws.amazon.com/quick/latest/userguide/
  • Bedrock AgentCore MCP 服务:https://docs.aws.amazon.com/bedrock/latest/userguide/agentcore-mcp.html
  • 飞书开放平台文档:https://open.feishu.cn/document/home/index
  • MCP 协议规范:https://spec.modelcontextprotocol.io/
  • AWS 中国官博原文:https://aws.amazon.com/cn/blogs/china/amazon-quick-build-mcp-service-design-practice/
http://www.jsqmd.com/news/983186/

相关文章:

  • QFIL读写eMMC分区保姆级教程:从XML解析到实战避坑(附system.xml配置详解)
  • MuleSoft驱动的企业级AI编排:安全可信的LLM集成实践
  • 怎样使用GTA圣安地列斯存档编辑器:5个实用技巧完全掌控游戏进度
  • 企业科研人/在职博士必看:Scholaread全流程效率实测,比Zotero快3倍
  • 大创项目申报系统毕业设计全套:SpringBoot+Vue前后端源码、MySQL脚本、开题报告与实操视频
  • 如何快速备份Bandcamp音乐收藏:Python下载器终极指南
  • 猫抓浏览器扩展:终极网页媒体资源嗅探与下载解决方案完全指南
  • 未来企业的组织架构里,会有多少个“数字岗位“?
  • 2025-2026汉中本地装修公司十强榜单 - 装修新知
  • FIFA 23 Live Editor:免费开源修改器的完整使用指南与创意玩法
  • 纯CSS实现的可折叠家谱树图,零JS依赖,开箱即用
  • 3分钟掌握MPV_lazy播放器:新手必学的播放列表管理技巧
  • Transformer也能玩转高光谱图像分类?SpectralFormer保姆级代码复现与实战解析
  • ARM Cortex-M4微控制器实战:K10系列核心架构、外设与低功耗设计详解
  • 嵌入式MCU电气特性与低功耗设计实战:从数据手册到稳定产品
  • 如何用开源自动化工具提升英雄联盟游戏效率:5分钟配置指南
  • 如何快速打造专属影院级播放器:MPV_lazy终极配置指南
  • STL文件缩略图:Windows资源管理器的3D模型可视化终极方案
  • QPDF Widget:为你的Qt应用注入专业PDF查看能力的终极指南
  • 【鸿蒙PC适配心得集大成】10 个 Qt 应用适配鸿蒙 PC 实战总结:8 大坑全景图谱 + 7 条铁律
  • 嵌入式SPI与SCI通信:MC68HC908MR24寄存器配置与实战避坑指南
  • 大题
  • Halcon实战:从“调参侠”到“方案设计师”,缺陷检测的6种核心思路拆解
  • 解锁iOS设备无限潜能:2026年最新越狱指南与安全定制方案
  • 2026 最强 AI 简历工具盘点:鹅来面 / Jobscan / 超级简历哪家强?
  • 基于FOC与无传感器技术的智能洗衣机电机控制实战解析
  • 提示词工程的本质:从模糊意图到结构化AI指令
  • Claude Code vs Codex 深度技术对比:24项功能逐帧拆解,AI编程智能体的终极对决
  • 嵌入式开发实战:深度解析Kinetis K20 DSPI与I2S时序规范与硬件设计
  • 模板驱动型文档自动化:从Word手工到工程化流水线