无状态MCP重新引起了我的兴趣(并启发了mcp-explorer和datasette-mcp)

Simon Willison's Blog 工具

摘要

Simon Willison讨论了简化协议实现的无状态MCP(MCP 2.0)规范,并介绍了他的新工具mcp-explorer和datasette-mcp,这些工具利用该规范构建。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/08/03 01:29

# 无状态 MCP 重新引起了我的兴趣(并催生了 mcp-explorer 和 datasette-mcp) 来源:https://simonwillison.net/2026/Jul/31/stateless-mcp/ 2026 年 7 月 31 日,星期二,是无状态 MCP 日(https://x.com/ade_oshineye/status/2082129440943866149)——MCP 2.0 的正式发布,或者用更正式但更难记的名字:2026-07-28 Model Context Protocol 规范(https://blog.modelcontextprotocol.io/posts/2026-07-28/)。这是 MCP 规范自首次发布以来最重要的一次变更,也重新点燃了我个人对该协议的兴趣。 背景介绍:MCP 即 Model Context Protocol(模型上下文协议),它描述了一种向基于 LLM 的智能体框架暴露新工具的标准方式。该协议由 Anthropic 于 2024 年 11 月推出(https://www.anthropic.com/news/model-context-protocol),在 2025 年大部分时间里引起了*巨大*的关注热潮,但随后在人们发现一个能访问终端和 `curl` 的智能体框架可以用更灵活的方式完成 MCP 能做的绝大部分事情后,MCP 多少被 Skills(https://simonwillison.net/2025/Oct/16/claude-skills/)(同样是 Anthropic 的发明)所掩盖。我在 2025 年回顾(https://simonwillison.net/2025/Dec/31/the-year-in-llms/#the-only-year-of-mcp)中写过这件事。 现在我又回到了 MCP。给智能体一个可以访问互联网的 shell 环境充满了风险(https://simonwillison.net/2026/Jul/22/openai-cyberattack/),而且需要一个足够强大的模型来有效驱动这样的环境。MCP 工具更容易审计和控制,而且足够简单,即使是能在笔记本上运行的较小模型也能很好地驱动它们。新的无状态 MCP 规范也大大降低了实现客户端和服务器的复杂度。我这周就构建了三个这样的工具! #### 无状态 MCP 带来了哪些便利 有状态和无状态 MCP 之间差异的最佳演示,在这篇介绍新规范 RC 版的 5 月 21 日博客文章(https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/)中。它包含了一个清晰的"前后对比"示例。 较旧的有状态 MCP(我称之为"遗留 MCP")需要两个 HTTP 请求——第一个用于初始化会话并获得 `Mcp-Session-Id`,第二个才真正调用工具: ``` POST /mcp HTTP/1.1 Content-Type: application/json { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-11-25", "capabilities": { }, "clientInfo": { "name": "my-app", "version": "1.0" } } } POST /mcp HTTP/1.1 Mcp-Session-Id: 1868a90c-3a3f-4f5b Content-Type: application/json { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "search", "arguments": { "q": "otters" } } } ``` 新的无状态方式只需要一个 HTTP 请求,看起来像这样: ``` POST /mcp HTTP/1.1 MCP-Protocol-Version: 2026-07-28 Mcp-Method: tools/call Mcp-Name: search Content-Type: application/json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "search", "arguments": { "q": "otters" }, "_meta": { "io.modelcontextprotocol/clientInfo": { "name": "my-app", "version": "1.0" } } } } ``` 从客户端和服务器端的实现角度来看,这都简洁得多。它也更适合构建可扩展的 Web 应用,因为现在你不再需要维护服务器端状态来追踪那些会话 ID,也不必担心将同一会话路由到同一台后端机器。 #### mcp-explorer 我找不到一个很好的 CLI 工具来交互式地探查 MCP 服务器,所以让 Codex 帮我构建了一个。**mcp-explorer(https://github.com/simonw/mcp-explorer)** 就是成果。它是一个无状态的 Python CLI 工具,所以你甚至不需要安装就可以试用——它可以像这样通过 uvx(https://docs.astral.sh/uv/guides/tools/#running-tools)运行: ``` uvx mcp-explorer list https://agentic-mermaid.dev/mcp ``` 这会查询 Ade Oshineye 的 agentic-mermaid.dev(https://agentic-mermaid.dev/)演示 MCP。上面的命令会返回以下工具列表: ``` execute(code: string, timeoutMs?: integer) - Execute Mermaid SDK code Run JavaScript in an isolated sandbox; return a value. describe_sdk(family: string, detail?: string) - Describe Mermaid SDK operations Return version-matched mutation operations for one diagram family. render_svg(source: string, options?: object) - Render Mermaid as SVG Render a Mermaid source string to themeable SVG. Returns { ok, svg }. render_ascii(source: string, useAscii?: boolean, targetWidth?: integer, options?: object) - Render Mermaid as text Render a Mermaid source string to text. Returns { ok, text }. render_png(source: string, scale?: number, background?: string, fitTo?: object, options?: object) - Render Mermaid as PNG Rasterize a Mermaid source string to PNG. Returns { ok, png_base64 }. ... ``` 然后要查看某个工具的详细信息: ``` uvx mcp-explorer inspect render_svg ``` 这会输出大量信息,包括输入和输出的 JSON schema。要调用该工具并传入参数: ``` uvx mcp-explorer call \ https://agentic-mermaid.dev/mcp \ render_svg \ -a source 'graph TD; A-->B' \ -a options '{"padding":24}' ``` 返回结果: ``` {"ok":true,"svg":"<svg ...>...</svg>"} ``` 我实现了一个 `-a name '{"json": "or text"}'` 的参数语法,因为 JSON 字符串的 shell 转义太繁琐了。文档(https://github.com/simonw/mcp-explorer/blob/main/README.md)中有更多关于不同参数传递方式的详细说明。 `list`、`inspect` 和 `call` 这三个子命令涵盖了 95% 的"让我看看这个 MCP 服务器能做什么"的需求。也许这就是我真正需要的全部功能。 #### datasette-mcp 现在无状态 MCP 让实现 MCP 服务器变得如此容易,我忍不住为 Datasette 构建了一个官方插件。**datasette-mcp(https://github.com/simonw/datasette-mcp)** 目前版本为 0.1a0,它基于新的无状态规范,并做了以下两件事: 1. 它利用新的 plugin hook(https://docs.datasette.io/en/latest/plugin_hooks.html)暴露任意 SQL 查询工具 2. 它引入了 `tree` 工具,用于发现模式(并已被安全加固以绕过 Datasette 的默认权限系统) 这给了我一个非常有趣的演示机制。例如,在 https://datasette.simonwillison.net/-/mcp 处有一个运行 demo 的实例。以下是我在 Claude Code 中一直使用的一个提示词: > `list tables in simonwillison.net` 然后: > `what has Simon said recently about MCP?` 它运行了 7 个单独的 SQL 查询来得出答案。 #### llm-mcp-client 我的 LLM 工具(https://llm.datasette.io/)早就该有一个官方的 MCP 集成了。新的 alpha 版 llm-mcp-client(https://github.com/simonw/llm-mcp-client)插件就是我对这件事的尝试: ``` llm install llm-mcp-client llm -T 'MCP("https://datasette.simonwillison.net/-/mcp")' 'count the notes' ``` 以下是输出(包括推理过程,我使用的是 LLM 0.32rc2(https://simonwillison.net/2026/Jul/30/llm-rc2/)): > ***考虑笔记数量*** > *我看到"count the notes"这个问题很可能是在要求我统计博客笔记的数量。也可能是指已发布的笔记或草稿,所以存在一些歧义。我需要弄清楚笔记的总数,可能需要对已发布的笔记和草稿分别计数,才能得到明确的答案。让我们执行这个计数吧!* > > 一共有 **151 条笔记**。 以及该提示词的 llm logs 输出(https://gist.github.com/simonw/4e8f558766150658ce35eab4f0fc3e04)。一旦这个插件完全成熟,我考虑把它直接整合进 LLM 核心。我也很期待在 Datasette Agent(https://agent.datasette.io/)和 llm-coding-agent(https://github.com/simonw/llm-coding-agent)中试验 MCP。 #### MCP 是一种更安全的智能体构建方式 在 MCP 首次发布几个月后,我写了 Model Context Protocol has prompt injection security problems(https://simonwillison.net/2025/Apr/9/mcp-prompt-injection/),在文中我指出,让最终用户自行混搭工具的模式,把防止数据外泄攻击的责任推给了用户自己。当时我还没有发明"致命三重奏"(Lethal Trifecta,https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/)这个说法,但那绝对是我心中所想。 随后,具有任意 shell 和 `curl` 访问权限的通用智能体出现了,而这在安全方面要难得多! 我对 MCP 逐渐欣赏的一点是,与在开放网络环境中执行任意命令相比——这是当今大多数通用和编码智能体工具的默认方式——MCP 更容易推理智能体的能力以及可能出问题的地方。我计划在基于 LLM 构建敏感应用时大量使用 MCP。

相似文章

MCP 2026-07-28 规范:传输层变为无状态

Hacker News Top

MCP 发布了新的规范版本 2026-07-28,从双向有状态协议转变为无状态的请求/响应核心,提升了可扩展性和可靠性。更新内容包括自描述请求、服务器发现、缓存提示和授权增强,并更新了 TypeScript、Python、Go 和 C# 的 SDK。