用 Amazon Bedrock AgentCore 为 Claude Desktop 添加安全的网页搜索功能
Amazon Bedrock 上的 Claude Desktop 能提供强大的 AI 辅助,但它没有集成 Web 搜索,所以回复内容受限于模型的训练知识截止时间。当你需要最新信息时——比如最近的文档更新、实时价格或天气情况——模型自己没法获取。Amazon Bedrock AgentCore 是一个用来大规模构建、连接和优化智能体的平台,支持任意框架或模型。借助 AgentCore Gateway(Amazon Bedrock AgentCore 的一项能力),你可以把 Claude Desktop 连接到 Web Search,从而填补知识截止带来的空白。Web Search 是一项全托管的、兼容 Model Context Protocol(MCP,模型上下文协议)的 Web 搜索能力,底层由覆盖数百亿文档的 Amazon 网页索引支撑。所有查询流量都留在 AWS 基础设施内部,无需管理外部 API 密钥,也没有任何查询会离开你的边界。在 Claude Desktop 中,你可以通过托管式 MCP 服务器连接到启用了 Web Search 目标的 AgentCore Gateway。本文将带你一步步完成这项集成,并使用基于 JSON Web Token(JWT)的入站认证来保护通信安全。
架构
许多在 AWS 上运行的企业,都用 AWS IAM Identity Center 来实现对其 AWS 账户的单点登录(SSO)。在本篇演示中,我们把 AWS IAM Identity Center 作为 AgentCore Gateway 的认证来源。这样一来,Amazon Bedrock 上的 Claude Desktop 就能通过受信任的、企业管理的身份流程来调用 Web Search。这种做法与组织现有的身份治理体系保持一致,无需单独的凭证,也不依赖第三方身份提供商。
为了把 AWS IAM Identity Center 和 AgentCore Gateway 的 JWT 认证打通,我们使用 Amazon Cognito 作为联邦层,配合 OAuth 2.0 授权码授予流程。IAM Identity Center 通过 Security Assertion Markup Language(SAML)处理用户认证,Amazon Cognito 负责签发 JWT,AgentCore Gateway 则在每次请求时验证这些令牌。整条认证链路都留在 AWS 内部。
下面的时序图展示了这套认证流程。
图 1:用户身份验证与授权时序图
前提条件
要跟着本文的步骤操作,你需要准备以下内容:
- 一个 AWS 账户,且具有创建 AWS Identity and Access Management (IAM) 角色和 Amazon Bedrock AgentCore 资源的权限。
- 在 AWS Organizations 中对管理账户拥有管理员权限(用于配置 AWS IAM Identity Center)。
- 已预先配置好 AWS IAM Identity Center,可通过 SSO 访问 AWS 账户。
- Claude Desktop 已配置 Amazon Bedrock 作为推理提供方。
- 已安装并配置 AWS Command Line Interface (AWS CLI) v2。
- Python 3.10 或更高版本。
- Boto3 SDK 已更新到最新版本。
Amazon Bedrock AgentCore 上的 Web Search 目前可在以下区域使用:美国东部(弗吉尼亚北部,us-east-1)、欧洲(爱尔兰,eu-west-1)、亚太地区(东京,ap-northeast-1)。请确认你的 gateway 创建在上述某个区域内。
配置
配置过程分两块:先搭建好认证链路(从 AWS IAM Identity Center 到 Amazon Cognito,再到 JWT),然后把 AgentCore Gateway 接入 Claude Desktop。下面我们逐步讲解。
第 1 步:创建 Amazon Cognito 用户池
在目标 AWS 账户中创建一个 Amazon Cognito 用户池,它将作为 AgentCore Gateway 的 OpenID Connect (OIDC) 令牌签发方。
export AWS_REGION=<your-region>
aws cognito-idp create-user-pool \
--pool-name "agentcore-websearch-pool" \
--region $AWS_REGION \
--auto-verified-attributes email \
--schema '[{"Name":"email","Required":true,"Mutable":true,"AttributeDataType":"String"}]' \
--username-attributes email \
--username-configuration "CaseSensitive=false" \
--mfa-configuration "OFF"
记录下用户池 ID:
export USER_POOL_ID=$(aws cognito-idp list-user-pools --max-results 10 \
--region $AWS_REGION \
--query "UserPools[?Name=='agentcore-websearch-pool'].Id" --output text)
echo "User Pool ID: $USER_POOL_ID"
再创建一个域名(必须全局唯一):
aws cognito-idp create-user-pool-domain \
--domain "<your-unique-prefix>" \
--user-pool-id $USER_POOL_ID \
--region $AWS_REGION
以下这些值后面会用到,先记好:
- 用户池 ID:
$USER_POOL_ID - 域名:
<your-unique-prefix>.auth.<region>.amazoncognito.com - Audience(受众):
urn:amazon:cognito:sp:<user-pool-id> - ACS URL:
https://<your-unique-prefix>.auth.<region>.amazoncognito.com/saml2/idpresponse
第 2 步:配置 IAM Identity Center 的 SAML 应用
在 AWS Organizations 的管理账户中,创建一个与 Cognito 联合的 SAML 应用:
- 打开 IAM Identity Center 控制台。
- 选择 Applications,点击 Add application,选择 I have an application I want to set up,再选 SAML 2.0,然后点击 Next。
- 填写以下信息:
- Display name:AgentCore Web Search
- 选择 Manually type your metadata value
- ACS URL:
https://<your-unique-prefix>.auth.<region>.amazoncognito.com/saml2/idpresponse - Audience:
urn:amazon:cognito:sp:<user-pool-id> - 下载 SAML 元数据 XML 文件,点击 Submit。
应用创建好后,编辑属性映射(attribute mappings),填入以下内容:
- Subject:
${user:subject},格式为 Persistent - Email:
${user:email},格式为 Basic
然后给需要访问 Web Search 的用户或用户组分配权限。
第 3 步:把 SAML IdP 接入 Cognito
回到目标账户,在 Cognito 用户池中把 IAM Identity Center 注册为 SAML 身份提供商(IdP):
# 将 IAM Identity Center 添加为 SAML IdP
METADATA=$(cat /path/to/downloaded-metadata.xml)
aws cognito-idp create-identity-provider \
--user-pool-id $USER_POOL_ID \
--provider-name "IAMIdentityCenterIdP" \
--provider-type SAML \
--provider-details "{\"MetadataFile\": $(echo "$METADATA" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))')}" \
--attribute-mapping '{"email": "email"}' \
--region $AWS_REGION
第 4 步:为 Amazon Bedrock AgentCore 创建 Cognito 应用客户端
接下来创建一个带客户端密钥(client secret)的应用客户端。Claude Desktop 会用它发起 OAuth 流程:先通过 IAM Identity Center 验证用户身份,再拿到一个 JWT,交由 AgentCore Gateway 使用。
aws cognito-idp create-user-pool-client \
--user-pool-id $USER_POOL_ID \
--client-name "agentcore-websearch-client" \
--generate-secret \
--supported-identity-providers "IAMIdentityCenterIdP" \
--callback-urls '["http://localhost:53280/callback"]' \
--allowed-o-auth-flows code \
--allowed-o-auth-scopes "openid" "email" "profile" \
--allowed-o-auth-flows-user-pool-client \
--region $AWS_REGION
记下输出里的 Client ID 和 Client Secret,它们就是你后续要用的应用客户端 ID 和密钥。
第 5 步:为 AgentCore Gateway 配置 Web Search 工具
这一步我们要新建一个 AgentCore Gateway,入站认证类型(Inbound Auth Type)设为 JSON Web Token(JWT,一种用于身份校验的令牌)。配置时需要用到前几步创建的 Cognito 用户池 ID 和应用客户端 ID。
运行下面这段 Python 脚本即可创建网关并完成配置。请把所有占位符替换成你环境中的真实值。
import boto3
import json
import time
session = boto3.Session(region_name="your-region")
iam_client = session.client("iam")
gateway_client = session.client("bedrock-agentcore-control")
ACCOUNT_ID = "your-target-aws-account-id"
ROLE_NAME = "websearch-gateway-role"
GATEWAY_NAME = "websearch-gateway"
COGNITO_DISCOVERY_URL = "https://cognito-idp.<your-region>.amazonaws.com/<user-pool-id>/.well-known/openid-configuration"
COGNITO_CLIENT_ID = "<cognito-application-client-id>"
# --- Step 1: 创建 IAM 执行角色 ---
trust_policy = {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "bedrock-agentcore.amazonaws.com"},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {"aws:SourceAccount": ACCOUNT_ID}
}]
permissions_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetGateway",
"Effect": "Allow",
"Action": "bedrock-agentcore:GetGateway",
"Resource": f"arn:aws:bedrock-agentcore:us-east-1:{ACCOUNT_ID}:gateway/*"
},
{
"Sid": "GetConfigBundle",
"Effect": "Allow",
"Action": "bedrock-agentcore:GetConfigurationBundleVersion",
"Resource": f"arn:aws:bedrock-agentcore:us-east-1:{ACCOUNT_ID}:configuration-bundle/*"
},
{
"Sid": "InvokeWebSearch",
"Effect": "Allow",
"Action": "bedrock-agentcore:InvokeWebSearch",
"Resource": "arn:aws:bedrock-agentcore:us-east-1:aws:tool/web-search.v1"
}
]
}
try:
iam_client.create_role(
RoleName=ROLE_NAME,
AssumeRolePolicyDocument=json.dumps(trust_policy),
Description="Execution role for web search AgentCore gateway",
)
print(f"✓ Role '{ROLE_NAME}' created.")
except iam_client.exceptions.EntityAlreadyExistsException:
print(f"✓ Role '{ROLE_NAME}' already exists, reusing.")
iam_client.put_role_policy(
RoleName=ROLE_NAME,
PolicyName="websearch-gateway-policy",
PolicyDocument=json.dumps(permissions_policy),
)
print(f"✓ Inline policy attached to '{ROLE_NAME}'.")
# --- Step 2: Create the gateway ---
response = gateway_client.create_gateway(
name=GATEWAY_NAME,
description="AgentCore gateway with managed Web Search connector",
roleArn=f"arn:aws:iam::{ACCOUNT_ID}:role/{ROLE_NAME}",
protocolType="MCP",
protocolConfiguration={
"mcp": {
"supportedVersions": ["2025-03-26"],
}
},
authorizerType="CUSTOM_JWT",
authorizerConfiguration={
"customJWTAuthorizer": {
"discoveryUrl": COGNITO_DISCOVERY_URL,
"allowedClients": [COGNITO_CLIENT_ID],
}
},
)
gateway_id = response["gatewayId"]
gateway_url = response.get("gatewayUrl")
print(f"✓ Gateway created: {gateway_id}")
print(f" URL: {gateway_url}")
# --- Step 3: Wait for gateway to become READY ---
print(" Waiting for gateway to reach READY status...", end="", flush=True)
for i in range(40): # up to ~10 minutes
resp = gateway_client.get_gateway(gatewayIdentifier=gateway_id)
status = resp.get("status")
if status == "READY":
print(f" READY (after {(i+1)*15}s)")
break
elif status == "FAILED":
print(f"\n✗ Gateway entered FAILED status.")
reasons = resp.get("statusReasons", [])
for r in reasons:
print(f" Reason: {r}")
exit(1)
print(".", end="", flush=True)
time.sleep(15)
else:
print(f"\n✗ Gateway did not reach READY within 10 minutes (last status: {status})")
exit(1)
# --- Step 4: Attach the managed Web Search connector target ---
gateway_client.create_gateway_target(
gatewayIdentifier=gateway_id,
name="web-search-tool",
description="Managed Web Search connector",
targetConfiguration={
"mcp": {
"connector": {
"source": {"connectorId": "web-search"},
"configurations": [{"name": "WebSearch", "parameterValues": {}}],
}
}
},
credentialProviderConfigurations=[
{"credentialProviderType": "GATEWAY_IAM_ROLE"}
],
)
print("✓ Web search target attached.")
print()
print("=" * 60)
print(f" Gateway ID: {gateway_id}")
print(f" Gateway URL: {gateway_url}")
print(f" Auth: CUSTOM_JWT (Cognito)")
print(f" Target: web-search (managed connector)")
print("=" * 60)
至此,你已经拿到了一个带 Web Search 工具的 AgentCore Gateway,并且入站请求使用 JWT 鉴权。
第 6 步:配置 Claude Desktop
按照 Claude Desktop 配置文档里的步骤,打开「Claude Desktop with Amazon Bedrock」的配置窗口。打开后依次选择 Connectors and Extensions → Add server → Blank。下图展示了配置窗口中的这些选项。
Figure 2:Claude Desktop 连接器配置窗口
填入以下信息:
- Name:websearchtool
- Transport:Streamable HTTP
- URL:填入第 5 步创建的 AgentCore Gateway 的资源 URL
- OAuth:Bring your own client
- Client ID:填入第 4 步创建的应用客户端 ID
- Client Secret:填入第 4 步创建的应用客户端密钥
- Authorization Server:填入
["https://<your-unique-prefix>.auth.<region>.amazoncognito.com/oauth2/authorize"] - Scope:openid
- Callback host:localhost
- Callback port:53280
填完后点击 sign in and test。浏览器会弹出认证页面,并跳转到 AWS IAM Identity Center 的 SSO 登录。输入你的凭据完成认证。如果成功,会看到类似「Authorization complete. You can close this tab and return to Claude.」的提示。
回到 Claude Desktop,你会看到 MCP 注册成功的消息,如下图。
Figure 3:Claude Desktop 中 MCP 服务器注册成功
接下来 Claude Desktop 会通过 MCP 的 tools/list 调用发现 WebSearchTool。只要模型需要联网获取最新信息,它就会自动调用这个工具。
测试与验证
在你常用的界面里(比如 Chat 或 Cowork),发一条必须联网才能回答的最新信息查询。你应该会看到一个工具执行确认框,说明 Claude 已经成功发现了 Web Search 工具。确认之后,回复中就会带上这次网页搜索的结果。
对话框会显示 Claude 想执行的查询,并给出三个选项:拒绝(Deny)、本次任务允许(Allow for this task)、允许一次(Allow once)。批准后,Web Search 的结果就会包含在回复中。
清理资源
如果你在跟随本文操作时创建了资源,按以下步骤删除:
# 删除网关目标
aws bedrock-agentcore-control delete-gateway-target --gateway-identifier <gateway-id> --target-id <target-id> --region $AWS_REGION
# Delete the gateway (only if it was created for this walkthrough)
aws bedrock-agentcore-control delete-gateway --gateway-identifier <gateway-id> --region $AWS_REGION
# Delete the IAM policy (only if it was created for this walkthrough)
aws iam delete-role-policy --role-name websearch-gateway-role --policy-name websearch-gateway-policy
# Delete the IAM role (only if it was created for this walkthrough)
aws iam delete-role --role-name websearch-gateway-role
# Delete the Cognito application client
aws cognito-idp delete-user-pool-client --user-pool-id $USER_POOL_ID --client-id <client-id> --region $AWS_REGION
# Delete the Cognito identity provider
aws cognito-idp delete-identity-provider --user-pool-id $USER_POOL_ID --provider-name IAMIdentityCenterIdP --region $AWS_REGION
# Delete the Cognito pool domain
aws cognito-idp delete-user-pool-domain --user-pool-id $USER_POOL_ID --domain <your-unique-prefix> --region $AWS_REGION
删除 Cognito 用户池
aws cognito-idp delete-user-pool --user-pool-id $USER_POOL_ID --region $AWS_REGION
最后,在管理账户的 IAM Identity Center 控制台中,删除第 2 步创建的 SAML 应用。
结语
本文完整演示了如何把 AgentCore 上的 Web Search 集成到 Claude Desktop。这里用的是 AWS IAM Identity Center 作为身份提供商(IdP),但同样的方案也适用于任何兼容 SAML 或 OIDC 的身份提供商。你可以在 Amazon Cognito 中把自己的 IdP 配置为联合身份源,直接替换当前的方案。这样一来,无需引入第三方依赖就能补上 Web 搜索能力的缺口,而且所有查询都留在你的 AWS 边界内。
要动手实践,按上面的步骤在自己的环境中完成集成即可。想了解网关的高级配置,参见 AgentCore Gateway 开发者指南。想深入了解 Web Search,参见 Web Search 文档。