MCP、CLI与Skills的上下文成本对比

发布时间 2026-11-11
来源 OpenRouter Blog
字数 4,395 字
查看原文 反馈

智能总结

OpenRouter 在一项 GitHub 任务上,用 GitHub MCP 服务器、gh CLI 和 gh 技能,在 Claude Haiku 5.5、Claude Sonnet 5.5、GPT-6 Luna 和 Gemini 3.8 Flash 上测量上下文成本。

OpenRouter · 2026年11月11日

MCP vs CLI vs Skills: What Each Costs in Context

你给智能体(Agent)的每一个工具,都会在每次请求时把定义发送给模型,并按输入token计费。一个模型上下文协议(MCP)服务器可能给上下文窗口增加数万个token。常见的替代方案是命令行工具(CLI)或技能(Skill)。

我们在一项GitHub任务上,用GitHub MCP服务器、gh CLI和一个gh技能,在Claude Haiku 5.5、Claude Sonnet 5.5、GPT-6 Luna和Gemini 3.8 Flash上做了测量。在Sonnet 5.5上,三种方式都正确回答了问题,但消耗的输入token差别很大。CLI用了1,421个,技能用了3,315个,而MCP服务器加载默认工具后用了59,417个。下面说明token都花在哪里,以及如何用我们的Tool Search服务器工具来削减它们。

TL;DR

  • 在Claude Sonnet 5.5上,GitHub MCP服务器的46个默认工具会给每次请求增加19,436个token。
  • 在Sonnet 5.5上,一个工具结果——GitHub的release对象——就花了约20,400个token,比全部46个定义还多。
  • Tool Search把46个工具的前期成本降到了600个token以内。在整个任务上,它把Sonnet 5.5的成本减半,却提高了Claude Haiku 5.5的成本。

MCP、CLI和技能之间有什么区别?

三者都给模型提供一种能力,区别在于模型在使用它之前需要读多少东西。

模型一开始看到的内容 模型执行时看到的内容
MCP服务器 每次请求都提供每个工具的名称、描述和JSON schema 工具返回的结果,形状由服务器决定
CLI 一个shell工具,以及一行说明CLI已存在 命令的输出,可由你通过--json之类的标志来控制形状
技能 每个技能的一行描述 技能里的SKILL.md文件(读一次),然后是命令输出

CLI依赖模型本来就会用那个工具。技能则教会模型如何使用工具,模型只在任务需要时才加载完整说明。

一个MCP服务器会给每个请求增加多少token?

可靠的计数方式是直接问模型。每家提供商在计算token之前,都会以自己的格式把工具定义写入提示;本地分词器会漏掉这部分。发送同一个请求,一次带工具、一次不带,usage.prompt_tokens的差值就是这些工具在每一轮的成本。

把这段代码保存为 mcp_cost.py。它使用MCP的2025-06-18版本,GitHub服务器接受这个版本。

"""一个MCP服务器会给每个请求增加多少提示token?去问模型。"""
import json
import os
import subprocess
import sys

import requests

API = "https://openrouter.ai/api/v1/chat/completions"
HEADERS = {"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"}

def list_mcp_tools(command):
    """启动stdio MCP服务器,完成握手,返回其tools/list的结果。"""
    proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                            stderr=subprocess.DEVNULL, text=True)

    def rpc(method, params, id=None):
        msg = {"jsonrpc": "2.0", "method": method, "params": params}
        if id is not None:
            msg["id"] = id
        proc.stdin.write(json.dumps(msg) + "\n")
        proc.stdin.flush()
        while id is not None:
            reply = json.loads(proc.stdout.readline())
            if reply.get("id") == id:
                return reply["result"]

    rpc("initialize", {"protocolVersion": "2025-06-18", "capabilities": {},
                       "clientInfo": {"name": "mcp-cost", "version": "1"}}, id=1)
    rpc("notifications/initialized", {})
    tools, cursor, id = [], None, 2
    while True:  # 跟随nextCursor,完整统计支持分页的tools/list
        page = rpc("tools/list", {"cursor": cursor} if cursor else {}, id=id)
        tools += page["tools"]
        cursor, id = page.get("nextCursor"), id + 1
        if not cursor:
            break
    proc.kill()
    return tools

def prompt_tokens(model, tools=None):
    body = {"model": model, "max_tokens": 16, "messages": [{"role": "user", "content": "说 ok。"}]}
    if tools:
        body["tools"] = tools
    if model.startswith("google/"):
        # Google Vertex和Google AI Studio对相同工具的计数不同,因此固定使用一个。
        body["provider"] = {"only": ["google-vertex"]}
    r = requests.post(API, headers=HEADERS, json=body, timeout=120)
    r.raise_for_status()
    return r.json()["usage"]["prompt_tokens"]

if __name__ == "__main__":
    mcp_tools = list_mcp_tools(sys.argv[1:])
    # MCP客户端发给模型的内容:每个工具的名称、描述和输入schema。
    tools = [{"type": "function", "function": {"name": t["name"], "description": t.get("description", ""),
                                               "parameters": t["inputSchema"]}} for t in mcp_tools]
    print(f"{len(tools)} 个工具")
    for model in ["anthropic/claude-haiku-5.5", "openai/gpt-6-luna", "google/gemini-3.8-flash"]:
        added = prompt_tokens(model, tools) - prompt_tokens(model)
        print(f"{model:30} 每次请求 +{added:,} 个提示token")

把服务器的启动命令作为参数传入,如下所示,针对GitHub MCP服务器v2.0.2。

$ python mcp_cost.py github-mcp-server stdio --toolsets=default
46 个工具
anthropic/claude-haiku-5.5     每次请求 +19,436 个提示token
openai/gpt-6-luna              每次请求 +8,903 个提示token
google/gemini-3.8-flash        每次请求 +8,525 个提示token

每加一个工具,成本就会增加。在Haiku 5.5上,issues工具集有10个工具,增加5,801个token。users工具集只有1个工具,增加619个。

你使用的模型也会改变计数。同样的46个工具,在Haiku 5.5上花19,436个token,在GPT-6 Luna上只花8,903个,所以要在你计划运行的模型上测量。

甚至提供该模型的提供商也会改变计数。在Gemini 3.8 Flash上,46个工具通过Google Vertex花8,525个token,通过Google AI Studio则花13,010个。这就是为什么脚本总是把Gemini请求发给Google Vertex。

同一任务用CLI、技能和MCP分别要花多少成本?

我们问每个模型:"GitHub仓库cli/cli的最新release是哪个,该仓库中最近打开的、带bug标签的三个issue是什么?"每种方式都在我们的Responses API上以工具调用循环运行,我们累加多次请求的usage.input_tokens。

  • CLI。 一个run_shell工具,以及一行"GitHub CLI gh已安装并已认证"。
  • 技能。 同一个工具,外加一行索引,指向一份1,492字符的gh用法SKILL.md。
  • MCP。 服务器工具,范围限定为任务所需的2个、默认的46个,或全部91个。

我们在2026年10月20日把每种组合跑了三次,取中位数。Haiku 5.5对提示的计数与Sonnet 5.5完全相同,但它在某些运行中多花了几轮,所以我们展示Sonnet更稳定的token数和计费成本。

方式 Sonnet 5.5 token数 Sonnet 5.5 每任务成本 GPT-6 Luna token数 Gemini 3.8 Flash token数
CLI 1,421 $0.0075 627 5,292
技能 3,315 $0.0118 1,542 6,107
MCP,2个工具 23,228 $0.0552 14,479 17,267
MCP,46个默认工具 59,417 $0.1274 116,282 35,409
MCP,全部91个工具 101,351 $0.2113 135,238 53,289
MCP,2个工具,结果上限4,000字符 5,357 $0.0191 2,726 2,943

这张表里每次运行都回答正确。失败出现在使用Tool Search时,见下文。在Sonnet 5.5上,默认MCP服务器用的输入token是CLI的42倍,成本是17倍:每1,000个任务$127对$7.50。在Sonnet 5.5上,输出token成本是输入的五倍,CLI运行的463个输出token占了其$0.0075中的$0.0046。

Bar chart of input tokens for the whole task, split into tool definitions and instructions versus task, tool results and replies: CLI 1,421, Skill 3,315, MCP with 2 tools capped 5,357, MCP with 2 tools 23,228, MCP with 46 tools 59,417, MCP with 91 tools 101,351.

技能比裸CLI贵,是因为文件一旦被模型读取,就会留在对话中。对于模型已经很熟悉的CLI工具,技能是可选的。对于你自己的CLI,技能就是模型学习命令的方式。