MCP 系列(08):企业治理——Registry、路由与可观测性

为什么需要治理

三个 MCP Server 靠记忆管理。二十个需要系统。

企业内 MCP Server 数量增加后出现的典型问题:

  • 新同事不知道已有哪些 Server,重复开发了 Jira 工具
  • Agent 调用了已废弃的 search_jira 工具(v1.x)而不是新的 search_issues(v2.x)
  • 某次工具调用失败,没有日志,不知道是 Server 挂了还是参数有问题
  • Token 消耗异常,不知道是哪个 Server 的哪个工具

Registry 解决发现,路由解决分发,可观测性解决定位。


MCP Registry

Registry 是企业内 MCP Server 的目录,记录每个 Server 的位置、版本、能力和责任人。

yaml 复制代码
# mcp-registry.yaml
servers:
  - id: jira-tools
    name: Jira 工具集
    description: "Jira 工单的搜索、创建、更新操作"
    version: "2.1.0"
    domain: engineering          # 按领域分类
    owner: "@team-platform"
    status: active               # active / deprecated / experimental
    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 工具集
    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: postgres-readonly
    name: PostgreSQL 只读查询
    version: "1.0.0"
    domain: data
    owner: "@team-data"
    status: active
    transport: stdio
    command: npx
    args: ["-y", "@modelcontextprotocol/server-postgres", "${DATABASE_URL}"]
    capabilities:
      tools: [query]
      resources: ["postgres://analytics/schema"]

  - id: jira-tools-legacy
    name: Jira 工具集(旧版)
    version: "1.2.0"
    domain: engineering
    status: deprecated
    deprecation:
      reason: "已被 jira-tools v2.x 取代,search_jira 更名为 search_issues"
      migration_guide: "将 search_jira 替换为 search_issues,参数结构不变"
      removal_date: "2026-10-01"
    capabilities:
      tools: [search_jira, create_jira_ticket]

Registry 解决三个问题:

  1. 发现:新 Agent 查 Registry 知道有哪些 Server 可用,不用靠口口相传
  2. 废弃声明:deprecated 状态 + migration_guide,Agent 代码迁移有明确指引
  3. 责任归属:每个 Server 有 owner,出问题知道找谁

工具路由策略

Agent 需要"搜索 Jira 工单"时,如何自动找到正确的 Server?四种策略:

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

在 Agent 的 settings.json 里直接声明所有 Server:

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

优点:简单、可预测。缺点:新增 Server 需要手动更新每个 Agent 的配置文件。

策略 2:按领域加载

Agent 启动时根据任务类型加载对应 Server,不一次性加载所有:

python 复制代码
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]:
    """根据任务领域加载相关 Server,避免加载不必要的服务"""
    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"
    ]

优点:减少不必要的 Server 启动开销,每个 Agent 只加载需要的工具。

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

和 Skill 系列第 06 篇的做法一样------把 Server 描述向量化,用户请求也向量化,找最近邻:

python 复制代码
def route_to_server(user_input: str, registry: list[dict]) -> list[str]:
    """返回与用户请求语义最匹配的 Server ID 列表"""
    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))

    # 取相似度最高的前 3 个
    scored.sort(key=lambda x: x[1], reverse=True)
    return [s[0] for s in scored[:3] if s[1] > 0.6]

适合 Server 数量多(> 20 个)且经常新增 Server 的场景。同样的问题------同领域 Server 描述相似,容易混淆------需要在描述里加负面示例(见 Skill 系列第 06 篇的讨论)。

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

先按 domain 粗过滤,再在 domain 内用 Embedding 精选:

python 复制代码
def hierarchical_route(user_input: str, registry: list[dict]) -> list[str]:
    # 第一层:LLM 快速分类 domain
    domain = llm_classify_domain(user_input)  # "engineering" / "data" / ...

    # 第二层:在 domain 内 Embedding 匹配
    domain_servers = [s for s in registry if s.get("domain") == domain]
    return embedding_route(user_input, domain_servers)

可观测性:接入 Langfuse

没有 Trace,MCP 工具调用是黑盒------失败了不知道原因,慢了不知道哪里慢,Token 贵了不知道贵在哪个工具。

三层 Trace 结构

python 复制代码
from langfuse import Langfuse
from langfuse.decorators import observe, langfuse_context

langfuse = Langfuse()

@observe(name="mcp_tool_call")
async def traced_tool_call(
    server_id: str,
    tool_name: str,
    arguments: dict,
    call_fn  # 实际调用 MCP Server 的函数
) -> dict:
    # 记录调用上下文
    langfuse_context.update_current_observation(
        input={"tool": tool_name, "arguments": arguments},
        metadata={
            "server_id": server_id,
            "server_version": get_server_version(server_id),
        }
    )

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

        langfuse_context.update_current_observation(
            output=result,
            metadata={"latency_ms": round(latency_ms, 2), "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},
            level="ERROR"
        )
        raise

在 Agent 会话里创建顶层 Trace

python 复制代码
@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"}
    )

    # Agent 运行时,每次工具调用都自动关联到这个 Trace
    result = await agent.run(user_input)

    langfuse_context.update_current_observation(output={"result": result})
    return result

Trace 能回答的问题

ini 复制代码
哪个工具调用最慢?
  → 按 latency_ms 排序 Span

哪个 Server 错误率最高?
  → 按 server_id 分组,统计 success=False 的比例

Token 消耗集中在哪里?
  → LLM Span 里的 usage 字段,按 tool_name 分组

某次 Agent 失败的根因是什么?
  → 在 Langfuse 搜 session_id,展开完整的 Trace 树

告警规则

把关键指标接入告警系统(Grafana / Prometheus / 内部监控):

yaml 复制代码
# 告警规则模板(Prometheus alerting rules 格式)
groups:
  - name: mcp_server_alerts
    rules:
      # Server 可用率告警
      - alert: MCPServerHighErrorRate
        expr: mcp_tool_call_error_rate_5m > 0.05
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "MCP Server {{ $labels.server_id }} error rate {{ $value | humanizePercentage }}"

      # 工具调用延迟告警
      - alert: MCPToolHighLatency
        expr: mcp_tool_call_p90_latency_ms > 5000
        for: 3m
        labels:
          severity: warning
        annotations:
          summary: "Tool {{ $labels.tool_name }} P90 latency {{ $value }}ms"

      # Server 版本仍在使用废弃工具
      - alert: DeprecatedToolInUse
        expr: mcp_deprecated_tool_calls_total > 0
        for: 0m
        labels:
          severity: info
        annotations:
          summary: "Deprecated tool {{ $labels.tool_name }} called {{ $value }} times today"

三级治理路线图

Level 1 --- 个人/小团队(立即可做):

  • 建 mcp-registry.yaml,列出所有 Server 的 id / version / owner / status
  • 每个 Server 的 README 写清楚工具清单和使用示例

Level 2 --- 团队共享(1-2 周):

  • Registry 存入 Git,变更走 PR review
  • 加 Langfuse Trace,至少记录每次工具调用的 tool_name / latency / success
  • 设置错误率告警

Level 3 --- 企业治理(持续建设):

  • 分层路由(domain 分类 + Embedding 精选)
  • 月度 Server 健康报告(调用量 / 错误率 / 主要用户)
  • Server 废弃流程规范(声明 → 告警 → 90 天宽限 → 删除)

总结

  1. Registry 是发现的基础:没有 Registry,20 个 Server 靠口口相传,重复开发和版本混乱是必然结果
  2. 路由策略按规模选:3 个 Server 静态配置就够;20+ 个用分层路由(domain 粗分 + Embedding 精选),避免 Embedding 在同领域 Server 间混淆
  3. 可观测性把黑盒变记录:Langfuse 的三层 Trace(会话级 → 工具调用级)让失败根因从"不知道"变成"打开 Dashboard 5 秒找到"

参考资料


欢迎访问 PrimeSkills ------ 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。

更多实用知识和有趣产品,欢迎访问我的个人主页

相关推荐
weigangwin1 小时前
agent-workspace-linux 不是远程桌面:Linux AI 工作区的隔离边界验收
linux·xvfb·mcp·桌面隔离·权限边界·bubblewrap·agent-workspace
冬奇Lab1 小时前
每日一个开源项目(第161篇):Open Interpreter - 开源 AI 编程 Agent,用 Rust 重写,支持 Kimi、Qwen、DeepSeek
人工智能·开源·资讯
renhongxia11 小时前
世界模型,是“空中楼阁”还是AGI的“最后一块拼图”?
运维·服务器·数据库·人工智能·算法·agi
天上路人1 小时前
AU-48双麦多功能语音处理模组:100dB AEC + 波束定向拾音,会议与监控全场景覆盖
人工智能·ai降噪·语音处理·ai语音·麦克风·回音消除
甲维斯1 小时前
Codex定制皮肤,Windows一键切换已经搞定!
人工智能
逐米时代2 小时前
AI智能体与制造执行系统(MES)的数据打通
人工智能
To_OC2 小时前
从 “卡死半天” 到 “打字机效果”:大模型流式输出前端实现全记录
前端·javascript·llm
dunge20262 小时前
2026年7月最新ChatGPT Plus / Pro 与 Codex:当 AI Agent 最新5.6版本来袭,必须理解事务、幂等与补偿
开发语言·人工智能·python
研究员子楚2 小时前
GEO行业发展标准体系白皮书V2.0-第10卷 · 全球篇:跨国标准协同与全球品牌语义治理框架
数据库·人工智能·microsoft·架构·geo