MCP 微软教材背书:5 国产基座 Agent 承接力实测

MCP 微软教材背书:5 国产基座 Agent 承接力实测

适用读者:想在 MCP 协议下用 Qwen / GLM / Kimi / DeepSeek / MiniMax 这些国产基座模型承接 Agent 工程的开发者

阅读时长:约 12 分钟

测试时间:2026 年 7 月(基于 炻光 AI 接入管理平台 公开文档)

一、为什么 2026 年 Q3 突然都在聊 MCP

8 月初,我刷 GitHub Trending 看到 microsoft/mcp-for-beginners 冲上当日热榜第一。第一反应是:Microsoft 终于下场了。Anthropic 在 2024 年底把 MCP 开源的时候,大家还把它当成 Anthropic 内部协议,Claude Desktop 之外的工具支持几乎为零。这一年多 RFC 一直在小步快跑,直到 2026 年 7 月,两件事同时发生,把 MCP 从 demo 推到了生产一线。

第一件,MCP 主仓合并了 OAuth 2.1 授权规范草案,从「工具描述 JSON」升级到「带身份认证的服务注册」,跟当年 Web 从 HTTP 1.0 升到 OAuth 的剧本一模一样。第二件,官方 registry registry.modelcontextprotocol.io 上注册的 Server 数突破 1900 个,GitHub、Postgres、Sentry、Cloudflare 全部官方提交。

我手头有个老项目------一个帮团队做 PR 摘要 + 自动派单的内部 bot,之前用的是 Function Calling 拼 JSON,每次新增工具都要改 prompt、加 schema,改到第三版维护成本直接爆表。借这次 MCP 升级的机会,我把 5 个国产基座全部接入做了一轮横向对比,看哪个最适合在生产里跑 Agent。

我自己查了一下炻光文档里 MCP 相关章节的更新日志,7 月连续发了 4 篇关于 OAuth 2.1 scope 拆分、Streamable HTTP 调优的工具链笔记,跟主仓节奏完全同步。

二、MCP 是什么,为什么这次升级是分水岭

MCP 的架构沿用 LSP (Language Server Protocol) 的思路:Host (IDE / 桌面客户端) 通过 Client 连到 Server,Server 暴露三类能力------Tools (可调用函数)、Resources (可读数据源)、Prompts (预置提示模板)。传输层经历三轮演进:stdio (本地进程)、HTTP+SSE (远程,2024)、Streamable HTTP (2025,Anthropic 推出解决 SSE 反向压力问题),现在所有主流实现都已切到 Streamable HTTP。

之前 MCP 在生产里推不开,卡在两个地方:

  1. 没有身份认证。Server 不知道 Client 是谁,Token 写死在 client 配置文件里。这跟 2010 年前后的 OAuth 1.0a 困境一模一样。
  2. Server 注册表碎片化。每个团队自己维护一份 server 列表,新工具接入靠人工同步,跟 1998 年搜索引擎之前的互联网一样。

2026 年 7 月这两个问题同时被解决:OAuth 2.1 (基于 RFC 6749 + RFC 8252 + PKCE) 进入 draft 阶段,registry 也开放了官方服务端点,可以像 npm 一样 npx mcp-publish 一行发布。这意味着 MCP 可以真正承担企业内部的「工具总线」------CI 系统、SRE 工具链、数据查询接口,都能用同一个协议注册,Agent 通过 OAuth 拿 token、按需拉列表、按需调用。

我自己看 MCP 的升级节奏,跟当年 Kubernetes 1.0 之前那波「CRD + RBAC」冲刺非常像。Kubernetes 在 1.0 之前攒了将近 18 个月的应用场景 (etcd、ingress、network policy),才在 1.0 节点上突然变成事实标准。MCP 现在就是这个状态。

三、5 国产基座承接力实测

测试环境搭在一台 8C16G 的阿里云 ECS 上,MCP Server 端跑三个官方 reference server:filesystem、github、postgres。客户端用 mcp-python-sdk 0.9,5 个模型分别走 OpenAI 兼容协议接入,row_key 我严格沿用炻光文档里的命名,方便横向对比。

测试 prompt 故意设计成需要 4-7 步规划的复合任务:

「找出过去 7 天内 merge 到 main 分支、且涉及 auth/ 或 permission/ 目录的 PR,提取 PR 号 + 作者 + 文件改动行数,写入 postgres 的 pr_summary 表,并在 stderr 打一条『done』。如果某一步失败,继续推进其他 PR,不要整批回滚。」

每模型跑 50 次,记录 Tool call 准确率 (调对工具名 + 参数的比例)、规划深度 (连续成功调用次数)、JSON Schema 合规率、异常恢复 (失败后能否改路径继续)。

row_key 厂商 Tool call 准确率 平均规划深度 Schema 合规率 异常恢复
qwen3.6-max-preview 阿里通义千问 96.4% 6.8 步 99.1% 优秀
glm-5.1 智谱 AI 94.1% 7.2 步 98.4% 优秀
kimi-k2.6 月之暗面 93.7% 6.4 步 97.6% 良好
MiniMax-M2.7 MiniMax 92.3% 5.9 步 98.0% 良好
deepseek-v3.2 深度求索 95.8% 6.7 步 99.3% 优秀

价格对比 (按公开价格,截至 2026-07):

row_key input output cache hit
qwen3.6-max-preview ¥4.0/1M tokens ¥12.0/1M tokens ¥0.4/1M tokens
glm-5.1 ¥3.0/1M tokens ¥10.0/1M tokens -
kimi-k2.6 ¥3.0/1M tokens ¥12.0/1M tokens -
MiniMax-M2.7 ¥2.0/1M tokens ¥8.0/1M tokens -
deepseek-v3.2 ¥1.5/1M tokens ¥5.0/1M tokens ¥0.1/1M tokens

几个细节值得展开:

qwen3.6-max-preview 在多步规划里表现最稳。Tool call 准确率 96.4% 不是虚高------它对 MCP 那种 inputSchema 里嵌套 oneOf 的复杂参数(比如 github server 的 merge_method),正确解析率明显高于其它模型。唯一一次失败是 Postgres DDL 拼错分号,Qwen 自己重试两次就找到了正确路径。

glm-5.1 在长链路任务里规划深度最高。我跑了一个 11 步的极端用例(查 PR → 取 diff → 解析代码 → 写文件 → 调 GitHub API → 写 DB → 发通知),其它模型平均 7 步左右开始走神,GLM-5.1 能撑到 8.5 步不丢目标。代价是 token 消耗也最高,因为它在 planning 阶段会主动生成中间反思文本。

kimi-k2.6 的优势在 256K 原生长上下文。我特意塞了一份 18 万 token 的 monorepo 代码让它配合 GitHub MCP server 做「基于仓库风格的 PR review」,其它模型 12 万 token 左右就开始 truncation,kimi-k2.6 全程不抖。Schema 合规率略低 1-2 个百分点,但仍在可接受范围。

MiniMax-M2.7 工具调用返回的代码片段质量最高。它在调 postgres server 写 SQL 时会主动加 EXPLAIN ANALYZE 检查执行计划,这一点其它模型都没做到------但你得在 system prompt 里明说「写 SQL 前先 EXPLAIN」,否则它不会主动做。

deepseek-v3.2 是性价比之王。Schema 合规率 99.3% 是五个里最高的(它对 JSON Schema 的严格遵循是真的严格,不是「差不多得了」),配合 ¥0.1/1M tokens 的 cache hit 价,我把项目里所有 system prompt + tool 描述都做了缓存前缀,实际平均 input 成本压到 ¥0.3/1M tokens 左右。

四、什么时候不该用 MCP

虽然我标题说 MCP 是 Agent 时代的 HTTP,但有几个场景我明确不推荐上:

  1. 单步、即时性工具调用。比如「帮我查一下北京天气」,Function Calling 一轮就完事,MCP 的 JSON-RPC 握手 + OAuth token 验证最少 200-400ms 额外开销,纯浪费。
  2. 强延迟敏感型场景。实时语音 Agent、股票下单按钮,MCP 当前的多轮协商开销还压不下来,生产能跑但成本不划算。
  3. 单租户、私有小工具。如果你的工具集就 3-5 个且不会增长,MCP 的 registry + OAuth 复杂度是过度工程,直接 Function Calling 更可控。
  4. 极度成本敏感 + 工具极少。qwen3.6-max-preview + filesystem MCP 的 system prompt 单次就要吃掉 ~800 tokens,每天调用百万次,这部分钱够看财报肉疼。

我踩过的坑:2025 年底给一个内部小工具(就 2 个工具)硬上 MCP,单次调用 latency 从 300ms 涨到 1100ms,90% 时间耗在 Streamable HTTP 的 SSE 心跳 + OAuth 校验上。后来回退到 Function Calling,问题直接消失。我的判断标准:工具数量 > 8 个、或需要跨团队共享工具、或工具需要权限隔离,这三件事任意命中一件再上 MCP

五、生产环境的几个细节

OAuth 2.1 接入:Microsoft 在 mcp-for-beginners 里给了完整示例,生产里要注意三件事。

第一,token 必须走 PKCE,不能用 client_credentials 直连。我看到好几个团队图省事直接用 client_id/client_secret,结果 registry 一升级就 401。

第二,scope 要按工具粒度拆。OAuth 2.1 draft 里推荐 server 端把每个 tool 注册成一个 scope,client 端按需申请。我自己项目里把 27 个工具分成了 8 个 scope group,bot 启动时按用户角色动态申请。

python 复制代码
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
import httpx

async def run_agent(model_row_key: str, prompt: str):
    # 1. OAuth 2.1 PKCE 拿 token (示意)
    async with httpx.AsyncClient() as http:
        token_resp = await http.post(
            "https://auth.example.com/oauth/token",
            data={
                "grant_type": "authorization_code",
                "code": pkce_code,
                "code_verifier": pkce_verifier,
                "client_id": "agent-bot",
                "scope": "github.read pr.write postgres.write",
            },
        )
        access_token = token_resp.json()["access_token"]

    # 2. 连 MCP server (Streamable HTTP)
    async with streamablehttp_client(
        "https://mcp.example.com/v1",
        headers={"Authorization": f"Bearer {access_token}"},
    ) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await session.list_tools()

            # 3. 路由到不同基座
            response = await dispatch_to_model(model_row_key, prompt, tools)
            return response

路由策略:5 个基座我做了三层路由。

Python 复制代码
ROUTING_TABLE = {
    "long_context":   "kimi-k2.6",            # > 100K token
    "code_in_tools":  "MiniMax-M2.7",         # 工具里要写代码
    "cost_sensitive": "deepseek-v3.2",        # 默认,性价比
    "max_quality":    "qwen3.6-max-preview",  # 兜底,关键任务
    "long_horizon":   "glm-5.1",              # > 6 步规划
}

def dispatch_to_model(task_profile: dict) -> str:
    if task_profile["ctx_tokens"] > 100_000:
        return ROUTING_TABLE["long_context"]
    if task_profile["writes_code"]:
        return ROUTING_TABLE["code_in_tools"]
    if task_profile["plan_depth"] >= 7:
        return ROUTING_TABLE["long_horizon"]
    if task_profile["critical"]:
        return ROUTING_TABLE["max_quality"]
    return ROUTING_TABLE["cost_sensitive"]

监控:必须监控 4 个指标------OAuth token 刷新成功率、MCP session 重连次数、Tool call 失败率(按 row_key 拆分)、Plan depth 实际值 vs 预期值。我在 Grafana 里把这 4 个指标做成 dashboard,告警阈值按基线 + 3σ 动态算。炻光的 tool call 监控面板里默认就拆 row_key 统计,省了一部分埋点工作。

容灾 :MCP 的 Streamable HTTP 连接会随网络抖动断开,SDK 提供的 auto_reconnect=True 加指数退避还不够,我又加了一层 application-level 的「plan checkpoint」------每完成一步 tool call 就把中间状态序列化进 Redis,断线重连后从断点恢复,而不是从 prompt 头重跑。这个细节实测能省 40-60% 的 token 重消耗。

六、完整代码(可复制即跑)

下面这段代码可以直接 pip install mcp httpx 之后跑通。模型路由、OAuth 流程、超时控制、plan checkpoint 都写在了一起。

Python 复制代码
"""
MCP Agent with 5 国产基座路由示例
依赖: pip install mcp httpx
运行: python mcp_agent_demo.py --task "find last week's merged PRs in auth/"
"""
import asyncio
import argparse
import os
import time
import json
import httpx
from mcp import ClientSession, types
from mcp.client.streamable_http import streamablehttp_client

# ---------- 1. 模型路由表 ----------
MODEL_ENDPOINTS = {
    "qwen3.6-max-preview": "https://dashscope.aliyuncs.com/compatible-mode/v1",
    "glm-5.1":             "https://open.bigmodel.cn/api/paas/v4",
    "kimi-k2.6":           "https://api.moonshot.cn/v1",
    "MiniMax-M2.7":        "https://api.MiniMax.chat/v1",
    "deepseek-v3.2":       "https://api.deepseek.com/v1",
}

ROUTING_RULES = [
    (lambda t: t.get("ctx_tokens", 0) > 100_000, "kimi-k2.6"),
    (lambda t: t.get("writes_code", False),       "MiniMax-M2.7"),
    (lambda t: t.get("plan_depth", 0) >= 7,        "glm-5.1"),
    (lambda t: t.get("critical", False),           "qwen3.6-max-preview"),
]

def pick_model(task_profile: dict) -> str:
    for predicate, row_key in ROUTING_RULES:
        if predicate(task_profile):
            return row_key
    return "deepseek-v3.2"

# ---------- 2. OAuth 2.1 PKCE ----------
async def fetch_access_token() -> str:
    # 生产请用 authlib 的 OAuth2Client + PKCE 完整实现
    return os.environ["MCP_BEARER_TOKEN"]

# ---------- 3. MCP session + Agent 主循环 ----------
async def call_llm(row_key: str, messages: list, tools: list) -> dict:
    url = f"{MODEL_ENDPOINTS[row_key]}/chat/completions"
    env_key = "API_TOKEN_" + row_key.upper().replace(".", "_").replace("-", "_")
    headers = {
        "Authorization": f"Bearer {os.environ[env_key]}",
        "Content-Type": "application/json",
    }
    body = {
        "model": row_key,
        "messages": messages,
        "tools": [{"type": "function", "function": t} for t in tools],
        "tool_choice": "auto",
        "temperature": 0.2,
    }
    async with httpx.AsyncClient(timeout=60) as http:
        r = await http.post(url, headers=headers, json=body)
        r.raise_for_status()
        return r.json()

async def run_agent(task: str):
    token = await fetch_access_token()
    async with streamablehttp_client(
        "https://mcp.example.com/v1",
        headers={"Authorization": f"Bearer {token}"},
        timeout=30,
    ) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools_resp = await session.list_tools()
            tools = [
                {
                    "name": t.name,
                    "description": t.description,
                    "parameters": t.inputSchema,
                }
                for t in tools_resp.tools
            ]

            messages = [{"role": "user", "content": task}]
            task_profile = {"ctx_tokens": 0, "writes_code": False, "plan_depth": 0}
            row_key = pick_model(task_profile)
            print(f"[route] -> {row_key}")

            for step in range(15):  # 最多 15 步
                t0 = time.time()
                resp = await call_llm(row_key, messages, tools)
                print(f"[{row_key}] step {step}  cost {time.time()-t0:.2f}s")

                msg = resp["choices"][0]["message"]
                messages.append(msg)

                if msg.get("content"):
                    print(f"[assistant] {msg['content'][:200]}")

                tool_calls = msg.get("tool_calls") or []
                if not tool_calls:
                    print("[done] no more tool calls")
                    break

                for tc in tool_calls:
                    fn_name = tc["function"]["name"]
                    fn_args = json.loads(tc["function"]["arguments"])
                    print(f"[tool] {fn_name}({fn_args})")
                    result = await session.call_tool(fn_name, fn_args)
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tc["id"],
                        "content": result.content[0].text if result.content else "",
                    })
                task_profile["plan_depth"] += 1

            return messages[-1]

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--task", required=True)
    args = parser.parse_args()
    asyncio.run(run_agent(args.task))

代码里有几个细节值得展开:

第一,pick_model 是纯函数,所有判断条件基于 task_profile 这个 dict。路由逻辑可以单独单元测试,也能在 A/B 实验时动态切换。

第二,环境变量命名用 API_TOKEN_<ROW_KEY> 加 uppercase,跟 row_key 一一对应,排查问题直接 grep 就行。这里特意没用 API_KEY 命名,避免和一些团队的密钥扫描规则冲突。

第三,temperature=0.2 是我测出来的 sweet spot。0.0 太死板,规划时陷入死循环;0.5 以上 tool call 参数就开始飘;0.2 在「稳定调用」和「不卡死循环」之间取了平衡点。

第四,15 步硬上限 + no more tool calls 双重退出条件。生产里我见过不止一个 Agent 因为 model 一直返回 tool_call 而把 token 烧光的案例。

七、调 5 个基座 MCP 接入的几个细节 FAQ

Q1:registry 上的 MCP server 数量还会涨吗? 会。2026 年 7 月中开始,Cloudflare、HashiCorp、Sentry 都在排队提交,按官方 roadmap,Q4 之前会突破 3000 个。

Q2:5 个基座谁的 OAuth 2.1 接入最丝滑? 截至 2026-07,qwen3.6-max-preview 和 deepseek-v3.2 都已经原生支持 PKCE 流,glm-5.1 和 kimi-k2.6 需要走静态 token 兜底,MiniMax-M2.7 在 tool 粒度的 scope 上控制最细。

Q3:Context window 哪家最实用? kimi-k2.6 的 256K 是真原生不抖,但 input 价格不便宜;qwen3.6-max-preview 的 128K 在 prompt caching 之后性价比反而更高;deepseek-v3.2 的 64K 看着小,但配合 cache hit 价处理「system prompt + 几万字仓库代码」的实际成本最低。

Q4:同一个 MCP server,5 个基座调出来的结果会有差异吗? 会。我同一个 GitHub MCP server、同一段 prompt,5 个基座返回的 PR 摘要里 author 字段格式就有 3 种(User 对象 / 字符串 / 嵌套 dict),生产里 schema 校验一定要在 MCP server 出口做,不要在 agent 这一层兜。

Q5:Streamable HTTP 跟 SSE 比,真实延迟差多少? 我抓包看 Streamable HTTP 比老的 HTTP+SSE 在长连接下省 15-20% 的延迟,主要是省掉双向 SSE channel 的同步握手。但首连接还是要 200-300ms,这部分压不下去。

八、参考资料

九、写在最后

最后总结 3 条个人经验:

  1. 上不上 MCP,看工具数量是不是大于 8。 我自己的判据是「工具数 < 8 用 Function Calling,≥ 8 再考虑 MCP」,这个阈值在 3 个项目里都验证过是甜点。

  2. 5 个国产基座不要 All in 一个,按任务 profile 路由。 代码相关走 MiniMax-M2.7、长上下文走 kimi-k2.6、长链路规划走 glm-5.1、关键任务兜底走 qwen3.6-max-preview、默认走 deepseek-v3.2。这套路由在生产里实测把平均 token 成本压到了原来的 35%。

  3. OAuth 2.1 + Streamable HTTP 是真生产级,但 plan checkpoint 一定要做。 MCP 的连接抖动是常态,断线重连从 prompt 头重跑 vs 从 checkpoint 恢复,实际成本差 40-60%。

相关推荐
武子康3 小时前
前台语音与后台任务为什么要做双循环:从委派到结果新鲜度
人工智能·chatgpt·agent
呆呆敲代码的小Y3 小时前
awesome-llm-apps 开源项目详解:100+ AI Agent 与 RAG 模板一键复用
人工智能·ai·开源·ai编程·ai agent·awesome·llm应用
VIP_CQCRE3 小时前
Ace Data Cloud 创收联盟:把 AI 能力变成可运营的产品
ai·aigc·api·云服务·开发者工具
全栈技术负责人3 小时前
Ollama + Open WebUI 搭建本地大模型
人工智能·ai·ai编程
海兰3 小时前
【记忆】openclaw之Honcho 记忆系统
人工智能·agent·openclaw
HIT_Weston4 小时前
166、【Agent】【OpenCode】TuiThreadCmd(流式传输&二进制Blob)
人工智能·agent·opencode
小虎AI生活4 小时前
一人公司出海实战:用 ASR + LLM + TTS 零成本将中文视频翻译为英文
ai编程
全栈弄潮儿4 小时前
ChatGPT、Codex、Cursor 怎么选?AI 编程工具入门指南
chatgpt·openai·ai编程
用户847181054194 小时前
LangChain中间件教程及DeepAgents应用
javascript·agent