Skip to content

MCP tool surface

StateLode keeps the tool surface small on purpose. Every extra tool adds choice, and LLMs get worse when the correct choice is hidden inside a wide menu.

Use this first. It returns lightweight task summaries and defaults to active work.

{
"projectId": "statelode",
"status": ["active", "in_progress"],
"assignee": "codex",
"limit": 10
}

Searching is truly read-only: a projectId that doesn’t exist is never created — the unknown_project error lists the workspace’s real slugs (knownProjects) so you can pick one and retry (see Workspaces, projects & tokens).

Add "sprint" to scope the search to a sprint: a sprint id, "active" (the project’s active sprint), or "none" (un-sprinted backlog).

Use this after task_search identifies a task you need to work on. It returns the full body, acceptance criteria, notes, blocker, dependencies, and updatedAt.

updatedAt is required for later mutations.

Use this for creates, updates, moves, comments, and blocking. Every mutation except create and comment must include the last updatedAt you saw.

{
"action": "move",
"payload": {
"id": "task_id",
"status": "in_progress",
"updatedAt": "2026-05-28T21:15:33.860Z",
"by": "codex"
}
}

If another agent won the race, StateLode returns STALE_WRITE with the fresh task inside the error. Retry with that fresh row. Do not guess.

Task lifecycle: a horizontal task-state chain with a cyan active signal and a dim retry branch for stale-write recovery.

Sprints are managed through task_mutate too — there is no fourth tool. A sprint is a named, goal-bearing group of tasks within one project, with a planned → active → completed lifecycle and exactly one active sprint per project.

ActionPayloadNotes
sprint_createprojectId, name, goal?Creates a planned sprint.
sprint_assignid, sprintId, updatedAtPuts a task in a sprint (sprintId: null removes it). Needs the task’s updatedAtSTALE_WRITE applies.
sprint_activatesprintIdMakes it the project’s active sprint. Fails if another is already active.
sprint_completesprintIdCloses the sprint.
{
"action": "sprint_activate",
"payload": { "sprintId": "sprint_id", "by": "codex" }
}

The board surfaces the active sprint as a lane with a priority-ordered “what’s next” queue, and a returning human sees a “since you were away” digest of what changed.

Workspace discovery (a resource, not a tool)

Section titled “Workspace discovery (a resource, not a tool)”

The server also exposes one MCP resource at statelode://workspace (application/json): the workspace your credential is bound to, plus the projects it can use —

{
"workspace": { "id": "", "name": "", "slug": "" },
"projects": [{ "slug": "statelode", "name": "StateLode" }]
}

Read it to discover a valid projectId instead of guessing one. It stays a resource so the tool count stays at three — the same reason sprints ride on task_mutate.