Enterprise SDLC MCP
# Enterprise SDLC MCP
Reusable build-time SDLC agent roles and skills, served over the [Model Context Protocol](https://modelcontextprotocol.io) (MCP), for any GitHub-first, AI-assisted software project.
This is **build-time tooling for how software gets delivered** — agent role definitions (Product Analyst, Solution Architect, Code Reviewer, etc.) and generic review checklists (PR review, architecture review, IAM least-privilege, eval-scenario design, ...). It is not a runtime dependency of any product; consuming repos only need it while an AI coding agent is doing SDLC work.
## Origin
This package was extracted (with git history) from [`support-ticket-triage-assistant`](https://github.com/raghuram-chittibomma/support-ticket-triage-assistant), where it was first built and used as the reference implementation. It now also serves [`supportrouter-aws`](https://github.com/raghuram-chittibomma/supportrouter-aws). Extracting it removed a fragile cross-repo coupling where a second project pointed directly at the first project's virtualenv and folder path.
## What's in the catalog
- **9 agents:** `product-analyst`, `solution-architect`, `implementation-planner`, `test-eval-designer`, `code-reviewer`, `refactor-reviewer`, `documentation-agent`, `release-manager`, `dependency-upgrade-agent`.
- **31 skills:** generic SDLC checklists (`pr-code-review`, `architecture-review`, `github-backlog-creation`, `release-readiness-review`, `application-security-review`, `dependency-supply-chain-review`, `cicd-pipeline-review`, `api-contract-review`, `incident-postmortem-review`, ...) plus stack-specific technical checklists (`cdk-stack-review`, `cloud-infra-review`, `iam-least-privilege-review`, `bedrock-guardrails-review`, `dynamodb-data-model-review`, `fastapi-service-review`, `frontend-accessibility-review`, `llm-as-judge-rubric-design`, `eval-scenario-design`, `synthetic-data-design`, `knowledge-graph-modeling-review`, `graph-rag-retrieval-review`, ...).
See `enterprise_sdlc_mcp/catalog/manifest.yaml` for the full index.
Every skill declares an `applies_when` tag so a consuming project can tell which ones are actually relevant to it, independent of the fixed `used_by` agent-role list:
| Tag | Meaning |
|-----|---------|
| `always` | Generic SDLC guidance — relevant to any project regardless of stack. |
| `api` | Only relevant if the project exposes an API surface (REST/GraphQL/RPC), independent of framework. |
| `frontend` | Only relevant if the project has a frontend/UI surface. |
| `infra` | Only relevant if the project provisions cloud/infra resources (any provider). |
| `llm-product` | Only relevant if the product itself is LLM-backed at runtime (not just built with an AI coding agent). |
| `graph` | Only relevant if the project's primary data store is a property graph / knowledge graph. |
| `graph-rag` | Only relevant if the project retrieves from a graph database to ground LLM-generated answers (graph-native retrieval, as distinct from document/vector retrieval). |
| `postgresql`, `dynamodb`, `aws`, `bedrock`, `langgraph`, `rag`, `fastapi` | Only relevant once that specific technology has been adopted — see the skill's own file for its "applies only if/when adopted" note. |
`list_skills()` returns `applies_when` for each entry so tooling (or an agent) can filter to what matters for a given project.
Every agent also declares a machine-readable `permissions` block — a structured companion to the prose "Code-Modify Permission" section in its own markdown — with a `code_modify` tier (`none` / `scoped` / `conditional`) and a `write_paths` allowlist. `list_agents()` returns this so tooling (a pre-merge hook, a CI gate) can check a PR's actually-changed files against what the authoring role was supposed to touch, instead of relying on someone reading prose. Pass `manifest_path` to `list_agents()` to get `write_paths` resolved against a real project instead of raw `{{project.*}}` placeholders.
Catalog markdown uses `{{project.*}}` placeholders resolved at serve time from each consuming repo's own `sdlc.project.yaml` manifest — deterministic string substitution, no LLM involved. See `enterprise_sdlc_mcp/catalog/manifest_keys.yaml` for the full, tested reference of every key the catalog can use (which keys are required for any project vs. only needed for a specific stack-tagged skill).
## Installing into a consuming project
This is designed to be installed **editable, from a local sibling checkout**, into each consuming project's own virtualenv — never referenced across repos by path.
```bash
# from the consuming project's own repo, with its own .venv active
git clone https://github.com/raghuram-chittibomma/enterprise-sdlc-mcp.git ../enterprise-sdlc-mcp
pip install -e ../enterprise-sdlc-mcp
```
**Starting a brand-new project?** Copy [`templates/new-project/`](templates/new-project/) into the repo root instead of building this by hand — it ships a filled-out `sdlc.project.yaml`, `AGENTS.md`, `.cursor/mcp.json`, the `docs/00_project`–`docs/03_operations` skeleton every core doc key points at, a `.skills/` overlay stub, and `.github/` PR/issue templates + a CI workflow. It's the same folder structure `support-ticket-triage-assistant` and `supportrouter-aws` already converged on by hand, now codified so a new repo gets it for free. See `templates/new-project/README.md` for the checklist.
Adding this to an existing repo instead? Add an `sdlc.project.yaml` manifest at the consuming repo's root (see `tests/fixtures/sdlc.project.yaml` for the shape) and enable the server in the consuming repo's `.cursor/mcp.json`:
```json
{
"mcpServers": {
"enterprise-sdlc": {
"command": "C:\\absolute\\path\\to\\consuming-project\\.venv\\Scripts\\python.exe",
"args": ["-m", "enterprise_sdlc_mcp.server"],
"env": {
"SDLC_PROJECT_MANIFEST": "C:\\absolute\\path\\to\\consuming-project\\sdlc.project.yaml"
}
}
}
}
```
Use **absolute paths** for both `command` and `SDLC_PROJECT_MANIFEST`. A relative `command` (e.g. `.venv/Scripts/python.exe`) is not reliably resolved against the workspace root by Cursor on Windows — it can silently fall back to the global interpreter on `PATH`, which won't have this package installed and fails with `ModuleNotFoundError`. Absolute paths avoid that ambiguity entirely. (On Linux/macOS use `.venv/bin/python`; the same relative-path caveat may not apply there, but absolute paths are still the safer default.)
No `PYTHONPATH` tricks are needed once the package is pip-installed into that project's own venv — just point `command` at that venv's own interpreter.
Already have this installed somewhere and just want to pick up a new version? See [`ROLLOUT.md`](ROLLOUT.md) for the upgrade checklist instead of repeating first-time setup.
## Project manifest reference
`sdlc.project.yaml` keys used by the **core** (`always`-tier) agents/skills — define these regardless of stack:
`display_name`, `repo_root`, `docs.architecture`, `docs.data_model`, `docs.test_strategy`, `docs.product_brief`, `docs.orchestrator_brief`, `docs.project_charter`, `docs.release_notes`, `docs.runbook`, `paths.source`, `paths.tests`, `paths.evals`, `paths.project_skills`, `milestone.current`, `extensions`.
A handful of keys are **conditional** — only needed if you invoke the specific stack-tagged skill that reads them (e.g. `paths.infra` for `cdk-stack-review`, `docs.eval_strategy` for `llm-as-judge-rubric-design`). See `enterprise_sdlc_mcp/catalog/manifest_keys.yaml` for the complete, tested list with descriptions and exactly which skill each conditional key belongs to.
An unresolved placeholder — a missing manifest key referenced by a skill you actually call — is a real gap: it leaks literal `{{project.x}}` text into the resolved output instead of failing loudly. Call the `validate_manifest` tool against your own `sdlc.project.yaml` to check which core/conditional keys are missing before that happens. `tests/test_manifest_keys.py` separately guards against catalog changes introducing an *undocumented* key.
## MCP surface
| Tool | Description |
|------|-------------|
| `list_agents` | Catalog agent IDs, titles, source file, and `permissions` (machine-readable `code_modify` tier + `write_paths` allowlist) |
| `get_agent` | Resolved agent role markdown for a project |
| `list_skills` | Catalog skill IDs, titles, and `applies_when` tags |
| `get_skill` | Resolved skill checklist for a project |
| `list_project_skills` | Domain skills from the project's own overlay path |
| `get_project_skill` | Read a project-local overlay skill file |
| `get_project_manifest` | Parsed project manifest |
| `validate_manifest` | Report which core/conditional `{{project.*}}` keys a project's manifest is missing |
| Prompt | Use |
|--------|-----|
| `independent_code_review` | Launch a Code Reviewer subagent with resolved role + `pr-code-review` skill |
| `architecture_review` | Launch a Solution Architect / Refactor Reviewer review pass |
| `launch_role` | Generic: launch any agent id with any comma-separated list of skill ids and free-text context — use this instead of adding a new hardcoded prompt function per pairing |
Resources are also exposed under `enterprise-sdlc://catalog/manifest`, `enterprise-sdlc://agents/{id}`, and `enterprise-sdlc://skills/{id}`.
## Hooks
MCP has no concept of hooks — a server can't register lifecycle interceptors the way it registers tools/prompts/resources (see `.cursor/hooks.json` for what Cursor's hooks actually are: local, `beforeShellExecution`/`afterFileEdit`/etc.-triggered scripts, distributed via version control, MDM, or an Enterprise team dashboard — never via MCP).
This repo ships one project-level hook, in `.cursor/hooks.json` (and mirrored into `templates/new-project/.cursor/`): `beforeShellExecution` flags `gh pr merge` and asks for confirmation that the required independent review (`get_agent("code-reviewer")` + `get_skill("pr-code-review")`) actually happened, since that step is otherwise only enforced by whoever remembers to read `AGENTS.md`/this README. It's a reminder, not a hard block — it can't verify the review actually ran, only ask.
That's deliberately the only hook shipped here. Broader safety hooks (destructive-git guard, dangerous-shell-command guard, secret-staging guard) are a good idea but belong at the **user level** (`~/.cursor/hooks.json`), not per-project — they're personal safety nets that should apply across every repo you touch, not something each consuming project should have to opt into separately.
## Development
```bash
pip install -e ".[dev]"
ruff check .
pytest
```
## Changelog
### 0.8.0
Closed a coverage gap found while onboarding the first graph/Graph-RAG consuming project: nothing in the catalog reviewed property-graph data modeling or graph-native retrieval, even though `postgresql-schema-review`/`dynamodb-data-model-review` cover the equivalent for their stacks.
- Added `knowledge-graph-modeling-review` — entity/relationship minimality, no persisted derivable relationships (the graph-modeling analogue of avoiding redundant columns), natural-key identity strategy, provenance fields, and cardinality/directionality documentation. Used by Solution Architect; tagged `graph`.
- Added `graph-rag-retrieval-review` — traversal depth/fan-out bounds, citeable retrieved-path identifiers, validation of dynamically generated queries (e.g. text-to-Cypher) before execution, and a hard rule that generated answers only assert relationships actually present in the retrieved subgraph. Complements (does not replace) `rag-retrieval-design-review`, the same way `fastapi-service-review` complements `api-contract-review`. Used by Solution Architect; tagged `graph-rag`.
- Added the `graph` and `graph-rag` `applies_when` tags to the catalog tag table.
- No new agent added — both gaps are checklists for the existing Solution Architect role, not a missing role.
### 0.7.0
Added the first Cursor hook to this repo, after establishing (see "Hooks" section above) that MCP and hooks are separate mechanisms — a catalog server can't push hook definitions to a client, so this had to ship as an actual `.cursor/hooks.json`, not new MCP server code.
- Added `.cursor/hooks.json` + `.cursor/hooks/pr_merge_gate.py`: a `beforeShellExecution` hook that asks for confirmation before `gh pr merge` runs, reminding whoever's merging that the independent-review requirement (`get_agent("code-reviewer")` + `get_skill("pr-code-review")`) should already be satisfied. Mirrored into `templates/new-project/.cursor/` so new consuming repos get it for free.
- Added `tests/test_hooks.py`, which runs both copies of the hook script as real subprocesses (matching Cursor's own JSON-over-stdin/stdout contract) and checks `hooks.json` points at a script that actually exists.
- Also fixed two blank-rendering list items introduced in the 0.6.0 scaffold docs (an ordered/bulleted list item whose entire content was an HTML comment rendered as an empty list marker on GitHub) in `AGENTS.md`, `PROJECT_CHARTER.md`, and `AI_ORCHESTRATOR_BRIEF.md`.
### 0.6.0
Closed the "new project scaffolding" gap: nothing previously codified how a brand-new consuming repo's folder structure should look, so `validate_manifest` could report a manifest as fully valid while every `docs.*` path it declared pointed at a file that was never created.
- Added `templates/new-project/` — a starter kit a new repo copies in wholesale: a filled-out `sdlc.project.yaml` (core keys pre-filled, conditional keys commented out with guidance), `AGENTS.md`, `.cursor/mcp.json`, the `docs/00_project`–`docs/03_operations` skeleton (one starter file per core `docs.*` key, plus an ADR convention note under `docs/01_architecture/DECISIONS/`), a `.skills/` project-overlay stub, and `.github/` templates (PR template, `story`/`feature_task`/`bug_report` issue templates matching the `github-backlog-creation` skill's Story→Task hierarchy, and a ruff+pytest CI workflow).
- This codifies, rather than invents, the convention: it matches the folder structure `support-ticket-triage-assistant` and `supportrouter-aws` already converged on by hand — the difference is a third project no longer has to reverse-engineer it from an existing consumer.
- Added `tests/test_new_project_template.py`, which fails CI if the shipped template ever drifts from `manifest_keys.yaml`'s core key contract, or if a `docs.*` path in the template manifest stops pointing at a real file in the scaffold.
- Updated the "Installing into a consuming project" section to point brand-new projects at the scaffold before the manual first-time-setup steps.
### 0.5.0
Addressed external review feedback on the two highest-priority remaining gaps: the core PR review skill had no actual review rigor, and code-modify permissions existed only as prose.
- Rewrote `pr-code-review.md` from a 6-item process-compliance checklist into a substantive correctness review: a Blocker/Major/Minor severity model, a mandatory evidence rule (cite file+line, quote the offending code — an unsupported claim isn't a finding), a correctness checklist (edge cases, error handling, concurrency, resource cleanup, external-call failure handling), and an explicit `## Output Format` with an always-rendered "None." path so a clean PR is stated as a real outcome, not implied by silence. The prior process checklist is retained as its own section.
- Updated `code-reviewer.md`'s Outputs/Allowed Actions to match: findings are severity-tagged with cited evidence, and a verdict (Approve/Request Changes) is always explicit.
- Added a structured `permissions` block (`code_modify`: `none`/`scoped`/`conditional`, plus a `write_paths` allowlist) to every agent in `manifest.yaml`, alongside — not replacing — each agent's existing prose "Code-Modify Permission" section. `list_agents()` now returns it, and can resolve `write_paths` against a real project manifest when one is passed in, so a CI gate or pre-merge hook can allowlist a PR's changed files against what the authoring role is actually meant to touch.
- Added `test_every_agent_declares_well_formed_permissions` to `tests/test_catalog_consistency.py`, enforcing the `code_modify`/`write_paths` shape (e.g. `none` must have an empty allowlist; `scoped`/`conditional` must have a non-empty one).
- Deliberately did not extend the severity/evidence/output-format convention to the other 15+ review-style skills yet — scoped to the flagged highest-priority file for now; worth revisiting as a separate pass.
### 0.4.0
Rounds out the tightening roadmap's P2 items plus the two previously-unscheduled gap items.
- Added `dependency-upgrade-agent` — a 9th agent role that plans and executes dependency/runtime version upgrades as their own isolated, tracked workflow (distinct from `refactor-reviewer`, which is structure-focused, and from `dependency-supply-chain-review`, which is a review checklist rather than an execution role).
- Added `incident-postmortem-review` (blameless postmortems, root cause vs. contributing factors, tracked follow-ups), `frontend-accessibility-review` (keyboard operability, alt text, contrast, screen-reader-perceivable state), and `cloud-infra-review` (a vendor-neutral infra baseline above the AWS-only `cdk-stack-review`, which is now also tagged `infra`).
- Added a `validate_manifest` tool that reports which core/conditional `{{project.*}}` keys a project's own manifest is missing, instead of only discovering the gap when a placeholder leaks into a live prompt.
- Added a generic `launch_role` prompt (agent id + comma-separated skill ids + free-text context) so new agent/skill pairings don't require new hardcoded prompt functions in `server.py`. The two existing convenience prompts are unchanged.
- Added `tests/test_catalog_consistency.py`, which fails CI if a skill's `manifest.yaml` `used_by` list and its own markdown "Used by:" line ever drift apart, or if `used_by` references an agent id that doesn't exist.
- Added `frontend` and `infra` `applies_when` tags.
- Added `ROLLOUT.md` — a version-agnostic checklist for upgrading a consuming repo's `enterprise-sdlc-mcp` install (or onboarding a new one), since that step had never been written down anywhere before now.
### 0.3.0
Closed the biggest coverage gaps identified in the tightening review — areas relevant to virtually any consuming project, unlike the AWS/LLM-specific skills already in the catalog.
- Added `application-security-review` — cloud/stack-agnostic secrets, input validation, authn/authz, and error-leakage checklist (complements the AWS-only `iam-least-privilege-review` / `bedrock-guardrails-review`).
- Added `dependency-supply-chain-review` — lockfile pinning, CVE triage, license compliance, and Dependabot/Renovate PR review. No skill covered this before.
- Added `cicd-pipeline-review` — vendor-neutral pipeline health checklist (required checks, secrets in CI, caching, flaky-check handling), independent of `cdk-stack-review`'s AWS-only infra focus.
- Added `api-contract-review` — a generic REST/GraphQL contract checklist decoupled from any framework; `fastapi-service-review` is now tagged as its FastAPI-specific complement (`applies_when: [fastapi, api]`).
- All four are used by the existing Solution Architect and Code Reviewer agents (plus Release Manager for `cicd-pipeline-review`) — no new agent role was added.
- Added the `api` `applies_when` tag for skills that only apply when a project exposes an API surface.
### 0.2.0
A tightening pass focused on keeping the catalog genuinely reusable across unrelated projects, not just its two current consumers. **No agent/skill ids, file paths, or manifest keys were removed or renamed** — existing consuming repos are unaffected by upgrading.
- Removed origin-project-specific details (support-ticket-triage domain language, hardcoded `ADR-004`/`ADR-005` references) from `dynamodb-data-model-review`, `iam-least-privilege-review`, `eval-scenario-design`, `architecture-review`, `synthetic-data-design`, `observability-dashboard-review`, `bedrock-guardrails-review`, `cdk-stack-review`, `llm-as-judge-rubric-design`, and `prompt-caching-review` so they read as genuinely generic (or genuinely generic-to-their-stack) guidance instead of one project's architecture presented as a universal rule.
- Genericized "Main Orchestrator" — previously an undefined, assumed-to-exist actor referenced across 7 agent/skill files — to "the coordinating agent (or human driving the session)".
- Added an `applies_when` tag to every skill in `manifest.yaml` (`always`, or a stack tag like `aws` / `dynamodb` / `bedrock` / `langgraph` / `rag` / `fastapi` / `postgresql` / `llm-product`), now returned by `list_skills()`.
- Documented the full `{{project.*}}` placeholder contract in `catalog/manifest_keys.yaml` (required vs. conditional keys, and which skill needs each conditional one).
- Expanded `tests/fixtures/sdlc.project.yaml` to define every documented key, and added `tests/test_manifest_keys.py`, which fails CI if a catalog file ever references an undocumented placeholder or if any catalog file fails to resolve cleanly against the fixture manifest.
## License
MIT — see `LICENSE`.
TDQS
Scored across 7 tools
Each tool targets a distinct resource (catalog agents, catalog skills, project skills, manifest), but list_skills vs list_project_skills and get_skill vs get_project_skill could be confused if descriptions are not read closely. The clear qualifiers reduce ambiguity.
All tools follow the consistent list_<plural>/get_<singular> pattern, with project-scoped variants prefixed by project_. This is a uniform, predictable naming convention.
7 tools is well-scoped for a read-only catalog server covering agents, skills, project overlays, and manifest resolution. No tool feels redundant or missing.
The tool surface covers the full lifecycle for this domain: listing and getting catalog agents, catalog skills, project-local skills, plus the manifest. No obvious dead ends for the server's stated purpose.