Skip to main content
Substrate exposes 32 tools over stdio MCP, grouped into three families: read tools for orientation and inspection, task and comment tools for everyday writes, and substrate-edit tools for changing the workflow itself. Every family follows the same conventions, so learning one transfers directly to the others.

Read (13)

Orient, list, and inspect. No envelope, no writes.

Tasks & Comments (7)

The everyday writes — create, update, and comment.

Substrate-Edit (12)

Change the workflow itself — boards, groups, policies.

Conventions Across Every Tool

agent_name

Every write tool requires an agent_name parameter. Pass a stable identifier for the calling agent — it is an audit tag, not authentication. The value is recorded on every write so the event log shows which agent made which change.

Versioned Updates

Updates carry a version. The tools update_task, update_board, update_group, update_policy, update_project, and the archive/unarchive tools all require the version from your most recent read of that entity. Sending a stale version returns a version_mismatch error with the current version in error.details.current_version.
Comments are the exception — they are last-write-wins and carry no version requirement.

custom_data Merges Key-by-Key

When you send custom_data on a write, Substrate merges it into the existing data key-by-key. Send only the keys you are changing. Set a key to null to delete it.

Writes vs. Reads

Writes return a structured envelope. Reads return raw data directly. See Envelopes & Errors for the full envelope shape and all error codes.

Discovering Schemas

Every tool advertises its exact input schema through the MCP tools/list call. That is the source of truth — consult it rather than guessing a field name. These reference pages describe what the tools are for and the behaviour that the schema alone cannot express.

Pagination

list_boards, list_tasks, list_comments, and get_task_history all accept a pagination object and return one. Pass the previous response’s pagination.cursor to fetch the next page.

A Note on Filters

Filters for list_tasks are top-level parameters, not nested under a filters key. An unrecognized key is ignored rather than rejected — so if a filter fails to narrow the result, the most likely cause is a misspelled parameter name.