使用 Python 入门 Model Context Protocol(MCP)——将 MCP 应用推向生产 (Bringing MCP Apps to Pro

75 阅读19分钟

欢迎来到本书的最后一章。很棒,你已经坚持到这里!你已经学会了如何构建服务器和客户端,可能也在思考:怎样迈出最后一步,把你构建的东西分享给全世界?

这个问题问得很好。本章将带你逐一梳理需要考虑的事项,确保你的 MCP 应用在生产环境中经过良好测试、稳定可靠、安全合规并具备优异性能。我们开始吧!

本章涵盖以下主题:

  • 架构与设计:讨论模块化设计、集成模式,以及 AI 对架构带来的特定影响
  • 打包与分发:讨论不同的打包选项、独立/嵌入式形态、发布渠道与语义化版本
  • 测试与部署自动化:介绍单元测试、集成测试与 AI 测试等策略,并将这些测试纳入 CI/CD,以“有把握地”发布
  • 运维与可观测性:讨论扩展性、弹性模式、可观测性、治理与前瞻性

架构与设计

在设计你的 MCP 应用时,需要牢记若干架构考量:包括模块化设计、集成模式,以及 AI 对架构的影响。本节我们将讨论:

  • 集成模式:MCP 如何融入你现有架构?可采用哪些模式以实现无缝集成?
  • 文档化:如何为架构与设计决策编写文档,以确保清晰性与可维护性?
  • 架构评审:从哪些关键方面审视你的架构,以确保其满足需求并具备可扩展、可维护与安全特性?

有了概览,我们分别展开。

集成模式

MCP 自带一组用于促进客户端与服务器无缝通信的集成模式。不过,如果你使用 Streamable HTTP 或 SSE 作为传输,服务器会以 HTTP 的方式通过 Web 应用托管,并且很可能组织为类似 RESTful API 的形态。这意味着你可能需要为 Web API 与 MCP 的沟通开发或使用特定中间件,以满足日志、安全等需要。其工作方式如下:注意 Web API 中使用的中间件,同时注意 Web API 多半是 RESTful,而客户端与服务器之间则按 MCP 协议使用 JSON-RPC:

image.png

(图 12.1 – 集成模式流程图)

在该时序图中可以看到各组件如何交互。用户向 Web API 发起请求,Web API 先通过其认证中间件校验请求;若通过,Web API 将请求数据转发给客户端。随后客户端使用 JSON-RPC 消息与服务器通信。

文档化

良好的文档有助于我们理解系统的各个大块以及它们如何协同工作,这能显著提升当前与未来开发者的理解与维护效率。文档对开发者与用户都很重要:文档完善的代码更易于理解、维护与使用。就文档化而言,需要考虑:

  • 代码注释与文档生成:代码应当有良好的注释,尤其是输入输出的契约定义。陈旧的信息有时比没有文档更糟,因此应尽可能从代码自动生成文档。理想状态是代码可生成 OpenAPI(原 Swagger)文档。例如,下述代码对路由加上了可被框架用于生成文档的元信息:

    from fastapi import FastAPI
    from pydantic import BaseModel
    from typing import List
    app = FastAPI()
    class Booking(BaseModel):
       id: int
       title: str
       description: str = False
       when: str
    @app.get("/booking/", response_model=Booking, tags=["bookings"],
        summary="Book a trip",  description="Lets user book a trip[]")
    def book_trip():
        return Booking(id=1, title="Trip to Paris", description="A
            wonderful trip to Paris", when="2023-09-15")
    

    当代码使用了诸如 tagssummary 等注解,框架即可自动生成 OpenAPI 文档。无论选择何种框架与运行时,都应确保代码便于文档化与文档生成。

  • 测试亦是文档:测试往往是理解功能预期行为的最佳途径。它提供了具体的行为示例,并能澄清复杂逻辑背后的意图。务必包含覆盖多种场景与边界条件的综合测试。

  • 加入上下文流程图与边界情况处理:Mermaid 图在业界日益常见,GitHub 也支持其渲染各类流程图、时序图等。考虑用 Mermaid 或其他方式绘制这些图。直观的可视化能为开发者与代码使用者节省大量时间。

架构评审

你的架构应考虑以下方面:

  • 模块化设计:将功能划分为清晰的边界,使各领域各自独立成模块。不同运行时有不同做法,但通用准则是:代码组织需直观、易懂、易维护;相关性强的代码尽量放在一起,模块间依赖最小化;并遵循“单一职责”原则——每个模块只有一个改变的理由。例如,不要把解析逻辑与业务逻辑放在同一模块。

  • 校验:实现健壮的数据校验机制以确保数据完整与正确。这包括输入校验、输出校验以及组件间契约校验。安全层面也相关,因为恶意方可能尝试利用系统漏洞。Python 的 MCP SDK 中常用 Pydantic 进行数据与配置校验。对输入与输出均使用此类库,有助于同时兼顾正确性与安全性。示例:

    from mcp.server.fastmcp import FastMCP
    from uuid import uuid4
    mcp = FastMCP(name="Tool Example")
    from pydantic import BaseModel
    class User(BaseModel):
        id: int
        name: str
        email: str
    users = []
    @mcp.tool()
    def create_user(user: User):
        # Create user logic here
        user.id = len(users) + 1
        users.append(user)
        return user
    if __name__ == "__main__":
        print("Starting MCP server...")
        mcp.run()
    

    其中 create_user 工具以 User 模型为输入,立即受益于校验与序列化。如下载荷会创建新用户:

    {
      "id": 0,
      "name": "chris",
      "email": "chris@example.com"
    }
    

    而如下载荷因缺少 id 会触发校验错误:

    {
      "name": "chris",
      "email": "chris@example.com"
    }
    

    如此即可为所有入站数据建立校验“闸门”,只允许正确数据进入系统。随后可按业务与安全需要,继续在落库前叠加更多规则。

  • AI 对架构的影响:若你同时交付客户端与服务器,客户端很可能能访问某个 AI 模型,这对架构提出了特别考量:客户端如何与模型通信、如何在客户端与服务器之间管理上下文、如何处理潜在的失败或超时。

    • 解耦架构:将内容管理、模型调用与 UI 解耦。
    • 延迟与可靠性,以及对 UI 的影响:与模型交互可能存在延迟。若模型响应较慢,UI 需保持可用并给出用户反馈;若模型因故障或限流而停止响应,也需优雅处理。同时应具备重试、熔断等降级与兜底机制(本章后续还会展开)。
    • Token 预算:Token 预算既是运行成本,也是架构问题。需要实施缓存等策略以优化 Token 使用。
    • 安全:落实安全最佳实践以保护应用与数据,包括保护 API、管理认证与授权、确保数据隐私与合规。尽可能践行“最小权限”,即让用户与服务仅访问其必需资源。相应地,你可能需要实现更细粒度的访问控制,并持续监控未授权访问企图。

打包与分发

在你写下第一行代码之前,就该想清楚你要构建的是什么。针对 MCP,你有多种方式来打包与分发你的应用。

打包选项

我们先看看几种常见的打包形态。

独立服务器(Standalone server) :可面向公众或私有使用。无论公有还是私有,都要考虑认证、授权与数据隐私。若在公司/组织内私发,还要考虑可发现性(内部团队如何找到并使用该服务)以及对内部政策的合规性。

嵌入式客户端/服务器(Embedded client/server) :通常包含客户端与服务端两个组件,且客户端很可能自带 AI 能力。因此必须评估隐私与安全、负责任 AI 的使用,以及可能适用的监管要求。

独立服务器

假设你的目标只构建一个 MCP 服务器:通常你要么包装一个已有 API,要么提供此前不存在的 API。既然是 MCP,就需要决定服务器运行位置。考虑点包括:

本地机器:此时服务器需要使用 STDIO 传输。因为运行在用户机器上,需从安全角度考虑沙箱:如何确保它不会访问不该访问的资源?是否允许它访问网络?这取决于你,但这些点都要权衡。参考文件系统 MCP 服务器示例,它通过配置限制可访问目录,并提供以容器方式运行的说明,以尽量缩小服务器权限范围(github.com/modelcontex…)。

通过 URL 远程访问:若服务器以远程方式访问,沙箱压力可能小一些,但必须重视认证与授权,以及端到端的 API 安全。可采用 OAuth2 或 API Key,并始终校验入站请求。此外考虑基于角色的访问控制(RBAC),避免用户对服务器功能拥有超出需要的权限。例如是否需要管理员、普通用户或访客等角色,以及各自能访问哪些资源与权限级别。

两种情况下,源码多半托管在 GitHub 等版本控制系统中。

嵌入式客户端/服务器

将 MCP 集成进既有架构需要周密规划。分发层面上,MCP 的实现通常与现有服务/应用一并部署。代码组织上,你仍可将它们做成可调用的独立服务(API/microservices),取舍在你。但务必认识到:交付 MCP 集成不仅是一个服务器,还包括一个 MCP 客户端。客户端负责与 MCP 服务器通信、处理请求并管理上下文。

分发渠道

你可以选择以下分发方式:

打包为 Docker 容器:无论部署到哪里,都能保证一致的运行环境。将镜像推送到 Docker Hub 或 GitHub Container Registry,用户即可拉取运行。务必说明容器如何配置以及需要设置的环境变量。例如:

FROM node:22.12-alpine AS builder
WORKDIR /app
COPY src/filesystem /app
COPY tsconfig.json /tsconfig.json
RUN --mount=type=cache,target=/root/.npm npm install
RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev

FROM node:22-alpine AS release
WORKDIR /app
COPY --from=builder /app/dist /app/dist
COPY --from=builder /app/package.json /app/package.json
COPY --from=builder /app/package-lock.json /app/package-lock.json
ENV NODE_ENV=production
RUN npm ci --ignore-scripts --omit-dev
ENTRYPOINT ["node", "/app/dist/index.js"]

以上示例来自文件系统 MCP 服务器(github.com/modelcontex…)。

通过包管理器分发:如果你的服务器用 Node.js 或 Python 编写,可分别发布为 npm 模块或 PyPI 包。这样用户可以在其项目中作为依赖安装与管理。对应地,.NET 使用 NuGet,Java 使用 Maven/Gradle。各个包管理器对打包与分发有不同要求,但通常需要准备 README、许可证,并将代码打成包。这也是让用户发现并使用你所构建的 MCP 服务器的好方式。

仓库分发:也可以直接开放源码仓库的访问权限,让用户自行 clone 并构建,便于其控制构建流程与依赖。务必提供清晰的运行与配置说明。比如 Playwright MCP 服务器给出的 VS Code/Claude 等宿主的启动配置(github.com/RBC/microso…):

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": [
        "@playwright/mcp@latest"
      ]
    }
  }
}

此配置展示了如何用 npx 启动服务器以及通过 args 传参。

采用语义化版本(Semantic Versioning)

语义化版本有助于你与使用者理解每个发布的变化性质。规则如下:

  • 主版本(major):做了不兼容的 API 变更
  • 次版本(minor):以向后兼容的方式新增功能
  • 补丁版本(patch):向后兼容的缺陷修复

例如版本 1.3.01 是主版本,3 是次版本,0 是补丁。仅修复 bug 时,从 1.3.0 升到 1.3.1;新增功能(兼容)时,从 1.3.01.4.0;若包含破坏性变更,则从 1.3.02.0.0

通过这种编码方式,能够清晰、可预测地向用户与开发者传达变更性质。团队也可据此选择升级策略:若只接受修复,可停留在 1.3.x;若希望拿到新功能但重视稳定,可选择允许任何 1.x.x,从而在保持兼容的前提下获得增量功能,避免破坏性变更带来的风险。

测试与部署自动化

测试是软件开发中至关重要的一环;在使用 AI 模型时尤其如此。自动化测试可帮助确保代码按预期运行,并在开发早期发现问题。另外,部署也应实现自动化,以保证一致性与可靠性。

测试策略

我们已提到测试也是一种文档形式。同样重要的是,它确保代码按预期表现。请确保你编写的测试足够全面、覆盖多种场景。可以考虑的测试包括:

  • 单元测试(Unit tests) :用于确保单个组件按设计工作。在 MCP 场景下,考虑将解析逻辑拆分到独立模块,便于测试。
  • 集成测试(Integration tests) :验证不同组件之间的交互是否符合预期。对于 MCP,如果你的集成存在于 Web 应用中,搭建端到端(E2E)测试是个好主意,模拟用户与 UI 的交互;测试会调用 Web 端点,进而调用客户端,客户端再调用 MCP 服务器的某个特性来处理请求并返回响应。
  • AI 测试(AI tests) :由于 AI 模型可能出现不可预测行为,必须有专门验证其输出的测试。这包括针对不同输入场景与边界情况进行测试,并确保模型响应处于可接受范围。可考虑使用对抗式测试来探测模型弱点——即构造专门“诱骗”模型犯错的输入。还建议准备一套固定的提示词集进行回归测试,以验证系统是否能正常工作,或在适当时机触发某个工具/功能。

总体来说,测试应关注性能、安全性与可用性等多方面。

部署自动化

把应用构建好、做好安全、架构设计与日志……这些都很重要,但如果没有稳健的部署流程,一切都等于零。那么什么是“稳健”?在 2025 年的语境中,稳健意味着:我们能一天多次、一键部署,并具备一系列护栏(guardrails) 。这些护栏确保测试已运行且通过、策略得到遵循、关键指标达标(例如不能让代码变得更慢)等。

可选的部署方案很多,如 GitHub Actions 或 Jenkins。它们有一个共同点:为了部署,你需要定义一个包含若干步骤的流水线(pipeline) ,并确保最后一步产出可部署的工件(artifact),或实际完成到生产环境的部署。

除了“能部署”,我们还需要保证部署过程可靠且可重复。另外,错误总会发生,因此必须支持回滚,以便在出现问题时恢复到上一个稳定版本。

这些要求在代码层面通常意味着需要一个用于描述流水线的 .yml 配置文件。此外,你可能需要按环境(或配置)进行区分,这也需要提前规划。

对于 MCP,这与常规软件是否不同?差异在于你可能同时交付 AI 能力。因此,你可能需要为 AI 建立独立的部署流水线,专门关注模型性能、上下文(context)管理等与 AI 相关的指标与工件。

运行与可观测性(Operations and observability)

当你的应用进入生产环境后,有一组问题需要处理:

  • 可观测性(Observability) :你真的知道应用运行得怎样吗?是否处于高负载、是否变慢、是否出错、是否安全?
  • 可扩展性与韧性(Scalability and resilience) :应用能否应对流量突增?能否弹性伸缩?遇到故障是否具备恢复能力?
  • 监控与反馈(Monitoring and feedback) :出问题时你是否能第一时间知晓?能否及时告警给正确的人?是否有闭环反馈以持续改进?
  • 治理与合规(Governance and compliance) :是否满足监管要求?是否有正确的策略,且在负责地管理数据?
  • 面向未来(Future proofing) :是否为未来变化做好准备?能否适配新技术,并持续改进?

可观测性

你是否真正了解应用的运行状况?如果是,说明你在日志、追踪和指标方面做得足够到位,并已构建仪表板便于可视化,也知道哪里需要优化。企业软件往往关系重大:需要保障数据安全、响应速度可接受、资源使用受控且功能可用。听起来不难,但当你服务成千上万甚至数百万用户时,会很有挑战。与其纠结难度,不如先把关键要素落实到位:

  • 日志(Logging) :理解应用行为的关键。记录输入、输出以及各阶段耗时,有助定位瓶颈并优化性能。要关注日志级别(info/debug/error 等)与上下文(如用户 ID、请求 ID)以提升日志可用性。
  • 追踪(Tracing) :理解请求在系统中的流经路径。用分布式追踪观察服务交互与瓶颈位置。与日志不同,追踪强调一次请求的全链路旅程,包含来源、目的地及各中间服务。
  • 指标(Metrics) :感知健康度、性能与可伸缩性。关键指标包括 CPU/内存、吞吐、响应时间、错误率等。

对 MCP 而言,可观测性与传统应用相似,但也有独特点,如模型性能Token 使用。例如监测“请求 Token 消耗 vs 缓存/复用时的消耗”。另外,MCP 规范内置了日志分类(错误、警告、普通日志等),应善加利用(见规范中的 server/utilities/logging)。

可扩展性与韧性

部署 MCP 应用的另一重点是可扩展与具备韧性。目标包括:

  • 流量突发:能在不降级的前提下承载突增(对电商大促等至关重要)。
  • 弹性伸缩:能随负载高效地扩/缩容。
  • 故障韧性:快速恢复并将停机最小化,让用户几乎无感。

解决思路:需要能快速扩缩容(多数云厂商均提供)。你要决定控制粒度:例如基于 CPU/内存阈值触发,还是交给平台自动决策。架构上,也可通过消息队列等解耦,降低对数据库的直接压力。常见机制:

  • 负载均衡(Load balancing) :将请求分布到多实例,提升响应性与可用性。对你的方案而言,往往需要分别对MCP 服务器AI 模型端点设定不同的负载均衡策略。
  • 限流(Rate limiting) :控制一定时间窗口内的请求量,防滥用、保公平并控制 API 成本。类似地,Web 与 AI 端点可能需要不同策略。
  • 熔断器(Circuit breakers) :在失败率达到阈值时“跳闸”,短期内拒绝后续请求,给系统恢复空间,并通过降级/兜底维持用户体验。

实现方式:部分在应用层,部分依赖基础设施。建议:

  • 使用负载均衡器分发流量(云厂商内建或专用 LB)。
  • API 网关或应用层实现限流。
  • 通过API 网关实现熔断与降级。

若使用公有云,可考虑 Azure API ManagementAmazon API Gateway。它们采用声明式策略(如 APIM 用 XML Policy)配置限流、缓存与安全等,无需改代码,并提供与 AI 相关的能力。

监控与反馈

针对性能瓶颈、错误率与用户行为,可采用以下策略:

  • APM(应用性能监控) :洞察性能瓶颈与错误。
  • 错误率治理:自动化错误跟踪与告警,快速定位与修复。
  • 用户行为分析:分析交互路径,发现优化空间。
  • AI 使用监控:防止滥用/误用,确保输出符合预期。应定期抽样请求进行合规与性能审查;在产品内加入用户反馈回路,以便进行提示词(prompt)调优上下文优化。同时,建立对提示注入不安全内容、**敏感实体(如竞品名)**的防护机制。选用的服务应覆盖这些需求。

主流云厂商提供完善的监控/告警方案,亦有专门的AI 提示分析工具(详见本章“资源”部分)。

治理与合规

治理确保应用在法律与伦理边界内运行。是否需要严格遵守,取决于行业:如 GDPR(数据保护)、HIPAA(医疗信息)等。务必建立合规框架

从工程角度,可通过记录所有交互并形成审计追踪(谁在何时做了什么)来简化合规;结合访问控制数据加密保护敏感信息。若你交付的是 AI 能力,还需关注偏见与公平性,制定稳健的系统提示与使用内容安全服务,帮助执行组织所需遵循的政策。

面向未来

当前系统满足现状还不够,未来如何保障安全、合规与可持续

  • MCP 仍在演进:需持续关注变化(例如 SSE 已被弃用,建议改用 Streamable HTTP),以及新特性与使用指引。
  • 工具链变更:如 Inspector 等配套工具的交互方式与功能可能更新。
  • SDK 升级破坏性变更:考虑固定在某一主版本上以稳定生产,同时确保安全补丁及时更新。结合 DependabotGitHub Advanced Security 等工具评估风险、权衡升级时机。

很难预知未来,但可以保持安全优先快速响应的姿态。软件迭代快、威胁频出——请持续跟进最佳实践,并及时调整系统。

小结

本章内容繁多,但核心是:认清问题并建立系统性的应对。无论通过库、云服务或其它手段,都要投入足够精力在安全上——这是全球企业的首要关切。请按“生产前—生产中—生产后”的阶段做好规划,并为未来准备。

如果你读到了这里,说明你已从本书中学到了很多:从构建首个服务器与客户端、集成 LLM、用 VS Code 等工具消费服务器,到最终负责任地部署上线。