← 文章 / AI技术
Simon Willison 4小时前 · 2026-08-01 11:03:17 · 1 阅读

无状态 MCP 重新点燃了我的兴趣,并催生了 mcp-explorer 和 datasette-mcp

无状态 MCP 重新点燃了我的兴趣(并催生了 mcp-explorer 和 datasette-mcp)

2026 年 7 月 31 日

周二是无状态 MCP 日——即 MCP 2.0 的发布,或者更正式但更难记的称呼:2026-07-28 版模型上下文协议规范。这是 MCP 规范自首次发布以来最重大的变化,也重新点燃了我个人对该协议的兴趣。

背景:MCP 是模型上下文协议,它定义了一种标准方式,向基于 LLM 的智能体框架暴露新工具。该协议由 Anthropic 于 2024 年 11 月推出,在 2025 年的大部分时间里引发了巨大关注,但后来被 Skills(Anthropic 的另一项发明)抢了风头,因为人们发现,一个能访问终端和 curl 的智能体框架,可以用更灵活的方式完成 MCP 能做的绝大部分事情。我在 2025 年回顾中写过这一点。

现在我又重新关注起 MCP。给智能体一个能访问互联网的 shell 环境风险极高,而且需要一个足够强大的模型才能有效驾驭这种环境。MCP 工具更容易审计和控制,而且足够简单,即使是能在笔记本上运行的较小模型也能很好地驱动它们。

新的无状态 MCP 规范还大大降低了实现协议客户端和服务器的复杂度。这周我就构建了三个这样的实现!

无状态 MCP 让哪些事情变得更简单

有状态与无状态 MCP 之间的差异,在 5 月 21 日的这篇博客文章中得到了最好的展示,该文介绍了新规范的候选版本。其中包含一个清晰的对比示例。

旧的有状态 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 应用,因为现在你不再需要维护服务端状态来跟踪那些 session ID,也无需担心将同一会话路由到同一台后端机器。

mcp-explorer

我没找到一款好用的 CLI 工具来交互式探测 MCP 服务器,于是让 Codex 帮我写了一个。 结果就是 **mcp-explorer**。它是一个无状态的 Python CLI 工具,甚至不需要安装就能试用——像这样配合 uvx 使用: ``` uvx mcp-explorer list https://agentic-mermaid.dev/mcp ``` 这条命令会查询 Ade Oshineye 的 agentic-mermaid.dev 演示 MCP。上述命令返回以下工具列表: `execute(code: string, timeoutMs?: integer)` - 执行 Mermaid SDK 代码 在隔离沙箱中运行 JavaScript;返回一个值。 `describe_sdk(family: string, detail?: string)` - 描述 Mermaid SDK 操作 返回某个图表系列对应的版本匹配的变更操作。 `render_svg(source: string, options?: object)` - 将 Mermaid 渲染为 SVG 将 Mermaid 源码字符串渲染为可定制主题的 SVG。返回 `{ ok, svg }`。 `render_ascii(source: string, useAscii?: boolean, targetWidth?: integer, options?: object)` - 将 Mermaid 渲染为文本 将 Mermaid 源码字符串渲染为文本。返回 `{ ok, text }`。 `render_png(source: string, scale?: number, background?: string, fitTo?: object, options?: object)` - 将 Mermaid 渲染为 PNG 将 Mermaid 源码字符串栅格化为 PNG。返回 `{ 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":" README 里还有[几个命令](https://github.com/simonw/mcp-explorer/blob/main/README.md),但大致思路你已经明白了。我发现构建这类 CLI 工具是熟悉规范非常高效的方式,即使大部分实际代码是由 AI 写的。

datasette-mcp

第二个项目是 **datasette-mcp**,这是一个 Datasette 插件,能为任何 Datasette 实例添加 `/-/mcp` 端点。 这大概是我第四次尝试构建这个插件,但得益于新的无状态 MCP 规范,我终于有了一个值得发布的版本。

它只提供了三个工具:list_databases()get_database_schema(database_name)execute_sql(database_name, sql)。这些工具的功能正如你所预期——不过目前 execute_sql() 是只读的。

把它们接入一个智能体,或者像 ChatGPT 或 Claude 这样的聊天工具,它们就能对你的 Datasette 实例执行 SQL 查询。

目前,我正把它运行在我博客的 Datasette 镜像上,地址是 datasette.simonwillison.net/-/mcp。为了把它连接到 ChatGPT 和 Claude,我折腾了一番,但最终还是搞定了。这里有一篇 新的 TIL 文章,详细展示了具体操作方法。

这里有一个 共享的 Claude 会话,我向它提问:

列出 simonwillison.net 中的表

然后接着问:

Simon 最近对 MCP 说了什么?

它运行了 7 次独立的 SQL 查询才得出答案。

llm-mcp-client

我的 LLM 工具早就该有一个官方的 MCP 集成了。新的 alpha 版 llm-mcp-client 插件正是我为此做的尝试:

llm install llm-mcp-client
llm -T 'MCP("https://datasette.simonwillison.net/-/mcp")' '统计笔记数量'

以下是输出结果(包含推理过程,我使用的是 LLM 0.32rc2):

正在考虑笔记数量

我看到“统计笔记数量”这个问题,很可能是在要求我统计博客笔记的总数。也可能是指已发布的笔记或草稿,所以这里存在一些歧义。我需要通过查询已发布笔记和草稿的数量来得出明确答案。让我们开始执行统计吧!

共有 151 条笔记

以及该提示对应的 llm logs 的输出结果

一旦这个功能成熟,我考虑直接将其引入 LLM 核心。我也很期待在 Datasette Agentllm-coding-agent 中尝试 MCP。

MCP 是构建智能体的更安全方式

MCP 发布几个月后,我写了《模型上下文协议存在提示注入安全问题》,文中指出让最终用户自行混搭工具的模式,实际上是把防范数据泄露攻击的责任推给了用户自己。当时我还没提出 致命三重奏 这个概念,但心里想的正是这个。

后来出现了能随意访问 shell 和 curl 的通用智能体,安全防护的难度就更大了!

我逐渐认识到 MCP 的一个优点:相比在开放网络环境中随意执行命令(这是当今大多数通用和编码智能体工具的默认方式),MCP 更容易让人理解智能体的能力边界以及可能出错的地方。

在基于 LLM 构建敏感应用时,我计划更多地依赖 MCP。

原始来源: Simon Willison

评论 (0)