Skip to main content
Glama
README.md
# sdlc-mcp

An MCP server that gives an AI agent your software delivery standard: artifact
templates, a domain glossary, and a **machine verdict** on whether an artifact is
ready to move on.

A prompt can tell an agent what shape a user story should have. What a prompt
cannot do is tell it whether the story it just wrote is actually acceptable. That
is what this server is for.

```
validate_artifact("US", content) ->  { "verdict": "fail", "blockers": [ ... ] }
```

## The idea

Three rules hold the whole thing together:

1. **Every task produces an artifact, and every artifact has an owning role.**
   Roles are defaults, not requirements: a project that does not staff an
   architect reassigns the architect's tasks down a declared fallback chain. The
   task still has to happen.
2. **Readiness is data, not opinion.** Definition of Ready and Definition of Done
   live in [`standard/rules.yaml`](standard/rules.yaml) as declarative records.
   Adding a rule means editing YAML. Adding a *kind* of rule means writing one
   function.
3. **The standard lives in version control**, so the same files that a human
   reviews are the context an agent reads. There is no second, prettier copy that
   drifts.

This is spec-driven development taken literally: the specification in the
repository is the source of truth an agent implements from, and the gate it has
to pass on the way out.

## Quickstart

```bash
git clone https://github.com/<you>/sdlc-mcp && cd sdlc-mcp
python -m venv .venv && . .venv/Scripts/activate     # POSIX: . .venv/bin/activate
pip install -e ".[dev]"

python -m sdlc_mcp --self-check      # verify the standard is consistent
python -m sdlc_mcp --overview        # print the standard as a Markdown table
pytest -q                            # 40 tests
python -m sdlc_mcp                   # serve over stdio
```

`--self-check` is the interesting one. It asserts that the standard does not
contradict itself: every artifact type points at a real category and a real role,
every task produces a known artifact type, every rule kind is implemented, every
template file exists, **every template satisfies its own required-section rules**,
and every bundled example produces the verdict it is supposed to. A standard that
contradicts itself is worse than no standard, because an agent reading it cannot
tell the difference. It runs in CI.

## Wiring it into an MCP client

Claude Code (`.mcp.json` in your project, or `claude mcp add`):

```json
{
  "mcpServers": {
    "sdlc": {
      "command": "python",
      "args": ["-m", "sdlc_mcp"]
    }
  }
}
```

Cursor (`.cursor/mcp.json`) uses the same shape. Any MCP client that speaks stdio
will work; `--transport streamable-http` and `--transport sse` are also available.

## Tools

| Tool | What an agent uses it for |
|---|---|
| `list_work_categories` | See the phases of delivery and what each must produce. |
| `get_work_category` | Get one phase in full: purpose, exit artifacts, tasks, owners. |
| `list_artifact_types` | See the artifact catalog with id conventions and owners. |
| `get_artifact_template` | Fetch the template **before** writing, plus the sections the rules will require. |
| `validate_artifact` | Get a pass/fail verdict with blockers and warnings, at the `ready` or `done` gate. |
| `lookup_glossary_term` | Resolve a domain term instead of inventing a meaning. On a miss, returns every known term so the agent can see what it should have asked for. |
| `next_tasks` | Given what already exists, what is still outstanding and who owns it. |
| `list_examples` | Find the reference artifacts, each declaring its expected verdict. |

**Resources:** `sdlc://standard/overview`, `sdlc://glossary`,
`sdlc://template/{artifact_type}`, `sdlc://example/{example_id}`.

**Prompts:** `draft_artifact` and `review_artifact` - workflows that put the tools
in the right order (template first, glossary second, validate last) so the agent
does not have to be reminded every session.

## What a verdict looks like

[`examples/US-LEND-009-not-ready.md`](examples/US-LEND-009-not-ready.md) is a
deliberately bad user story. Real output:

```json
{
  "artifact_type": "US",
  "gate": "ready",
  "verdict": "fail",
  "rules_checked": 13,
  "blockers": [
    {
      "rule": "no_placeholder",
      "message": "Placeholders left in the text mean the artifact is not ready, whoever wrote it.",
      "detail": "'TODO'"
    },
    {
      "rule": "frontmatter_enum",
      "message": "front matter 'priority' has a value outside the allowed set",
      "detail": "got 'high', allowed: must, should, could, wont"
    },
    {
      "rule": "section_min_items",
      "message": "A story with fewer than two acceptance criteria is a title, not a requirement.",
      "detail": "found 1"
    }
  ],
  "warnings": [
    {
      "rule": "section_forbids_text",
      "message": "Unfalsifiable acceptance criteria cannot be tested and cannot be implemented by an agent.",
      "detail": "found: 'as appropriate', 'etc.'"
    },
    {
      "rule": "section_required",
      "message": "required section 'Open questions' is missing"
    }
  ]
}
```

Blockers fail the gate. Warnings do not - they are the things worth arguing about
rather than the things worth refusing.

## Making it your standard

The Python in `src/` contains no process knowledge. Fork the repository, edit the
YAML in [`standard/`](standard/), and you are serving your own standard over the
same protocol:

| File | What it defines |
|---|---|
| [`categories.yaml`](standard/categories.yaml) | Phases of delivery, their exit artifacts and their tasks. |
| [`artifact-types.yaml`](standard/artifact-types.yaml) | The artifact catalog: owning category, owner role, id convention, template. |
| [`roles.yaml`](standard/roles.yaml) | Roles and the fallback chain used when one is not staffed. |
| [`rules.yaml`](standard/rules.yaml) | Definition of Ready and Definition of Done, per artifact type. |
| [`glossary.yaml`](standard/glossary.yaml) | The domain terms and their agreed meaning. |
| [`templates/`](standard/templates) | One Markdown template per artifact type. |

Run `python -m sdlc_mcp --self-check` after editing. It will tell you what you
broke.

### Rule kinds

| Kind | Fields | Checks |
|---|---|---|
| `frontmatter_required` | `key` | The key exists and is not empty. |
| `frontmatter_pattern` | `key`, `pattern` | The value matches a regex - used for id conventions. |
| `frontmatter_enum` | `key`, `values` | The value is one of an allowed set. |
| `section_required` | `heading` | A section with that heading exists (case- and punctuation-insensitive). |
| `section_min_items` | `heading`, `min` | The section has at least N list items or table rows. |
| `section_forbids_text` | `heading`, `tokens` | The section avoids named weasel phrases. |
| `no_placeholder` | `tokens` | No `TODO`/`TBD` and no unreplaced `<angle bracket>` template slots anywhere. |
| `links_resolve` | - | Outbound artifact references resolve against the ids you pass in. |

Every rule carries a `severity` (`blocker` or `warning`) and an optional `message`
that replaces the generic one. The messages in `rules.yaml` are written to be read
by whoever has to fix the artifact, human or otherwise.

Adding a kind: write a checker in
[`validation.py`](src/sdlc_mcp/validation.py) and register it in
`KNOWN_RULE_KINDS`. An unregistered kind referenced from YAML is reported by
`--self-check` and, at runtime, degrades to a loud warning rather than a silent
pass.

## Layout

```
standard/          the standard itself, as data
  templates/       one Markdown template per artifact type
examples/          filled-in reference artifacts in a demo domain
src/sdlc_mcp/
  markdown.py      front matter, sections, list items, references
  validation.py    the rule engine: kinds, findings, verdicts
  catalog.py       loads the standard, answers questions, self-checks
  model.py         immutable value types
  server.py        MCP tools, resources and prompts
tests/             40 tests, no network, no fixtures beyond the repo
```

## Design notes

- **`links_resolve` does nothing when you pass no ids.** Without a universe of
  known artifacts there is nothing to resolve against, and reporting every
  reference as broken would teach callers to ignore the rule. Pass `known_ids` and
  it starts working.
- **Unknown rule kinds warn, they do not pass quietly.** A typo in the standard
  should be visible at the point of use, not discovered when a bad artifact
  reaches implementation.
- **Templates are validated against their own rules.** A template that cannot
  pass the gate teaches the agent to produce failures, which is a subtle and
  expensive way to break a standard.
- **The owner fallback is transitive and terminates.** If nobody in the chain is
  staffed, the default role is returned unchanged: the task still belongs to
  somebody, which is exactly the conversation the fallback is meant to force.
- **No Markdown library.** Artifacts follow the bundled templates, so heading and
  list detection is sufficient; a parser would be a dependency for no gain.

## The demo domain

The glossary and examples describe **BookLoop**, a fictional community
book-lending platform. It exists only to make the artifacts concrete - loans,
copies, branches and due dates are small enough to hold in your head and rich
enough to show what a real use case and a real ADR look like. Replace
`standard/glossary.yaml` and `examples/` with your own and nothing else changes.

The standard shipped here is a generic reference implementation written for this
repository.

## Licence

MIT - see [LICENSE](LICENSE).

TDQS

A4/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct operation: category lookup, artifact type/template retrieval, validation, glossary lookup, task planning, and example listing. The list/get pairs are clearly separated by singular detail vs. plural overview.

Naming Consistency4/5

Most tools follow a clear verb_noun pattern such as get_work_category, list_artifact_types, validate_artifact, and lookup_glossary_term. The outlier is next_tasks, which is not verb-led and breaks the otherwise consistent naming convention.

Tool Count5/5

Eight tools is a well-scoped size for an SDLC standard assistant. Each tool covers a meaningful part of the workflow without redundancy or bloat.

Completeness3/5

The core standard, template, validation, glossary, and task-planning capabilities are present. However, the set tells agents to read example artifacts before writing their own, yet only offers list_examples with no way to retrieve a specific example, leaving an obvious gap in that workflow.

Maintenance

ActivityMaintained
ResponsivenessNo issues