MCP 的故事并不是“一个协议赢了,另一个概念输了”这么简单。Simon Willison 的态度变化,更像是在提醒 AI 开发者:当 Agent 已经能够访问终端、执行 curl 并组合命令时,工具协议的价值不再只取决于“能不能调用工具”,还取决于它是否足够轻量、可组合、容易部署和观察。
2025 年底,Simon Willison 在年度回顾中用「The Only Year of MCP」概括 MCP 的快速流行。他当时提到,MCP 走红还不到一年,就被 Anthropic 提出的 Skills 概念抢走了部分注意力。一个能够访问终端并运行 curl 的 Agent,确实可以用更通用的方式完成许多工作,不必为每个工具都接入专门的 MCP 服务。
但这并不意味着 MCP 失去意义。进入 2026 年上半年,围绕 MCP 的讨论又出现了新的重心:无状态、低耦合的协议形态,可能比“给模型增加多少个预定义工具”更重要。
从工具清单转向能力边界
传统工具调用通常把能力描述成一组函数:搜索、查询数据库、创建工单、发送消息。模型看到的是名称、参数和返回值,开发者则需要维护工具注册、权限控制、连接生命周期和错误处理。
Skills 和终端型 Agent 的优势在于通用性。只要环境提供了合适的命令行工具,Agent 就能通过脚本和 HTTP 接口完成组合任务。例如,它可以读取配置、调用 API、过滤 JSON,然后把结果交给下一个步骤。这种方式减少了专用适配器,但也把更多责任交给运行环境:凭证怎么注入、命令能访问哪些目录、网络请求是否受限,都必须显式设计。
MCP 的价值则更接近一个稳定的能力边界:客户端不必了解服务内部的实现,只需要按照协议发现和调用能力。若服务端采用无状态设计,每个请求都携带完成任务所需的上下文,服务就可以更容易地水平扩展、重启和调试。
这两种方式并非互斥:
- Skills 适合快速组合现有命令和 API,尤其适合探索性任务。
- MCP 适合把经过治理的能力暴露给多个 Agent、客户端或团队。
- 无状态设计适合云端部署、弹性扩缩容和故障恢复。
- 有状态会话仍然有用,但应该只在确实需要上下文、事务或长任务时引入。
“无状态”究竟改变了什么
一个无状态工具服务不依赖某台机器内存里的会话对象来理解请求。请求中应包含必要的输入,服务端根据输入完成处理,并返回结构化结果。
可以这样实践:下面这个 Python 示例使用标准库启动一个简单的 HTTP 服务。它提供一个无状态的 lookup 接口,服务端不会保存用户会话;每次请求都通过 JSON 传入查询词。示例只是一个可改造的协议骨架,不代表某个官方 MCP 实现。
把代码保存为 server.py 后运行:
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
if self.path != "/tools/lookup":
self.send_error(404, "not found")
return
try:
length = int(self.headers.get("Content-Length", "0"))
payload = json.loads(self.rfile.read(length))
query = str(payload.get("query", "")).strip()
if not query:
raise ValueError("query is required")
result = {
"query": query,
"items": [
{"name": "example", "summary": f"Result for {query}"}
],
}
body = json.dumps(result).encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
except (ValueError, json.JSONDecodeError) as exc:
body = json.dumps({"error": str(exc)}).encode("utf-8")
self.send_response(400)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
if __name__ == "__main__":
HTTPServer(("127.0.0.1", 8000), Handler).serve_forever()
启动并调用它:
python server.py
curl -s http://127.0.0.1:8000/tools/lookup \
-H 'Content-Type: application/json' \
-d '{"query":"MCP"}'
这个例子有三个值得保留的特征:请求输入是显式的,返回结果是结构化 JSON,服务端没有依赖进程内会话。生产环境中还需要补上认证、超时、速率限制、审计日志和输入校验。
终端自由度与协议治理的取舍
“Agent 能运行 curl”确实带来了很强的自由度,但自由度越高,治理成本也越高。一个直接访问终端的 Agent 可能遇到以下问题:
- 命令注入和参数拼接风险。
- 访问了不应读取的文件或环境变量。
- 凭证通过命令行参数、日志或错误信息泄漏。
- 外部 API 返回恶意内容,进一步影响后续命令。
- 任务执行缺乏稳定的输入输出契约,导致结果难以测试。
MCP 或类似协议的核心收益,正在于把能力包装成可描述、可授权、可审计的接口。它不一定比直接调用命令更灵活,却更容易成为团队级基础设施。
因此,选择协议时可以按任务性质划分:探索阶段允许 Agent 使用受限终端和少量脚本;进入生产后,把高频、敏感或需要审计的操作收敛为稳定接口。对于接口本身,优先采用无状态请求,只有在长连接、事务协调或大规模流式任务中才引入会话状态。
开发团队应该关注什么
Simon Willison 的重新拥抱更值得被理解为一次工程判断,而不是立场反转。协议的价值会随着 Agent 能力变化而重新排序:当 Agent 可以自己组合命令时,简单的工具封装不再稀缺;可发现性、权限边界、可观测性和部署模型反而成为关键。
落地时可以检查这份清单:
- 每个工具是否有清晰、稳定的输入输出 schema?
- 请求是否能够在不同实例之间独立执行?
- 是否能记录调用者、参数摘要、耗时和错误类型?
- 凭证是否通过安全的运行时注入,而不是进入提示词或命令行?
- 终端能力是否限制了目录、网络、系统调用和资源消耗?
- 哪些能力适合保留为 Skill,哪些能力应该升级为受治理的 MCP 服务?
MCP 的下一阶段未必是工具数量继续增加,而可能是协议变得更轻、更无状态、更容易嵌入已有系统。对开发者来说,最实际的策略不是在 MCP 和 Skills 之间二选一,而是让自由组合能力服务于探索,让稳定协议承载生产边界。