ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

转变数据交互:在 Amazon Bedrock AgentCore Runtime 上部署 Elastic 的 MCP 服务器以构建 agentic AI 应用程序

转变数据交互:在 Amazon Bedrock AgentCore Runtime 上部署 Elastic 的 MCP 服务器以构建 agentic AI 应用程序 1. 为什么要在 AgentCore Runtime 上跑 Elastic MCP 服务器Amazon Bedrock AgentCore Runtime 是 AWS 面向 agentic AI 应用推出的托管运行时它把会话隔离、身份鉴权、工具发现、可观测性这些原本要自己搭的活全包了。Elastic 的 MCP 服务器则是一个遵循 Model Context Protocol 的中间层把自然语言请求翻译成 Elasticsearch 查询再把命中结果整理成模型能读的结构。两者拼在一起你就能让 agent 用一句“帮我找巴黎的活动”直接打到 Elasticsearch 索引上不用手写 DSL。这套组合适合谁一类是做企业知识检索的团队手里已经有 Elasticsearch 集群想让 LLM 直接查另一类是搭 agentic AI 应用的开发者需要给 agent 挂一个“能查结构化数据”的工具又不想自己维护一套 HTTP 网关。MCP 协议的好处是工具发现是动态的agent 启动时通过tools/list拿到可用工具运行时通过tools/call执行整个链路是标准化的 JSON-RPC 2.0。我试过把本地 MCP 原型直接搬到 AgentCore Runtime最大的感受是身份鉴权这块省心。AgentCore 用 IAM 做入站鉴权SigV4 签名由客户端 SDK 处理MCP 服务器本身不用管 token 校验。会话隔离也是自动的每个客户端会话拿到独立的Mcp-Session-Id无状态服务器也能维持对话上下文。整条链路是这样的Python 客户端带上 SigV4 签名请求 AgentCore Runtime 的调用端点Runtime 把请求转发给容器里的 Elastic MCP 服务器MCP 服务器解析tools/call里的query_body向 Elasticsearch 发起检索结果以 SSE 流式返回客户端解析后展示。下面按部署顺序拆开讲每一步都给可复制的配置。2. 前置准备Elasticsearch 连接与 TaoToken 模型接入在动 AgentCore 之前先把两个外部依赖确认好Elasticsearch 集群和模型调用通道。Elasticsearch 这边你需要一个可访问的端点以及一个能读目标索引的 API Key。索引结构建议提前建好比如本文演示用的events索引字段包括name、description、venue、address、start_date、price_range、type。MCP 服务器不会替你建索引它只负责查询。连接信息通过环境变量传给容器格式是ELASTICSEARCH_URL和ELASTICSEARCH_API_KEY后面在 AgentCore 配置里会用到。模型调用通道这块AgentCore Runtime 本身负责 agent 的托管和工具编排但底层基础模型走的是 Amazon Bedrock。如果你在本地调试阶段想先用一个统一的 OpenAI 兼容入口来验证 MCP 工具调用链路可以用 TaoToken 的 API 做过渡。它的 Base URL 是https://taotoken.net/api模型 ID 按你实际用的填比如claude-sonnet-4-5这类。API Key 在控制台生成地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。生成后先存到环境变量里别硬编码进脚本。这里要强调一点TaoToken 在这套方案里扮演的是模型调用入口不是替代 AgentCore Runtime。AgentCore 负责 agent 的部署、会话、工具发现TaoToken 负责把模型请求发出去。两者职责不重叠。如果你只想快速验证 MCP 服务器能不能正确返回 Elasticsearch 数据可以先用 TaoToken 的模型对话页手动发一轮请求确认工具描述和参数格式没问题再去配 AgentCore。模型对话入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。依赖清单先列一下后面脚本会用到依赖用途获取方式Elasticsearch 8.x数据存储与检索自建或云托管Elasticsearch API KeyMCP 服务器读索引集群控制台生成Docker构建 MCP 服务器镜像本地安装AWS CLI推送镜像到 ECR配置好凭证Python 3.10运行客户端本地安装TaoToken API Key模型调用过渡验证控制台生成环境变量建议统一写进一个.env文件本地调试时 source 一下export ELASTICSEARCH_URLhttps://your-cluster.es.us-west-2.aws.found.io:443 export ELASTICSEARCH_API_KEYyour_base64_api_key export TAOTOKEN_API_KEYsk-xxxxxxxx export AWS_REGIONus-west-2 export AWS_ACCOUNT_ID123456789012确认 Elasticsearch 能通先用 curl 打一发curl -s -H Authorization: ApiKey $ELASTICSEARCH_API_KEY \ $ELASTICSEARCH_URL/events/_count | jq返回{count: N, ...}就说明连接和权限都没问题。这一步别跳过后面 MCP 服务器报的很多错根因都在这里。3. 可复制配置MCP 服务器容器化与 AgentCore Runtime 注册这一节是全文的核心给出从镜像构建到 Runtime 注册的完整可复制配置。先看 MCP 服务器的容器化。Elastic 官方提供了 MCP 服务器仓库我们用它的Dockerfile-8000构建暴露 8000 端口。部署脚本deploy-elastic-mcp.sh大致做四件事拉仓库、构建镜像、建 ECR 仓库、推镜像。关键命令如下git clone https://github.com/elastic/mcp-server-elasticsearch.git cd mcp-server-elasticsearch docker build -f Dockerfile-8000 -t elastic-mcp-server:latest . aws ecr create-repository \ --repository-name elastic-mcp-server \ --region $AWS_REGION aws ecr get-login-password --region $AWS_REGION | \ docker login --username AWS --password-stdin \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com docker tag elastic-mcp-server:latest \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/elastic-mcp-server:latest docker push \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/elastic-mcp-server:latest镜像推上去后进 AWS 控制台的 Amazon Bedrock AgentCore路径是 Build and Deploy Agent Runtime Host Agent。基本配置里填{ name: hosted_agent_elastic_mcp, containerImage: 123456789012.dkr.ecr.us-west-2.amazonaws.com/elastic-mcp-server:latest, protocol: MCP, inboundAuth: IAM, serviceRole: Create and use a new service role, environmentVariables: { ELASTICSEARCH_URL: https://your-cluster.es.us-west-2.aws.found.io:443, ELASTICSEARCH_API_KEY: your_base64_api_key } }协议选 MCP入站身份验证选 Use IAM username服务角色选新建。环境变量这里就是前面准备的 Elasticsearch 连接信息容器启动时会读到。创建完成后在 View invocation code 里复制 Agent Runtime ARN形如arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/hosted_agent_elastic_mcp-xWSaxNGjf5这个 ARN 是客户端调用的入口记下来。如果你用 Cline MCP 或 Claude Code 这类客户端做本地联调配置三件套要写全Base URL 填 AgentCore Runtime 的调用端点Key 用 IAM 凭证SigV4 签名Model ID 填你在 Bedrock 里选的模型。以 Cline 的 MCP 配置为例{ mcpServers: { elastic-agentcore: { url: https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/hosted_agent_elastic_mcp-xWSaxNGjf5/invocations, transport: sse, auth: { type: awsSigV4, service: bedrock-agentcore, region: us-west-2 } } } }注意transport用sse因为 AgentCore 的 MCP 响应是 Server-Sent Events 格式。auth里的 service 和 region 要和 Runtime 一致否则签名对不上会返回 403。Codex 的auth.json如果也要接这套结构类似把 provider 指向 AgentCore 端点凭证走 AWS 默认链。不过 Codex 对 SSE 的支持要看版本建议先用 Python 客户端验证通了再换客户端。4. 验证请求端到端检索一次 Elasticsearch 数据配置完 Runtime接下来用 Python 客户端跑一次端到端验证。客户端要做三件事SigV4 签名、发tools/call请求、解析 SSE 响应。先装依赖python3 -m venv venv source venv/bin/activate pip install boto3 botocore httpx核心的鉴权类这样写import boto3 from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest class AWSAuth: def __init__(self, servicebedrock-agentcore, regionus-west-2): self.session boto3.Session() self.credentials self.session.get_credentials() self.region region self.service service def get_auth_headers(self, url, methodPOST, bodyNone): request AWSRequest(methodmethod, urlurl, databody) SigV4Auth(self.credentials, self.service, self.region).add_auth(request) headers dict(request.headers) headers[Content-Type] application/json headers[Accept] application/json, text/event-stream return headers然后构造 MCP 请求。先列工具确认 MCP 服务器注册了哪些工具import json, httpx AGENT_ARN arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/hosted_agent_elastic_mcp-xWSaxNGjf5 ENDPOINT fhttps://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/{AGENT_ARN.split(/)[-1]}/invocations auth AWSAuth() list_payload {jsonrpc: 2.0, method: tools/list, id: 1} body json.dumps(list_payload) headers auth.get_auth_headers(ENDPOINT, bodybody) resp httpx.post(ENDPOINT, contentbody, headersheaders, timeout30) print(resp.status_code) print(resp.text[:500])正常会返回工具列表里面能看到search工具及其参数 schema。接着发一次真实检索chat_request { jsonrpc: 2.0, id: 3, method: tools/call, params: { name: search, arguments: { index: events, query_body: { query: { bool: { should: [ {match: {name: paris}}, {match: {description: paris}}, {match: {venue: paris}}, {match: {address: paris}} ] } }, size: 10 } } } } body json.dumps(chat_request) headers auth.get_auth_headers(ENDPOINT, bodybody) resp httpx.post(ENDPOINT, contentbody, headersheaders, timeout60)响应是 SSE 格式以data:开头解析时去掉前缀再json.loadsif resp.text.startswith(data: ): response_json json.loads(resp.text[6:]) result response_json.get(result, {}) for item in result.get(content, []): if item[type] text: events json.loads(item[text]) for e in events: print(e[name], e[venue], e[start_date])跑通后你会看到类似输出Paris Fashion Week Murray-Howell Theater 2026-04-02这说明 agent 已经能正确调用 Elastic 数据了。整个链路是客户端 SigV4 签名 → AgentCore Runtime 鉴权 → MCP 服务器解析tools/call→ Elasticsearch 执行 bool query → 结果 SSE 返回 → 客户端解析展示。再补一个复杂查询的验证带日期范围和价格过滤{ jsonrpc: 2.0, method: tools/call, params: { name: search, arguments: { index: events, query_body: { query: { bool: { must: [ {range: {start_date: {gte: 2026-01-01}}}, {term: {price_range: $$$}} ], should: [ {match: {type: Fashion}}, {match: {type: Music}} ] } }, size: 20 } } } }这个请求验证的是 MCP 服务器能不能透传复杂 DSL。如果返回结果符合预期说明query_body是原样传给 Elasticsearch 的没有做额外改写。5. 本篇常见错排查401、local proxy failed 与 reading choices部署过程中最容易卡在几个报错上逐个说。401 Unauthorized / 403 Forbidden。AgentCore 的入站鉴权走 IAM签名不对就 401。检查三点SigV4Auth的 service 是不是bedrock-agentcoreregion 是不是和 Runtime 一致AWSRequest的 url 是不是完整的调用端点。另外Content-Type和Accept头要在签名之后手动加别加进签名体里否则签名对不上。如果你用的是临时凭证确认boto3.Session()能拿到有效 token。local proxy failed。这个报错通常出现在客户端配置里填了本地代理地址但代理没起来。AgentCore 的调用端点是公网 HTTPS不需要本地代理。检查你的 MCP 客户端配置把url直接指向https://bedrock-agentcore.region.amazonaws.com/runtimes/runtime-id/invocations别经过任何中间层。如果你在 Cline 里配了proxy字段删掉。reading choices / 解析 SSE 失败。这个报错说明客户端把 SSE 响应当普通 JSON 解析了。AgentCore 的 MCP 响应以data:开头必须先去前缀再json.loads。如果你用 OpenAI SDK 直接打这个端点它会尝试解析choices字段自然找不到。正确做法是用httpx或requests拿原始文本手动处理 SSE。代码里那段if response.text.startswith(data: )就是干这个的。OAuth 相关报错。如果你在 Runtime 配置里选了 OAuth 而不是 IAM客户端就要走 OAuth 流程拿 token。本文用的是 IAM 入站鉴权不需要 OAuth。如果你确实要用 OAuth确认 token 端点、client id、scope 都配对且 token 没过期。混用 IAM 和 OAuth 配置会导致签名和 token 双重校验失败。Elasticsearch 连接超时。MCP 服务器容器里读的是环境变量ELASTICSEARCH_URL如果这个地址在容器网络里不可达会报连接超时。确认你的 Elasticsearch 端点允许来自 AgentCore Runtime 所在 VPC 的访问安全组和网络 ACL 都放行。本地 curl 能通不代表容器里能通网络路径不一样。tools/list 返回空。如果tools/list返回的 tools 数组是空的说明 MCP 服务器没正确注册工具。检查镜像是不是用Dockerfile-8000构建的端口是不是 8000Runtime 协议是不是选的 MCP。协议选错会导致工具发现失败。排障时建议先单独验证 Elasticsearch 连通性再验证 MCP 服务器本地能不能起最后才查 AgentCore 配置。分层排查比一上来就怀疑 Runtime 高效得多。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有 SigV4 签名和 SSE 解析的完整示例。6. 长期运行与 CTA把 MCP 工具挂进 Coding Plan验证通过后如果你打算把这套 Elastic MCP 工具长期挂在 agent 工作流里比如让 coding agent 在写代码时随时查内部文档索引建议走 Coding Plan 而不是每次手动发请求。Coding Plan 的入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它适合需要持续调用模型和工具的场景。具体做法是把 AgentCore Runtime 的调用端点注册成 Coding Plan 里的一个工具源模型在需要查 Elasticsearch 时自动触发tools/call。这样你写代码时问“我们内部 API 的鉴权字段叫什么”agent 会自己去查索引不用你切窗口。API Key 管理在控制台 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 建议给 Coding Plan 单独生成一个 Key和本地调试的分开方便按用途轮换。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后提醒一个实操细节AgentCore Runtime 的容器镜像更新后要在控制台重新部署一次环境变量不会自动继承旧版本。我踩过的坑是改了 Elasticsearch 端点但忘了重新部署客户端一直打到旧集群排查了半天。每次改配置后确认 Runtime 状态是 Active 再发请求。
返回列表