# Plot Speaks (remote · plotspeaks.com)

Voice mysteries, history battles and trivia with your assistant as host. Sign in to keep progress.

- Trust score: 68/100 (medium)
- Change this week: +3
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- remote · `account.plotspeaks.com`: 31/100, [markdown](https://verifymcp.io/servers/com-plotspeaks-plot-speaks/account.md), [page](https://verifymcp.io/servers/com-plotspeaks-plot-speaks/account)
- remote · `plotspeaks.com`: 68/100 (this document), [markdown](https://verifymcp.io/servers/com-plotspeaks-plot-speaks/plotspeaks.md), [page](https://verifymcp.io/servers/com-plotspeaks-plot-speaks/plotspeaks)

## Channel facts

- Endpoint: `https://plotspeaks.com/mcp`
- Transports: `streamable-http`
- Auth: `none`
- Version: `0.6.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, 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.

- **Endpoint Security**: 57/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation check failed: no authorisation is required to call this server, and it exposes a tool marked destructive (submit_story).
  - HTTPS is enforced; there's no plaintext access path.
  - HSTS check failed: the Strict-Transport-Security header is absent.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 75/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 7029 tokens (~260/item across 27 items; 25 tools + 2 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 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.
- **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 27 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).
  - Supports UI / widget rendering.

## Install

### How do I install the Plot Speaks MCP server?

Plot Speaks is a hosted endpoint at https://plotspeaks.com/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add --transport http com-plotspeaks-plot-speaks 'https://plotspeaks.com/mcp'
```

### Cursor

```json
{
  "mcpServers": {
    "com-plotspeaks-plot-speaks": {
      "url": "https://plotspeaks.com/mcp"
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "com-plotspeaks-plot-speaks": {
      "type": "http",
      "url": "https://plotspeaks.com/mcp"
    }
  }
}
```

### Codex

```toml
[mcp_servers.com-plotspeaks-plot-speaks]
url = "https://plotspeaks.com/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "com-plotspeaks-plot-speaks": {
      "type": "remote",
      "url": "https://plotspeaks.com/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add com-plotspeaks-plot-speaks --url 'https://plotspeaks.com/mcp' --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  com-plotspeaks-plot-speaks:
    url: "https://plotspeaks.com/mcp"
```

### Netclaw

```json
{
  "McpServers": {
    "com-plotspeaks-plot-speaks": {
      "Transport": "http",
      "Url": "https://plotspeaks.com/mcp"
    }
  }
}
```

### Vellum

```bash
assistant mcp add com-plotspeaks-plot-speaks -t streamable-http -u 'https://plotspeaks.com/mcp'
```

### Other

```json
{
  "mcpServers": {
    "com-plotspeaks-plot-speaks": {
      "type": "http",
      "url": "https://plotspeaks.com/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## 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-04 (score 68, +1)

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

### 2026-11-03 (score 67, 0)

- [security] Tool “claim_plays” rewrote its description, which is the text the model reads
- [security] Tool “game_board” rewrote its description, which is the text the model reads
- [security] Tool “get_cue” rewrote its description, which is the text the model reads
- [security] Tool “list_stories” rewrote its description, which is the text the model reads
- [security] Tool “team_roster” rewrote its description, which is the text the model reads
- [security] Tool “world_update” rewrote its description, which is the text the model reads
- [security] Tool “write_story” rewrote its description, which is the text the model reads
- [security] Tool “pick_for_me” rewrote its description, which is the text the model reads
- [security] Tool “request_team” rewrote its description, which is the text the model reads
- [security] Tool “reveal_solution” rewrote its description, which is the text the model reads
- [security] Tool “start_story” rewrote its description, which is the text the model reads
- [functional regression] Schema quality: 216 → 260
- [functional] Schema quality: good → excellent
- [cosmetic] “claim_plays” reworded the description of “play_ids”
- [cosmetic] “game_board” reworded the description of “play_id”
- [cosmetic] “game_board” reworded the description of “slug”
- [cosmetic] “get_cue” reworded the description of “cue”
- [cosmetic] “get_cue” reworded the description of “play_id”
- [cosmetic] “get_cue” reworded the description of “slug”
- [cosmetic] “list_stories” reworded the description of “collection”
- [cosmetic] “start_story” reworded the description of “versus_code”
- [cosmetic] “submit_story” reworded the description of “email_when_approved”
- [cosmetic] “team_roster” reworded the description of “team”
- [cosmetic] “world_update” reworded the description of “day”
- [cosmetic] “world_update” reworded the description of “initiative”
- [cosmetic] “world_update” reworded the description of “location”
- [cosmetic] “world_update” reworded the description of “npcs”
- [cosmetic] “world_update” reworded the description of “party”
- [cosmetic] “world_update” reworded the description of “play_id”
- [cosmetic] “world_update” reworded the description of “quests”
- [cosmetic] “world_update” reworded the description of “rest”
- [cosmetic] “world_update” reworded the description of “slug”
- [cosmetic] “write_story” reworded the description of “genre”
- [cosmetic] “write_story” reworded the description of “length”
- [cosmetic] “list_stories” reworded the description of “page”
- [cosmetic] “roll” reworded the description of “hidden”
- [cosmetic] “start_story” reworded the description of “chapter”
- [cosmetic] “start_story” reworded the description of “minutes”
- [cosmetic] “start_story” reworded the description of “new_campaign”
- [cosmetic] “start_story” reworded the description of “path_code”
- [cosmetic] “start_story” reworded the description of “play_id”
- [cosmetic] “start_story” reworded the description of “resume_code”
- [cosmetic] “start_story” reworded the description of “slug”
- [cosmetic] “start_story” reworded the description of “team”

### 2026-11-02 (score 67, +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-10-31 (score 66, +1)

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

### 2026-10-29 (score 65, +1)

- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “list_stories” rewrote its description, which is the text the model reads
- [security] Tool “withdraw_submission” rewrote its description, which is the text the model reads
- [functional improvement] Stability: unverified → 0.03
- [functional] New prompt “make_a_game_or_quiz”
- [functional] New prompt “write_a_story”
- [functional] New tool “submission_status”
- [cosmetic] “submit_story” added an optional parameter “email_when_approved”
- [cosmetic] “list_stories” reworded the description of “collection”
- [cosmetic] “pick_for_me” reworded the description of “collection”
- [cosmetic] “withdraw_submission” reworded the description of “claim_code”
- [cosmetic] “withdraw_submission” made “claim_code” optional

### 2026-10-28 (score 64)

First indexed and scored.

## MCP tools (25)

### `open_plot_speaks` (~123 tokens)

Open Plot Speaks

Returns the Plot Speaks welcome: a short spoken introduction, a question offering to list the stories, start one or write one, and a menu of story categories with example titles. With skip_intro the introduction is left out; with instructions it adds the how-to-play.

Input parameters:

- `instructions` (boolean): True when the user asks how Plot Speaks works or wants the instructions again: adds the how-to-play
- `skip_intro` (boolean): True when the user has heard the introduction before or asks to skip it: returns only the question and the menu

### `pick_for_me` (~223 tokens)

Pick something for me

Picks ONE Plot Speaks story or game to play now, ranked from the player's mood, the time they have, how many are playing and an optional collection, skipping what a signed-in player has already played. Returns the pick's title, slug and one-line pitch, plus a runner-up. Records only anonymous counts of the mood matched and length asked for. If nothing fits every filter it says so instead of picking.

Input parameters:

- `all_ages` (boolean): True to keep it suitable for every age (nothing rated above PG)
- `collection` (string): Only from this collection, by name or id: Murder Mysteries, Greek Myths, Classic Detectives, Horror and Ghosts, Seasons, Holiday Specials, Bedtime, Dice Games, Road Trip, Read-Aloud Classics, Written…
- `minutes` (integer): How long they have
- `mood` (string): The mood or kind of thing, in their words, e.g. spooky, light, a mystery, something calm
- `players` (integer): How many are playing

### `list_stories` (~538 tokens)

List stories

Lists the Plot Speaks stories and games that can be played by voice, three at a time with a one-line pitch each; the page argument gives the next three. Narrow it by a collection (Murder Mysteries, Greek Myths, Classic Detectives, Horror and Ghosts, Seasons, Holiday Specials, Bedtime, Dice Games, Road Trip, Read-Aloud Classics, Written by players), by length (max_minutes), by what's new (new: true), by kind (mysteries, adventures, choose-your-path stories, trivia, guessing games, game shows, dice games, word games, party and storytelling games, Table Talk, Story Time read-alouds, wind-downs, open worlds and campaigns) or, within mysteries, classic or dark. With group_by_category and no page it returns the whole catalogue under kind headings. An unknown kind or collection returns a message naming the valid ones.

Input parameters:

- `audience` (string): Narrow by audience: general, or the all-ages pieces. Omit for everything
- `collection` (string): A collection, by name or id, loosely matched: greek-myths, classic-detectives, ghost-gothic, seasons, holidays, bedtime, dice, road-trip, classics, players. Examples: "Greek Myths", "detective storie…
- `genre` (string): Within mysteries and adventures: murder-mystery (all murder mysteries), classic (murder mysteries that aren't dark), dark (dark murder mysteries) or adventure
- `group_by_category` (boolean): True, with no page, for the whole list grouped under kind headings
- `kind` (string): Only list this kind: mystery, adventure, branching (choose your path), trivia, guessing (guessing games), gameshow (game shows), dice (dice games), word (word games), party (party and storytelling),…
- `max_minutes` (integer): Only pieces this many minutes long or shorter
- `new` (boolean): True for what's new: the newest pieces first, with their What's New line
- `not_played` (boolean): True to leave out what this player has already played (signed-in players only)
- `page` (integer): Which page of three to return, from 1; page 2 gives items 4 to 6 of the same filtered list. Each result states the page and total pages

### `claim_plays` (~183 tokens)

Add earlier plays to my account

Attaches plays made earlier without an account to the signed-in player's Plot Speaks account, so they appear in their history (with how each ended) and in the "not played yet" filter, and marks the trivia clues already heard in those games. Returns a sentence naming the titles added and how many could not be added (id not found, or already on another account). Without a signed-in account it returns an error saying so. Changes the account's history; plays on another account are left alone.

Input parameters:

- `play_ids` (array, required): 1 to 50 play ids, as returned by start_story, e.g. ["3f2b8c1e-9d4a-4e7b-a1c2-5b6d7e8f9a0b"]; ids of plays made in this conversation without an account

### `my_history` (~53 tokens)

What I've played

Returns what a signed-in Plot Speaks player has played, newest first, with how each ended. Without an account it says how to get one.

Input parameters:

- `limit` (integer): How many to list (default 15)

### `start_story` (~586 tokens)

Start a story

Loads a Plot Speaks story or game, of any kind (mystery, choose-your-path, trivia, dice or word game, Team Trivia, campaign), by slug or title. Returns its script as text (setting, cast, scenes or board, and how it is narrated; one chapter at a time for multi-chapter stories) and a play id the play's other tools take. Records an anonymous play (story, connecting assistant, time; no conversation text), and on the account connector adds it to the player's history. An unknown slug or title returns an error naming close matches or the available stories; a chapter past the last returns an error; an unreleased chapter returns its release date.

Input parameters:

- `chapter` (integer): Chapter number for a multi-chapter story, e.g. 2 for the second chapter (default 1); an error if the story has fewer chapters
- `minutes` (integer): For a trivia game: minutes the player has, e.g. 25, so the game is sized to fit
- `new_campaign` (boolean): For a campaign, when a signed-in player already has one: true starts a fresh campaign instead of carrying on their latest (default false)
- `path_code` (string): For a choose-your-path story: the three-word path code a friend received at an ending, e.g. brave-river-stone, to follow that friend's choices; codes last 30 days, an unknown one returns an error
- `play_id` (string): With chapter above 1: the play id returned for chapter 1, e.g. 3f2b8c1e-9d4a-4e7b-a1c2-5b6d7e8f9a0b, so both chapters count as one play; ignored if it belongs to another story
- `resume_code` (string): For a campaign: the three-word code given at the end of an earlier session, e.g. amber-otter-lantern; carries on that campaign's world instead of starting one. An unknown code returns an error
- `slug` (string, required): The story's slug or title, matched loosely, 2 to 80 characters, e.g. example-dinner-party or The Last Toast
- `team` (string): For the team-trivia story: the team as the player said it, e.g. Steelers, Pittsburgh or PIT; "Yankees vs Red Sox" gives a rivalry board. Several matches or an unsupported team return a message instea…
- `versus_code` (string): For a trivia board: the three-word code a friend received at the end of their game, to play the same board and compare scores; pass slug "versus" with it, the code names the game. Codes last 30 days

### `choose` (~156 tokens)

Make a choice

Moves a Plot Speaks choose-your-path story on by the player's choice and returns what happens next: the scene to narrate and the choices that follow, or the ending. With no choice it returns where the play is now and the path so far (for resuming). With go_back it returns to the last choice so the player can choose again.

Input parameters:

- `choice` (string): The player's answer: the choice's number, or their words for it
- `go_back` (boolean): True when the player wants to go back to their last choice and choose again (after an ending, or any time they ask)
- `play_id` (string, required): The play id from start_story
- `slug` (string, required): The story slug

### `game_board` (~204 tokens)

Trivia board

Returns the current state of a Plot Speaks game in play, as text, without changing it. For trivia: the scores and the categories and values still on the board. For a survey or letter game: the scores, the open question or puzzle and what is revealed so far. For a timeline game: the line so far, lives and the open card. For Worms!: the tiles, stacks and open roll. Reads only; nothing is recorded. A play id that does not belong to that game returns an error, and a story that is not a game returns an error saying so.

Input parameters:

- `play_id` (string, required): The play id start_story returned for this game, e.g. 3f2b8c1e-9d4a-4e7b-a1c2-5b6d7e8f9a0b
- `slug` (string, required): The game's slug or title, e.g. team-trivia

### `game_question` (~278 tokens)

Trivia clue

Opens one clue on a Plot Speaks trivia board and returns its text (not the answer). Category "final" opens the final once the board is clear. In a survey or letter game it deals the next question or puzzle: pass category "next" ("skip" gives the open one up; "no steal" closes a survey question after three strikes). In a timeline game it starts a round: pass the deck's name, then " for " and the players' names (the reply deals the first card); "next" repeats the open card. In Worms!, Yacht (and Pigs!) it sets up the game: pass "rules" for the how-to-play beats, or "players", the names and "and Wormbot" (Skipper in Yacht, Hambot in Pigs!) or "no CPU" ("play again" after a game).

Input parameters:

- `category` (string, required): The category the player picked, or "final" ("next" in a survey or letter game; the deck's name in a timeline game; "rules" or "players Ann, Bob and Wormbot" in Worms!)
- `play_id` (string, required): The play id from start_story
- `slug` (string, required): The game's slug
- `value` (integer): The value the player picked, e.g. 300

### `game_answer` (~274 tokens)

Trivia answer

Checks a player's answer to the open trivia clue, scores it and returns the ruling with the answer, or the next step of a stepped clue. In a survey game it checks an answer against the hidden board; in a letter game it takes a called letter or a solve attempt, in the player's own words; in a timeline game it takes where the open card goes (before X, between X and Y, at the end), in the player's own words; in Worms! it takes the face to keep ("the fours", "worms"), "roll again" or "stop", and "take" or "steal"; in Yacht it takes the dice to keep ("the threes", "keep 3 3 5", "keep all", "none", "reroll the one") or "score it", then the box ("full house", "fours", "chance") and a yes or no to "Take a zero?"; in Pigs! it takes "yes" (throw again) or "no" (bank).

Input parameters:

- `answer` (string, required): What the player said, in their words
- `play_id` (string, required): The play id from start_story
- `player` (string): The answering player's name, for the scores
- `slug` (string, required): The game's slug

### `game_challenge` (~89 tokens)

Challenge a ruling

Challenges the last trivia ruling: three different AI models judge the player's answer against the clue, and the ruling flips only if at least two agree it should count. Once per clue. In a timeline game it re-checks the last placement against the years and says what was heard.

Input parameters:

- `play_id` (string, required): The play id from start_story
- `slug` (string, required): The game's slug

### `team_roster` (~149 tokens)

Team roster

Returns a sports team's current roster for Plot Speaks Team Trivia, read live from ESPN (cached for hours): players grouped by position with jersey numbers, and the head coach, as plain text. Covers the leagues in the Team Trivia database. Reads only; nothing is recorded. A name that fits several teams returns an error listing the candidates with their leagues; a team not in the database returns an error listing the leagues covered; if ESPN does not answer, the text says so.

Input parameters:

- `team` (string, required): The team as the player said it: a city, name, nickname or abbreviation, e.g. Steelers, Pittsburgh or PIT; a full name such as Pittsburgh Steelers is the most exact

### `request_team` (~91 tokens)

Request a team

Records a player's request for a sports team that Plot Speaks Team Trivia doesn't cover yet, for the people who maintain the database. Stores the team name and note as a request event, with no account or personal details attached, and returns a confirmation.

Input parameters:

- `note` (string): Anything else they said about it
- `team` (string, required): The team they'd like added, with its league if they said it

### `roll` (~155 tokens)

Roll dice

Rolls dice for a Plot Speaks campaign or adventure on the server: "1d20+5", "2d6", "adv 1d20+3" (advantage), "dis 1d20" (disadvantage), "4d6 drop lowest". Returns each die and the total.

Input parameters:

- `dice` (string, required): The roll, e.g. 1d20+5
- `hidden` (boolean): True for a roll the story's rules keep secret from the players (a world clock, a hidden table); the result comes with a note that it is hidden and not for reading aloud
- `why` (string): What the roll is for, e.g. Mira's stealth check

### `world_recall` (~101 tokens)

Recall the campaign

Returns a Plot Speaks campaign's state (day, place, party with hit points, spell slots and gear, people met, quests, the story so far) by play id, or by the three-word resume code the players were given.

Input parameters:

- `play_id` (string): The play id, when you have it
- `resume_code` (string): The three-word resume code the players say
- `slug` (string, required): The campaign's slug

### `world_update` (~583 tokens)

Update the campaign

Applies changes to a Plot Speaks campaign's saved world: new characters, damage and healing, spells cast, items, gold, rests, location, day, people met (the dead stay dead), quests, fight turn order (initiative) and a one-line story note. Send only what changed; fields left out are untouched. Returns a RECORDED list, a REFUSED list giving the reason for each change the campaign's rules do not allow, and the updated state. Saves to the campaign play (no personal data). An unknown slug, a non-campaign story or an unknown play id returns an error.

Input parameters:

- `day` (integer): The campaign day number, e.g. 3, if it moved on
- `initiative` (array): The turn order in a fight, first is up, naming only creatures the party can see (the screen shows it), e.g. ["Mira","Goblin","Tobin"]; sending the list again replaces it, and an empty list ends the f…
- `location` (string): Where the party is now, e.g. the Sunken Chapel (kept to 120 characters)
- `note` (string): One line for the story so far (kept to 240 characters)
- `npcs` (array): People met or changed, each {name, status, note}; status e.g. friendly, hostile or dead (the dead stay dead); notes kept to 160 characters. E.g. [{"name":"Old Bram","status":"friendly"}]
- `party` (array): Up to 6 party members to add or change, matched by name (an unknown name adds a character). Each: name, plus any of class, level (1 to 5), hp, max_hp, damage, heal, spend_slot (spell level 1 to 5), m…
- `play_id` (string, required): The campaign's play id from start_story or world_recall, e.g. 3f2b8c1e-9d4a-4e7b-a1c2-5b6d7e8f9a0b
- `quests` (array): Quests taken or changed, each {name, status, note}; status is open, done or failed; notes kept to 160 characters. E.g. [{"name":"Find the lantern","status":"done"}]
- `rest` (string): "short" or "long": applies that rest's recovery to the party under the campaign's rules
- `slug` (string, required): The campaign's slug or title, e.g. the campaign named in start_story's script

### `check_accusation` (~89 tokens)

Check an accusation

Checks a formal accusation in a Plot Speaks mystery. Returns the verdict line for the accused person, starting Correct. or Innocent., and the name it matched. Records the accusation and verdict anonymously.

Input parameters:

- `accused` (string, required): The name of the person the user accused
- `play_id` (string): The play id from start_story
- `slug` (string, required): The story slug

### `reveal_solution` (~124 tokens)

Full reveal

Returns the full solution of a Plot Speaks mystery (who did it, why, and the clues that pointed there) and what became of each character. Without gave_up: true it is refused unless an accusation is already recorded for that play; with gave_up: true it answers at once. Records that the play ended in a reveal.

Input parameters:

- `gave_up` (boolean): True when the player has said they give up or want the answer without accusing anyone
- `play_id` (string, required): The play id from start_story
- `slug` (string, required): The story slug

### `get_cue` (~268 tokens)

Get a scene cue

Returns one scene cue from a Plot Speaks mystery or adventure script, as text: a READ ALOUD part (the scene as spoken narration) and, where the cue has them, NARRATOR NOTES that are not meant to be read aloud because they would spoil the scene; cue S1 also lists the follow-up cues to listen for. With a play id it records the scene reached as an anonymous play event, which the play's watch page shows as a timeline. An unknown slug returns an error naming the available stories; a cue id the story lacks returns an error saying so (or that the story has no cues).

Input parameters:

- `cue` (string, required): The cue id as written in the story's script: S, a number and an optional letter; the S and case may be omitted. E.g. S1, S3b or 3b
- `play_id` (string): The play id start_story returned, e.g. 3f2b8c1e-9d4a-4e7b-a1c2-5b6d7e8f9a0b; when given, the cue is logged against that play
- `slug` (string, required): The story slug or title, e.g. example-dinner-party

### `rate_story` (~287 tokens)

Rate a story

Saves a rating and feedback for a Plot Speaks story the user has just played: 1 to 5 stars, whether anything was given away too early, an optional comment about the story, optional feedback about the experience for the people who make Plot Speaks, and, for a story still being tested, the player's verdict (passed, or needs work). Needs the play id from start_story; one rating per play; stars or a verdict (or both).

Input parameters:

- `comment` (string): The player's comment about the story, if any, in their words
- `feedback` (string): Feedback about the experience (the narration, the connector, what to improve), if any, in the player's words; read by the people who make Plot Speaks
- `play_id` (string, required): The play id from start_story
- `slug` (string, required): The story slug
- `spoiled` (boolean): True if the player felt the narrator gave something away too early
- `stars` (integer): 1 to 5 (optional when a verdict is given)
- `verdict` (string): For a story being tested: "passed" if it passed the player's test, "needs_work" if something should be improved (put what, in their words, in feedback)
- `wish` (string): What else the player would like to play, if they said, in their words

### `write_story` (~211 tokens)

Write a story

Returns the writing kit for a new Plot Speaks story as one text: a short introduction to how a story is built (a public story.md plus a private answer key, secrets.md, reviewed by a person before anything is published), a suggested way for the writer and assistant to draft, review and submit it together, and the format template for the chosen genre and length. Reads only; nothing is stored or recorded beyond anonymous counts of genre and length. Genre and length are fixed choices, and omitting either gives the default.

Input parameters:

- `genre` (string): Kind of story to write: murder-mystery (default), dark (a dark murder mystery), adventure, branching (a choose-your-path story), trivia (a trivia board) or game (a voice game); chooses which template…
- `length` (string): Playing time of the story: "20" or "30" minutes in one chapter (default "30"), or "2-chapter" for a story in two sittings

### `review_story` (~124 tokens)

Review a story draft

Runs the format checks on a draft story.md, and with secrets.md also the answer-key checks (including whether story.md gives the culprit away). Returns a status, the findings with line numbers, and a fair-play checklist. Nothing sent is stored.

Input parameters:

- `secrets_md` (string): The full text of secrets.md (the private answer key), if written
- `slug` (string): The story's folder name, e.g. the-last-toast; checks that name is plotspeaks-<slug>
- `story_md` (string, required): The full text of story.md

### `submit_story` (~311 tokens)

Submit a story

Submits a finished Plot Speaks story for human review, credited to the name the writer chooses. Runs the format checks, a safety screen and a daily limit, then stores it; nothing is public until a person approves it. Returns a submission id and a one-time claim code for withdrawing or updating it. With replaces_id and claim_code, it replaces an earlier submission.

Input parameters:

- `author_name` (string, required): The name credited publicly as "Written by" (2 to 60 characters; a pen name is fine). Checked by the reviewer with the story.
- `claim_code` (string): Only to update an earlier submission: the claim code from its receipt
- `contact` (string): Optional: how the reviewer can reach the writer (email or handle). Seen only by the reviewer.
- `email_when_approved` (boolean): True records the writer's request for one email, to the verified Google address of the account they signed in with, when a person approves the story (default false: no email). It takes effect only on…
- `replaces_id` (string): Only to update an earlier submission: its submission id
- `secrets_md` (string): The full text of secrets.md (kept private on the server; mysteries need one)
- `story_md` (string, required): The full text of story.md

### `withdraw_submission` (~105 tokens)

Withdraw a submission

Deletes a story submitted to Plot Speaks (pending or published) when its submission id and claim code match. On the account connector, a signed-in writer can withdraw their own story with just the id.

Input parameters:

- `claim_code` (string): The claim code from the receipt, e.g. ABCD-EFGH-JKMN. Needed unless the writer is signed in on the account connector and the story is theirs.
- `id` (string, required): The submission id from the receipt

### `submission_status` (~103 tokens)

Check a submission

Read-only. Shows where a story submitted to Plot Speaks stands when its submission id and claim code match: received and waiting for a person, approved (with the story's link), or not accepted (with the reviewer's short note, if there is one). Changes nothing.

Input parameters:

- `claim_code` (string, required): The claim code from the receipt, e.g. ABCD-EFGH-JKMN
- `id` (string, required): The submission id from the receipt

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/com-plotspeaks-plot-speaks/plotspeaks#diagnostics

## Score history

- 2026-11-05: 68
- 2026-11-04: 68
- 2026-11-03: 67
- 2026-11-02: 67
- 2026-11-01: 66
- 2026-10-31: 66
- 2026-10-30: 65
- 2026-10-29: 65
- 2026-10-28: 64

## Common questions

### What is the Plot Speaks MCP server?

Plot Speaks is an MCP server listed in the public MCP registry as com.plotspeaks/plot-speaks. Voice mysteries, history battles and trivia with your assistant as host. Sign in to keep progress. This page covers its hosted endpoint (https://plotspeaks.com/mcp).

### Is the Plot Speaks MCP server safe to use?

Plot Speaks scores 68 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 Plot Speaks MCP server expose?

Plot Speaks exposes 25 tools: open_plot_speaks, pick_for_me, list_stories, claim_plays, my_history, and 20 more. Their descriptions and schemas cost roughly 5,408 tokens of context every time the server is loaded.

### Does the Plot Speaks MCP server require authentication?

No. We connected to Plot Speaks without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.

### Is the Plot Speaks MCP server still maintained?

Plot Speaks is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- Remote endpoint: https://plotspeaks.com/mcp
- Website: https://plotspeaks.com/
- Changelog RSS feed: https://verifymcp.io/servers/com-plotspeaks-plot-speaks/plotspeaks.xml
- Changelog JSON feed: https://verifymcp.io/servers/com-plotspeaks-plot-speaks/plotspeaks.json
- HTML version of this page: https://verifymcp.io/servers/com-plotspeaks-plot-speaks/plotspeaks
