news 2026/9/12 1:53:01

SpacetimeDB MCP 指南:通过 Model Context Protocol 以工具调用方式操作运行中的数据库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpacetimeDB MCP 指南:通过 Model Context Protocol 以工具调用方式操作运行中的数据库

SpacetimeDB MCP 指南:通过 Model Context Protocol 以工具调用方式操作运行中的数据库

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

SpacetimeDB 主机本身支持 MCP(Model Context Protocol)协议,MCP 感知的客户端(AI Agent、编辑器等)可以直接通过工具调用(tool call)操作一个正在运行的数据库,而无需在 Shell 中敲击命令。本文以仓库内的 MCP Skill 文档(codex-plugin/plugins/spacetimedb/skills/mcp/SKILL.md)为骨架,结合 CLI 与 HTTP 层的源码实现,完整讲解 MCP 工具的形态、host-wide 与 database-scoped 两种服务器模式、权限规则、常见错误排查,以及它们与spacetimeCLI 的分工边界。读完本文,你将掌握如何用spacetimedb.list_databasesspacetimedb.get_schemaspacetimedb.sqlspacetimedb.callspacetimedb.ping五个工具安全地检查与变更线上数据。

概览:主机即 MCP 服务器

SpacetimeDB 的主机(host)直接说 MCP 协议,因此一个支持 MCP 的客户端可以用工具调用来操作一个正在运行的数据库,而不是使用 Shell 命令。如果客户端暴露了spacetimedb工具,那么凡是"读取或修改一个运行中数据库"的任务,都应当优先使用这些工具。

一个关键事实是:这些工具是"被动"注册的——它们以spacetimedb.list_databasesspacetimedb.get_schemaspacetimedb.sqlspacetimedb.callspacetimedb.ping的形式出现在客户端的工具列表中,但没有任何主动的提示或广播来宣告它们的存在。因此在使用前,务必先查看客户端暴露的工具列表(tools/list),确认工具确实存在,而不是想当然地认为它们缺失。

从源码看,这一能力在服务端有两个落地位置:

  • HTTP 路由层:crates/client-api/src/routes/mcp.rs实现了完整的 MCP JSON-RPC 处理逻辑(initializepingtools/listtools/call四个方法),并分别挂载在主机级路由POST /v1/mcp(见 crates/client-api/src/routes/mod.rs)和数据库级路由POST /database/:name_or_identity/mcp(见 crates/client-api/src/routes/database.rs)上;
  • CLI 桥接层:spacetime mcp命令(crates/cli/src/subcommands/mcp.rs)在 stdio 上循环读取 MCP 客户端发出的 JSON-RPC 行,转发给主机,并把主机的 JSON 响应逐行写回 stdout,从而把"任意支持 stdio MCP 的客户端"接驳到 SpacetimeDB 主机。

何时使用 MCP 工具,何时使用 CLI

MCP 工具与spacetimeCLI 各司其职,二者是互补关系而非替代关系:

任务使用
列出数据库、读取 schema、运行 SQL、调用 reducerMCP 工具
init、build、publish、generate、start、logsspacetimeCLI(参见 codex-plugin/plugins/spacetimedb/skills/cli/SKILL.md)

MCP 工具只能操作一个已经存在的数据库:它们无法搭建项目骨架、编译模块、发布(publish)或生成绑定(bindings)。所以两者的边界非常清晰——脚手架与生命周期管理交给 CLI,运行时数据检查与变更交给 MCP 工具

在两者都可用的场景下,优先使用 MCP 工具,原因有三:

  1. 类型化:每个工具都有明确的参数 schema(inputSchema);
  2. 返回 JSON:结果结构化,便于客户端解析与后续处理;
  3. 可门控:客户端可以根据工具的annotations(如readOnlyHintdestructiveHint)对破坏性工具进行权限门控,降低误操作风险。

当然,如果没有连接任何 MCP 客户端,那么使用等价的 CLI 命令(spacetime listspacetime describespacetime sqlspacetime call等)是完全正确的选择。

五个工具的完整参考

无论服务器处于哪种模式,核心工具集都是同一套。下表汇总了工具、参数与返回内容:

工具参数返回
list_databases自己拥有的数据库,包含 identity 与名称
get_schemadatabase表与 reducer 的 JSON 描述
sqldatabasesql、可选confirmed以 JSON 返回的行
calldatabasereducer、可选args(JSON 数组)reducer 的执行结果
ping可选message健康检查

在服务端源码 crates/client-api/src/routes/mcp.rs 的tools_list函数中可以看到每个工具携带的annotations

  • list_databasesget_schema标记为readOnlyHint: truedestructiveHint: false(只读);
  • sqlcall标记为readOnlyHint: falsedestructiveHint: true(可能变更数据,客户端应谨慎对待);
  • 所有工具均设置openWorldHint: false

list_databases只列出你自己拥有的数据库,因此对于匿名身份(anonymous identity)来说,它返回的结果为空。当你不知道数据库名称时,从这里开始排查是最稳妥的第一步——先用list_databases {}拿到身份与名称,再用名称去查询 schema 或执行 SQL。

两种服务器形态:先读tools/list,再决定参数

一个 MCP 服务器要么是host-wide(主机级),要么是scoped(绑定到单个数据库)。不要假设是哪一种,先读取工具列表来确认。源码 crates/client-api/src/routes/mcp.rs 中的host_wide = scope.is_none()正是这一区分的核心逻辑,它同时决定了tools_listtarget_database的行为。

Host-wide(主机级)形态

通过spacetime mcp(不带数据库参数)启动,或直接对POST /v1/mcp发起请求。此时每个数据工具都必须携带一个必填的database参数,其值可以是数据库名称或 identity,并且list_databases会被提供:

{ "name": "sql", "arguments": { "database": "mydb", "sql": "SELECT * FROM message" } }

从源码的target_database逻辑(crates/client-api/src/routes/mcp.rs)可以看到,host-wide 模式下如果database参数缺失,会返回INVALID_PARAMS级别的协议错误database argument must be a string;如果提供了参数,则既可以是名称(NameOrIdentity::Name),也可以是 64 位十六进制的 identity(NameOrIdentity::Identity)。

Scoped(数据库级)形态

通过spacetime mcp <database>启动,或对POST /v1/database/<db>/mcp发起请求。此时连接已经固定了目标数据库,因此没有database参数,也没有list_databases工具

{ "name": "sql", "arguments": { "sql": "SELECT * FROM message" } }

即使工具调用中多传了database参数,target_database也会优先采用 URL 中已经解析好的数据库(Target::Resolved),忽略参数中的值——源码中的target_database_prefers_the_url_scope_then_the_argument测试用例明确验证了这一行为。

如何启动这两种形态

CLI 参考(docs/docs/00300-resources/00200-reference/00100-cli-reference/00100-cli-reference.md)与 MCP 参考文档(docs/docs/00300-resources/00200-reference/00150-mcp.md)给出了标准启动方式:

spacetime mcp --server local # host-wide,每个工具需带 database 参数 spacetime mcp my-database --server local # scoped,固定到 my-database
  • 省略数据库参数 → host-wide 模式;
  • 传入数据库名称或 identity → scoped 模式;
  • 数据库参数也可以来自SPACETIMEDB_DB_NAME环境变量(见 crates/cli/src/subcommands/mcp.rs 中Arg::new("database").env("SPACETIMEDB_DB_NAME"));
  • 命令使用你已保存的 SpacetimeDB 身份,除非传入--anonymous
  • --server参数接受服务器昵称、主机名或 URL。

CLI 桥接的实现细节(crates/cli/src/subcommands/mcp.rs)是:在 stdio 上逐行读取 JSON-RPC,通过POST转发到主机的mcp端点;若收到 HTTP 202 状态码(表示这是一个无 id 的 notification,无需应答)则继续;否则把 JSON 响应写回 stdout。对应的 HTTP 端点说明如下:

POST /v1/mcp # host-wide POST /v1/database/<name-or-identity>/mcp # database-scoped

HTTP 方式使用与其他 SpacetimeDB HTTP API 相同的 bearer token 进行鉴权;也可以省略授权头,此时使用匿名身份。需要注意,spacetime mcp目前标记为UNSTABLE(命令行工具会打印WARNING: This command is UNSTABLE and subject to breaking changes.,见 crates/cli/src/util.rs 的UNSTABLE_WARNING常量),可能尚未出现在已发布的 CLI 中。因此,如果客户端无法启动它,就回退到cliskill 中的等价 CLI 命令。

不变的四条规则

无论使用哪种形态,MCP 工具都以你的身份运行,与 HTTP API 的行为完全一致。权限与数据模型遵循 codex-plugin/plugins/spacetimedb/skills/concepts/SKILL.md 中描述的 SpacetimeDB 核心概念,具体到 MCP 场景有四点需要始终牢记:

  1. Reducer 是写路径。call来变更数据。reducer 在一个事务中运行,要么整体提交(Committed),要么整体回滚(Failed/BudgetExceeded)。源码 crates/client-api/src/routes/mcp.rs 的tool_call_reducer会以你的 identity 建立连接上下文、调用 reducer、再断开连接,最终把结果翻译为可读文本(如reducer 'send_message' committed),失败时则返回带错误文本的 HTTP 错误。

  2. SQL 写入需要所有权。sql工具可以读取公开表(public tables);但通过 SQL 写入需要你拥有该数据库。通常应优先使用call——把授权与校验逻辑保留在模块的 reducer 中,客户端无需直接面对写 SQL。

  3. 私有表对客户端不可读。get_schema仍然会显示私有表(private tables)的声明,因此当sql报出no such table时,通常意味着该表是私有表,而不是表不存在。可读性取决于你的身份,不要假设某个私有表一定可读。

  4. 工具错误是带内返回的。一个失败的 reducer 或一条错误的查询,返回的是一个带isError: true的结果,错误消息以文本形式出现在content里,而不是传输层失败。重试之前,务必先读取错误文本。源码中execution_error_to_tool_result(crates/client-api/src/routes/mcp.rs)正是把所有执行期错误转换为这种带内工具结果,其测试用例failed_reducer_surfaces_in_band_with_messageexecution_errors_become_in_band_tool_results都验证了isError: true与错误文本的传递。

实战:检查一个数据库的完整流程

下面是针对一个名为mydb的数据库从"发现"到"查询"再到"写入"的完整工具调用序列(host-wide 模式):

list_databases {} get_schema { "database": "mydb" } sql { "database": "mydb", "sql": "SELECT * FROM message" } call { "database": "mydb", "reducer": "send_message", "args": ["hello"] }

几点实操细节:

  • get_schema返回的 JSON 包含类型的 typespace、所有表(含私有表的声明)以及 reducer 列表。服务端实现(tool_get_schema)会等待数据库 leader 的模块就绪(超时上限 10 秒,见源码常量MODULE_WAIT_TIMEOUT),再把模块定义序列化为 JSON。拿到 schema 后,可以据此确定要查询的表名、可调用的 reducer 名及其参数顺序。
  • sqlconfirmed参数:传入"confirmed": true可以让读取等待持久化确认(durably confirmed)后再返回,适用于对一致性要求较高的读取场景(服务端SqlQueryParams { confirmed }会透传给sql_direct)。
  • callargs是位置参数:按 reducer 声明的参数顺序传入 JSON 数组。无参时省略args或传空数组[]均可——源码reducer_args_json明确将Nonenull都规范化为[],而args必须是 JSON 数组,传字符串或对象会被拒绝(args must be a JSON array)。
  • scoped 模式下所有调用去掉database参数、list_databases不可用,其余完全一致。

常见错误排查速查表

消息含义
database argument must be a string服务器是 host-wide 形态,而你省略了database参数(或传了非字符串值)
unknown tool: list_databases服务器已 scoped 到某一个数据库,list_databases不可用
`x` not found此服务器上不存在名为x的数据库,或调用时把名称用在了需要 identity 的位置
no such table: x表是私有表(当前身份不可读),或你查询了错误的数据库
完全没有spacetimedb工具没有连接 MCP 服务器。此时应改用 CLI 命令(参见cliskill)

注意第一个错误在服务端表现为 JSON-RPC 协议错误(INVALID_PARAMS,错误码 -32602),而非带内工具错误——因为它发生在参数解析阶段;其余运行期错误则统一走带内isError: true返回。这点区别可以在排查时帮你快速定位问题出在"参数形态"还是"数据库/表"层面。

与官方参考文档的关系

本文对应的完整官方参考见 docs/docs/00300-resources/00200-reference/00150-mcp.md,其中包含相同的工具表、权限说明与错误对照,并额外给出了 HTTP 端点的鉴权细节(bearer token 或匿名身份)。CLI 命令的详细参数(spacetime mcp [OPTIONS] [database]--server--anonymousSPACETIMEDB_DB_NAME)可在 docs/docs/00300-resources/00200-reference/00100-cli-reference/00100-cli-reference.md 中查阅。如果要在自己的 Agent 工作流中复用本文的能力,可直接参考本文开篇引用的 Skill 文件 codex-plugin/plugins/spacetimedb/skills/mcp/SKILL.md。

需要再次强调的是:MCP 支持目前仍处于 unstable 阶段,接口可能随版本变化;在实际环境中操作前,先通过tools/list确认工具形态,再按本文的规则发起调用,是稳妥的做法。

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 1:52:47

轮胎字符识别:端到端OCR实战与边缘部署

简介&#xff1a;本资源是一份面向计算机、人工智能、自动化等专业学生的机器学习课程大作业实践项目&#xff0c;聚焦轮胎图像中字符的识别任务&#xff0c;完整覆盖数据预处理、模型训练、推理部署与结果可视化全流程。资源适用于零基础入门者系统学习&#xff0c;也支持进阶…

作者头像 李华
网站建设 2026/9/12 1:52:38

Karakeep 迁移指南:从 Hoarder 更名到新镜像与裸机升级全流程

Karakeep 迁移指南&#xff1a;从 Hoarder 更名到新镜像与裸机升级全流程 【免费下载链接】hoarder A self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search 项目地址: https://gitcode.com/GitHub_Trend…

作者头像 李华
网站建设 2026/9/12 1:50:59

大模型幻觉治理:从2%指标误区到提示工程实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 1:45:28

RetroArch 缩略图加载失败:按症状排查修复

RetroArch 缩略图加载失败&#xff1a;按症状排查修复 【免费下载链接】RetroArch Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3. 项目地址: https://gitcode.com/GitHub_Trending/re/RetroArch RetroArch 缩略图不显示、游戏列表一片…

作者头像 李华
网站建设 2026/9/12 1:44:40

Spark 性能优化:从 Stage 分析、Task 倾斜到 Shuffle 量优化

Spark 性能优化&#xff1a;从 Stage 分析、Task 倾斜到 Shuffle 量优化本文深入探讨 Spark 作业性能瓶颈定位的核心方法&#xff0c;通过 Stage 分析识别作业执行路径&#xff0c;Task 倾斜定位数据处理不均衡点&#xff0c;Shuffle 量优化减少数据传输开销。结合实例演示与调…

作者头像 李华