MCP Setup
Connect Claude or Codex to Grain, save private artifacts and internal apps, and choose sharing explicitly.
Grain gives coding agents tools to create, edit, save, verify, and share grains. Connect the local stdio server with grain mcp; run grain login separately when authentication is needed. The local server is not an HTTP endpoint and does not use the OpenAPI document. To connect a remote MCP client, such as a web chat client, see Remote MCP. Initialization writes recognized project configuration. Optional desktop onboarding and Settings → Integrations provide local plugin installation commands for Claude Code or Codex. The desktop app bundles the Grain skill and MCP launcher; users run their chosen agent’s commands. Personal defaults are a separate preference with preview and explicit consent.
Default destination
With the optional preference installed, use Grain in place of Claude Artifacts or Codex Sites for saved artifacts and internal apps. New grains default to the docs folder in the selected Grain organization. Each grain is its own workspace; docs is not a folder inside a previously selected grain. User instructions can choose another folder, organization, existing grain, or local-only output. Skill installation alone cannot guarantee automatic selection.
Personal instructions preserve unrelated content and upgrade only exact known Grain blocks. A user-edited block or skill is not overwritten. Setup reports Codex overrides that would shadow the target personal file. MCP registration alone does not change personal preferences. The complete client snippets and native plugin commands are on Integrations.
Transport, authentication and schema discovery
The supported server is a local process. A client starts grain mcp, keeps JSON-RPC messages on stdin/stdout, and discovers the server name (grain) and tool definitions with the MCP initialize and tools/list flow. Every tool has a title and explicit read-only, destructive, idempotent and open-world hints, so clients can ask for approval before tools that change or delete work. The server's instructions are short enough for clients that truncate them (Claude Code keeps 2,048 characters); the full workflow comes from the read-only grain_guide tool. The tool schemas in the generated inventory below are the same registry the server advertises; clients should still use their negotiated schema rather than hard-coding a copy.
The server uses the CLI’s local authentication and workspace access. Run grain login before asking an agent to create, edit or share a workspace. Do not put mca_ or another raw credential into an MCP config. A project config only contains the executable and mcp argument. For the hosted HTTP server, which signs in with OAuth instead, see Remote MCP.
To verify a client connection, start a fresh client session after writing its config, ask it to list Grain tools, and run a private artifact request. A tool list proves registration; a returned webUrl plus filesSynced, revisionRecorded and commitOutcome: confirmed proves an artifact save. Sharing is a separate explicit mutation.
Raw project configuration
grain init writes the following entries while preserving unrelated servers. If no recognized file exists it creates .mcp.json; use grain init --no-agent-config to skip repository wiring.
.mcp.json:
{
"mcpServers": {
"grain": { "command": "grain", "args": ["mcp"] }
}
}.codex/config.toml:
[mcp_servers.grain]
command = "grain"
args = ["mcp"].cursor/mcp.json:
{
"mcpServers": {
"grain": { "type": "stdio", "command": "grain", "args": ["mcp"] }
}
}The project entry does not install the CLI, sign in, create a workspace or modify the optional default-artifact preference. Do those steps through Install and Integrations.
Command-line setup
To configure Grain for your account across projects, run:
grain setupThis signs in through your browser, installs the bundled Grain plugin for detected Claude Code or Codex clients, checks the MCP server, and launches Grain. To install just the agent plugin or choose clients explicitly:
grain mcp install --claude --codex
grain mcp status --json
grain setup --check --jsonProduction installation uses each agent’s native plugin commands and includes the Grain skill and MCP tools. It requires Claude Code 2.1.269+ or Codex 0.154.0+. Existing direct Grain MCP entries are preserved; setup reports the migration command to review and run before retrying. Disabled or ambiguous plugins require review in Settings → Integrations. Development checkouts retain isolated direct MCP registrations. Restart an already-running agent after installation.
The initialization command recognizes .mcp.json for Claude Code, .codex/config.toml for Codex and .cursor/mcp.json for Cursor. Existing recognized files are updated; when none exists, .mcp.json is created.
grain mcpWith no subcommand, this is a long-running stdio process that responds to MCP requests. It does not print a share URL by itself. The install and status subcommands manage client registration; they do not start the stdio server.
Available tools
Grain exposes 41 MCP tools. This table is generated from the operation registry; workspace operations require an explicit ID.
| Tool | Title | CLI command | Required fields | Optional fields | Read-only | Destructive |
|---|---|---|---|---|---|---|
app_connections_connect | Get a link to connect an app | grain connections | app | readOnly, organization | No | No |
app_connections_execute | Use a connected app | grain connections | app, tool | arguments, account, organization | No | Yes |
app_connections_list | List app connections | grain connections | — | app, organization | Yes | No |
app_connections_search_tools | Find tools for a connected app | grain connections | app | query, limit, organization | Yes | No |
grain_app_restart | Restart app preview server | grain app restart | workspace | — | No | No |
grain_app_status | Check app preview server | grain app status | workspace | — | Yes | No |
grain_artifact | Save HTML grain | grain artifact | name, html | folder, organization | No | No |
grain_artifact_update | Update HTML grain | grain artifact | workspace, html | name, expectedRevisionId, title, description | No | Yes |
grain_checkout | Check out workspace for editing | grain checkout | workspace | — | No | No |
grain_checkpoint | Record checkpoint | grain checkpoint | workspace | message | No | No |
grain_command | Manage app commands (combined) | grain command | workspace, request | — | No | Yes |
grain_command_list | List app commands | grain command | workspace | — | Yes | No |
grain_command_run | Run app commands | grain command | workspace, commands | — | No | Yes |
grain_command_schema | Get app command schema | grain command | workspace, commandId | — | Yes | No |
grain_config | Manage app configuration (combined) | grain config | workspace, request | — | No | Yes |
grain_config_inspect | Inspect app configuration | grain config | workspace | — | Yes | No |
grain_config_open_tab | Open app tab | grain config | workspace, tabId | — | No | No |
grain_config_update | Update app configuration | grain config | workspace, expectedHash, patch | — | No | Yes |
grain_config_validate | Validate app configuration | grain config | workspace, patch | — | Yes | No |
grain_exec | Run sandbox command | grain exec | workspace, command | — | No | Yes |
grain_feedback | Send feedback to the Grain team | grain feedback | source, kind, text | workspace, toolName | No | No |
grain_guide | Read Grain workflow guide | — | — | — | Yes | No |
grain_history | Read revision history | grain history | workspace | limit, before, revision | Yes | No |
grain_list | List workspaces and folders | grain list | — | organization, folder, query, workspace | Yes | No |
grain_logs | Read dev server logs | grain logs | workspace | lines, source | Yes | No |
grain_metadata | Read workspace title and description | grain metadata | workspace | — | Yes | No |
grain_new | Create workspace | grain new | name | template, folder, organization | No | No |
grain_open | Open in Grain app | grain open | workspace | — | No | No |
grain_operation | Check or cancel operation (combined) | grain operation | kind, operationId, workspace | action | No | Yes |
grain_operation_cancel | Cancel operation | grain operation cancel | kind, operationId, workspace | — | No | Yes |
grain_operation_status | Check operation status | grain operation status | kind, operationId, workspace | — | Yes | No |
grain_pull | Pull remote changes | grain pull | workspace | — | No | Yes |
grain_push | Push checkout changes | grain push | workspace | reload, title, description | No | Yes |
grain_release | Release local checkout | grain release | workspace | — | No | Yes |
grain_run | Start long-running sandbox command | grain job | command, workspace | timeoutMs, requestId | No | Yes |
grain_screenshot | Capture app screenshot | grain screenshot | workspace | maxWidth | Yes | No |
grain_share_create | Create share link | grain share create | audience, workspace | password, name, path, reuseExisting | No | Yes |
grain_share_list | List shares | grain share list | workspace | — | Yes | No |
grain_share_revoke | Revoke share | grain share revoke | shareId, workspace | — | No | Yes |
grain_share_update | Update share | grain share update | shareId, workspace | mode, password, name, path, regenerateSlug | No | Yes |
grain_upgrade | Add app runtime | grain upgrade | workspace | target, idempotencyKey | No | No |
Create and update
For a complete single-page HTML document up to 256 KiB, grain_artifact creates and saves it in one call. It returns the actual private workspace link and publication state. Do not push again unless you make another edit.
To revise an artifact, call grain_artifact_update with its existing workspace ID and the full new html instead of creating a duplicate. grain_artifact itself is create-only and not destructive; grain_artifact_update is marked destructive (it replaces content) and idempotent (repeating the same HTML is a no-op), and uses the same CLI path as grain --workspace <id> artifact. It replaces index.html in the grain's latest revision and keeps every other file. expectedRevisionId is optional and used when given. Set it to the revisionId from your previous grain_artifact or grain_artifact_update result: if anyone changed the grain since then, the call returns remote_drift and writes nothing, like the hosted update_grain tool's expected_revision_id. Without it, only a change that lands during the call is detected; edits made earlier are replaced (they remain in history). Optional title and description are recorded on the new revision. Unchanged HTML returns already_correct without a new revision. The result reports created: false and updated: true when a new revision was recorded, and its revisionId is the value to pass next time. A clean local checkout of the grain is brought up to the new revision; one with local changes is left alone and the result carries a stale_checkout warning with its path. Only html grains can be updated this way: runtime grains return runtime_required and other templates such as wiki return unsupported. Updates never rename or move a grain: omit name, or pass the current name. There is no CLI or MCP rename; rename a grain with Rename in the Grain app. Use grain_checkout and grain_push for grains this cannot update.
For iterative or multi-file work, use grain_new, edit its returned checkout, and grain_push when complete. Pass a template explicitly: html and wiki are sandboxless managed-content workspaces; empty supplies a Vite runtime; nextjs supplies Next.js. The react-vite template is a promotion target, not a selectable new-workspace template.
For existing work, discover with grain_list, retain its explicit workspace ID, and use grain_checkout before editing. Keep existing grains in their location. MCP workspace tools never fall back to a machine default. Organization ambiguity returns candidates for selection; viewers can discover accessible grains but cannot create them.
For a small complete document, grain_artifact accepts the required name and html fields and returns a private workspace URL without creating a share. A request conceptually looks like this in an MCP client:
{
"name": "Quarterly report",
"html": "<!doctype html><h1>Quarterly report</h1>",
"folder": "docs"
}For multi-file work, use grain_new and edit the returned checkout. Every workspace operation requires the explicit workspace field; a machine default is not a substitute.
A checkout is a local editing copy. Push changes before runtime installs/builds/tests with grain_exec; never run those in the local copy. HTML has no sandbox. grain_run starts bounded longer commands and returns an operation ID for polling/cancellation. Jobs survive MCP disconnect on the same host, not host failure. Pull and review runtime-authored changes before checkpointing.
App configuration and commands have separate read and write tools. grain_config_inspect returns the manifest and its hash, grain_config_validate checks a patch without saving, grain_config_update applies a hash-checked command/tab patch, and grain_config_open_tab opens a named tab. grain_command_list and grain_command_schema discover registered commands, and grain_command_run invokes them through the existing authorized API. grain_operation_status polls an upgrade or long-running command, and grain_operation_cancel requests cancellation. The combined grain_config, grain_command and grain_operation tools accept the same requests through an action field and remain available for existing workflows. Script authors read JSON stdin; Grain owns temporary input files. Saving configuration does not open tabs.
Completion and recovery
Return data.webUrl and data.workspaceUrl for private delivery. data.webUrl is an https://rungrain.com/w/<workspace ID> link that opens in any browser or chat and offers to open the workspace in the Grain app; it grants no access by itself. data.workspaceUrl (also data.openUrl) is the grain:// link that opens the desktop app directly, and tabOpenUrl follows an explicit named-tab opening. grain_list and grain_metadata also return a webUrl for each workspace. Check filesSynced, revisionRecorded, and commitOutcome; an upload and a confirmed history revision are separate outcomes. Use grain_history before retrying uncertain saves and recover the same grain rather than creating duplicates.
On remote_drift, pull and review while preserving wanted local changes. A configuration conflict requires a new inspection/hash and a merged patch. Pending upgrades are not ready: poll until success with runtimeReady: true. Follow next_action on structured errors. Login failure requires grain login, not opening a workspace or bypassing authentication.
grain_screenshot requires a Grain desktop on the same computer and uses its existing content session. It does not navigate to or publish a URL.
The full machine-readable operation snapshot is generated at docs/generated/grain-operations.json in the repository. It is a development artifact for checking registry parity; MCP clients should use tools/list at runtime.
Sharing
Grains remain private unless sharing is requested. Building an internal app alone does not authorize distribution. Save, verify, and checkpoint completed work before creating a share with an explicit audience:
public: anyone with the link.password: anyone with the link and password.
New grains start restricted: only the organization and invited guests, signed in, can open the canonical link https://rungrain.com/w/<id>. Public or password opens it to anyone with the link. Guests and restricted access are managed in the desktop Share dialog. grain_share_list is read-only and reports the grain link's general access, its guests (builders and owners only), and each share; create can reuse an existing target and change its access. Update/revoke require a share ID. MCP share calls accept a password as a tool input and deliver it to the CLI through GRAIN_SHARE_PASSWORD, rather than putting it in argv. The server never prints the password in tool results. Return the actual shareUrl and canonicalUrl; do not invent a public URL or expose a raw private preview URL. Revocation cannot retract downloaded copies. For a raw CLI share, use the hidden-prompt --password-env flow in First Artifact; --password <value> is intended only for disposable test values.