Install the MCP server
Use this guide to connect an MCP client to a Screenplay application. Screenplay
runs locally, against a model directory you own. Desktop packages include their
runtime: you do not need Docker, a .NET SDK, or a separately installed cratis
executable to run a downloaded bundle.
Desktop installation
Section titled “Desktop installation”Choose the simplest supported channel, in this order:
- Curated directory: when Screenplay is listed, install it from Claude Desktop Settings → Extensions → Browse extensions or ChatGPT Plugins. Directory submissions require publisher review; this release does not claim an approved listing. OpenAI public local-MCP distribution still requires OpenAI’s explicit support. Until a listing is live, use the download below.
- Desktop download: get the native package from the Screenplay releases.
- Advanced/headless clients: use Docker, the .NET tool, or manual stdio registration below. These options remain supported.
Claude Desktop bundle
Section titled “Claude Desktop bundle”Download screenplay-VERSION-RID.mcpb and its matching .sha256 file. Select
osx-arm64 for Apple Silicon, osx-x64 for Intel macOS, or win-x64 for Windows
x64. Verify the checksum before opening it. Bundles currently are unsigned;
checksums from the Cratis-owned HTTPS release verify integrity, not publisher
signing. Review the package’s permissions and origin.
Open the MCPB in an up-to-date Claude Desktop. If your OS does not associate the file, use Settings → Extensions → Advanced settings → Extension Developer → Install Extension. Review the trust dialog, complete installation and enable the extension. There is no model folder to configure: Screenplay works in the folder the host shares with it, and otherwise asks Claude to open the folder you name in the conversation (“open the Screenplay model in ~/Projects/shop”). Check its tools and version in Settings → Extensions. Enterprise device policies can restrict installation; do not bypass them.
Install an updated bundle to update a privately downloaded extension; remove it in Claude’s Extensions UI. The CLI cannot verify this host-owned state.
ChatGPT Desktop plugin
Section titled “ChatGPT Desktop plugin”Download screenplay-VERSION-RID-plugin.zip and its .sha256. Use the same native
macOS/Windows RID choices, and a ChatGPT Desktop version/account that exposes local
Plugins and stdio MCP. An empty model starts in the plugin’s persistent data
folder. To choose an existing model without authoring JSON, use the coordinated
CLI desktop installer (Cratis CLI 3.25.0 or later). First,
install the Cratis CLI; you do not need a running Chronicle
store for these desktop commands:
cratis screenplay mcp install --clients chatgpt --model-root /absolute/path/to/specificationsIt registers a source in your personal marketplace, preserving unrelated plugins. Restart ChatGPT, open Plugins, and install/enable Screenplay from the local marketplace. This is source registration, not an unattended host install. Keep confirmation enabled for tools that change files. Local plugins are not a hosted Screenplay service and are not automatically in the public directory.
For manual local/repository marketplace development, follow the maintainer packaging guide. Never copy files into an undocumented host-internal cache.
Install and manage with the Cratis CLI
Section titled “Install and manage with the Cratis CLI”Install the Cratis CLI using the procedure for your operating
system, then check cratis --version. Desktop management requires CLI 3.25.0 or
later. These commands do not require a Chronicle connection. For all options and
recovery steps, see Screenplay desktop MCP lifecycle.
cratis screenplay mcp install --clients claude,chatgpt --model-root /absolute/path/to/specificationscratis screenplay mcp statuscratis screenplay mcp update --clients claude,chatgptcratis screenplay mcp uninstall --clients chatgptOmit --clients in an interactive terminal to choose detected supported hosts.
Noninteractive install, update and uninstall require explicit clients; status
can inspect all supported clients. Add --dry-run to preview
without downloading, writing or launching; release metadata may still be checked.
--version VERSION pins a Screenplay release independently of the CLI version.
Claude needs no model folder: the server picks the folder the host or the
conversation names. --model-root configures the ChatGPT source. Status distinguishes source registration/handoff from a
verified host install and reports available updates when the release check works.
Host-owned removal still happens in each host’s UI.
Linux self-contained packages are available for compatible local MCP clients, but Claude/ChatGPT Desktop support on Linux is not claimed. Windows arm64 is not packaged. Docker and the .NET tool below are the portable/headless alternatives.
Get the server for advanced clients
Section titled “Get the server for advanced clients”The server ships in the cratis/screenplay Docker image, and in the .NET tool
Cratis.Screenplay.Tool. Both contain the same screenplay program, including
the MCP server and the event model board. Pick one:
- Docker needs only Docker. Nothing else is installed on your machine.
- .NET tool needs the .NET 10 SDK and runs the server as a local process. See Use the .NET tool instead.
Pull the image once before you connect a client, so the first launch is not spent downloading it:
docker pull cratis/screenplaylatest follows the newest stable release. To stay on a version, use its tag, for
example cratis/screenplay:1.2.3, in every configuration below.
Cratis CLI hosting shipped in CLI 3.11.0. If you have the CLI installed,
use its bundled Cratis.Screenplay.Mcp library without installing a second tool:
cratis screenplay mcp ./specificationsFor the MCP App board (visualize-model), use CLI versions that bundle
Screenplay 4.47.0 or later, or the standalone Cratis.Screenplay.Tool 4.47.0
or later. CLI hosting and board support are separate requirements. The host
must also support MCP Apps. See View a model.
In a client configuration, use "command": "cratis" and
"args": ["screenplay", "mcp", "/Users/you/work/shop/specifications"].
Project-local AI registration and user-level desktop installation are separate
operations. Installing AI guidance alone does not install a desktop extension or
the server. cratis screenplay generate generates source models;
cratis screenplay mcp hosts the MCP server.
Host developers can consult the embedding API.
Repair-capable server setup
Section titled “Repair-capable server setup”The server exposes a repair contract v1
for saved-file PLAY0166 and PLAY0478 proposals. The experimental
VS Code repair bridge is a separate,
explicitly configured process client; browser Monaco does not spawn a process.
Registering Copilot MCP or installing a desktop plugin does not enable editor repairs.
An editor host must explicitly approve an executable and one physical
application root. The server accepts an existing directory, or a missing directory
whose parent exists; it creates the root on the first write, not on startup or reads.
Supported process forms are cratis screenplay mcp ROOT,
screenplay mcp ROOT, or the server/Cratis.Screenplay.Tool binary from a complete,
checksum-verified unpacked native bundle (.exe on Windows). Launch without a shell
and pass the approved root as one argument. Do not use a project’s executable,
download on startup, inspect desktop-private caches or fall back to Docker silently.
Native bundles include their runtime; the .NET global tool needs the installation
below. Linux packages require compatible native dependencies; Windows arm64 is not
packaged. Checksums do not provide publisher signatures.
A compatible host checks repair-capabilities after the MCP handshake and refuses
older or incompatible contracts rather than downgrading evidence protection. Both
initial actions require pinned mode in that host, complete preview and explicit
Apply. CLI 3.25.0 is the desktop-management prerequisite only; it does not prove
repair-contract support in an embedded compiler. Check the actual server’s tool
and contract, and only claim compatibility for distributions containing it. The
capability-supporting server must be released before a CLI or bundle embedding it
can be called compatible; no specific CLI release is established here.
For VS Code, configure these exact launch forms as an absolute executable plus separate argument-prefix strings in User settings:
| User-installed executable | screenplay.repairs.arguments | Effective invocation |
|---|---|---|
Absolute cratis path | ["screenplay", "mcp"] | cratis screenplay mcp /absolute/model/root |
Absolute screenplay path | ["mcp"] | screenplay mcp /absolute/model/root |
Absolute unpacked server/Cratis.Screenplay.Tool path (.exe on Windows) | ["mcp"] | Cratis.Screenplay.Tool mcp /absolute/model/root |
Set screenplay.repairs.modelRoot to that existing physical directory and
screenplay.repairs.enabled to true. The extension appends the root, launches
without a shell and verifies the runtime contract. Keep the complete verified
bundle together; do not copy just its binary or read a desktop host’s private
installation cache. This setup does not change the Copilot registration below.
Choose where the model lives
Section titled “Choose where the model lives”You rarely have to. When the server starts without a root, it picks the folder the first time it needs one:
- A
paththe assistant passes toopen-workspace, which also switches to another folder in the same session. - The folder your MCP client offers through its workspace roots, when the client
offers exactly one. That folder is the project, not necessarily the model: the
server serves the folder already holding the project’s
.playfiles, else itsSourceorsrcfolder, else aScreenplayfolder in the project. Discovery does not create that folder; the first write does. Existing workspaces keep their root: if.screenplay/identities.jsonor.screenplay/pending.jsonexists at the offered folder or along the directory path down to the discovered model folder (including both ends), the server binds the directory holding that state. With state at several directories on that path, it prefers the one nearest the offered folder and reportsrootBindingConflictinopen-workspaceandworkspace-state, listing the competing roots even if opening fails. If any state root on that path holds a pending journal, opening and writes are refused and the journal’s root is named. To inspect or recover a competing journal, first pass its root explicitly asopen-workspace.path, then useworkspace-stateandrecover-workspace. Existing state never causes a fallbackScreenplayfolder to be created. The server never migrates state automatically. Empty.screenplayfolders and backup artifacts alone do not select a root; symbolic links in metadata paths are refused. This preserves identities and interrupted-write recovery when upgrading from 4.66. When the client offers several, the assistant is told to choose withpath. When the client changes its roots, a folder bound from them is let go. - The folder the server was launched from, when it already holds
.playfiles or a.screenplayfolder. This is what a terminal client such as Claude Code or Pi gives you: start it in the project and the model is the project.
screenplay mcpIf none of these applies, the server works in Documents/Screenplay in your home
folder, creating it on the first write. Its Documents parent must already exist.
Opening, reading and proposing changes create nothing. That is where a chat in
Claude or ChatGPT desktop puts the .play files, so you can open, commit or move
them like any other files.
Pass path to open-workspace to work somewhere else.
Pass a root, as below, to restrict the connection to one model and its Git
worktrees. The root may be missing if its parent exists: reads see an empty model,
and the first managed write creates the root and its .screenplay state.
open-workspace.path accepts the same physical directory or the
corresponding model folder in a registered worktree of the same repository.
Unrelated repositories and other model folders return RootChangeRefused.
Case aliases require physical directory identity; symbolic links and reparse
points remain rejected. Without Git worktree metadata, only the original root
is admitted. Changing applications requires a new authorized connection.
Work on another branch in a worktree
Section titled “Work on another branch in a worktree”If the startup root is /work/shop/.cratis/screenplay and Git has a registered
worktree at /work/shop-feature, pass either /work/shop-feature or
/work/shop-feature/.cratis/screenplay as open-workspace.path. The server
opens the same relative model folder, .cratis/screenplay, in that checkout;
the folder may be missing if its parent exists and is created on the first write.
It verifies Git’s shared directory and the
worktree registration’s back-pointer, not a common path prefix. The main
checkout is also available when the server starts in a linked worktree.
Submodules and checkouts created with --separate-git-dir cannot switch roots:
their .git pointers lack the linked-worktree commondir proof. Start a separate
connection directly at their model root instead. Root switching also refuses
repositories with enabled or unverifiable extensions.worktreeConfig, or any
config.worktree entry in the checkout’s .git directory: per-worktree
configuration can override whether Git treats that checkout as bare.
One workspace is active at a time. Switching or reopening clears outstanding
proposals, even when both roots have identical source and revisions. Read the
new workspace’s revisions and create a fresh proposal before applying. Source
writes, identity state and recovery journals stay inside the opened model root;
state from another checkout is not reused unless you explicitly pass
workspaceJson to import a workspace. That import adds identities only to a
root that has no .screenplay state yet; otherwise open-workspace returns
IdentityImportConflict. A pending recovery journal in one root does not block
opening another root, but still blocks reopening its own root. Commit
.screenplay/identities.json with each model, as usual.
The embedded MCP library does not read .cratis/ai.json itself: a model root
selected through mcpServers.screenplay.root by the hosting CLI is a supplied
startup root and follows the same worktree rules. With Docker, both the
worktree and its shared Git metadata must be visible at the paths Git records.
Otherwise use a native server or a separate connection rooted directly at that
worktree’s model.
Choose one application root
Section titled “Choose one application root”For a native server, you can name a missing model directory whose parent exists;
it stays absent until the first write. For Docker, create the host directory before
mounting it, or use an existing directory containing the model’s .play files:
mkdir specificationsThe container sees only the directory you mount. Every configuration below mounts
it at /model and starts the server on that path:
docker run -i --rm -v /Users/you/work/shop/specifications:/model cratis/screenplay mcp /modelThe server waits for MCP messages on standard input, so the container runs with
-i and without -t. Starting it by hand does not open a UI. Your MCP client
normally launches and owns the process; when the client stops, the container is
removed.
Use an absolute, physical path on the left of the -v mapping. A relative path
fails, because the directory a client starts the command from differs between
clients and between configuration scopes. The server also rejects a root that is a
symbolic link, or that has one in an ancestor. Inside the container /model is a
real directory, so the mapping is safe; keep the host path itself free of links. On
macOS and Linux, resolve it with:
cd specificationspwd -POn Linux, the container runs as an unprivileged user that may not own the mounted
directory, so apply can fail with a permission error. Add
--user "$(id -u):$(id -g)" before the image name to write files as yourself.
One root is one application, even when its model spans hundreds of files and nested features. Keep unrelated applications in separate roots, each with its own mount and its own server entry.
Connect your client
Section titled “Connect your client”Every client launches the same command: docker run -i --rm -v <root>:/model cratis/screenplay mcp /model. Replace the path with your own. If a client cannot
find docker, give the absolute path of the executable, which on macOS Docker
Desktop is usually /usr/local/bin/docker.
Claude Code
Section titled “Claude Code”From a terminal, register the server. Everything after -- is the command Claude
Code runs:
claude mcp add --transport stdio screenplay -- \ docker run -i --rm -v /Users/you/work/shop/specifications:/model cratis/screenplay mcp /modelThe default scope is private to you and the current project, which suits a
machine-specific path. Add --scope project only when the path is the same for
everyone, because it writes .mcp.json at the project root for you to commit.
Check the registration, then start claude and run /mcp to see the server’s
status and tools:
claude mcp listClaude Code asks before it calls an MCP tool. To keep the two tools that change
files behind a prompt while you allow the read-only ones, put rules in
.claude/settings.json:
{ "permissions": { "allow": [ "mcp__screenplay__describe-application", "mcp__screenplay__search-declarations", "mcp__screenplay__find-declaration", "mcp__screenplay__declaration-details", "mcp__screenplay__find-references", "mcp__screenplay__dependencies", "mcp__screenplay__diagnostics", "mcp__screenplay__read-document", "mcp__screenplay__syntax-schema" ], "ask": [ "mcp__screenplay__apply", "mcp__screenplay__recover-workspace" ] }}Claude Code runs in a terminal and does not draw MCP Apps
views, so the server does not offer it visualize-model. See View a model
for clients that do.
Codex reads MCP servers from ~/.codex/config.toml, shared by the Codex CLI, the
IDE extension and the desktop app. Register the server from a terminal:
codex mcp add screenplay -- \ docker run -i --rm -v /Users/you/work/shop/specifications:/model cratis/screenplay mcp /modelOr add the table yourself. A .codex/config.toml inside a trusted project
scopes the server to that project:
[mcp_servers.screenplay]command = "docker"args = [ "run", "-i", "--rm", "-v", "/Users/you/work/shop/specifications:/model", "cratis/screenplay", "mcp", "/model",]startup_timeout_sec = 30default_tools_approval_mode = "writes"The server marks every tool read-only except apply and recover-workspace, so
the writes approval mode prompts for exactly those two. In the Codex terminal UI,
run /mcp to list the connected servers. codex mcp list shows what is
configured.
Codex is not among the hosts the MCP Apps documentation lists as drawing views. The server offers visualize-model only to a host that advertises support, so use a client from View a model when you want the board.
VS Code
Section titled “VS Code”Put this in your workspace’s .vscode/mcp.json, using a workspace whose physical
root contains specifications:
{ "servers": { "screenplay": { "type": "stdio", "command": "docker", "args": [ "run", "-i", "--rm", "-v", "${workspaceFolder}/specifications:/model", "cratis/screenplay", "mcp", "/model" ] } }}GitHub Copilot in VS Code draws MCP Apps views, so the event model board appears
inline in the chat. The VS Code extension is a separate way to see
the same board on a .play file and does not need the MCP server.
Claude Desktop
Section titled “Claude Desktop”Add the server to claude_desktop_config.json (Settings, Developer, Edit Config)
and restart the app:
{ "mcpServers": { "screenplay": { "command": "docker", "args": [ "run", "-i", "--rm", "-v", "/Users/you/work/shop/specifications:/model", "cratis/screenplay", "mcp", "/model" ] } }}Claude Desktop draws MCP Apps views, so it shows the event model board.
Other clients
Section titled “Other clients”Configure docker with the same arguments in the client’s stdio server
configuration. Do not add flags that write to standard output; the server’s
output must carry only protocol messages.
Read, inspection and proposal tools do not publish source changes; apply and
recover-workspace do. The server does not mark them destructive, because both are
journaled and recoverable, so a client that confirms every destructive call does not
ask each time. Keep approval on for them where you want a deliberate step, and
allow them where you would rather just say what you want.
Use the .NET tool instead
Section titled “Use the .NET tool instead”If you would rather run the server as a local process, install the tool. It needs the .NET 10 SDK:
dotnet tool install --global Cratis.Screenplay.Toolscreenplay --versionTo update it later, run dotnet tool update --global Cratis.Screenplay.Tool.
Ensure the .NET global-tool directory is on PATH.
Then in any configuration above, replace the Docker command with screenplay and
the arguments with mcp followed by the absolute path of the root, with no
mount. For example, in Claude Code:
claude mcp add --transport stdio screenplay -- screenplay mcp /Users/you/work/shop/specificationsIn a JSON or TOML configuration that becomes "command": "screenplay" and
"args": ["mcp", "/Users/you/work/shop/specifications"].
Verify the connection
Section titled “Verify the connection”Ask the client:
List the tools the screenplay MCP server offers.Then ask it to look at an existing model:
Use the screenplay server to describe the application: how many modules,features and slices does it have, and are there any diagnostics?For an existing model, you should receive compact model counts and a
sourceRevision, not the entire model text. Application-read tools can report
that an empty root contains no .play files; continue with
Create a model to open a workspace and propose its first documents.
No source is written until an accepted proposal is applied.
Keep the model’s identity state
Section titled “Keep the model’s identity state”After the first apply, keep .screenplay/identities.json with the model in source
control. It contains stable identity assignments and document mappings, not a
second copy of your .play source. Reopening the same root loads those identities
automatically.
Do not delete a pending-operation marker or backup to make an error disappear.
Inspect workspace-state; use explicit recovery only after reviewing its status.
See identity state and recovery.
Check common startup failures
Section titled “Check common startup failures”dockernot found: verifyPATHor configure the absolute path of the executable. Check that Docker is running withdocker info.- Server times out on first start: the image was still downloading. Run
docker pull cratis/screenplay, or raise the client’s startup timeout; Codex usesstartup_timeout_sec. - Permission denied on apply (Linux): add
--user "$(id -u):$(id -g)"before the image name. - Root rejected: the path passed to
mcpmust be an existing physical directory, or a missing directory whose parent exists, not a symlink or one.playfile. Links in ancestors are also rejected. With Docker that is the container path/model, so check the host path on the left of-vinstead. - Empty model although files exist: the host path on the left of
-vdoes not exist, or is misspelled. Docker creates a missing host directory for a-vmount instead of failing, so the server opens an empty folder. Check the path exists before you start the client. - Missing runtime (.NET tool): install the .NET 10 SDK and retry
screenplay --version. - Identity conflict: retain the state file; do not bootstrap over it. Restore externally changed declaration names or paths before making an explicit refactoring proposal.
- Pending operation: inspect recovery status before opening or editing the model.
The MCP reference lists tools, validation policies and limits, including the opt-in propose-number-enum-members refactoring. It previews positional enum pins and writes nothing until explicit apply.