用 Bedrock AgentCore 和 Mistral Vibe 搭一个可上线的电商 MCP Server

2026-07-09 26 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:12 分钟

MCP Server 不再只是给本地 IDE 塞几个工具函数。这个方案把电商场景里的商品搜索、下单、评论提交和退货处理做成可被 Agent 调用的工具,并用 Amazon Bedrock AgentCore 承载运行时,用 Amazon Cognito 和双层 JWT 做身份边界,最后连接到 Mistral AI Studio 的 Vibe。重点不是“能跑一个 demo”,而是把数据、身份、部署和连接器一起拉到接近生产环境的形态。

这套架构解决的不是聊天,而是可控执行

电商 MCP Server 的核心价值在于:Agent 不直接碰数据库,也不绕过业务规则。它只能调用服务暴露的 MCP tools,比如:

  • search_products:按关键词、分类或价格范围检索商品。
  • place_order:创建订单,并校验用户身份与库存逻辑。
  • submit_review:提交商品评价,通常需要确认购买关系或登录态。
  • process_return:处理退货申请,受订单状态、时间窗口和策略约束。

底层数据使用 Amazon DynamoDB,身份管理交给 Amazon Cognito。Bedrock AgentCore 负责把 MCP Server 运行起来并暴露给 Agent 生态,Mistral Vibe 则作为上层 AI Studio 里的连接入口。

这里的边界很关键:MCP tool 应该是业务 API 的薄封装,而不是让模型拼 DynamoDB 查询。模型负责意图理解,服务负责授权、校验、幂等和审计。

双层 JWT:用户身份和连接器身份要分开

文章强调了两层 JWT 认证,这一点非常适合生产 MCP Server。

一层用于确认“调用者是谁”。比如用户通过 Cognito 登录后拿到 access token,MCP Server 根据 token 判断这个用户能不能下单、退货或提交评论。

另一层用于确认“连接器是不是可信”。Mistral Vibe 连接 MCP Server 时,服务端还需要验证连接器级别的 token,避免任何拿到 endpoint 的客户端都能调用工具。

可以这样实践:把请求头拆成两个明确的身份来源。

POST /mcp HTTP/1.1
Host: mcp.example.com
Content-Type: application/json
Authorization: Bearer <cognito_user_access_token>
X-Connector-Authorization: Bearer <vibe_connector_jwt>

{
  "jsonrpc": "2.0",
  "id": "req-001",
  "method": "tools/call",
  "params": {
    "name": "search_products",
    "arguments": {
      "query": "wireless keyboard",
      "limit": 5
    }
  }
}

服务端校验时也要保持两套配置,不要把用户池 token 和连接器 token 混在一个 verifier 里。下面是一个可改造的 Node.js 示例,假设你使用 jose 校验 JWT。运行前需要替换 COGNITO_JWKS_URLCONNECTOR_JWKS_URLCOGNITO_ISSUERCONNECTOR_ISSUER

mkdir mcp-auth-demo
cd mcp-auth-demo
npm init -y
npm install express jose
// server.js
const express = require("express");
const { createRemoteJWKSet, jwtVerify } = require("jose");

const app = express();
app.use(express.json());

const userJwks = createRemoteJWKSet(new URL(process.env.COGNITO_JWKS_URL));
const connectorJwks = createRemoteJWKSet(new URL(process.env.CONNECTOR_JWKS_URL));

function bearer(value) {
  if (!value || !value.startsWith("Bearer ")) {
    throw new Error("missing bearer token");
  }
  return value.slice("Bearer ".length);
}

async function verifyJwt(token, jwks, issuer, audience) {
  const result = await jwtVerify(token, jwks, {
    issuer,
    audience
  });
  return result.payload;
}

app.post("/mcp", async (req, res) => {
  try {
    const userToken = bearer(req.headers.authorization);
    const connectorToken = bearer(req.headers["x-connector-authorization"]);

    const [user, connector] = await Promise.all([
      verifyJwt(userToken, userJwks, process.env.COGNITO_ISSUER, process.env.COGNITO_AUDIENCE),
      verifyJwt(connectorToken, connectorJwks, process.env.CONNECTOR_ISSUER, process.env.CONNECTOR_AUDIENCE)
    ]);

    const toolName = req.body?.params?.name;
    if (toolName === "place_order" && !user.sub) {
      return res.status(403).json({ error: "user identity required" });
    }

    res.json({
      jsonrpc: "2.0",
      id: req.body.id,
      result: {
        content: [
          {
            type: "text",
            text: `Tool ${toolName} accepted for user ${user.sub} via connector ${connector.sub}`
          }
        ]
      }
    });
  } catch (err) {
    res.status(401).json({ error: err.message });
  }
});

app.listen(3000, () => {
  console.log("MCP auth demo listening on http://localhost:3000/mcp");
});
export COGNITO_JWKS_URL="https://cognito-idp.<region>.amazonaws.com/<user-pool-id>/.well-known/jwks.json"
export COGNITO_ISSUER="https://cognito-idp.<region>.amazonaws.com/<user-pool-id>"
export COGNITO_AUDIENCE="<app-client-id>"
export CONNECTOR_JWKS_URL="https://<connector-issuer>/.well-known/jwks.json"
export CONNECTOR_ISSUER="https://<connector-issuer>"
export CONNECTOR_AUDIENCE="<mcp-server-audience>"
node server.js

这段代码不是原方案的完整实现,但它展示了生产 MCP Server 里最容易被低估的一件事:同一次工具调用里可能同时有“用户授权”和“连接器授权”。两者失败任何一个,都不应该继续执行业务动作。

MCP tool 设计要像业务接口,不要像数据库快捷方式

电商工具很容易被设计得过宽。比如 update_order 这种工具看起来通用,实际会把状态机、退款策略、客服权限和库存回滚全部暴露给模型。更稳妥的方式是把工具收敛成明确动作:place_orderprocess_returnsubmit_review

可以这样定义工具 schema:

{
  "name": "process_return",
  "description": "Create a return request for an existing order item after validating user ownership and return policy.",
  "inputSchema": {
    "type": "object",
    "required": ["orderId", "itemId", "reason"],
    "properties": {
      "orderId": {
        "type": "string",
        "description": "The customer order ID"
      },
      "itemId": {
        "type": "string",
        "description": "The order item ID to return"
      },
      "reason": {
        "type": "string",
        "enum": ["DAMAGED", "WRONG_ITEM", "NOT_AS_DESCRIBED", "NO_LONGER_NEEDED"]
      }
    }
  }
}

几个工程判断值得坚持:

  • 参数里使用业务 ID,不让模型传 DynamoDB partition key 结构。
  • 返回值给人类可读摘要,也保留机器可判断的状态码或枚举。
  • 写操作必须做幂等,例如下单请求可以带 clientRequestId
  • 所有写工具记录审计日志,包括 user id、connector id、tool name、请求摘要和结果。

用 CDK 管住资源生命周期

原文方案使用 AWS CDK 部署,这对 MCP Server 很重要。因为它至少涉及计算运行时、DynamoDB 表、Cognito 用户池、权限策略和连接器配置。手工点控制台能跑通一次,但很难复现、审计和清理。

下面是一个可改造的 CDK TypeScript 片段,展示 DynamoDB 和 Cognito 的基础资源。它不是完整 Bedrock AgentCore 部署模板,但适合作为电商 MCP Server 的数据与身份底座。

mkdir ecommerce-mcp-infra
cd ecommerce-mcp-infra
npx cdk init app --language typescript
npm install aws-cdk-lib constructs
// lib/ecommerce-mcp-infra-stack.ts
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as cognito from "aws-cdk-lib/aws-cognito";

export class EcommerceMcpInfraStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const products = new dynamodb.Table(this, "ProductsTable", {
      partitionKey: { name: "productId", type: dynamodb.AttributeType.STRING },
      billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
      removalPolicy: cdk.RemovalPolicy.DESTROY
    });

    const orders = new dynamodb.Table(this, "OrdersTable", {
      partitionKey: { name: "userId", type: dynamodb.AttributeType.STRING },
      sortKey: { name: "orderId", type: dynamodb.AttributeType.STRING },
      billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
      removalPolicy: cdk.RemovalPolicy.DESTROY
    });

    const userPool = new cognito.UserPool(this, "CustomersUserPool", {
      selfSignUpEnabled: true,
      signInAliases: { email: true }
    });

    const appClient = userPool.addClient("McpClient", {
      authFlows: {
        userPassword: true,
        userSrp: true
      }
    });

    new cdk.CfnOutput(this, "ProductsTableName", { value: products.tableName });
    new cdk.CfnOutput(this, "OrdersTableName", { value: orders.tableName });
    new cdk.CfnOutput(this, "UserPoolId", { value: userPool.userPoolId });
    new cdk.CfnOutput(this, "UserPoolClientId", { value: appClient.userPoolClientId });
  }
}
npm run build
npx cdk bootstrap
npx cdk deploy

生产环境里不要直接使用 RemovalPolicy.DESTROY。上面的设置方便实验后清理;真实订单、评论和退货数据应该启用保留策略、备份、加密和更严格的 IAM 权限。

连接到 Mistral Vibe 前,先把契约压实

Vibe 连接 MCP Server 时,最容易出问题的不是“连不上”,而是工具语义不稳定。建议在接入前完成这几项检查:

  • 每个工具的 description 都说明何时使用、何时不要使用。
  • 写操作工具返回明确结果,比如 ORDER_CREATEDRETURN_REJECTED_POLICY_EXPIRED
  • 错误信息能给模型下一步行动线索,但不泄露内部表名、策略 ARN 或 token 细节。
  • 连接器 JWT 和用户 JWT 的过期时间、audience、issuer 都有独立校验。
  • DynamoDB 访问路径来自服务端逻辑,而不是模型可控字段。

一个实用的系统提示词可以这样写,作为连接器侧的行为约束:

You are an ecommerce assistant connected to MCP tools.
Use search_products before recommending unavailable products.
Use place_order only after the user confirms product, quantity, shipping address, and payment intent.
Use process_return only for an authenticated user's own order.
Never invent order status, return eligibility, inventory, or review submission results. Call the relevant tool instead.

落地建议:把 Agent 当成新客户端,而不是新后门

这类电商 MCP Server 的正确打开方式,是把 Agent 当成一个高权限、需要严密约束的新客户端。它可以提升搜索、下单和售后流程的自然语言体验,但不能绕过已有的业务边界。

采用时可以按这个顺序推进:先实现只读的 search_products,验证 Vibe 到 Bedrock AgentCore 的连接和认证;再接入低风险写操作,比如 submit_review;最后才开放 place_orderprocess_return 这类会影响订单、库存和退款的工具。

上线前的最低检查清单:JWT 双层校验、工具级授权、写操作幂等、审计日志、DynamoDB 最小权限、CDK 可重复部署、清理流程可执行。做到这些,MCP Server 才不像一个漂亮的 demo,而更像一个能接入真实电商系统的服务边界。


相关推荐