# Rystic (mcpb · rystic-mcp_0.0.35.mcpb)

Start, seed, clock, inspect and diff Rystic API simulators from your agent.

- Trust score: 40/100 (low)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- mcpb · `rystic-mcp_0.0.35.mcpb`: 40/100 (this document), [markdown](https://verifymcp.io/servers/ai-rystic-rystic/rystic-mcp.md), [page](https://verifymcp.io/servers/ai-rystic-rystic/rystic-mcp)

## Channel facts

- Registry: `mcpb`
- Package: `https://github.com/Rystic-Inc/rystic/releases/download/v0.0.35/rystic-mcp_0.0.35.mcpb`
- Transport: `stdio`
- SHA-256: `83fc166ec278d535a2c58d60c2d98d1318f67e116752931d5e1940b329acac71`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Supply Chain Security**: 0/100
  - No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.
  - Known CVEs could not be checked: we found no dependency list to check in this bundle: either it runs a compiled binary, whose bundled manifests we do not read, or none of the package.json, requirements.txt, pyproject.toml or uv.lock files it ships for its runtime declares a dependency we can read (a requirements.txt that only points at a setup.py project, a local path, or a nested requirements file we cannot follow counts as none).
  - Install-script risk not yet assessed.
  - Dependency health could not be checked: we found no dependency list to check in this bundle: either it runs a compiled binary, whose bundled manifests we do not read, or none of the package.json, requirements.txt, pyproject.toml or uv.lock files it ships for its runtime declares a dependency we can read (a requirements.txt that only points at a setup.py project, a local path, or a nested requirements file we cannot follow counts as none).
- **Provenance & Transparency**: 32/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - License check failed: the license (Proprietary) isn't a recognized OSI-approved license.
  - Actively maintained (last published 2 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 73/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 4759 tokens (~237/item across 20 items; 19 tools + 1 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 17/100
  - Stability observed for 5 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.
  - An AI judge read all 21 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the Rystic MCP server?

Rystic ships as an MCPB bundle, a single file you download and open in an MCP host that supports MCPB bundles, such as Claude Desktop. The host reads the launch command from the bundle's own manifest, so there is no command to copy. Before opening it, check the file's SHA-256 matches the one the MCP registry declares for it, 83fc166ec278d535a2c58d60c2d98d1318f67e116752931d5e1940b329acac71; the commands to do that are on this page. If it does not match, do not open it.

- Download bundle: `https://github.com/Rystic-Inc/rystic/releases/download/v0.0.35/rystic-mcp_0.0.35.mcpb`
- SHA-256: `83fc166ec278d535a2c58d60c2d98d1318f67e116752931d5e1940b329acac71`

### Verify on macOS / Linux

```bash
echo "83fc166ec278d535a2c58d60c2d98d1318f67e116752931d5e1940b329acac71  rystic-mcp_0.0.35.mcpb" | shasum -a 256 -c
```

### Verify on Windows (PowerShell)

```powershell
(Get-FileHash -Algorithm SHA256 .\rystic-mcp_0.0.35.mcpb).Hash -eq "83fc166ec278d535a2c58d60c2d98d1318f67e116752931d5e1940b329acac71"
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-05 (score 40, +1)

No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-11-02 (score 39, +1)

- [functional regression] Schema quality: 4088 → 4759
- [functional improvement] Stability: unverified → 0.07

### 2026-10-31 (score 38)

First indexed and scored.

## MCP tools (19)

### `advance_clock` (~123 tokens)

Move the instance's clock by whole seconds, forward or (negative) back: give seconds or duration, exactly one. Events fire as the clock passes them. Returns the clock the twin then reads.

Input parameters:

- `duration` (string): a non-zero duration of whole seconds such as 90s, 15m or 48h
- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `seconds` (integer): a non-zero number of seconds

### `check_test_case` (~359 tokens)

Grade the instance's run since its baseline against a saved test case's checks, as `rystic grade` does, with no model: capture the run as save_test_case does, with the twin's event timeline as world.json, into a new grid cell dir holding the case's eval, grade it, and write its verdict.json. case is the cell_dir or eval path save_test_case returned, or any eval file; a case dir's checks/ YAML files are graded too. The case's world must name exactly the instances' twins, by twin name or by grid name (the twin name without -twin). Returns result (pass, fail, error, or incomplete when every graded check passed but one was skipped), reason, cell_dir, notes, and per check its id (nothing_destructive, checks[i] in eval order, then checks/<file>[j]), result (pass, fail, error or skipped), detail and, for a failure, the rows behind it. A script check is skipped, never run. To check a new run, reset or load_scenario the instance, run the agent, then call this.

Input parameters:

- `case` (string, required): an absolute path: the cell_dir or eval path save_test_case returned, or an eval file
- `instance` (string): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `instances` (array): several instances, one per twin, for a case across twins; instead of instance
- `out_dir` (string): an absolute path, not yet existing or empty, to write the new run's cell dir to (default: a new temp dir)

### `diff_state` (~353 tokens)

Compare the instance's state now with its baseline, the state it had when start_twin started it, load_scenario loaded a scenario or reset cleared it: rows created, changed (each changed field's JSON Pointer path, before and after) and deleted, per resource. register narrows it to one register. counts cover every row that differs (in register, when given); resources holds a page of them, in resource, then created, changed and deleted, then key order. concise (the default) gives created and deleted rows with string values over 256 bytes cut, and changed rows as their fields; detailed adds each changed row's state and cuts only a row over 12 KB. A cut row is marked truncated. A page holds at most limit rows and about 20 KB. When more remain, next_cursor reads the next page; whenever anything is cut, truncated is true and hint names the call that gets the rest. An instance with no baseline (started outside this server) gets one on the first call, which answers baseline first_seen and an empty diff.

Input parameters:

- `cursor` (string): the next_cursor a page returned, to read the page after it; omit for the first page
- `format` (string): concise (the default) trims each entry to what picks the next call; detailed carries the whole entry
- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `limit` (integer): at most this many entries on the page (default 50); a page also stops near 20 KB
- `register` (string): only this register's rows

### `inspect_state` (~370 tokens)

Return the instance's state (GET /_rystic/inspect) a page at a time: state is resource, then row key, then row, in key order. register narrows it to one register, and key with it to one row; matched counts the rows they match. concise (the default) cuts string values over 256 bytes and lists those rows in cut_rows; detailed cuts only a row over 12 KB. A page holds at most limit rows and about 20 KB. When more remain, next_cursor reads the next page; whenever anything is cut, truncated is true and hint names the call that gets the rest. A state larger than one page also carries state_uri, a resource link to the whole state uncut. view asks for one of the twin's named views instead, such as identities, answered as {view, result}; a view that is a file, or larger than a page, comes back as its size and the URL to fetch it from.

Input parameters:

- `cursor` (string): the next_cursor a page returned, to read the page after it; omit for the first page
- `format` (string): concise (the default) trims each entry to what picks the next call; detailed carries the whole entry
- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `key` (string): only the row with this key, in register
- `limit` (integer): at most this many entries on the page (default 50); a page also stops near 20 KB
- `register` (string): only this register's rows
- `view` (string): a named view instead of the state, read whole

### `list_calls` (~354 tokens)

List the API calls the instance served since its last reset (GET /_rystic/calls), oldest first, a page at a time; method, path_prefix, status and actor filter them. concise (the default) gives each call's seq, at, method, path, status and actor; detailed gives the twin's whole record. total counts every call since the reset, matched the kept calls the filters match. A page holds at most limit calls and about 20 KB. When more remain, next_cursor reads the next page; whenever anything is cut, truncated is true and hint names the call that gets the rest.

Input parameters:

- `actor` (string): only calls made as this actor
- `cursor` (string): the next_cursor a page returned, to read the page after it; omit for the first page
- `format` (string): concise (the default) trims each entry to what picks the next call; detailed carries the whole entry
- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `limit` (integer): at most this many entries on the page (default 50); a page also stops near 20 KB
- `method` (string): only calls with this HTTP method, such as POST
- `path_prefix` (string): only calls whose path starts with this, such as /v1/charges
- `status` (integer|string): only calls answered with this status, such as 404, or this class, such as "4xx"
- `tail` (integer): deprecated, prefer cursor: start the page at the last N entries

### `list_scenarios` (~70 tokens)

List the named starting worlds the instance's twin ships (GET /_rystic/scenarios), each with a summary.

Input parameters:

- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)

### `list_sent` (~358 tokens)

List what the instance sent since its last reset: webhooks, emails and other outbound effects (GET /_rystic/egress), oldest first, a page at a time. Each event names its effect and type as the twin's model calls them; no field marks a webhook apart from an email, so filter on effect or type. concise (the default) gives each event's seq, effect, type and owner; detailed adds the payload. delivery, when present, sums up webhook delivery with its newest 20 attempts in results (results_total counts the attempts the twin reports). total counts every event since the reset, matched the kept events the filters match. A page holds at most limit events and about 20 KB, and an event over 12 KB is cut and marked truncated. When more remain, next_cursor reads the next page; whenever anything is cut, truncated is true and hint names the call that gets the rest.

Input parameters:

- `cursor` (string): the next_cursor a page returned, to read the page after it; omit for the first page
- `effect` (string): only events with this effect
- `format` (string): concise (the default) trims each entry to what picks the next call; detailed carries the whole entry
- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `limit` (integer): at most this many entries on the page (default 50); a page also stops near 20 KB
- `tail` (integer): deprecated, prefer cursor: start the page at the last N entries
- `type` (string): only events of this type

### `list_twins` (~48 tokens)

List the twin instances running on this machine: each one's name, twin, version, URL, runner and status from a live probe. Call it first to find the instance the other tools take.

### `load_scenario` (~97 tokens)

Replace the instance's state with a named scenario, keeping the twin's built-in records (POST /_rystic/scenario). The loaded state becomes diff_state's baseline.

Input parameters:

- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `name` (string, required): the scenario, as list_scenarios names it

### `reset` (~83 tokens)

Reset the instance to the twin's built-in records, dropping scenario and seeded state (POST /_rystic/reset), clearing its calls and sent log. The reset state becomes diff_state's baseline.

Input parameters:

- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)

### `restore_twin` (~340 tokens)

Roll the instance back to a snapshot snapshot_twin saved: reset it, then land the snapshot's state, clock, id counters, pending scheduled events and network shaping, so ids minted after the restore continue where the snapshot left off. The restored state becomes diff_state's baseline. A snapshot taken on another version of the twin is refused. On a twin release older than the seed round trip, which holds no id counters, every result carries a warning: ids minted after the restore can collide with restored records, and per-account records can come back duplicated. A snapshot does not hold, so a restore does not bring back: the idempotency cache (a replayed request makes a new object), the request-id counter, the calls and sent logs (they start empty), the webhook delivery queue, credential bindings, upload sessions, the rate limiter, the clock's wall offset, scheduled events in full (only the pending events of the world's own schedule come back; one that uses a value a fired event bound is dropped, and a schedule loaded on its own replays from its start), built-in records deleted before the save (the reset brings them back), and whether a scenario installed the network shaping (once landed, the shaping stays through later resets). A pending default-actor call on a route that needs a credential binding fails the restore after the reset, which leaves the instance reset.

Input parameters:

- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `name` (string, required): the snapshot's name, as snapshot_twin saved it

### `save_test_case` (~347 tokens)

Save the instance's run since its baseline as a test case: write a grid cell dir (before is diff_state's baseline, after the state now, with the calls and sent log since the last reset) and draft an eval from it with `rystic grade --draft`. The draft expects each row the run created or changed, forbids any other creation, change, call actor or method, and allow_deletes each row it deleted; the saved cell passes it. The state after the last seed through this server since the baseline is the run's before, so seeded rows are setup, not the run's; rows a scenario timeline event seeds during the run count as the run's. Returns the draft YAML and cell_dir, whose eval.yaml holds the draft, so `rystic grade <cell_dir>` passes. Trim the checks to what the task requires before keeping them. An instance with no baseline is refused: reset, load_scenario or diff_state it before the run.

Input parameters:

- `instance` (string): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `instances` (array): several instances, one per twin, for a case across twins; instead of instance
- `name` (string, required): the case's name: the eval name in cell.json and the temp dir's prefix
- `out_dir` (string): an absolute path, not yet existing or empty, to write the cell dir to (default: a new temp dir)
- `prompt` (string): the task the agent was given, the draft's prompt (default: a placeholder to replace)

### `save_world` (~495 tokens)

Save the instance's state as a scenario file at file, the scenario document `rystic run --seed <file>` boots and POST /_rystic/seed lands, so a teammate, a CI job or a later run starts a twin in this state. It holds what snapshot_twin holds: the whole state, the clock, the id counters, the pending scheduled events and, when your plan includes network shaping and a profile is installed, that shaping. The file names the twin but no instance, version or model hash; a twin release that cannot take a record refuses the load and lists the records. An existing file, a symlink included, is refused unless force is true, which replaces the file or writes through the symlink. New files are private to your user; replacing a file preserves its permissions. It refuses a pending event that acts as a named caller and a scenario too large for the seed route to take back. On a twin release older than the seed round trip, which holds no id counters, the result carries a warning: ids minted after a load can collide with loaded records. The file does not hold, so loading it does not bring back: the idempotency cache (a replayed request makes a new object), the request-id counter, the calls and sent logs (they start empty), the webhook delivery queue, credential bindings, upload sessions, the rate limiter, the clock's wall offset, scheduled events in full (only the pending events of the world's own schedule come back; one that uses a value a fired event bound is dropped, and a schedule loaded on its own replays from its start), built-in records deleted before the save (the reset brings them back), and whether a scenario installed the network shaping (once landed, the shaping stays through later resets). It holds no rng_seed and no credentials either, which the twin does not expose; add those keys to the file by hand when a run needs them. A pending default-actor call on a route that needs a credential binding fails the load.

Input parameters:

- `file` (string, required): the absolute path to write, such as a scenarios/ file in your repo
- `force` (boolean): replace an existing file (default: refuse it)
- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)

### `seed` (~148 tokens)

Merge records into the instance's state (POST /_rystic/seed). body is {register: {key: {field: value}}}; `rystic describe <twin> -json` shows each register with an example record. Seeding leaves diff_state's baseline where it is, so seeded rows read as created; save_test_case reads the seeded state as the run's starting state instead.

Input parameters:

- `body` (object, required): the seed document: {register: {key: {field: value}}}
- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)

### `set_clock` (~106 tokens)

Pin the instance's clock to an RFC3339 instant (POST /_rystic/clock); events due by then fire. Returns the clock the twin then reads.

Input parameters:

- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `time` (string, required): an RFC3339 instant such as 2026-05-01T09:00:00Z

### `sign_in` (~136 tokens)

Sign in to Rystic, or sign up, in the browser, so start_twin can download twins: call it when a tool fails with license_or_lease. The first call returns a URL and a code at once; show both to the user, who opens the URL, checks that the page shows the same code and approves. Then call sign_in again: it answers pending until the user has approved, then stores the API key where `rystic login` stores it and answers signed_in. A link lasts 15 minutes; a call after that returns a new one. The API key never appears in a result.

### `snapshot_twin` (~384 tokens)

Save the instance's world under name, so restore_twin can roll back to it: try one path, roll back, try another. It holds the whole state, never a page,, the clock, the id counters, the pending scheduled events and, when your plan includes network shaping, that shaping. This CLI stores it per instance; it outlives a restart of the instance on the same twin version. A snapshot of the same name is replaced, and the result says so. Omit name to list the instance's snapshots. It refuses a pending event that acts as a named caller (a restore cannot rebind its credential) and a world too large for the seed route to take back. A snapshot does not hold, so a restore does not bring back: the idempotency cache (a replayed request makes a new object), the request-id counter, the calls and sent logs (they start empty), the webhook delivery queue, credential bindings, upload sessions, the rate limiter, the clock's wall offset, scheduled events in full (only the pending events of the world's own schedule come back; one that uses a value a fired event bound is dropped, and a schedule loaded on its own replays from its start), built-in records deleted before the save (the reset brings them back), and whether a scenario installed the network shaping (once landed, the shaping stays through later resets). A pending default-actor call on a route that needs a credential binding fails the restore after the reset, which leaves the instance reset.

Input parameters:

- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)
- `name` (string): the snapshot's name (letters, digits, '.', '_' and '-', at most 64); omit to list the instance's snapshots

### `start_twin` (~302 tokens)

Start a twin in the background, as `rystic run <twin> -d` does, and return its instance name and URL; point the code under test at the URL. A twin that is not installed is pulled first, as `rystic run` pulls one, which can take a minute; a call that carries a progressToken gets the download as notifications/progress, and cancelling the call stops the pull and any twin it started. It takes a free port unless port is given, and stores the state it boots into as diff_state's baseline. The twin keeps running after this server exits; stop_twin ends it.

Input parameters:

- `clock` (string): start the twin's clock at this RFC3339 instant
- `name` (string): the instance name the other tools take (default: default)
- `port` (integer): listen port; omit or 0 for a free one
- `project` (string): the project label `rystic ps --project` groups by (default: default)
- `runner` (string): how to run it (default: your rystic config, else native)
- `scenario` (string): boot into this named scenario (the twin's own catalog)
- `twin` (string, required): the twin's name, as `rystic list` prints it
- `version` (string): the version to run (default: the installed current one, else the newest release)

### `stop_twin` (~65 tokens)

Stop a running instance and remove its record and diff baseline, as `rystic stop` does.

Input parameters:

- `instance` (string, required): the instance: its name, its twin when that twin runs one instance, or <twin>/<name> (list_twins names them)

## Diagnostics

Captured diagnostic sections: Provenance. The full working is on the page: https://verifymcp.io/servers/ai-rystic-rystic/rystic-mcp#diagnostics

## Score history

- 2026-11-05: 40
- 2026-11-04: 39
- 2026-11-03: 39
- 2026-11-02: 39
- 2026-11-01: 38
- 2026-10-31: 38

## Common questions

### What is the Rystic MCP server?

Rystic is an MCP server listed in the public MCP registry as ai.rystic/rystic. Start, seed, clock, inspect and diff Rystic API simulators from your agent. This page covers its MCPB bundle (https://github.com/Rystic-Inc/rystic/releases/download/v0.0.35/rystic-mcp_0.0.35.mcpb).

### Is the Rystic MCP server safe to use?

Rystic scores 40 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Rystic MCP server expose?

Rystic exposes 19 tools: advance_clock, check_test_case, diff_state, inspect_state, list_calls, and 14 more. Their descriptions and schemas cost roughly 4,538 tokens of context every time the server is loaded.

### What licence is the Rystic MCP server under?

Rystic declares the Proprietary licence, which is not on the OSI-approved list. Read the terms before using it at work, and note this covers the source only, not the cost of any service it calls.

## Links

- Repository: https://github.com/Rystic-Inc/rystic
- Website: https://www.rystic.ai/mcp
- Changelog RSS feed: https://verifymcp.io/servers/ai-rystic-rystic/rystic-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/ai-rystic-rystic/rystic-mcp.json
- HTML version of this page: https://verifymcp.io/servers/ai-rystic-rystic/rystic-mcp
