← Back to Blog
October 22, 2026

How to connect SaveState's MCP server to Claude Code and Cursor

Node v22.23.4, npm 10.9.9, and @savestate/cli 0.9.0. Version, mcp help, then stdio initialize and tools/list.

This check used the published npm package @savestate/cli at version 0.9.0. The commands below are the ones that ran, and the transcripts are the text those commands printed.

The machine

node -v printed v22.23.4. npm -v printed 10.9.9 and exited 0, with empty stderr. command -v claude exited 1 and wrote no path. command -v cursor exited 1 and wrote no path. Claude Code and Cursor were not installed, so they were not started and they did not read the config files. The files were written under /tmp/ss-mcp-verify/project. The command inside each file was started from that directory.

Confirm the published package

With no arguments, npx -y @savestate/cli printed usage and exited 1. The version check is the flag below.

$ npx -y @savestate/cli --version

Exit code 0. stdout was 0.9.0 and a newline. stderr was empty.

$ npx -y @savestate/cli mcp --help

Exit code 0. stderr was empty. stdout:

Usage: savestate mcp [options]

Start MCP server for Claude Code integration

Options:
  -h, --help  display help for command

The help text says this command starts an MCP server for Claude Code integration. The only option it lists is -h, --help. The Cursor file in the next section starts that same command.

Claude Code: .mcp.json

The Claude Code project file is .mcp.json in the project root. This is the file that was written and then used to spawn the process. claude mcp add was not run, because claude was not on PATH.

{
  "mcpServers": {
    "savestate": {
      "command": "npx",
      "args": [
        "-y",
        "@savestate/cli",
        "mcp"
      ],
      "env": {
        "SAVESTATE_PASSPHRASE": "your-passphrase"
      }
    }
  }
}

Cursor: .cursor/mcp.json

The Cursor project file is .cursor/mcp.json. The file written for this check had the same bytes as .mcp.json.

{
  "mcpServers": {
    "savestate": {
      "command": "npx",
      "args": [
        "-y",
        "@savestate/cli",
        "mcp"
      ],
      "env": {
        "SAVESTATE_PASSPHRASE": "your-passphrase"
      }
    }
  }
}

command is npx. args is -y, @savestate/cli, mcp. env.SAVESTATE_PASSPHRASE is your-passphrase. The launcher applied that env object on top of the parent environment, so npx stayed on PATH and the child received SAVESTATE_PASSPHRASE.

stdio initialize and tools/list

Each file was loaded, and npx -y @savestate/cli mcp was spawned with SAVESTATE_PASSPHRASE=your-passphrase. After two seconds, stdout was empty. stderr was:

SaveState MCP server running on stdio

The client then wrote one JSON line, plus a newline, for initialize. Protocol version 2024-11-05. Client name savestate-verify. Client version 0.0.0.

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"savestate-verify","version":"0.0.0"}}}

The server replied with one line:

{"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"savestate","version":"0.5.0"}},"jsonrpc":"2.0","id":1}

serverInfo in that reply is {"name":"savestate","version":"0.5.0"}. The npm package version from --version was 0.9.0. The handshake serverInfo.version was 0.5.0.

The client then wrote a notification with no id:

{"jsonrpc":"2.0","method":"notifications/initialized"}

Then tools/list:

{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}

The server replied with one line. The launch from .mcp.json and the launch from .cursor/mcp.json both returned this same line:

{"result":{"tools":[{"name":"savestate_snapshot","description":"Create a new encrypted snapshot of the current AI agent state. Captures CLAUDE.md files, memory, settings, and project structure. Returns snapshot ID and stats.","inputSchema":{"type":"object","properties":{"label":{"type":"string","description":"Optional human-readable label for this snapshot"},"tags":{"type":"array","items":{"type":"string"},"description":"Optional tags for organizing snapshots"},"adapter":{"type":"string","description":"Adapter to use (claude-code, clawdbot, etc.). Auto-detected if not specified."},"full":{"type":"boolean","description":"Force a full snapshot instead of incremental"},"passphrase":{"type":"string","description":"Encryption passphrase. Required for snapshot creation."}},"required":["passphrase"]}},{"name":"savestate_restore","description":"Restore AI agent state from a snapshot. Use \"latest\" as snapshotId to restore the most recent snapshot. Returns details about what was restored.","inputSchema":{"type":"object","properties":{"snapshotId":{"type":"string","description":"Snapshot ID to restore, or \"latest\" for most recent"},"adapter":{"type":"string","description":"Adapter to use for restore. Auto-detected if not specified."},"dryRun":{"type":"boolean","description":"Preview what would be restored without making changes"},"passphrase":{"type":"string","description":"Decryption passphrase. Required for restore."}},"required":["snapshotId","passphrase"]}},{"name":"savestate_list","description":"List available snapshots with their metadata. Shows ID, timestamp, platform, label, and size.","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Maximum number of snapshots to return (default: 10)"},"platform":{"type":"string","description":"Filter by platform (claude-code, clawdbot, etc.)"}}}},{"name":"savestate_status","description":"Check SaveState initialization status and detected adapter. Returns whether SaveState is configured and which adapter would be used.","inputSchema":{"type":"object","properties":{}}}]},"jsonrpc":"2.0","id":2}

The tools array has four names, in this order:

  • savestate_snapshot
  • savestate_restore
  • savestate_list
  • savestate_status

savestate_snapshot lists passphrase as required. savestate_restore lists snapshotId and passphrase as required. savestate_list and savestate_status do not list required fields. This check did not call the tools.

The published 0.9.0 file dist/mcp/server.js does not read SAVESTATE_PASSPHRASE. The variable was set because it is the env value in the two config files. Passphrases for snapshot and restore are the tool arguments in the tools/list reply.

Pro is $9/mo.

This check started the local stdio server from the published npm package. Pro is $9/mo. Card today. No waitlist.

Subscribe to Pro, $9/mo

After you pay, claim the API key yourself. Then savestate login.

Prefer the CLI first? Install from npm

Questions? See the FAQ or open an issue on GitHub.