拥有百年历史的荷兰零售商 HEMA 面临的并不是“缺少文档”,而是知识散落在多个开发者门户里。工程师需要反复切换页面、选择系统、搜索关键词,再判断哪份结果仍然有效。HEMA 构建内部 AI 助手 HAL,利用 Amazon Bedrock AgentCore 与模型上下文协议(Model Context Protocol,MCP),把受治理的内部知识送到团队已经在使用的工具中。
这套方案值得关注的地方,不只是给文档加了聊天框,而是重新划分了身份、模型和企业知识之间的边界:客户端不持有 AWS 凭证,用户身份由 Microsoft Entra ID 承载,MCP 则把可调用的知识能力变成明确、可治理的工具。
门户搜索为什么会拖慢开发流程
传统开发者门户通常按组织结构建设:API 文档在一个站点,运行手册在另一个站点,平台规范可能又藏在 Wiki 或代码仓库里。开发者提出的却往往是跨系统问题,例如:
- 某个服务怎样申请测试环境?
- 生产发布需要经过哪些审批?
- 出现库存同步延迟时应该查看哪份运行手册?
- 哪个 API 可以读取门店信息,它的认证方式是什么?
普通搜索引擎返回的是页面列表,工程师仍需自己拼接答案。HAL 的思路是把问题交给模型理解,再通过受控工具查找相关知识,最终返回一段带有上下文的答案。
MCP 在这里承担的是工具契约,而不是另一个知识仓库。一个 MCP 工具可以代表文档检索、服务目录查询或运行手册读取,并明确声明输入参数和返回结构。模型不必了解每个后端系统的私有接口,只需要按协议选择合适的工具。
身份边界比模型选择更重要
HEMA 方案中的关键约束是:客户端不需要 AWS 凭证。一个合理的请求链路可以概括为:
开发者所在工具
│ Microsoft Entra ID access token
▼
HAL 应用后端 / 身份边界
│ 验证用户、角色和访问范围
▼
Amazon Bedrock AgentCore
│ 仅选择获准的 MCP 工具
▼
文档、服务目录、运行手册等内部知识源
这种设计避免把云平台长期密钥分发到浏览器、IDE 插件或聊天客户端。客户端只证明“我是谁”,后端再决定“我可以调用什么”。AWS 访问权限保留在服务端,由工作负载身份和最小权限策略控制。
这里至少存在三层授权:
- 用户能否访问 HAL:由 Entra ID 登录状态、租户、应用角色或用户组决定。
- HAL 能否调用某个 MCP 工具:由服务端工具白名单和 AWS 侧权限决定。
- 工具能否返回某类数据:由知识源本身的权限和数据分类决定。
如果只验证第一层,模型仍可能成为绕过内部权限的“统一搜索入口”。因此,MCP 工具不能默认继承全量读取权限;工具应该接收经过验证的用户上下文,或者只查询已经为目标受众整理过的知识集合。
可以这样实践:先做一个最小 MCP 知识工具
下面是一个可运行的示例,用本地数据模拟内部文档检索。它不是 HEMA 的实际代码,也没有复刻其生产架构;它用于展示如何把知识检索封装为边界清晰的 MCP 工具。
先创建虚拟环境并安装 MCP Python SDK:
python -m venv .venv
source .venv/bin/activate
python -m pip install "mcp[cli]"
保存为 server.py:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("internal-developer-knowledge")
DOCUMENTS = [
{
"title": "申请测试环境",
"audience": "developer",
"content": "在服务目录中选择应用,提交测试环境申请,并填写成本中心。",
},
{
"title": "生产发布检查清单",
"audience": "developer",
"content": "发布前需要通过自动化测试、安全扫描和变更审批。",
},
{
"title": "库存同步故障处理",
"audience": "operator",
"content": "先检查消息积压,再核对同步任务最近一次成功时间。",
},
]
@mcp.tool()
def search_internal_docs(
query: str,
audience: str = "developer",
limit: int = 5,
) -> list[dict]:
"""搜索允许当前受众读取的内部开发文档。"""
words = [word.lower() for word in query.split() if word.strip()]
matches = []
for document in DOCUMENTS:
if document["audience"] != audience:
continue
text = f'{document["title"]} {document["content"]}'.lower()
score = sum(word in text for word in words)
if score > 0 or not words:
matches.append({**document, "score": score})
matches.sort(key=lambda item: item["score"], reverse=True)
return matches[: max(1, min(limit, 10))]
if __name__ == "__main__":
mcp.run()
启动 MCP Inspector 进行本地测试:
npx -y @modelcontextprotocol/inspector python server.py
在生产环境中,audience 不应由模型或客户端任意填写。更稳妥的做法是由 HAL 后端根据已验证的 Entra ID 声明计算访问范围,再把结果注入工具调用。工具侧还应重新检查该范围,避免仅依赖提示词约束。
可以把工具治理规则单独配置,例如:
version: 1
tools:
search_internal_docs:
enabled: true
allowed_entra_roles:
- HAL.User
- Platform.Engineer
allowed_collections:
- developer-handbook
- public-runbooks
denied_classifications:
- confidential
- personal-data
limits:
max_results: 10
timeout_seconds: 5
audit:
log_user_id: true
log_tool_name: true
log_query_text: false
log_result_metadata: true
这份配置同样是建议性示例。实际系统需要根据审计要求决定是否记录问题原文;问题可能包含客户信息、故障细节或源代码,全部写入日志会制造新的数据泄露面。
从演示走向生产,需要补齐哪些环节
把 MCP 工具接到模型并不困难,困难的是让答案长期可信。落地时可以按以下顺序推进:
- 从高频、低敏感知识开始:优先接入开发规范、环境申请说明和公开运行手册,不要一开始就连接客户数据或生产数据库。
- 限制工具能力:搜索工具默认只读;涉及发布、退款、权限变更等写操作时,应加入人工确认和二次授权。
- 保留来源元数据:答案最好附带文档标题、更新时间和内部引用标识,让开发者能够核验,而不是盲信生成内容。
- 在服务端完成云认证:浏览器和插件只携带 Entra ID 令牌,不保存 AWS access key、secret key 或可长期复用的代理凭证。
- 测量答案质量:建立一组真实开发问题,持续检查工具选择、召回文档、答案正确性和拒答行为。
- 处理提示词注入:内部文档同样可能包含恶意或过期指令。工具返回值应被视为数据,而不是拥有更高优先级的系统指令。
- 设计失败模式:知识源超时、权限不足或证据不充分时,HAL 应明确说明无法确认,而不是补写一个看似合理的答案。
HEMA 的实践说明,企业 AI 助手的价值不只来自模型本身。真正减少门户跳转的,是身份体系、Agent 运行层与知识工具之间形成了清晰边界。MCP 负责标准化“模型可以使用什么”,Entra ID 回答“当前用户是谁”,服务端 AWS 权限则约束“系统能够代表用户做什么”。这三部分同时成立,内部问答才能从方便的演示走向可治理的工程能力。