Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 121 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"crates/fs-utils",
"crates/lib",
"crates/metrics",
"crates/spacetimedb-mcp",
"crates/paths",
"crates/pg",
"crates/physical-plan",
Expand Down Expand Up @@ -280,6 +281,8 @@ rustc-hash = "2"
rustyline = { version = "12.0.0", features = [] }
scoped-tls = "1.0.1"
scopeguard = "1.1.0"
rmcp = "1.7"
schemars = "1"
second-stack = "0.3"
self-replace = "1.5"
semver = "1"
Expand Down
23 changes: 23 additions & 0 deletions crates/spacetimedb-mcp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "spacetimedb-mcp"
version = "0.1.0"
edition.workspace = true

[[bin]]
name = "spacetimedb-mcp"
path = "src/main.rs"

[dependencies]
rmcp = { workspace = true, features = ["server", "transport-io", "macros"] }
spacetimedb-lib = { workspace = true, features = ["serde"] }
reqwest.workspace = true
tokio.workspace = true
serde.workspace = true
serde_json.workspace = true
schemars.workspace = true
anyhow.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true

[lints]
workspace = true
85 changes: 85 additions & 0 deletions crates/spacetimedb-mcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# spacetimedb-mcp

A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for
SpacetimeDB. It exposes SpacetimeDB to MCP-aware agents and editors as a set of
tools, built on the official Rust MCP SDK ([`rmcp`](https://crates.io/crates/rmcp)).

> Status: early. Read-only schema introspection works today (`get_schema`,
> `list_tables`, `list_reducers`); a `ping` health check is also included.
> Further tools (SQL, subscriptions, the CLI workflow) are deferred for now.

## Transport

The server speaks JSON-RPC over **stdio**: an MCP client launches it as a
subprocess and exchanges messages on stdin/stdout. Logs go to **stderr only** —
stdout is reserved for the protocol stream, so anything else printed there would
corrupt it.

## Build

```bash
cargo build -p spacetimedb-mcp
```

The binary lands at `target/debug/spacetimedb-mcp`.

## Test

```bash
cargo test -p spacetimedb-mcp
```

Unit tests cover the schema-to-output transformations and the
serialize/deserialize round trip the client relies on; an integration test
serves a canned schema over a throwaway HTTP server and checks the full
fetch-and-decode path, so no running SpacetimeDB instance is required.

## Run

Point an MCP client at the built binary. The introspection tools talk to a
running SpacetimeDB host, configured via environment variables:

| Variable | Default | Purpose |
| ------------------- | ----------------------- | -------------------------------------------------- |
| `SPACETIMEDB_HOST` | `http://127.0.0.1:3000` | Base URL of the SpacetimeDB host to query. |
| `SPACETIMEDB_TOKEN` | _(unset)_ | Bearer token, required only for private databases. |

The target database (a name or identity) is passed as an argument to each tool,
so one server can introspect any database on the host. Example client config:

```json
{
"mcpServers": {
"spacetimedb": {
"command": "/path/to/target/debug/spacetimedb-mcp",
"env": { "SPACETIMEDB_HOST": "http://127.0.0.1:3000" }
}
}
}
```

## Smoke test

Drive the JSON-RPC handshake by hand to confirm the round trip works:

```bash
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"ping","arguments":{"message":"hi"}}}' \
| ./target/debug/spacetimedb-mcp 2>/dev/null
```

The `tools/call` response should echo `pong: hi`.

## Tools

| Tool | Arguments | Description |
| --------------- | ---------- | -------------------------------------------------------------------- |
| `ping` | `message?` | Health check. Echoes an optional message back. |
| `get_schema` | `database` | Full module definition (typespace, tables, reducers) as JSON. |
| `list_tables` | `database` | Names of all tables in the database. |
| `list_reducers` | `database` | Reducers in the database, with each reducer's lifecycle role if any. |

All introspection is read-only. Write operations, SQL, and subscriptions are
intentionally out of scope for now.
Loading