> ## Documentation Index
> Fetch the complete documentation index at: https://docs.substrate.42.pe/llms.txt
> Use this file to discover all available pages before exploring further.

# Substrate-Edit MCP Tools: Boards, Groups, Policies

> The 12 MCP tools for editing boards, groups, policies, and project settings. Changes take effect immediately — no migration, no restart.

These twelve tools edit substrate-as-code — the same thing you could edit by hand in `.substrate/boards/<id>.json`. Changes take effect on the next read: no migration step, no server restart required. All twelve require `agent_name`; all update and archive operations also require the current `version` of the entity you are changing.

<Tip>
  Reach for these tools to **extend** an existing board. Creating a second board that models the same flow is the most common way a substrate stops being a single source of truth.
</Tip>

***

## Project

### `update_project`

Updates top-level project metadata. Send only the fields you are changing.

<ParamField path="version" type="integer" required>
  The version from your last `get_project` read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<ParamField path="name" type="string">
  New project name.
</ParamField>

<ParamField path="description" type="string">
  New project description.
</ParamField>

***

## Boards

### `create_board`

Creates a new board and returns it with its generated id.

<ParamField path="name" type="string" required>
  Board name.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<ParamField path="description" type="string">
  Board description.
</ParamField>

<ParamField path="field_schema" type="object">
  Optional initial field schema. Validated structurally on creation.
</ParamField>

<ParamField path="project_id" type="string">
  Project to create the board under. Defaults to the current project.
</ParamField>

### `update_board`

Updates a board's metadata or field schema. Send only what is changing.

<ParamField path="id" type="string" required>
  The board id.
</ParamField>

<ParamField path="version" type="integer" required>
  The version from your last read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<ParamField path="name" type="string">
  New board name.
</ParamField>

<ParamField path="description" type="string">
  New board description.
</ParamField>

<ParamField path="field_schema" type="object">
  Replaces the entire field schema. Use `field_schema_patch` when changing one field.
</ParamField>

<ParamField path="field_schema_patch" type="object">
  Merges into the existing schema key-by-key. Set a key to `null` to delete that field. Prefer this over `field_schema` when changing a single field.
</ParamField>

Schema changes never reject existing task data — validation is lazy. Existing tasks are not revalidated when you tighten a schema.

<Warning>
  `update_board` refuses to **downgrade** a `human_only` field. An agent can neither clear the `human_only` flag nor delete the field to escape a human gate. Both operations return `forbidden`.
</Warning>

### `archive_board`

Soft-deletes a board. Idempotent.

<ParamField path="id" type="string" required>
  The board id.
</ParamField>

<ParamField path="version" type="integer" required>
  The version from your last read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

### `unarchive_board`

Restores an archived board. Idempotent.

<ParamField path="id" type="string" required>
  The board id.
</ParamField>

<ParamField path="version" type="integer" required>
  The version from your last read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

***

## Groups

### `create_group`

Creates a new group on a board.

<ParamField path="board_id" type="string" required>
  The board to add the group to.
</ParamField>

<ParamField path="name" type="string" required>
  Group name.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<ParamField path="description" type="string">
  Group description.
</ParamField>

<ParamField path="position" type="integer">
  Display position. Defaults to the next available slot.
</ParamField>

<ParamField path="color" type="string">
  Display color for the group.
</ParamField>

### `update_group`

Updates a group's display properties. Send only the fields you are changing.

<ParamField path="id" type="string" required>
  The group id.
</ParamField>

<ParamField path="version" type="integer" required>
  The version from your last read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<ParamField path="name" type="string">
  New group name.
</ParamField>

<ParamField path="description" type="string">
  New group description.
</ParamField>

<ParamField path="position" type="integer">
  New display position.
</ParamField>

<ParamField path="color" type="string | null">
  New display color. Set to `null` to clear it.
</ParamField>

### `reorder_groups`

Reorders all groups on a board in one atomic write. You must supply every group id — partial lists are rejected.

<ParamField path="board_id" type="string" required>
  The board whose groups to reorder.
</ParamField>

<ParamField path="ordered_ids" type="string[]" required>
  The complete ordered list of group ids. Must be exactly the board's current group ids.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

### `archive_group`

Archives a group. The group must have no active tasks — move them first. Idempotent once the group is already archived.

<ParamField path="id" type="string" required>
  The group id.
</ParamField>

<ParamField path="version" type="integer" required>
  The version from your last read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

If active tasks still reference the group, the tool returns `conflict`. Move or archive the tasks first, then retry.

***

## Policies

### `create_policy`

Creates a policy on a board. The two policy types have different `definition` shapes.

<ParamField path="board_id" type="string" required>
  The board to add the policy to.
</ParamField>

<ParamField path="name" type="string" required>
  Policy name.
</ParamField>

<ParamField path="type" type="'transition_guard' | 'agent_responsibility'" required>
  Policy class. Immutable after creation.
</ParamField>

<ParamField path="definition" type="object" required>
  The policy logic. Shape is validated against `type` — see below.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<ParamField path="description" type="string">
  Human-readable explanation of what the policy does.
</ParamField>

<ParamField path="priority" type="integer">
  Evaluation priority. Lower numbers run first.
</ParamField>

<ParamField path="enabled" type="boolean">
  Defaults to `true`. Set to `false` to create a disabled policy.
</ParamField>

**Definition shapes:**

`transition_guard` — Blocks a matching move unless every `require` condition passes.

```json theme={null}
{
  "from_group": "<group_id or *>",
  "to_group": "<group_id or *>",
  "require": [{ "field": "task.tests_passing", "op": "eq", "value": true }],
  "on_failure_message": "Set tests_passing before moving to review."
}
```

`agent_responsibility` — Never blocks. Attaches a `message` as a suggestion in the write envelope whenever `when` matches. An empty `when` matches every write.

```json theme={null}
{
  "when": { "any_of": [{ "field": "task.group_id", "op": "eq", "value": "<group_id>" }] },
  "message": "Remember to update the changelog before shipping."
}
```

Conditions are `{ field, op, value?, values? }` or a compound `{ all_of | any_of | none_of: Condition[] }`. Fields resolve literal-then-`custom_data`, so a custom gate field is referenced as `task.<name>`. See [Authoring Policies](/authoring/write-policies) for the full grammar.

### `update_policy`

Updates a policy. Send only the fields you are changing. The policy `type` is immutable — archive the policy and create a new one to change class.

<ParamField path="id" type="string" required>
  The policy id.
</ParamField>

<ParamField path="version" type="integer" required>
  The version from your last read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<ParamField path="name" type="string">
  New policy name.
</ParamField>

<ParamField path="description" type="string">
  New description.
</ParamField>

<ParamField path="definition" type="object">
  Replacement definition. Re-validated against the policy's existing `type`.
</ParamField>

<ParamField path="priority" type="integer">
  New evaluation priority.
</ParamField>

<ParamField path="enabled" type="boolean">
  Enable or disable the policy.
</ParamField>

<Note>
  Policy `type` is immutable. To change a policy from `transition_guard` to `agent_responsibility` (or vice versa), archive the existing policy and create a new one.
</Note>

### `archive_policy`

Archives a policy. Idempotent.

<ParamField path="id" type="string" required>
  The policy id.
</ParamField>

<ParamField path="version" type="integer" required>
  The version from your last read.
</ParamField>

<ParamField path="agent_name" type="string" required>
  A stable identifier for the calling agent.
</ParamField>

<Warning>
  Archiving a guard removes a rail. The action is git-visible and event-logged rather than silent — but an agent under pressure archiving the gate that blocks it is the residual risk in the model.
</Warning>

***

## After Editing

Run `substrate validate` to check all board files for structural errors. Then prove the rail fires as expected: see [Validate Gates](/authoring/validate-gates).
