stepwell
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@stepwellShow the current progress for /home/user/stepwell-project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
stepwell
CLI + MCP server for reading, checking and managing the project docs
(BACKLOG.md, PROGRESS.md, docs/archive/*) in repos following the
STEPWELL method — steps, archive pattern, test-first.
Status: fifteen phases complete. Phase 1 — core library (fault-tolerant parsers,
status/validation reports) · Phase 2 — MCP server + CLI (read tools, resources) ·
Phase 3 — mutations (archive_item, progress_update, each dry-run + apply) ·
Phase 4 — locale profiles (de/en, test-first) · Phase 5 — server name stepwell ·
Phase 6 — review fixes (stale span, synonym regexes, CRLF roundtrip, stale check,
STEP_DUPLICATE) + tool CRUD (backlog_add/update/remove, progress_plan_phase,
CLI ASCII aliases, title parameter). Phases 7–15: CI + field test + packaging,
archive/index hardening, coverage gate, annotations, init/templates, JSON schema
versioning, token economy, STEPWELL naming, language switch to English primary.
Current state and step history: PROGRESS.md.
Principles
Markdown stays the source of truth. The tool reads, validates and assists — it does not replace the docs. If the docs are lost, no data is lost.
Fault tolerance instead of abort. Projects follow the method, not byte-exact: structure drift is reported as a structured warning (
ParseResult<T>withwarnings[]), never as a crash. Every partial result stays queryable.Dry-run first. The two write tools (
archive_item,progress_update) return a plan with a diff preview by default; writing happens only withdryRun: false/--apply— afterwards the result is freshly parsed and verified.Narrow write surface. The error-prone structural operations are automated by the tool (verbatim move, Done Index, status cells, item CRUD, phase planning). Everything else (prose, goal/acceptance texts) is edited directly in the Markdown files by humans/agents.
Multi-project. The project root is passed per tool call / CLI invocation — one server instance serves any number of STEPWELL projects.
File requirement: all four files are mandatory —
BACKLOG.md, PROGRESS.md, docs/archive/BACKLOG_ARCHIVE.md,
docs/archive/PROGRESS_ARCHIVE.md. If one is missing, the project does not
load (hard error with a clear message).
Format legend (canonical: PLAYBOOK §3 + §7):
Symbol | Meaning | ID series |
🔴 critical · 🟠 high · 🟡 medium · 🟢 low | backlog priority = section |
|
🔵 test gap | backlog priority = section | no series — explicit ID required |
⬜ open · 🔄 in progress · ✅ done · ⛔ blocked | step status in | steps |
other series letters ( | thematic series, not priority-bound | consecutive, never reused |
Related MCP server: MCP Backlog Server
Requirements & setup
Node.js ≥ 22.18 — the repo ships TypeScript source and uses Node's native type stripping (no build step).
npm install
npm run typecheck # strict, covers src AND tests
npm run test # Vitest, protocol-faithful against the fixtures
npm run test:watchMCP server
Server name stepwell (transport stdio, entry packages/mcp/src/serve.ts).
This repo already wires the server into opencode.json (restart opencode after
config changes). Other MCP clients (Claude Desktop, Cursor, …) follow the same
pattern:
{
"mcp": {
"stepwell": {
"type": "local",
"command": ["node", "/path/to/stepwell-tool/packages/mcp/src/serve.ts"],
"enabled": true
}
}
}Manual verification with the inspector:
npx @modelcontextprotocol/inspector node packages/mcp/src/serve.tsThe test suite covers the same protocol path automatically
(InMemoryTransport + client, plus a real stdio handshake test).
Distribution (two channels)
MCP server:
npx stepwell(orserve.ts) — operational, tools as below. The published package ships compileddist(since 10.4/H1) and therefore runs directly fromnode_modules—prepublishOnlybuilds before publishing.SKILL.md:
packages/mcp/skills/stepwell/SKILL.md(included in the npm pack) — portable signpost for skill ecosystems (Claude Skills, Gemini CLI, …): which tool when, gates (release/content), test-first, status maintenance only via tools. It replaces neither the MCP server nor PLAYBOOK.md — both remain binding.
Tools
All tools take root (absolute path to the project root) per call. All JSON text
payloads are compact (no indentation — token economy, E1). docs_validate,
progress_update and archive_item also deliver their data as
structuredContent only on opt-in with structured: true (M3/9.7, dedupe since
E1 — default is text only); error responses (isError: true, including
PROJECT_NOT_INITIALIZED) carry no structuredContent.
Errors (missing mandatory file, unknown ID/phase) return isError: true
with a clear message — the server does not crash.
Read
Tool | Parameters | Result |
|
| Aggregate: open items per priority, 🔄 steps + assigned phases, ✅ quote of the table, all findings + warnings, |
|
| Items of BACKLOG.md without |
|
| Merge view for one item ID across open BACKLOG ↔ Done Index ↔ BACKLOG_ARCHIVE, including |
|
| Rows of the progress table |
|
| Detail block including |
|
| Validate findings (consistency rules) + collected parse warnings, |
Write (dry-run + apply)
Tool | Parameters | Behaviour |
|
| Plans the verbatim move of an item: remove the block (span-based) from BACKLOG.md, in the archive copy flip the checkbox → |
|
| Sets the status cell(s) of the steps (missing rows are added, name derived from the scope bullet); on 🔄 creates a detail-block skeleton under "Active Phases" ( |
|
| Creates an open item at the end of the target section: ID with convention check ( |
|
| Changes title/priority/text/section in the block format (span recomputation, checkbox and |
|
| No hard delete: block moves verbatim into BACKLOG_ARCHIVE (checkbox stays |
|
| Plans a phase ahead: table rows for all steps ( |
Response formats: dry-run returns the plan {dryRun, changes:[{file, description, before, after, diff}]}; apply returns {written, verification:{ok, messages}}.
With detail: "summary" (E1) dry-run changes are projected onto {file, description, beforeLines, afterLines} + top-level marker detail: "summary" —
the default stays "diff" with the full preview (safety note unchanged).
Locale profiles
The doc files may be formatted in German or English — mixed within the same repo is forbidden; one language per project. The tool separates:
Reading: always language-tolerant (zero-config). Parser and validator recognise the role markers of both languages via union matching —
Erledigt-Index|Done Index,Ort|Location,erledigt|done,Ziel|Goal,Abnahme|Acceptance,Verifikation|Verification,Umfang|Scope,Fortschritt|Progress,Laufende Phasen|Active Phases,abgeschlossen|completed,Stand:|As of:.Writing: the
localeoption onarchive_itemandprogress_update/backlog_remove("de" | "en"; default = auto-detection from the file context, tie →ensince 14.3). Generated texts (index line, done/verification/removed markers, skeletons) follow the target language; CLI equivalent:--locale de|en.More languages:
packages/core/src/profile.tsholds the role synonyms — a new language is a new key per role, no parser rebuild.
Resources (resource templates)
The root is percent-encoded into the URI segment (Windows paths
contain : and \); the read callback decodes it. Content verbatim,
text/markdown:
stepwell://{root}/backlog → BACKLOG.md
stepwell://{root}/progress → PROGRESS.md
stepwell://{root}/archive/{kind} → kind = "backlog" | "progress"
stepwell://{root}/phase/{phase} → phase context: phase verbatim + table rows
+ merged backlog item bodies in step order (G5/12.6)
stepwell://{root}/hashes → SHA256 per doc file (application/json;
hash short-circuit, E2/12.5 — fast-path foundation E3)
stepwell://templates/{kind} → skeletons of the four mandatory files
(kind = "backlog" | "progress" |
"backlog-archive" | "progress-archive")M4 alternative check (G5): resource instead of tool — the phase context is a pure read path, and the composition happens at read time instead of as a duplicate in the files (anti-drift): a subagent gets phase + item bodies in one read, without a new tool growing the surface.
Example: stepwell://D%3A%5Cproj%5Cdemo/backlog
Project init (M8, variant A): for newly created projects the agent reads the four
skeletons from stepwell://templates/{kind} and creates the files itself —
deliberately no init_project write tool (M4 guardrail: keep the write surface
small); the skeletons live canonically in stepwell-core (projectTemplates) and are
finding-free under docs_validate. The init-fallback guidance (PROJECT_NOT_INITIALIZED)
points to this path.
CLI
packages/mcp/src/cli.ts — runnable directly in the workspace repo
(node packages/mcp/src/cli.ts …); from the installed package
(npm i -g stepwell or npx stepwell) under the bin name
stepwell.
Human output on stdout; --json returns the core payloads with a leading
schema version field (currently 2, bumped with N1/13.2 — a resource-URI change is a MAJOR contract). Field contract per command:
Command | Fields (besides |
|
|
|
|
|
|
|
|
|
|
|
|
| like |
Contract rule (M6/Decision 16): a breaking change to this field set ⇒
bump schema (in lockstep with the npm MAJOR).
Releases (version policy, L6)
Format:
CHANGELOG.mdper Keep a Changelog 1.1.0,[Unreleased]on top, curated user-relevant aggregates. Redundancy rule: no git-log dump, no duplication of Done Index/BACKLOG_ARCHIVE — item/commit history stays in the STEPWELL files. Date formatYYMMDD/HHMM(Decision 11) instead of ISO — documented deviation.Lockstep SemVer (Decision 16): root,
stepwellandstepwell-corealways carry the same version. MAJOR = breaking in the tool/JSON/resource contract (always together with theschemafield), MINOR = new tools/features, PATCH = fixes. 0.x until the passed field test;1.0.0= release moment.Publish checklist: (1) curate
Unreleasedin the CHANGELOG, (2) bump the version in all threepackage.json(lockstep), (3) CHANGELOG section[<version>] - <YYMMDD/HHMM>, (4) git tagv<version>, (5) publish onlystepwell(npm publish --otp, dist-taglatest; core is distributed as a dependency), (6) CI jobpack-smokemust be green — dynamic since 10.5/H1, proves the handshake against the installed artefact (server stepwell).
# Status aggregate
node packages/mcp/src/cli.ts status --root <project> [--json]
# List/filter backlog — icons or ASCII aliases (red/kritisch/p1, hoch/p2, mittel/p3, niedrig/p4, blue/test/p5)
node packages/mcp/src/cli.ts backlog --root <project> [--priority red,yellow] [--open false] [--section HIGH] [--json]
# Progress table — status as icon or alias (open, running/wip, done, blocked)
node packages/mcp/src/cli.ts progress --root <project> [--status done] [--json]
# Consistency check (exit 1 on findings — CI-suitable)
node packages/mcp/src/cli.ts validate --root <project> [--json]
# Archive a completed item (dry-run preview, then --apply)
node packages/mcp/src/cli.ts archive --root <project> --id H1 [--note "Commit abc1234"] [--locale en] [--apply]
# Maintain step status (dry-run preview, then --apply) — --title renames the block heading
node packages/mcp/src/cli.ts progress-update --root <project> --phase "Phase 2" --step 2.2 --status running [--title "New title"] [--note "…"] [--checkpoint <sha>] [--locale en] [--apply]Invalid values exit with code 2 and the list of allowed aliases (e.g.
🔴=red/kritisch/p1, …, ⬜=open, 🔄=running/wip, ✅=done, ⛔=blocked).
Exit codes: 0 success (or no validate findings) · 1 error or
validate findings · 2 usage error (unknown command, missing required option).
CI (optional)
This repo uses GitHub Actions (.github/workflows/ci.yml): install → typecheck
→ test (JUnit + coverage report as artefact) → validate --root . (exit 1 on
doc findings flips the job).
For smaller projects the local run suffices — the pipeline is overkill when nobody looks at it:
npm install && npm run typecheck && npm run test && node packages/mcp/src/cli.ts validate --root .STEPWELL projects may copy ci.yml as a template; the method (PLAYBOOK) does not
require CI.
Warning codes
Parse warnings arise when parsing individual files (drift tolerance),
validate findings check cross-file consistency (docs_validate
collects both). Convention warnings affect only open files — archives
are append-only and never flagged. A UTF-8 BOM (U+FEFF) at the start of a file
is silently tolerated (stripped deterministically, T5/9.13) — no warning.
Code | Level | Meaning |
| parse | no priority suffix in the title — priority taken from the section emoji |
| parse | several priority markers in the title — one is captured |
| parse | unknown priority emoji (e.g. 🟣) — |
| parse | item without |
| parse | item ID without a title after the separator |
| parse | unknown status icon in the table — |
| parse | table row without a status column |
| validate |
|
| validate | item ID appears twice |
| validate | ID violates |
| validate | Done Index entry without an archive block |
| validate | completed archive block ( |
| validate | 🔄 row without a matching detail block |
| validate | detail block without a 🔄 step (orphaned or planned ahead via |
| validate | step number appears twice in the progress table — |
| validate | legacy |
| validate | root without a STEPWELL project (all four files missing) — exactly one finding with guidance instead of an error desert; |
Typical workflow (agent + stepwell)
1. docs_status → where do we stand? Which priorities are open?
2. backlog_list --open → what is next? (BINDING: sequential by priority)
3. (work on the code, test-first — the agent edits prose directly)
4. progress_plan_phase → plan a new phase ahead (rows + scope skeleton)
5. progress_update (🔄) → step started: keep table + detail block clean
6. progress_update (✅) → step done; if the phase is complete, the block moves into the archive
7. backlog_add/update → create/change items format-safe (instead of hand-editing)
8. archive_item → archive the completed item verbatim + Done Index
9. backlog_remove → move an obsolete item into the archive (without a done marker)
10. docs_validate → must be clean before committingThe PLAYBOOK rules (sequence, test-first, commit discipline, archive pattern) live in
docs/PLAYBOOK.md; the review checklist in
docs/LESSONS.md.
Architecture
Design rule (M4/Decision 17): the tool surface stays small — tools only for concrete structure/read operations, no guide/meta tools; method knowledge lives in PLAYBOOK.md, SKILL.md and the resources. Every new tool (or new parameter surface) justifies the surface growth via the alternative check (parameter on an existing tool/resource instead of a new tool) — documented like the docs_review decision (L5).
packages/
├── core/ stepwell-core — zero dependencies, no MCP dependency
│ ├── src/backlog.ts BACKLOG parser (sections, item blocks, Done Index)
│ ├── src/progress.ts PROGRESS parser (table, detail blocks) + scopeSteps
│ ├── src/archive.ts archive parser (ArchiveItem = BacklogItem + doneLine)
│ ├── src/project.ts loadProject (4-file requirement, lazy + memoized), backlogShow
│ ├── src/status.ts docsStatus (aggregate)
│ ├── src/validate.ts docsValidate (consistency rules + parse warnings)
│ ├── src/mutations.ts plan/apply: archive_item, progress_update, backlog CRUD, planPhase
│ ├── src/aliases.ts ASCII aliases for priority emojis and status icons (CLI)
│ ├── src/diff.ts line-based mini diff for the plan preview
│ ├── src/profile.ts locale profiles: role synonyms de/en (read union, write canonical)
│ └── tests/fixtures/ project-a (clean) + project-b-drift (cases D1–D15)
│ + project-d-tablefirst (table before detail blocks),
│ README there = working specification
└── mcp/ stepwell — thin transport layer over core
├── src/server.ts createDocsServer (all tools + resources)
├── src/tools.ts tool registration (JSON payloads, isError wrapping)
├── src/resources.ts resource templates (percent-encoded root)
├── src/serve.ts stdio entry
└── src/cli.ts stepwell command lineStack: TypeScript (strict,
NodeNext,noUncheckedIndexedAccess,exactOptionalPropertyTypes), npm workspaces, Vitest, MCP SDK v1.x stable (^1.30.0) + zod v3. Deliberately decided against build/bundle steps: Node ≥ 22.18 executes the TS source directly (type stripping), import specifiers therefore end on.ts.Data model:
ParseResult<T> = { value, warnings[] },Warning = { code, file, line?, message }— item blocks carryspan(lines) andraw(verbatim) as the basis of the verbatim move.Tests: 318 tests, developed test-first (RED → GREEN). Mutations in tests run exclusively against temp copies of the fixtures — the originals are read-only and protected by a test.
Development
npm install && npm run typecheck && npm run test # acceptance before every completion
npx vitest run packages/core # core only
npx vitest run packages/mcp # MCP/CLI onlyNew features follow the STEPWELL method: plan → package in PROGRESS.md →
implement test-first → verification → commit → maintain status. Details:
AGENTS.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
Stateless advisor + validator for Conducted Development: kickoff, artifact validation, rule checks.
Versioned documentation registry and semantic search for AI tools and coding assistants.
Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.
Access and maintain design system docs, tokens, components, skills, and contexts across any project.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables AI-native task management using plain markdown files to create, update, query, and organize Epics, Stories, Tasks, and Milestones without requiring a database.-
- AlicenseBqualityCmaintenanceManages backlog items and todos with status tracking, priorities, and dependencies. Stores work items as human-readable markdown files with automatic versioning.7MIT
- AlicenseNot gradedqualityDmaintenanceProvides direct access to local documentation files through simple search and overview tools, enabling LLMs to query project-specific markdown documentation without requiring vector databases or RAG pipelines.MIT
- AlicenseAqualityAmaintenanceRepository-native protocol and MCP server for coordinating work items, documentation, changelogs, and project memory between humans and AI agents, using Markdown files in a Git repository as the canonical data source.303MIT