MCP 系列(八):企业治理——注册、路由与可观测性

Dev.to AI 2026-07-17T02:31:21.465455

MCP 系列(八):企业治理 —— 注册、路由与可观测性

为什么治理变得必要

三台 MCP 服务器,靠脑子记还能凑合。二十台?那必须得有个系统来管。

当企业里的 MCP 服务器数量多起来之后,一些可以预见的问题就会冒出来:

注册解决的是「找得到」的问题。路由解决的是「发得准」的问题。可观测性解决的是「查得清」的问题。

MCP 注册(Registry)

MCP Registry 相当于企业内部的 MCP 服务器黄页:它记录了每台服务器的位置、版本、能力清单以及负责人信息。

# mcp-registry.yaml
servers:
  - id: jira-tools
    name: Jira Tools
    description: "Search, create, and update Jira tickets"
    version: "2.1.0"
    domain: engineering
    owner: "@team-platform"
    status: active
    transport: stdio
    command: python
    args: ["/opt/mcp/jira/server.py"]
    capabilities:
      tools: [search_issues, create_issue, update_issue]
      resources: [jira://projects, jira://sprint/current]
    metrics:
      monthly_calls: 4521
      avg_latency_ms: 180
      error_rate: 0.2%
  - id: github-tools
    name: GitHub Tools
    version: "1.5.0"
    domain: engineering
    owner: "@team-platform"
    status: active
    transport: stdio
    command: npx
    args: ["-y", "@modelcontextprotocol/server-github"]
    capabilities:
      tools: [create_pull_request, search_repositories, get_file_contents]
  - id: jira-tools-legacy
    name: Jira Tools (Legacy)
    version: "1.2.0"
    domain: engineering
    status: deprecated
    deprecation:
      reason: "Superseded by jira-tools v2.x; search_jira renamed to search_issues"
      migration_guide: "Replace search_jira with search_issues; argument structure unchanged"
      removal_date: "2026-10-01"
    capabilities:
      tools: [search_jira, create_jira_ticket]

注册表解决了三个问题:

工具路由策略

当一个 Agent 需要“搜索 Jira 工单”时,它怎么找到正确的 Server?四种策略:

策略 1:静态配置(最简单)

在 Agent 设置中直接声明所有 Server:

{
  "mcpServers": {
    "jira": {
      "command": "python",
      "args": ["/opt/mcp/jira/server.py"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"]
    }
  }
}

简单且可预测。添加新 Server 需要手动更新每个 Agent 的配置文件。

策略2:按领域加载

只加载当前任务相关的服务器,减少不必要的启动开销。每个 Agent 只加载它需要的工具。

DOMAIN_SERVERS = {
    "engineering": ["jira-tools", "github-tools", "gitlab-tools"],
    "data": ["postgres-readonly", "bigquery-tools"],
    "communication": ["slack-tools", "email-tools"],
}

def load_servers_for_task(task_type: str) -> list[dict]:
    domain = classify_task_domain(task_type)
    server_ids = DOMAIN_SERVERS.get(domain, [])
    registry = load_registry()
    return [s for s in registry["servers"] if s["id"] in server_ids and s["status"] == "active"]

策略3:嵌入路由(语义匹配)

思路与技能系列第06篇相同——把服务器描述和用户请求分别转成向量,然后找最相似的几个:

def route_to_server(user_input: str, registry: list[dict]) -> list[str]:
    query_embedding = embedder.embed(user_input)
    scored = []
    for server in registry:
        desc_embedding = get_cached_embedding(server["id"], server["description"])
        score = cosine_similarity(query_embedding, desc_embedding)
        scored.append((server["id"], score))
    scored.sort(key=lambda x: x[1], reverse=True)
    return [s[0] for s in scored[:3] if s[1] > 0.6]

适用于20个以上服务器且频繁新增的场景。局限性也和技能路由一样:同一领域的服务器在向量空间中容易扎堆。可以在描述里加入反例来区分它们。

策略4:分层路由(推荐)

先按领域粗筛,再在领域内做嵌入匹配:

def hierarchical_route(user_input: str, registry: list[dict]) -> list[str]:
    # 第一层:用 LLM 快速判断领域
    domain = llm_classify_domain(user_input)  # "engineering" / "data" / ...
    # 第二层:在领域内做嵌入匹配
    domain_servers = [s for s in registry if s.get("domain") == domain]
    return embedding_route(user_input, domain_servers)

可观测性:接入 Langfuse

没有追踪,MCP 工具调用就是个黑盒。一旦出问题,你根本不知道原因。

3. 会话级追踪(Session-Level Trace)

@observe(name="agent_session")
async def run_agent_session(user_input: str, session_id: str):
    langfuse_context.update_current_trace(
        session_id=session_id,
        user_id="user:alice",
        metadata={
            "task_type": "jira_query"
        }
    )
    result = await agent.run(user_input)
    langfuse_context.update_current_observation(
        output={"result": result}
    )
    return result

会话内的每一次工具调用会自动挂载到会话追踪树上。

追踪能回答什么问题?

这些问题的答案,靠日志很难拼凑,但通过追踪链路可以清晰地串联起来。

4. 资源治理(Resource Governance)

除了调用层面的可观测性,企业还需要对 MCP 资源本身 进行治理。资源治理的核心目标:


注册中心(Registry)

注册中心是 MCP 治理体系中的核心基础设施,负责统一管理所有 MCP 服务器的描述信息、健康状态和连接方式。类比微服务架构中的服务注册中心(如 Consul、Eureka),MCP 注册中心让客户端能够动态发现可用的 MCP 服务器,而不是硬编码连接地址。

注册中心的核心功能

轻量级实现方案(基于 OCI 镜像)

对于中小团队,可以用 Container Registry(容器镜像仓库) 作为最简单的注册中心:每个 MCP 服务器打包成 OCI 镜像,镜像标签即为版本号。客户端拉取镜像并运行容器即完成部署。但这种方式缺少动态路由和健康检查能力,适合前期验证。

完整方案:自定义注册服务

更推荐的做法是搭建一个专用的 MCP 注册服务,实现上述全部功能。例如:

注册中心的数据模型示例

{
  "servers": [
    {
      "id": "jira-server-prod",
      "name": "Jira Production Server",
      "version": "2.3.1",
      "status": "healthy",
      "endpoint": "https://mcp-jira.acme.com:8080",
      "resources": ["issue:read", "issue:write", "project:list"],
      "tools": ["create_issue", "search_issues", "update_status"],
      "prompts": ["jira_ticket_formatter"],
      "health_check_url": "/health",
      "last_heartbeat": "2025-03-20T10:30:00Z",
      "owner_team": "platform",
      "allowed_apps": ["assistant-prod", "workflow-engine"]
    }
  ]
}

路由(Routing)

当注册中心维护了多个 MCP 服务器(尤其是同一工具的多个实例)时,客户端需要一个路由策略来决定每次请求发给哪个服务器

路由策略类型

  1. 轮询(Round-robin):依次分发请求,适合无状态、负载均摊的场景。
  2. 加权轮询(Weighted Round-robin):根据服务器性能或配额权重分配请求,适合异构集群。
  3. 最小连接(Least Connections):将新请求分配给当前活跃连接最少的服务器,适合长连接场景。
  4. 一致性哈希(Consistent Hashing):基于请求特征(如用户 ID、会话 ID)将同类请求固定转发到同一台服务器,有利于利用本地缓存。
  5. 地理位置路由(Geo-routing):根据客户端 IP 或区域,将请求路由到离它最近的服务器,降低延迟。

路由决策流程

客户端发起调用请求
    ↓
从注册中心获取可用服务器列表(含标签/权重)
    ↓
根据路由策略选择目标服务器
    ↓
检查目标服务器的安全策略是否允许本次调用
    ↓
发起调用,同时上报调用追踪数据到可观测平台
    ↓
收集返回结果和延迟信息,反馈给路由层(用于后续调优)

熔断与降级

路由层还需要内置熔断器(Circuit Breaker)。当某个服务器连续出错或超时超过阈值时,路由层自动将该服务器从可用列表移除,并在一段时间后尝试恢复。如果所有服务器都熔断,则应触发降级逻辑:返回友好错误提示,或切换到备用后端(如本地 LLM 模型调用)。


可观测性(Observability)——完善追踪链路

前面我们只展示了三层追踪的基础写法。在实际企业场景中,还需要补充自定义属性细粒度指标,让追踪数据真正可分析。

在追踪中嵌入业务维度

除了 latency、token count、error 等系统指标,还应该记录:

这些数据能帮助运营团队快速定位问题:比如“所有延迟飙升的请求都来自 Jira 服务器的 create_issue 工具”,然后就能精准排查 Jira 服务器的瓶颈。

示例:完整的工具调用追踪(带业务维度)

@observe(name="mcp_tool_call_v2")
async def traced_tool_call_v2(
    server_id: str,
    tool_name: str,
    arguments: dict,
    call_fn
) -> dict:
    langfuse_context.update_current_observation(
        input={
            "tool": tool_name,
            "arguments": arguments
        },
        metadata={
            "server_id": server_id,
            "server_version": get_server_version(server_id),
            "user_intent": "ticket_creation",
            "request_source": "assistant-prod/v3.2"
        }
    )

    # 记录调用开始时间
    t0 = time.perf_counter()

    try:
        result = await call_fn(tool_name, arguments)
        latency_ms = (time.perf_counter() - t0) * 1000

        # 计算输出大小(近似 token 数)
        output_size_chars = len(str(result))

        langfuse_context.update_current_observation(
            output=result,
            metadata={
                "latency_ms": round(latency_ms, 2),
                "output_size_chars": output_size_chars,
                "success": True
            }
        )
        return result
    except Exception as exc:
        latency_ms = (time.perf_counter() - t0) * 1000
        langfuse_context.update_current_observation(
            output={"error": str(exc)},
            metadata={
                "latency_ms": round(latency_ms, 2),
                "success": False,
                "error_type": type(exc).__name__
            },
            level="ERROR"
        )
        raise

可视化与告警

只有追踪数据还不够,需要配合看板(Dashboard)告警(Alert) 才能形成闭环。

这些能力可以借助开源工具(Grafana + Prometheus + Tempo / Signoz)或商业可观测平台(Datadog、New Relic、Langfuse Cloud)实现。


小结:注册中心让 MCP 服务器可以被发现和管理,路由策略让客户端能智能选择目标,而可观测性让企业能实时掌握整个系统的健康状况。这三者共同构成了 MCP 企业治理的基石。下一章将讨论 安全与权限控制,即如何保护 MCP 服务器和数据不被滥用。

MCP 系列(八):企业治理 — 注册、路由与可观测性

→ sort Spans by latency_ms

哪个服务器的延迟最高?

→ group by server_id, count success=False fraction

哪个服务器的错误率最高?

→ LLM Span usage field, grouped by tool_name

token 消耗主要集中在哪儿?

查看原文