@mlmcps/ml-specs-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +347 -0
  3. package/agents/coder.md +76 -0
  4. package/agents/developer.md +78 -0
  5. package/agents/pr-author.md +36 -0
  6. package/agents/reviewer.md +65 -0
  7. package/agents/scanner.md +66 -0
  8. package/agents/spec-author.md +91 -0
  9. package/agents/spec-reviewer.md +59 -0
  10. package/commands/code.md +29 -0
  11. package/commands/fix.md +67 -0
  12. package/commands/nfr.md +114 -0
  13. package/commands/pr.md +32 -0
  14. package/commands/repo-adopt.md +86 -0
  15. package/commands/repo-doctor.md +57 -0
  16. package/commands/repo-estate.md +79 -0
  17. package/commands/repo-impact.md +77 -0
  18. package/commands/repo-init.md +155 -0
  19. package/commands/repo-refresh.md +58 -0
  20. package/commands/repo-rollout.md +84 -0
  21. package/commands/repo-status.md +59 -0
  22. package/commands/spec-advance.md +81 -0
  23. package/commands/spec-build.md +66 -0
  24. package/commands/spec-fanout.md +64 -0
  25. package/commands/spec-review.md +24 -0
  26. package/commands/spec-verify.md +55 -0
  27. package/commands/spec.md +73 -0
  28. package/mcp/README.md +173 -0
  29. package/mcp/ml-specs-server.mjs +708 -0
  30. package/package.json +44 -0
  31. package/scripts/branch-policy.mjs +71 -0
  32. package/scripts/fix-specs.mjs +289 -0
  33. package/scripts/lib/cli.mjs +43 -0
  34. package/scripts/lib/estate.mjs +108 -0
  35. package/scripts/lib/http.mjs +73 -0
  36. package/scripts/lib/knowledge.mjs +91 -0
  37. package/scripts/lib/nfr.mjs +119 -0
  38. package/scripts/lib/policy.mjs +114 -0
  39. package/scripts/lib/scm.mjs +189 -0
  40. package/scripts/lib/specs.mjs +192 -0
  41. package/scripts/lib/trace.mjs +90 -0
  42. package/scripts/lib/tracker.mjs +257 -0
  43. package/scripts/nfr-compile.mjs +120 -0
  44. package/scripts/spec-brief.mjs +127 -0
  45. package/scripts/spec-dashboard.mjs +331 -0
  46. package/scripts/spec-fanout.mjs +120 -0
  47. package/scripts/spec-gate.mjs +329 -0
  48. package/scripts/spec-trace.mjs +91 -0
  49. package/scripts/survey-estate.mjs +230 -0
  50. package/scripts/tracker-sync.mjs +91 -0
  51. package/templates/ci/knowledge-check.mjs +176 -0
@@ -0,0 +1,66 @@
1
+ ---
2
+ description: Implement a feature strictly against an approved spec, test-first
3
+ argument-hint: <path to spec file, e.g. specs/0001-foo.md> — or several, to build in parallel
4
+ ---
5
+
6
+ You are in the **IMPLEMENT** phase of spec-driven development.
7
+
8
+ Spec: **$ARGUMENTS**
9
+
10
+ The spec is the contract. Anything not in it is out of scope — if a gap surfaces, the spec gets
11
+ updated first, then the code. Never the other way round.
12
+
13
+ Steps:
14
+
15
+ 1. **Read the spec in full**, plus `CLAUDE.md` and `docs/PATTERNS.md`, and detect the stack (any
16
+ language) from the manifest/build file. Check its Status is `Approved` — if it's still `Draft`,
17
+ say so and stop; building an unapproved contract is how rework happens.
18
+
19
+ Note the difference between the two knowledge sources the agent will use: `docs/PATTERNS.md`
20
+ **describes** how this repo happens to write code, and the architecture standards
21
+ (`.mlskills.json` + the `ml-skills` server) **prescribe** how it must. When they disagree, the
22
+ doc is the one that is out of date — the developer agent is told to flag the divergence rather
23
+ than copy local style, and that flag is a finding for you to relay, not noise to suppress.
24
+
25
+ 2. **Resolve gaps before delegating.** If something the implementation needs isn't in the spec,
26
+ STOP and put it to the user with the AskUserQuestion tool as concrete options with a
27
+ recommendation. Update the spec (with a **Revisions** row) before any code is written. Do this
28
+ here, in the main thread — a subagent has no channel to the human, so an unresolved gap becomes
29
+ a guess the moment you hand off.
30
+
31
+ 3. **Present a short implementation plan** (plan mode) and get approval before any edits.
32
+
33
+ 4. Use the **developer** agent to implement it — one agent per spec. Give it the spec path
34
+ and the approved plan; its own instructions carry the discipline (test per acceptance criterion,
35
+ a functional/E2E test for every user-facing or contract-level one, targeted tests during the
36
+ loop, the full final-acceptance suite once at the end, real results only). Don't restate those
37
+ rules — and don't implement inline instead, or the work silently loses the agent's guarantees.
38
+
39
+ **Several specs at once?** Spawn one `developer` per spec, each in **its own git worktree**,
40
+ and run them concurrently — that's the three-developers pattern in `specs/AGENTS.md`. Only do
41
+ this for specs that don't touch the same files; sequence coupled ones instead, because paper
42
+ conflicts are cheaper than merge conflicts.
43
+
44
+ 5. **Relay what the agent returns, unsoftened** — the file list, the real test output, and anything
45
+ it flagged as wrong in the spec. If it reports a failing suite, report the failure; never
46
+ convert "it built" into "it works". If it surfaced a spec gap, go back to step 2.
47
+
48
+ 6. **Advance the spec:** `/spec-advance <spec-file> Implemented` — that command re-checks each
49
+ criterion's named test actually exists and records the branch, so the status is evidence-backed
50
+ rather than self-declared.
51
+
52
+ 7. **Then the VERIFY phase, in this order:**
53
+ - `/spec-verify <spec-file>` — the `reviewer` agent judges the implementation against the
54
+ spec's acceptance criteria and runs the final-acceptance suite. This is the gate for
55
+ `Verified`; do not set that status yourself.
56
+ - `/code-review` (and `/security-review` if auth/data exposure is involved) — these check the
57
+ diff for bugs, a different question from "does it match the spec". Run both.
58
+ - `/spec-advance <spec-file> Verified` once they're clean, then `/pr <spec-file>` for the PR text.
59
+
60
+ Keep the spec in the same branch/PR as the implementation, follow the repo's branch-naming and
61
+ commit conventions, and only commit/push when the human asks.
62
+
63
+ When you do commit, the message names the humans who own the change and nothing else — no
64
+ `Co-Authored-By:` line for an assistant, no "Generated with"/"Made with" line, no model or vendor
65
+ name, no tool badge or emoji. This applies to every commit on the branch: a squash merge aggregates
66
+ trailers from all of them, so one stray line resurfaces on the merge commit.
@@ -0,0 +1,64 @@
1
+ ---
2
+ description: One spec, N repos, N pull requests — find who else a contract change breaks, then open a branch and PR in each, all carrying the same key
3
+ argument-hint: `<spec-id> <contract...>` — e.g. `0031 payment.captured "POST /payments/{id}/capture"` · add `--dry-run` to read the requests first
4
+ model: sonnet
5
+ ---
6
+
7
+ Fan a spec out across the services it actually touches: **$ARGUMENTS**
8
+
9
+ A change spanning four services is four pull requests that a reviewer correlates
10
+ by hand and hopes they got right. Every branch here is the same derived name, so
11
+ the four are provably one change — and the impact query finds the service one hop
12
+ out that nobody remembered.
13
+
14
+ ## 1. Plan before you open anything
15
+
16
+ ```
17
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/spec-fanout.mjs <spec-id> <contract...> --plan
18
+ ```
19
+
20
+ That reads `docs/ESTATE.md` and prints the targets with a reason each: named on
21
+ the spec, consumes a changed contract, or one hop further out. It opens nothing.
22
+
23
+ **Stop and show the user this plan.** Two things are worth their attention before
24
+ anything is created:
25
+
26
+ - **A repo they did not expect.** That is the query doing its job, and it is also
27
+ the most common moment to discover the estate index is stale. If a name looks
28
+ wrong, run `/repo-estate` before fanning out — a stale graph reports confidently
29
+ that nothing else breaks, which is worse than no graph.
30
+ - **A repo missing that they did expect.** Same cause, opposite symptom.
31
+
32
+ ## 2. Dry run
33
+
34
+ ```
35
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/spec-fanout.mjs <spec-id> <contract...> --dry-run
36
+ ```
37
+
38
+ Prints the exact branch-creation and pull-request calls that would be sent, and
39
+ sends none of them. This is what you hand to whoever owns the organisation when
40
+ asking for a token.
41
+
42
+ ## 3. Open them
43
+
44
+ Drop `--dry-run` once the user has agreed to the plan. Credentials come from the
45
+ environment (`ADO_ORG`/`ADO_PROJECT`/`ADO_PAT`, or `GITHUB_OWNER`/`GITHUB_TOKEN`
46
+ with `SDD_SCM_TOOL=github`) — never from a file in the repo.
47
+
48
+ ## What can go wrong, and what to say
49
+
50
+ - **`spec … is Draft; no branch is cut before the approval gate`** — correct
51
+ behaviour, not a bug. The contract is still being negotiated. Point at
52
+ `/spec-advance`.
53
+ - **Some repos opened, some failed.** Expected and reported, never thrown: a
54
+ permissions error on the fourth repo must not hide that three succeeded. Report
55
+ which failed and why. Re-running is safe for the ones that worked only if their
56
+ branches do not already exist — say so rather than guessing.
57
+ - **`branches diverged — not one change`** — the fan-out lost its shared name.
58
+ That defeats the whole point; stop and investigate rather than merging.
59
+
60
+ ## Close
61
+
62
+ Tell the user the branch name, how many pull requests are open, and that each
63
+ body carries the acceptance criteria as a reviewer checklist. If any repo failed,
64
+ lead with that.
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: Adversarially review a draft spec BEFORE any code — checks contracts, acceptance criteria, and cross-module ripple are complete and testable
3
+ argument-hint: <path to spec file, e.g. specs/0001-foo.md>
4
+ ---
5
+
6
+ Spec: **$ARGUMENTS**
7
+
8
+ Use the **spec-reviewer** agent to review this spec adversarially, before any code exists. It
9
+ runs read-only and with fresh context — it reports what needs changing rather than editing the spec.
10
+
11
+ `/spec` already runs this pass on every spec it writes. Reach for this command when the spec was
12
+ written by hand, was edited substantially since it was drafted, or came from someone else.
13
+
14
+ Relay the agent's verdict: the per-check results, the must-fix list, and its final **approve** /
15
+ **revise** / **split** call. Separate the must-fixes the agent says are resolvable from the code
16
+ from the ones needing a human contract decision — offer to fix the first group, and put the second
17
+ to the user with the AskUserQuestion tool as concrete options with a recommendation, not as open
18
+ questions.
19
+
20
+ Do not start implementation, and do not change the spec's Status — that's `/spec-advance`. After a
21
+ clean review and the human's approval: `/spec-advance <spec-file> Approved` → `/spec-build <spec-file>`.
22
+
23
+ (This reviews the **paper**. Its counterpart, `/spec-verify`, reviews the **code** against that
24
+ paper once it's built.)
@@ -0,0 +1,55 @@
1
+ ---
2
+ description: Adversarially verify an implemented change against its spec's acceptance criteria, and run the final-acceptance suite — read-only, decides whether the spec can be Verified
3
+ argument-hint: <path to spec file, e.g. specs/0001-foo.md>
4
+ ---
5
+
6
+ Spec: **$ARGUMENTS**
7
+
8
+ You are in the **VERIFY** phase of spec-driven development. This command is **read-only** — it
9
+ judges the implementation, it does NOT fix it.
10
+
11
+ Use the **reviewer** agent to review the current branch/diff against this spec. It runs with
12
+ fresh context, so it judges the code against the written contract rather than against the intent
13
+ of whoever wrote it.
14
+
15
+ This is not a substitute for `/code-review` — they answer different questions and you want both:
16
+
17
+ | | Question it answers |
18
+ |---|---|
19
+ | `/spec-verify` (this) | Does the implementation satisfy **this spec's** acceptance criteria, each with a test that would fail on regression? |
20
+ | `/code-review` (built-in) | Is the **diff** itself correct — bugs, edge cases, simplifications — regardless of any spec? |
21
+
22
+ **If the change touches a published contract** (an event payload, an API request/response shape,
23
+ shared data, an exported package type), also run `/repo-impact <spec-file>` — neither this review nor
24
+ `/code-review` looks outside this repo, so a change that breaks a consumer passes both cleanly.
25
+
26
+ Relay the agent's verdict without softening it:
27
+ - The **per-acceptance-criterion table**: satisfied / not satisfied / **untested** (implemented but
28
+ with no test that would fail if the behavior regressed, or a user-facing criterion covered only
29
+ by a unit test with no functional/E2E test).
30
+ - The **must-fix list**, each with `file:line`.
31
+ - The **final-acceptance result** (spec §6.1) — the real command and its real output. If the suite
32
+ could not be run, say so explicitly; never report an unrun suite as green.
33
+ - The **architecture standards result** — from **`verify_evidence`** on the `ml-skills` MCP server,
34
+ with `base` set to the branch this work forked from so findings are scoped to what this change
35
+ actually touched. Report its `verdict` verbatim: `fail`, `pass`, `partial`, or `inconclusive`.
36
+ **`inconclusive` means clean but nothing was ratified, so nothing could have failed — it is not a
37
+ pass**, and rounding it to one is how a gate goes decorative without anyone noticing. Findings in
38
+ files this diff did not touch are pre-existing, not this change's problem — say so rather than
39
+ turning the review into a cleanup project. If ml-skills is not installed, report the standards
40
+ verdict as **unavailable**; an unrun check is not a clean one.
41
+
42
+ Then split the must-fixes into two groups and act:
43
+ 1. **Code fixes** — the implementation doesn't match the approved spec. Offer to fix them
44
+ (`/spec-build` or the `coder` agent), then re-run this command.
45
+ 2. **Spec gaps** — the code is right and the *spec* is wrong or silent. That is a contract change:
46
+ put it to the user with the AskUserQuestion tool as concrete options with a recommendation.
47
+ Update the spec (with a **Revisions** row) before touching code. Never quietly widen the spec to
48
+ match what was built.
49
+
50
+ Next step:
51
+ - **Clean** (every criterion satisfied, functional/E2E present for the user-facing ones, full suite
52
+ green, no new error-severity standards finding) → `/spec-advance <spec-file> Verified`, then
53
+ `/pr <spec-file>`.
54
+ - **Not clean** → fix, then re-run `/spec-verify <spec-file>`. Do not advance the spec's status and
55
+ do not open a PR on a failing verdict.
@@ -0,0 +1,73 @@
1
+ ---
2
+ description: Draft a spec-driven-development spec for a feature/ticket (no implementation)
3
+ argument-hint: <ticket-id or short feature description>
4
+ ---
5
+
6
+ You are in the **SPECIFY** phase of spec-driven development. Your job is to produce a
7
+ specification document — **do NOT write any implementation code in this phase.**
8
+
9
+ Feature / ticket: **$ARGUMENTS**
10
+
11
+ Aim for a spec the human can approve in **one pass**. Every blocking question you leave in the
12
+ document costs them a read, a revision, and a re-read — so resolve those up front, and let an
13
+ adversarial pass find the holes before the human does rather than after.
14
+
15
+ Steps:
16
+
17
+ 1. Detect the stack (any language) from the manifest/build file and existing source, then read
18
+ `CLAUDE.md`, `docs/PATTERNS.md`, and `specs/README.md` so you follow this project's conventions.
19
+
20
+ 2. Explore the relevant code to ground the spec in reality (current behavior, the affected
21
+ module/component/bounded context, the data/API contracts, relevant events or cross-module
22
+ calls). Cite real `file:line` references.
23
+
24
+ 3. **Resolve blocking ambiguity BEFORE writing — never defer it into the document.** A question is
25
+ **blocking** if its answer would change a contract: API shape, data model or migration,
26
+ error/status codes, scope boundary, or backward compatibility. Rule of thumb: if knowing the
27
+ answer would make you rewrite a section, it's blocking.
28
+ Ask all of them in **one batch** with the AskUserQuestion tool — never one at a time, and never
29
+ as open prose. Each question gets concrete options grounded in the code you just read, your
30
+ recommendation first, and a line on what choosing it means. The user should be able to accept
31
+ your defaults in seconds.
32
+ A question whose answer changes **nothing** in this spec (a later optimization, something for
33
+ another team) is not blocking — that goes in section 8, and only that.
34
+
35
+ 4. Copy `specs/TEMPLATE.md` and fill every section, using the answers from step 3. Make acceptance
36
+ criteria concrete and testable (Given/When/Then), and map each AC to a planned test for this
37
+ project's stack. (If `specs/` or `specs/TEMPLATE.md` is missing, the repo hasn't been set up —
38
+ tell the user to run `/repo-init` first, or fall back to the plugin template at
39
+ `${CLAUDE_PLUGIN_ROOT}/templates/specs/TEMPLATE.md`.)
40
+
41
+ 5. **Actually create the file** — use the Write tool to save it as `specs/NNNN-<slug>.md`,
42
+ creating the `specs/` directory if it doesn't exist. Do NOT just print the spec in chat — it must
43
+ land on disk.
44
+
45
+ **Pick NNNN from every branch, not just this one.** The next number after the highest that
46
+ exists *anywhere*, or two people speccing in parallel both get `0007-` and find out at merge:
47
+
48
+ ```
49
+ git log --all --pretty=format: --name-only --diff-filter=A -- 'specs/[0-9]*' | sort -u
50
+ ```
51
+
52
+ Union that with the working tree (`specs/` and `specs/archive/`) and take max + 1. If the repo
53
+ has a remote, `git fetch --quiet` first so branches you haven't pulled are counted too — and if
54
+ the fetch fails (offline, no remote), say so and note the number may collide, rather than
55
+ quietly numbering off a stale view.
56
+
57
+ 6. **Adversarial pass before the human sees it.** Spawn the **spec-reviewer** agent on the file
58
+ you just wrote. It reads with fresh context and will catch contract gaps and untestable criteria
59
+ you cannot see, because you wrote them. Fix every **blocker** and **needs-work** item it returns.
60
+ If a fix needs a human contract decision, batch it back through AskUserQuestion (step 3) — do
61
+ not write it into section 8 instead. Re-run the reviewer only if you made substantial changes.
62
+
63
+ 7. Summarize for the user: the spec path, the contract decisions taken, cross-module impact, and
64
+ what the reviewer flagged and you fixed. Then **ask them to review/approve.** On their approval,
65
+ record it with `/spec-advance specs/NNNN-<slug>.md Approved`; the next step after that is
66
+ `/spec-build specs/NNNN-<slug>.md`. Leave the Status at `Draft` yourself — you don't approve
67
+ your own spec.
68
+
69
+ **If the user sends the spec back for changes:** update the file, add a row to its **Revisions**
70
+ table recording what changed and why, and point them at that row. They should only have to re-read
71
+ what moved — not the whole document.
72
+
73
+ Keep the spec tight and honest. Flag risks and cross-service impacts explicitly.
package/mcp/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # ml-specs MCP server
2
+
3
+ The **deterministic** half of the toolkit, exposed over MCP so any client — Claude Code, Cursor, a
4
+ custom agent, a CI script — can use it without a model in the loop.
5
+
6
+ Everything here is **read-only**. No tool writes, moves, or deletes anything.
7
+
8
+ ## What ports, and what doesn't
9
+
10
+ Skills and hooks have no MCP equivalent: MCP cannot register a `SessionStart` or `PreToolUse`
11
+ hook, and it cannot spawn a subagent with its own tool allowlist and model. Those stay in the
12
+ plugin, and so does the real subagent execution the commands rely on.
13
+
14
+ Two things do port. First, the computation — the parts that read files and return facts, where a
15
+ model adds nothing:
16
+
17
+ | Tool | Answers |
18
+ |------|---------|
19
+ | `estate_lookup` | Who produces/consumes this contract? (from `docs/ESTATE.md`) |
20
+ | `knowledge_check` | Do the docs still match the code — every `file:line`, link, and shard? |
21
+ | `spec_list` | What specs exist, at what status, with how many criteria met? |
22
+ | `spec_next_number` | What's the next free spec number **across all branches**? |
23
+ | `spec_gate` | Does this spec have the mechanical evidence for its next status? |
24
+ | `spec_trace` | Is the id chain from ticket to test case intact, for one spec or all? |
25
+ | `spec_brief` | The approved spec packaged for whoever implements it (markdown) |
26
+ | `nfr_check` | Which non-functional requirements do **not** route into something enforceable? |
27
+ | `estate_survey` | What state are the neighbouring repos in, before spending `/repo-init` on them? |
28
+
29
+ The last five are `scripts/` exposed. They were the half of the toolkit that most needed to be
30
+ reachable from outside Claude Code and least was: `spec_gate` is the lifecycle gate itself, so
31
+ until now a CI job could not ask the one question the whole loop turns on — *does this spec have
32
+ the evidence for `Verified`?*
33
+
34
+ They are **invoked as subprocesses, not imported**. The scripts parse their arguments at module top
35
+ level, so importing one would run its CLI — but invoking is also the stronger no-drift guarantee.
36
+ An imported function can diverge from the CLI in argument handling and defaults; a subprocess is
37
+ the same execution path a human gets. One process spawn per call is nothing for a read-only tool.
38
+
39
+ Read-only holds **by construction**: `--apply`, `--out` and `--gates` are never passed, there is no
40
+ parameter that could smuggle one in, and a test asserts those flags do not appear anywhere in the
41
+ dispatch. Writing stays in the plugin, where a human approves it.
42
+
43
+ Two behaviours worth knowing, because both are deliberate:
44
+
45
+ - **A failed gate is a result, not an error.** These scripts exit 1 to mean "the gate failed".
46
+ The tool returns the verdict with `exitCode: 1` rather than raising, because a legitimate `FAIL`
47
+ the caller cannot read is worse than no answer. Exit 2 — *could not run* — is still an error.
48
+ - **`nfr_check` returns `present: false` when the repo has no `docs/NFRS.md`**, for the same reason
49
+ `estate_lookup` does: absent means the non-functional requirements are **unknown**, not that
50
+ there are none. Reporting "nothing failed to compile" would be a false all-clear on exactly the
51
+ requirements most likely to be agreed and then lost.
52
+
53
+ Templates are also served as resources under `mlspec://templates/…`.
54
+
55
+ Second, the **commands**, served as MCP prompts — all 18 of them, described from their own
56
+ frontmatter, with `$ARGUMENTS` filled in at `prompts/get`. Clients namespace these, so `spec`
57
+ arrives as `/mcp__ml-specs__spec` rather than `/spec`; that is the client's doing, not a choice
58
+ made here.
59
+
60
+ Where a command delegates to an agent, that agent's instructions are appended to the prompt as an
61
+ appendix, because a client with no subagent mechanism would otherwise skip the step silently — a
62
+ command that appears to run while quietly dropping its adversarial pass is worse than one that
63
+ fails. Inline execution loses the isolated context, tool restrictions and parallelism the plugin
64
+ gets. `/spec-fanout` degrades most, being parallel by design.
65
+
66
+ `estate_lookup` returns `present: false` with an explicit note when the repo has no estate index.
67
+ That distinction is the whole point: "no index" is not "no consumers", and a false all-clear on a
68
+ cross-service change is worse than no answer, because it gets believed.
69
+
70
+ ## Run it
71
+
72
+ ```bash
73
+ node ml-specs-server.mjs --root /path/to/the/repo # stdio transport; --root defaults to cwd
74
+ ```
75
+
76
+ No dependencies and no install step — stdio MCP is newline-delimited JSON-RPC 2.0, implemented
77
+ directly here for the same reason `scripts/validate-plugin.mjs` has no dependencies: nothing in this
78
+ repo is ever installed before it runs. The two `package.json` files exist only to *publish* — they
79
+ declare no dependencies and there is no `node_modules`.
80
+
81
+ ## Sharing it with a team
82
+
83
+ **First, the honest bit:** you cannot ship JavaScript to someone's machine and prevent them
84
+ reading it. `node_modules` is source, and even a compiled single-executable can be unpacked. So
85
+ pick based on what you're actually solving:
86
+
87
+ | Goal | Do this | Cost |
88
+ |---|---|---|
89
+ | Teammates get **only these nine tools** | `@mlmcps/ml-specs-mcp` npm package (below) | Public on npmjs — anyone can read the package source |
90
+ | Teammates get the **whole toolkit**, without repo access | `@mlmcps/ml-specs` npm package as the marketplace source | Public on npmjs; updates arrive on tag, not on merge |
91
+ | Teammates get the whole toolkit **and** the repo | Private repo + `/plugin marketplace add` | They can clone everything, history included |
92
+ | Genuinely no readable source | Single executable (`node --experimental-sea-config`, `bun build --compile`) | Per-platform builds; unpackable anyway |
93
+
94
+ **Hosting it remotely does not work for this server** — and the reason is worth knowing. Every tool
95
+ here answers questions about *the repo the caller is sitting in*. A remotely hosted server would
96
+ inspect files on the server, not on the teammate's laptop, so it would return answers about the
97
+ wrong repo. This server is local by design, not by omission.
98
+
99
+ ### Public npm package (recommended)
100
+
101
+ The package ships `mcp/`, `scripts/` (the tools invoke them) and the one CI module it imports —
102
+ zero dependencies, no agents, no templates. Since 0.19.0 it is **public on npmjs.org under
103
+ MIT**, so a teammate needs no token, no registry config, and no access to this repo. The repo itself
104
+ stays private; `files[]` is what keeps the rest of it out of the tarball.
105
+
106
+ ```bash
107
+ # you, once per release — normally CI does this on a tag
108
+ npm publish # publishConfig points at registry.npmjs.org, access public
109
+ ```
110
+
111
+ Teammates configure nothing. In any repo they work in, `.mcp.json`:
112
+
113
+ ```json
114
+ {
115
+ "mcpServers": {
116
+ "ml-specs": {
117
+ "command": "npx",
118
+ "args": ["-y", "@mlmcps/ml-specs-mcp", "--root", "."]
119
+ }
120
+ }
121
+ }
122
+ ```
123
+
124
+ That file is safe to commit — it names a package, not a path on anyone's laptop.
125
+
126
+ ## Wire it into a repo
127
+
128
+ Copy `../templates/mcp/.mcp.json` to that repo's root as `.mcp.json`, set the absolute path, and
129
+ commit it — project-scoped config, so the whole team gets it. Or register it per-user:
130
+
131
+ ```bash
132
+ claude mcp add ml-specs -- node /abs/path/to/ml-specs/mcp/ml-specs-server.mjs --root .
133
+ ```
134
+
135
+ Verify with `/mcp` in Claude Code; the nine tools should be listed.
136
+
137
+ ## How updates reach people
138
+
139
+ Which mechanism applies depends on how they got it — and the first case is the one most teams
140
+ should be in, because it has no separate update step at all.
141
+
142
+ **Installed as part of the plugin** (Claude Code users). The bundled `.mcp.json` resolves through
143
+ `${CLAUDE_PLUGIN_ROOT}`, so the server is *inside* the plugin: when the marketplace updates the
144
+ plugin, the server comes with it. With `autoUpdate: true` that's automatic on the next launch —
145
+ restart Claude to pick it up. **There is nothing extra to publish or install.** If your whole team
146
+ uses Claude Code, you do not need the npm package.
147
+
148
+ **Installed from npm** (Cursor, custom agents, CI, or people who shouldn't get the whole plugin):
149
+
150
+ | `.mcp.json` args | Update behaviour | Use when |
151
+ |---|---|---|
152
+ | `["-y", "@mlmcps/ml-specs-mcp@0.19.0", …]` | **Pinned.** Everyone runs exactly what you tested; bumping is a commit teammates can review. | A team — recommended |
153
+ | `["-y", "@mlmcps/ml-specs-mcp", …]` | Resolves the latest at launch, so a new session can silently change versions. | Solo, or you want the newest always |
154
+
155
+ Servers start per session, so either way a **restart** is what applies an update — nothing hot-reloads.
156
+
157
+ **Which version is actually running?** Version skew across a team is the predictable failure here
158
+ (one stale npx cache, one freshly-updated plugin, two different answers). Ask it directly:
159
+
160
+ ```bash
161
+ npx @mlmcps/ml-specs-mcp --version # or: node .../mcp/ml-specs-server.mjs --version
162
+ ```
163
+
164
+ It prints the version *and the resolved file path*, so "which copy is this" is answerable in one
165
+ line. The same version is reported in the MCP handshake, and the repo's validator keeps all five
166
+ places it's written from drifting.
167
+
168
+ ## Relationship to the plugin
169
+
170
+ They compose — install both. The plugin gives you the loop (`/spec` → … → `/pr`), the agents, and
171
+ the hooks; this gives every tool the same facts underneath. `knowledge_check` shares one
172
+ implementation with the CI gate in `../templates/ci/knowledge-check.mjs`, imported rather than
173
+ copied, so the two can't drift apart.