用 Amazon Bedrock 与 MCP Server 构建可调用的视觉智能

2026-07-16 28 预计阅读时间: 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.

预计阅读时间:10 分钟

视觉模型并不难调用,难的是把“读取图片、选择模型、组织提示词、解析结果、执行后续动作”稳定地接入不同应用。Computer Vision MCP Server 展示了一种更清晰的做法:把视觉能力封装成 MCP 工具,通过统一接口交给 AI Agent 调用,再由 Amazon Bedrock 中的多模态模型完成图像理解。

这种架构的价值不只在于少写几段 API 代码。它把模型、工具和业务流程分开,使桌面助手、开发工具、客服系统或自动化工作流能够复用同一套视觉能力。

MCP 把视觉模型变成标准工具

传统视觉集成通常直接写在应用内部:前端上传图片,后端转换格式,调用某个模型 API,然后把模型返回值映射为业务字段。这种方式在单一应用中足够直接,但模型一换、调用方一多,适配代码便会迅速扩散。

引入 MCP 后,可以把职责拆成三层:

  • MCP 客户端或 Agent:理解用户目标,决定何时调用视觉工具。
  • Computer Vision MCP Server:定义工具名称、输入参数和输出格式,并处理图片读取、校验与模型调用。
  • Amazon Bedrock:提供受管的模型推理接口,完成图片描述、分类、信息提取或视觉问答。

例如,Agent 收到“检查这张仓库照片里是否有未佩戴安全帽的人”后,不需要知道图片如何编码,也不需要了解 Bedrock 请求结构。它只需调用一个类似 analyze_image 的 MCP 工具,并传入图片与任务描述。

统一接口也让工具更容易组合。一次视觉分析的结果可以继续交给工单工具、数据库工具或通知工具,而不必让视觉服务器承担完整业务流程。

工具设计决定了结果是否可用

一个只返回长段自然语言的视觉工具很容易演示,却不一定适合生产系统。工具契约应围绕业务决策设计,而不是简单暴露模型能力。

可以考虑提供几类边界明确的工具:

  • describe_image:生成适合人类阅读的图片描述。
  • extract_visual_fields:按照指定字段提取标签、编号、日期等信息。
  • classify_image:从调用方提供的有限类别中选择结果。
  • answer_visual_question:针对图片回答一个具体问题。

如果下游程序需要自动执行动作,返回值最好包含结构化字段,例如:

{
  "decision": "review",
  "confidence": 0.74,
  "observations": [
    "A person is visible near the loading area",
    "A helmet cannot be confirmed because the image is blurred"
  ],
  "requires_human_review": true
}

这里的 confidence 不应被当作经过校准的客观概率,除非系统确实完成过评估与校准。更稳妥的做法是设置人工复核条件,并保存模型版本、提示词版本和原始输入的审计记录。

可以这样实践:创建一个最小视觉 MCP Server

下面是一个可改造的最小示例。它使用 Python MCP SDK 暴露 analyze_image 工具,并通过 Amazon Bedrock Runtime 的 Converse API 调用支持视觉输入的模型。示例假设本机已经配置 AWS 凭证,并且所选区域和账号可以访问对应的多模态模型。

安装依赖:

python -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]" boto3

将以下代码保存为 vision_server.py。运行前需要把 BEDROCK_MODEL_ID 改成账号所在区域中已获准使用、且支持图像输入的 Bedrock 模型 ID。

import base64
import os
from pathlib import Path

import boto3
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("bedrock-vision")

MODEL_ID = os.environ["BEDROCK_MODEL_ID"]
AWS_REGION = os.getenv("AWS_REGION", "us-east-1")
MAX_IMAGE_BYTES = 5 * 1024 * 1024

bedrock = boto3.client("bedrock-runtime", region_name=AWS_REGION)


def load_image(image_path: str) -> tuple[str, bytes]:
    path = Path(image_path).expanduser().resolve()
    if not path.is_file():
        raise ValueError(f"Image does not exist: {path}")

    image = path.read_bytes()
    if len(image) > MAX_IMAGE_BYTES:
        raise ValueError("Image exceeds the 5 MiB limit")

    formats = {
        ".jpg": "jpeg",
        ".jpeg": "jpeg",
        ".png": "png",
        ".gif": "gif",
        ".webp": "webp",
    }
    image_format = formats.get(path.suffix.lower())
    if image_format is None:
        raise ValueError("Supported formats: jpg, jpeg, png, gif, webp")

    return image_format, image


@mcp.tool()
def analyze_image(image_path: str, question: str) -> str:
    """Analyze a local image and answer one focused question."""
    image_format, image = load_image(image_path)

    response = bedrock.converse(
        modelId=MODEL_ID,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "image": {
                            "format": image_format,
                            "source": {"bytes": image},
                        }
                    },
                    {
                        "text": (
                            "Inspect the image carefully. Distinguish visible facts "
                            "from uncertainty. If evidence is insufficient, say so. "
                            f"Question: {question}"
                        )
                    },
                ],
            }
        ],
        inferenceConfig={"maxTokens": 800, "temperature": 0.1},
    )

    parts = response["output"]["message"]["content"]
    return "\n".join(part["text"] for part in parts if "text" in part)


if __name__ == "__main__":
    mcp.run(transport="stdio")

配置环境变量并启动服务器:

export AWS_REGION="us-east-1"
export BEDROCK_MODEL_ID="替换为支持视觉输入的模型ID"
python vision_server.py

实际接入 MCP 客户端时,通常由客户端通过标准输入输出启动该进程。例如可以采用下面的配置形式;具体字段名称需要按所用客户端调整:

{
  "mcpServers": {
    "bedrock-vision": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["/absolute/path/to/vision_server.py"],
      "env": {
        "AWS_REGION": "us-east-1",
        "BEDROCK_MODEL_ID": "替换为支持视觉输入的模型ID"
      }
    }
  }
}

这段示例使用本地文件路径,适合开发环境。在容器、远程 Agent 或多租户服务中,可以把输入改成受控的对象存储引用或经过大小限制的 Base64 数据,同时避免让调用方读取任意服务器文件。

从演示走向生产要补上的边界

视觉 Agent 会把模型的不确定性带入自动化流程,因此上线前应明确以下约束:

  • 最小权限:MCP Server 使用独立 IAM 身份,只允许调用指定 Bedrock 模型及必要资源。
  • 输入隔离:限制文件类型、尺寸、来源和可访问目录,防止路径遍历、超大文件与恶意内容。
  • 数据治理:确认图片是否包含人脸、证件、医疗信息或内部文档,并配置相应的保留与审计策略。
  • 结构化输出:对需要机器执行的结果使用 JSON Schema 校验,解析失败时不得默认放行。
  • 人工复核:安全、金融、医疗和合规决策不应只依赖一次视觉推理。
  • 可观测性:记录工具名称、延迟、模型 ID、令牌消耗和错误类型,但避免把敏感图片或完整提示词直接写入普通日志。
  • 评估集:用真实业务图片建立固定测试集,比较准确率、拒答表现、成本和延迟,而不是只检查几个成功样例。

Computer Vision MCP Server 的核心意义,是把视觉智能从一次性模型调用变成可发现、可组合、可治理的工具。落地时应从一个问题明确、风险可控的场景开始,例如商品图片归类、设备面板读数辅助提取或工单附件摘要。确认工具契约和评估指标稳定后,再让 Agent 执行更复杂的后续动作。


相关推荐