@contentrain/mcp 1.2.1 → 1.4.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.
- package/README.md +93 -25
- package/dist/annotations-Clhbw2lh.mjs +126 -0
- package/dist/annotations-Clhbw2lh.mjs.map +1 -0
- package/dist/{apply-manager-BkPMfpsN.mjs → apply-manager-D5ym5Jba.mjs} +7 -7
- package/dist/{apply-manager-BkPMfpsN.mjs.map → apply-manager-D5ym5Jba.mjs.map} +1 -1
- package/dist/{astro-parser-BJ-54JGe.mjs → astro-parser-B-nLl0zE.mjs} +3 -3
- package/dist/{astro-parser-BJ-54JGe.mjs.map → astro-parser-B-nLl0zE.mjs.map} +1 -1
- package/dist/{branch-lifecycle-wGJg25LT.mjs → branch-lifecycle-CFVpTpNT.mjs} +33 -3
- package/dist/{branch-lifecycle-wGJg25LT.mjs.map → branch-lifecycle-CFVpTpNT.mjs.map} +1 -1
- package/dist/{compiler-rIC4ETHv.mjs → compiler-k4yttlzM.mjs} +2 -2
- package/dist/{compiler-rIC4ETHv.mjs.map → compiler-k4yttlzM.mjs.map} +1 -1
- package/dist/{compiler-sfc.cjs-BbD04rn_.mjs → compiler-sfc.cjs-D0d_OicF.mjs} +2 -2
- package/dist/{compiler-sfc.cjs-BbD04rn_.mjs.map → compiler-sfc.cjs-D0d_OicF.mjs.map} +1 -1
- package/dist/config-BIl5Ybj0.mjs +40 -0
- package/dist/config-BIl5Ybj0.mjs.map +1 -0
- package/dist/content-manager-DqDLSNQ-.d.mts +63 -0
- package/dist/content-manager-DqDLSNQ-.d.mts.map +1 -0
- package/dist/context-J0OU9Nfp.mjs +102 -0
- package/dist/context-J0OU9Nfp.mjs.map +1 -0
- package/dist/contracts-DfL0BfrD.mjs +2 -0
- package/dist/core/apply-manager.mjs +10 -10
- package/dist/core/config.d.mts +13 -0
- package/dist/core/config.d.mts.map +1 -1
- package/dist/core/config.mjs +2 -3
- package/dist/core/content-manager.d.mts +2 -45
- package/dist/core/content-manager.mjs +3 -4
- package/dist/core/context.d.mts +32 -2
- package/dist/core/context.d.mts.map +1 -1
- package/dist/core/context.mjs +7 -7
- package/dist/core/contracts/index.d.mts +2 -0
- package/dist/core/contracts/index.mjs +2 -0
- package/dist/core/doctor.d.mts +76 -0
- package/dist/core/doctor.d.mts.map +1 -0
- package/dist/core/doctor.mjs +8 -0
- package/dist/core/graph-builder.mjs +3 -4
- package/dist/core/meta-manager.mjs +2 -3
- package/dist/core/model-manager.d.mts +34 -1
- package/dist/core/model-manager.d.mts.map +1 -1
- package/dist/core/model-manager.mjs +3 -4
- package/dist/core/ops/index.d.mts +137 -0
- package/dist/core/ops/index.d.mts.map +1 -0
- package/dist/core/ops/index.mjs +4 -0
- package/dist/core/overlay-reader.d.mts +42 -0
- package/dist/core/overlay-reader.d.mts.map +1 -0
- package/dist/core/overlay-reader.mjs +2 -0
- package/dist/core/scan-config.mjs +2 -3
- package/dist/core/scanner.mjs +4 -5
- package/dist/core/validator/index.d.mts +129 -0
- package/dist/core/validator/index.d.mts.map +1 -0
- package/dist/core/validator/index.mjs +6 -0
- package/dist/{detect-DinOQAmK.mjs → detect-DL9mFmaS.mjs} +2 -2
- package/dist/{detect-DinOQAmK.mjs.map → detect-DL9mFmaS.mjs.map} +1 -1
- package/dist/doctor-CgBoT6h1.mjs +338 -0
- package/dist/doctor-CgBoT6h1.mjs.map +1 -0
- package/dist/{fs-BnIQ4dKj.mjs → fs-DLbVB-Ek.mjs} +2 -2
- package/dist/fs-DLbVB-Ek.mjs.map +1 -0
- package/dist/git/branch-lifecycle.d.mts +30 -1
- package/dist/git/branch-lifecycle.d.mts.map +1 -1
- package/dist/git/branch-lifecycle.mjs +4 -5
- package/dist/git/transaction.d.mts +2 -2
- package/dist/git/transaction.d.mts.map +1 -1
- package/dist/git/transaction.mjs +8 -8
- package/dist/{graph-builder-tM7zj-SX.mjs → graph-builder-DXv2JEp-.mjs} +3 -3
- package/dist/{graph-builder-tM7zj-SX.mjs.map → graph-builder-DXv2JEp-.mjs.map} +1 -1
- package/dist/{id-DV_T9Ic8.mjs → id-CIO9s0x_.mjs} +1 -1
- package/dist/{id-DV_T9Ic8.mjs.map → id-CIO9s0x_.mjs.map} +1 -1
- package/dist/index-D0wQJSgs.d.mts +2 -0
- package/dist/index.mjs +22 -17
- package/dist/index.mjs.map +1 -1
- package/dist/local-DvP4Y4T-.mjs +182 -0
- package/dist/local-DvP4Y4T-.mjs.map +1 -0
- package/dist/{meta-manager--0IwAPCl.mjs → meta-manager-C900rEyG.mjs} +2 -2
- package/dist/{meta-manager--0IwAPCl.mjs.map → meta-manager-C900rEyG.mjs.map} +1 -1
- package/dist/{model-manager-DW_fOGRM.mjs → model-manager-BhLsUgaB.mjs} +241 -49
- package/dist/model-manager-BhLsUgaB.mjs.map +1 -0
- package/dist/{node-Cbq5eR5i.mjs → node-DN9hZeil.mjs} +1 -1
- package/dist/{node-Cbq5eR5i.mjs.map → node-DN9hZeil.mjs.map} +1 -1
- package/dist/ops-DjEWi5Wa.mjs +486 -0
- package/dist/ops-DjEWi5Wa.mjs.map +1 -0
- package/dist/overlay-reader-DOdyDRIv.mjs +74 -0
- package/dist/overlay-reader-DOdyDRIv.mjs.map +1 -0
- package/dist/paths-C3xNyc7z.mjs +52 -0
- package/dist/paths-C3xNyc7z.mjs.map +1 -0
- package/dist/paths-CYl5vCBD.mjs +54 -0
- package/dist/paths-CYl5vCBD.mjs.map +1 -0
- package/dist/providers/github/index.d.mts +201 -0
- package/dist/providers/github/index.d.mts.map +1 -0
- package/dist/providers/github/index.mjs +494 -0
- package/dist/providers/github/index.mjs.map +1 -0
- package/dist/providers/gitlab/index.d.mts +158 -0
- package/dist/providers/gitlab/index.d.mts.map +1 -0
- package/dist/providers/gitlab/index.mjs +361 -0
- package/dist/providers/gitlab/index.mjs.map +1 -0
- package/dist/providers/local/index.d.mts +106 -0
- package/dist/providers/local/index.d.mts.map +1 -0
- package/dist/providers/local/index.mjs +12 -0
- package/dist/{scan-config-QgnJ1-52.mjs → scan-config-jC6XmiqF.mjs} +2 -2
- package/dist/{scan-config-QgnJ1-52.mjs.map → scan-config-jC6XmiqF.mjs.map} +1 -1
- package/dist/{scanner-DUoXnmtI.mjs → scanner-DKMwc03k.mjs} +7 -7
- package/dist/{scanner-DUoXnmtI.mjs.map → scanner-DKMwc03k.mjs.map} +1 -1
- package/dist/serialization-B1CEzR4H.mjs +2 -0
- package/dist/server/http/index.d.mts +107 -0
- package/dist/server/http/index.d.mts.map +1 -0
- package/dist/server/http/index.mjs +248 -0
- package/dist/server/http/index.mjs.map +1 -0
- package/dist/{server-Dtq8vqbK.mjs → server-BkhhtEE2.mjs} +486 -355
- package/dist/server-BkhhtEE2.mjs.map +1 -0
- package/dist/server-WqGx6ait.d.mts +50 -0
- package/dist/server-WqGx6ait.d.mts.map +1 -0
- package/dist/server.d.mts +2 -7
- package/dist/server.mjs +22 -17
- package/dist/{source-map-generator-DpO-ejrt.mjs → source-map-generator-BWDva49I.mjs} +1 -1
- package/dist/{source-map-generator-DpO-ejrt.mjs.map → source-map-generator-BWDva49I.mjs.map} +1 -1
- package/dist/{svelte-parser-1bBcMx3T.mjs → svelte-parser-Dr9mmZuk.mjs} +3 -3
- package/dist/{svelte-parser-1bBcMx3T.mjs.map → svelte-parser-Dr9mmZuk.mjs.map} +1 -1
- package/dist/templates/index.mjs +1 -1
- package/dist/{templates-bRPzYq4M.mjs → templates-VrLVqfe5.mjs} +1 -1
- package/dist/{templates-bRPzYq4M.mjs.map → templates-VrLVqfe5.mjs.map} +1 -1
- package/dist/testing/conformance.d.mts +59 -0
- package/dist/testing/conformance.d.mts.map +1 -0
- package/dist/testing/conformance.mjs +59 -0
- package/dist/testing/conformance.mjs.map +1 -0
- package/dist/tools/annotations.d.mts +24 -0
- package/dist/tools/annotations.d.mts.map +1 -0
- package/dist/tools/annotations.mjs +2 -0
- package/dist/{transaction-C_Pvux78.mjs → transaction-DgkNgWSI.mjs} +61 -32
- package/dist/transaction-DgkNgWSI.mjs.map +1 -0
- package/dist/tsx-parser-BOMZE_yQ.mjs +2 -0
- package/dist/{tsx-parser-BWiMGAIR.mjs → tsx-parser-CQc6nr-o.mjs} +1 -1
- package/dist/{tsx-parser-BWiMGAIR.mjs.map → tsx-parser-CQc6nr-o.mjs.map} +1 -1
- package/dist/util/detect.mjs +2 -3
- package/dist/util/fs.mjs +1 -2
- package/dist/util/id.mjs +1 -1
- package/dist/validator-B0nNRFeU.mjs +906 -0
- package/dist/validator-B0nNRFeU.mjs.map +1 -0
- package/dist/{vue-parser-DTPTN3Yb.mjs → vue-parser-COgjArqv.mjs} +3 -3
- package/dist/{vue-parser-DTPTN3Yb.mjs.map → vue-parser-COgjArqv.mjs.map} +1 -1
- package/package.json +82 -23
- package/testing/conformance/01-new-collection-entry/expected/.contentrain/config.json +15 -0
- package/testing/conformance/01-new-collection-entry/expected/.contentrain/content/blog/blog/en.json +6 -0
- package/testing/conformance/01-new-collection-entry/expected/.contentrain/context.json +22 -0
- package/testing/conformance/01-new-collection-entry/expected/.contentrain/meta/blog/en.json +7 -0
- package/testing/conformance/01-new-collection-entry/expected/.contentrain/models/blog.json +16 -0
- package/testing/conformance/01-new-collection-entry/scenario.json +19 -0
- package/testing/conformance/01-new-collection-entry/setup/.contentrain/config.json +15 -0
- package/testing/conformance/01-new-collection-entry/setup/.contentrain/models/blog.json +16 -0
- package/testing/conformance/02-new-singleton/expected/.contentrain/config.json +15 -0
- package/testing/conformance/02-new-singleton/expected/.contentrain/content/marketing/hero/en.json +4 -0
- package/testing/conformance/02-new-singleton/expected/.contentrain/context.json +22 -0
- package/testing/conformance/02-new-singleton/expected/.contentrain/meta/hero/en.json +5 -0
- package/testing/conformance/02-new-singleton/expected/.contentrain/models/hero.json +16 -0
- package/testing/conformance/02-new-singleton/scenario.json +18 -0
- package/testing/conformance/02-new-singleton/setup/.contentrain/config.json +15 -0
- package/testing/conformance/02-new-singleton/setup/.contentrain/models/hero.json +16 -0
- package/testing/conformance/03-new-dictionary/expected/.contentrain/config.json +15 -0
- package/testing/conformance/03-new-dictionary/expected/.contentrain/content/marketing/ui-strings/en.json +5 -0
- package/testing/conformance/03-new-dictionary/expected/.contentrain/context.json +22 -0
- package/testing/conformance/03-new-dictionary/expected/.contentrain/meta/ui-strings/en.json +5 -0
- package/testing/conformance/03-new-dictionary/expected/.contentrain/models/ui-strings.json +7 -0
- package/testing/conformance/03-new-dictionary/scenario.json +19 -0
- package/testing/conformance/03-new-dictionary/setup/.contentrain/config.json +15 -0
- package/testing/conformance/03-new-dictionary/setup/.contentrain/models/ui-strings.json +7 -0
- package/testing/conformance/README.md +77 -0
- package/testing/conformance/scenarios.json +36 -0
- package/dist/config-B5kc2oeV.mjs +0 -27
- package/dist/config-B5kc2oeV.mjs.map +0 -1
- package/dist/context-DIDt_TxX.mjs +0 -46
- package/dist/context-DIDt_TxX.mjs.map +0 -1
- package/dist/core/content-manager.d.mts.map +0 -1
- package/dist/core/validator.d.mts +0 -23
- package/dist/core/validator.d.mts.map +0 -1
- package/dist/core/validator.mjs +0 -7
- package/dist/fs-BnIQ4dKj.mjs.map +0 -1
- package/dist/model-manager-DW_fOGRM.mjs.map +0 -1
- package/dist/serializer-CnHTtmc1.mjs +0 -2
- package/dist/server-Dtq8vqbK.mjs.map +0 -1
- package/dist/server.d.mts.map +0 -1
- package/dist/transaction-C_Pvux78.mjs.map +0 -1
- package/dist/tsx-parser-BFLv292Y.mjs +0 -2
- package/dist/util/serializer.d.mts +0 -2
- package/dist/util/serializer.mjs +0 -2
- package/dist/validator-SQYUV2JP.mjs +0 -581
- package/dist/validator-SQYUV2JP.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/Contentrain/ai/tree/main/packages/mcp)
|
|
5
5
|
[](https://ai.contentrain.io/packages/mcp)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Provider-agnostic MCP engine for Contentrain — local-first by default, with optional GitHub and GitLab backends and an HTTP transport for remote drivers such as Studio.
|
|
8
8
|
|
|
9
9
|
Start here:
|
|
10
10
|
|
|
@@ -25,7 +25,7 @@ This package is the runtime core behind Contentrain's MCP integration. It can be
|
|
|
25
25
|
- an embeddable server (`createServer(projectRoot)`)
|
|
26
26
|
- a low-level toolkit for config, models, content, validation, scanning, and git transaction flow
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## Install
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
31
|
pnpm add @contentrain/mcp
|
|
@@ -44,7 +44,7 @@ Optional parser support for higher-quality source scanning:
|
|
|
44
44
|
|
|
45
45
|
They are listed as optional dependencies. The scanner still works without them, but Vue/Astro/Svelte detection is stronger when they are installed.
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## What It Does
|
|
48
48
|
|
|
49
49
|
`@contentrain/mcp` manages a `.contentrain/` directory in your project and exposes MCP tools for:
|
|
50
50
|
|
|
@@ -54,28 +54,30 @@ They are listed as optional dependencies. The scanner still works without them,
|
|
|
54
54
|
- validation and auto-fix
|
|
55
55
|
- normalize scan and apply flows
|
|
56
56
|
- bulk operations
|
|
57
|
-
- branch submission and branch-health awareness
|
|
57
|
+
- branch submission, review-mode merge, and branch-health awareness
|
|
58
|
+
- project health checking (doctor)
|
|
58
59
|
|
|
59
60
|
All write operations are designed around git-backed safety:
|
|
60
61
|
|
|
61
62
|
- a dedicated `contentrain` branch serves as the content state single source of truth
|
|
62
|
-
- each write creates a temporary worktree on a feature branch forked from `contentrain`
|
|
63
|
+
- each write creates a temporary worktree on a feature branch forked from `contentrain` (branch name: `cr/{operation}/{model}/{locale}/{timestamp}-{suffix}`)
|
|
63
64
|
- auto-merge: feature merges into `contentrain`, baseBranch advanced via update-ref, `.contentrain/` files selectively synced to developer's working tree
|
|
64
65
|
- review: feature branch pushed to remote for team review
|
|
65
66
|
- developer's working tree is never mutated during MCP git operations (no stash, no checkout, no merge)
|
|
66
67
|
- context.json is committed together with content changes, not as a separate commit
|
|
67
|
-
-
|
|
68
|
-
-
|
|
68
|
+
- canonical JSON output — sorted keys, 2-space indent, trailing newline
|
|
69
|
+
- validation + next-step hints surfaced to the caller
|
|
69
70
|
|
|
70
|
-
##
|
|
71
|
+
## Tool Surface
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
17 MCP tools with [annotations](https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#annotations) (`readOnlyHint`, `destructiveHint`, `idempotentHint`) for client safety hints:
|
|
73
74
|
|
|
74
75
|
| Tool | Purpose | Read-only | Destructive |
|
|
75
76
|
| --- | --- | --- | --- |
|
|
76
77
|
| `contentrain_status` | Project status, config, models, branch health, context | Yes | — |
|
|
77
78
|
| `contentrain_describe` | Full schema and sample data for a model | Yes | — |
|
|
78
79
|
| `contentrain_describe_format` | File-format and storage contract reference | Yes | — |
|
|
80
|
+
| `contentrain_doctor` | Project health report (env, structure, models, orphans, branches, SDK) | Yes | — |
|
|
79
81
|
| `contentrain_init` | Create `.contentrain/` structure and base config | — | — |
|
|
80
82
|
| `contentrain_scaffold` | Apply a starter template such as blog, docs, landing, saas | — | — |
|
|
81
83
|
| `contentrain_model_save` | Create or update a model definition | — | — |
|
|
@@ -84,13 +86,13 @@ All write operations are designed around git-backed safety:
|
|
|
84
86
|
| `contentrain_content_delete` | Delete content entries | — | **Yes** |
|
|
85
87
|
| `contentrain_content_list` | Read content entries | Yes | — |
|
|
86
88
|
| `contentrain_validate` | Validate project content, optionally auto-fix structural issues | — | — |
|
|
87
|
-
| `contentrain_submit` | Push `
|
|
89
|
+
| `contentrain_submit` | Push `cr/*` branches to remote | — | — |
|
|
88
90
|
| `contentrain_merge` | Merge a review-mode branch into contentrain locally | — | — |
|
|
89
91
|
| `contentrain_scan` | Graph- and candidate-based hardcoded string scan | Yes | — |
|
|
90
92
|
| `contentrain_apply` | Normalize extract/reuse execution with dry-run support | — | — |
|
|
91
93
|
| `contentrain_bulk` | Bulk locale copy, status updates, and deletes | — | — |
|
|
92
94
|
|
|
93
|
-
##
|
|
95
|
+
## Quick Start
|
|
94
96
|
|
|
95
97
|
### Configure via CLI (recommended)
|
|
96
98
|
|
|
@@ -120,7 +122,7 @@ const transport = new StdioServerTransport()
|
|
|
120
122
|
await server.connect(transport)
|
|
121
123
|
```
|
|
122
124
|
|
|
123
|
-
##
|
|
125
|
+
## Example MCP Flow
|
|
124
126
|
|
|
125
127
|
Typical agent workflow:
|
|
126
128
|
|
|
@@ -132,7 +134,7 @@ Typical agent workflow:
|
|
|
132
134
|
6. For hardcoded strings, use `contentrain_scan` then `contentrain_apply`
|
|
133
135
|
7. Push review branches with `contentrain_submit`
|
|
134
136
|
|
|
135
|
-
##
|
|
137
|
+
## Normalize Flow
|
|
136
138
|
|
|
137
139
|
Normalize is intentionally split into two phases:
|
|
138
140
|
|
|
@@ -145,7 +147,7 @@ Normalize is intentionally split into two phases:
|
|
|
145
147
|
- creates or updates models
|
|
146
148
|
- writes content entries
|
|
147
149
|
- records source tracking
|
|
148
|
-
- creates a review branch
|
|
150
|
+
- creates a review branch (`cr/normalize/extract/{domain}/{timestamp}`)
|
|
149
151
|
|
|
150
152
|
### 2. Reuse
|
|
151
153
|
|
|
@@ -154,15 +156,70 @@ Normalize is intentionally split into two phases:
|
|
|
154
156
|
- patches source files using agent-provided expressions
|
|
155
157
|
- adds imports when needed
|
|
156
158
|
- enforces patch path safety and scope checks
|
|
157
|
-
- creates a separate review branch
|
|
159
|
+
- creates a separate review branch (`cr/normalize/reuse/{model}/{locale}/{timestamp}`)
|
|
158
160
|
|
|
159
161
|
This split keeps content extraction separate from source rewriting.
|
|
160
162
|
|
|
161
|
-
|
|
163
|
+
### Transport / provider requirements
|
|
164
|
+
|
|
165
|
+
Normalize (`contentrain_scan` and `contentrain_apply`) requires local disk access — AST scanners walk the source tree and patch files in place. It runs only on a `LocalProvider` (stdio transport, or HTTP transport configured with a `LocalProvider`).
|
|
166
|
+
|
|
167
|
+
Remote providers such as `GitHubProvider` expose `astScan: false`, `sourceRead: false`, and `sourceWrite: false`. Calling these tools over a remote provider returns a uniform capability error:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"error": "contentrain_scan requires local filesystem access.",
|
|
172
|
+
"capability_required": "astScan",
|
|
173
|
+
"hint": "This tool is unavailable when MCP is driven by a remote provider (e.g. GitHubProvider). Use a LocalProvider or the stdio transport."
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Agents driving a remote transport should fall back to a local transport (or a local checkout) before invoking normalize.
|
|
178
|
+
|
|
179
|
+
## Remote Providers
|
|
180
|
+
|
|
181
|
+
MCP supports three backends behind the same `RepoProvider` contract:
|
|
182
|
+
|
|
183
|
+
- **LocalProvider** — simple-git + worktree. Every tool (normalize included) works on it. Stdio transport defaults to this.
|
|
184
|
+
- **GitHubProvider** — Octokit over the Git Data + Repos APIs. No clone, no worktree. `@octokit/rest` ships as an optional peer dependency.
|
|
185
|
+
- **GitLabProvider** — gitbeaker over the GitLab REST API. No clone, no worktree. `@gitbeaker/rest` ships as an optional peer dependency. Supports gitlab.com and self-hosted CE / EE.
|
|
186
|
+
|
|
187
|
+
Each remote provider implements the same surface: reader (readFile / listDirectory / fileExists), writer (applyPlan — one atomic commit), branch ops (list / create / delete / diff / merge / isMerged / getDefaultBranch). `mergeBranch` goes straight through on GitHub; on GitLab it opens an MR and immediately accepts it so the final `MergeResult` shape matches either way.
|
|
188
|
+
|
|
189
|
+
### GitLab — installation & usage
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
pnpm add @gitbeaker/rest
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { createGitLabProvider } from '@contentrain/mcp/providers/gitlab'
|
|
197
|
+
import { createServer } from '@contentrain/mcp/server'
|
|
198
|
+
|
|
199
|
+
const provider = await createGitLabProvider({
|
|
200
|
+
auth: { type: 'pat', token: process.env.GITLAB_TOKEN! },
|
|
201
|
+
project: {
|
|
202
|
+
projectId: 'acme/site', // or numeric project ID
|
|
203
|
+
host: 'https://gitlab.company.com', // omit for gitlab.com
|
|
204
|
+
},
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
const server = createServer({ provider })
|
|
208
|
+
// serve over stdio or the HTTP transport from @contentrain/mcp/server/http
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Capabilities: `sourceRead`, `sourceWrite`, `astScan`, `localWorktree` are all `false`; `pushRemote`, `branchProtection`, `pullRequestFallback` are `true`. Normalize / scan / apply reject with a capability error on GitLabProvider — fall back to a local transport for those flows.
|
|
212
|
+
|
|
213
|
+
### Bitbucket — coming soon
|
|
214
|
+
|
|
215
|
+
Bitbucket Cloud + Data Center support is on the roadmap. Until the provider ships, use the `contentrain_describe_format` tool to drive Contentrain content operations manually from a Bitbucket checkout via the LocalProvider path.
|
|
216
|
+
|
|
217
|
+
## Core Exports
|
|
162
218
|
|
|
163
219
|
The package also exposes low-level modules for embedding and advanced use:
|
|
164
220
|
|
|
165
221
|
- `@contentrain/mcp/server`
|
|
222
|
+
- `@contentrain/mcp/server/http`
|
|
166
223
|
- `@contentrain/mcp/core/config`
|
|
167
224
|
- `@contentrain/mcp/core/context`
|
|
168
225
|
- `@contentrain/mcp/core/model-manager`
|
|
@@ -171,27 +228,38 @@ The package also exposes low-level modules for embedding and advanced use:
|
|
|
171
228
|
- `@contentrain/mcp/core/scanner`
|
|
172
229
|
- `@contentrain/mcp/core/graph-builder`
|
|
173
230
|
- `@contentrain/mcp/core/apply-manager`
|
|
231
|
+
- `@contentrain/mcp/core/scan-config`
|
|
232
|
+
- `@contentrain/mcp/core/doctor`
|
|
233
|
+
- `@contentrain/mcp/core/contracts`
|
|
234
|
+
- `@contentrain/mcp/core/ops`
|
|
235
|
+
- `@contentrain/mcp/core/overlay-reader`
|
|
174
236
|
- `@contentrain/mcp/util/detect`
|
|
175
237
|
- `@contentrain/mcp/util/fs`
|
|
176
238
|
- `@contentrain/mcp/git/transaction`
|
|
177
239
|
- `@contentrain/mcp/git/branch-lifecycle`
|
|
240
|
+
- `@contentrain/mcp/tools/annotations`
|
|
178
241
|
- `@contentrain/mcp/templates`
|
|
242
|
+
- `@contentrain/mcp/providers/local`
|
|
243
|
+
- `@contentrain/mcp/providers/github`
|
|
244
|
+
- `@contentrain/mcp/providers/gitlab`
|
|
179
245
|
|
|
180
246
|
These are intended for Contentrain tooling and advanced integrations, not for direct manual editing of `.contentrain/` files.
|
|
181
247
|
|
|
182
|
-
##
|
|
248
|
+
## Design Constraints
|
|
183
249
|
|
|
184
250
|
Key design decisions in this package:
|
|
185
251
|
|
|
186
|
-
- local-first
|
|
187
|
-
-
|
|
252
|
+
- local-first **by default** — stdio transport + LocalProvider works without any network dependency
|
|
253
|
+
- provider-agnostic engine — the same 17 tools run over LocalProvider, GitHubProvider, or GitLabProvider behind a single `RepoProvider` contract
|
|
254
|
+
- remote provider SDKs (`@octokit/rest`, `@gitbeaker/rest`) are optional peer dependencies — pulled in only when their provider is used
|
|
188
255
|
- JSON-only content storage
|
|
189
|
-
- git-backed write workflow
|
|
190
|
-
- canonical serialization
|
|
256
|
+
- git-backed write workflow (worktree transaction locally, single atomic commit over the Git Data / REST APIs remotely)
|
|
257
|
+
- canonical serialization — byte-deterministic output, sorted keys, trailing newline
|
|
191
258
|
- framework-agnostic MCP layer
|
|
192
259
|
- agent decides content semantics, MCP enforces deterministic execution
|
|
260
|
+
- capability gates — tools that need source-tree access (normalize, scan, apply, doctor) reject with a uniform `capability_required` error on remote providers
|
|
193
261
|
|
|
194
|
-
##
|
|
262
|
+
## Development
|
|
195
263
|
|
|
196
264
|
From the monorepo root:
|
|
197
265
|
|
|
@@ -202,17 +270,17 @@ pnpm --filter @contentrain/mcp typecheck
|
|
|
202
270
|
pnpm exec oxlint packages/mcp/src packages/mcp/tests
|
|
203
271
|
```
|
|
204
272
|
|
|
205
|
-
##
|
|
273
|
+
## Related Packages
|
|
206
274
|
|
|
207
275
|
- `contentrain` — CLI and local review tooling
|
|
208
276
|
- `@contentrain/query` — generated runtime query SDK
|
|
209
277
|
- `@contentrain/rules` — IDE/agent rules and prompts
|
|
210
278
|
- `@contentrain/types` — shared schema and model types
|
|
211
279
|
|
|
212
|
-
##
|
|
280
|
+
## Documentation
|
|
213
281
|
|
|
214
282
|
Full documentation at **[ai.contentrain.io/packages/mcp](https://ai.contentrain.io/packages/mcp)**.
|
|
215
283
|
|
|
216
|
-
##
|
|
284
|
+
## License
|
|
217
285
|
|
|
218
286
|
MIT
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
//#region src/tools/annotations.ts
|
|
2
|
+
/**
|
|
3
|
+
* Centralized tool annotations registry.
|
|
4
|
+
* MCP clients use these hints to distinguish read-only vs. write vs. destructive tools.
|
|
5
|
+
*
|
|
6
|
+
* Also serves as the **single source of truth for the tool name list**. Consumers
|
|
7
|
+
* that need to enumerate every registered tool (e.g. parity tests in
|
|
8
|
+
* `@contentrain/rules` / `@contentrain/skills`) should import `TOOL_NAMES` below
|
|
9
|
+
* rather than hardcoding the list.
|
|
10
|
+
*/
|
|
11
|
+
const TOOL_ANNOTATIONS = {
|
|
12
|
+
contentrain_status: {
|
|
13
|
+
title: "Project Status",
|
|
14
|
+
readOnlyHint: true,
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
idempotentHint: true
|
|
17
|
+
},
|
|
18
|
+
contentrain_describe: {
|
|
19
|
+
title: "Describe Model",
|
|
20
|
+
readOnlyHint: true,
|
|
21
|
+
destructiveHint: false,
|
|
22
|
+
idempotentHint: true
|
|
23
|
+
},
|
|
24
|
+
contentrain_describe_format: {
|
|
25
|
+
title: "Describe Format",
|
|
26
|
+
readOnlyHint: true,
|
|
27
|
+
destructiveHint: false,
|
|
28
|
+
idempotentHint: true
|
|
29
|
+
},
|
|
30
|
+
contentrain_doctor: {
|
|
31
|
+
title: "Project Health Report",
|
|
32
|
+
readOnlyHint: true,
|
|
33
|
+
destructiveHint: false,
|
|
34
|
+
idempotentHint: true
|
|
35
|
+
},
|
|
36
|
+
contentrain_init: {
|
|
37
|
+
title: "Initialize Project",
|
|
38
|
+
readOnlyHint: false,
|
|
39
|
+
destructiveHint: false,
|
|
40
|
+
idempotentHint: false
|
|
41
|
+
},
|
|
42
|
+
contentrain_scaffold: {
|
|
43
|
+
title: "Scaffold Template",
|
|
44
|
+
readOnlyHint: false,
|
|
45
|
+
destructiveHint: false,
|
|
46
|
+
idempotentHint: false
|
|
47
|
+
},
|
|
48
|
+
contentrain_model_save: {
|
|
49
|
+
title: "Save Model",
|
|
50
|
+
readOnlyHint: false,
|
|
51
|
+
destructiveHint: false,
|
|
52
|
+
idempotentHint: true
|
|
53
|
+
},
|
|
54
|
+
contentrain_model_delete: {
|
|
55
|
+
title: "Delete Model",
|
|
56
|
+
readOnlyHint: false,
|
|
57
|
+
destructiveHint: true,
|
|
58
|
+
idempotentHint: false
|
|
59
|
+
},
|
|
60
|
+
contentrain_content_save: {
|
|
61
|
+
title: "Save Content",
|
|
62
|
+
readOnlyHint: false,
|
|
63
|
+
destructiveHint: false,
|
|
64
|
+
idempotentHint: true
|
|
65
|
+
},
|
|
66
|
+
contentrain_content_delete: {
|
|
67
|
+
title: "Delete Content",
|
|
68
|
+
readOnlyHint: false,
|
|
69
|
+
destructiveHint: true,
|
|
70
|
+
idempotentHint: false
|
|
71
|
+
},
|
|
72
|
+
contentrain_content_list: {
|
|
73
|
+
title: "List Content",
|
|
74
|
+
readOnlyHint: true,
|
|
75
|
+
destructiveHint: false,
|
|
76
|
+
idempotentHint: true
|
|
77
|
+
},
|
|
78
|
+
contentrain_validate: {
|
|
79
|
+
title: "Validate Project",
|
|
80
|
+
readOnlyHint: false,
|
|
81
|
+
destructiveHint: false,
|
|
82
|
+
idempotentHint: true
|
|
83
|
+
},
|
|
84
|
+
contentrain_submit: {
|
|
85
|
+
title: "Submit Branches",
|
|
86
|
+
readOnlyHint: false,
|
|
87
|
+
destructiveHint: false,
|
|
88
|
+
idempotentHint: true
|
|
89
|
+
},
|
|
90
|
+
contentrain_merge: {
|
|
91
|
+
title: "Merge Branch",
|
|
92
|
+
readOnlyHint: false,
|
|
93
|
+
destructiveHint: false,
|
|
94
|
+
idempotentHint: false
|
|
95
|
+
},
|
|
96
|
+
contentrain_scan: {
|
|
97
|
+
title: "Scan Source Code",
|
|
98
|
+
readOnlyHint: true,
|
|
99
|
+
destructiveHint: false,
|
|
100
|
+
idempotentHint: true
|
|
101
|
+
},
|
|
102
|
+
contentrain_apply: {
|
|
103
|
+
title: "Apply Normalize",
|
|
104
|
+
readOnlyHint: false,
|
|
105
|
+
destructiveHint: false,
|
|
106
|
+
idempotentHint: false
|
|
107
|
+
},
|
|
108
|
+
contentrain_bulk: {
|
|
109
|
+
title: "Bulk Operations",
|
|
110
|
+
readOnlyHint: false,
|
|
111
|
+
destructiveHint: false,
|
|
112
|
+
idempotentHint: false
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Canonical list of every registered MCP tool name, derived from the
|
|
117
|
+
* single source of truth above. Re-exported here with a stable name so
|
|
118
|
+
* parity tests in sibling packages (`@contentrain/rules`,
|
|
119
|
+
* `@contentrain/skills`) can assert against it without depending on
|
|
120
|
+
* `TOOL_ANNOTATIONS` internals.
|
|
121
|
+
*/
|
|
122
|
+
const TOOL_NAMES = Object.freeze(Object.keys(TOOL_ANNOTATIONS));
|
|
123
|
+
//#endregion
|
|
124
|
+
export { TOOL_NAMES as n, TOOL_ANNOTATIONS as t };
|
|
125
|
+
|
|
126
|
+
//# sourceMappingURL=annotations-Clhbw2lh.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotations-Clhbw2lh.mjs","names":[],"sources":["../src/tools/annotations.ts"],"sourcesContent":["import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\n\n/**\n * Centralized tool annotations registry.\n * MCP clients use these hints to distinguish read-only vs. write vs. destructive tools.\n *\n * Also serves as the **single source of truth for the tool name list**. Consumers\n * that need to enumerate every registered tool (e.g. parity tests in\n * `@contentrain/rules` / `@contentrain/skills`) should import `TOOL_NAMES` below\n * rather than hardcoding the list.\n */\nexport const TOOL_ANNOTATIONS: Record<string, ToolAnnotations> = {\n // ─── Context (read-only) ───\n contentrain_status: {\n title: 'Project Status',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_describe: {\n title: 'Describe Model',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_describe_format: {\n title: 'Describe Format',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_doctor: {\n title: 'Project Health Report',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n },\n\n // ─── Setup (write + git) ───\n contentrain_init: {\n title: 'Initialize Project',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n contentrain_scaffold: {\n title: 'Scaffold Template',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n\n // ─── Model (write + git) ───\n contentrain_model_save: {\n title: 'Save Model',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_model_delete: {\n title: 'Delete Model',\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n },\n\n // ─── Content (mixed) ───\n contentrain_content_save: {\n title: 'Save Content',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_content_delete: {\n title: 'Delete Content',\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n },\n contentrain_content_list: {\n title: 'List Content',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n },\n\n // ─── Workflow (mixed) ───\n contentrain_validate: {\n title: 'Validate Project',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_submit: {\n title: 'Submit Branches',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_merge: {\n title: 'Merge Branch',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n\n // ─── Normalize (mixed) ───\n contentrain_scan: {\n title: 'Scan Source Code',\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n },\n contentrain_apply: {\n title: 'Apply Normalize',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n\n // ─── Bulk (write + git) ───\n contentrain_bulk: {\n title: 'Bulk Operations',\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n },\n}\n\n/**\n * Canonical list of every registered MCP tool name, derived from the\n * single source of truth above. Re-exported here with a stable name so\n * parity tests in sibling packages (`@contentrain/rules`,\n * `@contentrain/skills`) can assert against it without depending on\n * `TOOL_ANNOTATIONS` internals.\n */\nexport const TOOL_NAMES: readonly string[] = Object.freeze(Object.keys(TOOL_ANNOTATIONS))\n"],"mappings":";;;;;;;;;;AAWA,MAAa,mBAAoD;CAE/D,oBAAoB;EAClB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,sBAAsB;EACpB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,6BAA6B;EAC3B,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,oBAAoB;EAClB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CAGD,kBAAkB;EAChB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,sBAAsB;EACpB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CAGD,wBAAwB;EACtB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,0BAA0B;EACxB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CAGD,0BAA0B;EACxB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,4BAA4B;EAC1B,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,0BAA0B;EACxB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CAGD,sBAAsB;EACpB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,oBAAoB;EAClB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,mBAAmB;EACjB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CAGD,kBAAkB;EAChB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACD,mBAAmB;EACjB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CAGD,kBAAkB;EAChB,OAAO;EACP,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EACjB;CACF;;;;;;;;AASD,MAAa,aAAgC,OAAO,OAAO,OAAO,KAAK,iBAAiB,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { c as writeText, o as readText, r as pathExists } from "./fs-
|
|
2
|
-
import { t as readConfig } from "./config-
|
|
3
|
-
import { S as writeContent, _ as resolveMdFilePath, c as validateModelDefinition, h as resolveJsonFilePath, l as writeModel, m as resolveContentDir, o as listModels, s as readModel } from "./model-manager-
|
|
4
|
-
import {
|
|
5
|
-
import { t as
|
|
6
|
-
import { n as
|
|
1
|
+
import { c as writeText, o as readText, r as pathExists } from "./fs-DLbVB-Ek.mjs";
|
|
2
|
+
import { t as readConfig } from "./config-BIl5Ybj0.mjs";
|
|
3
|
+
import { S as writeContent, _ as resolveMdFilePath, c as validateModelDefinition, h as resolveJsonFilePath, l as writeModel, m as resolveContentDir, o as listModels, s as readModel } from "./model-manager-BhLsUgaB.mjs";
|
|
4
|
+
import { r as writeContext } from "./context-J0OU9Nfp.mjs";
|
|
5
|
+
import { n as createTransaction, t as buildBranchName } from "./transaction-DgkNgWSI.mjs";
|
|
6
|
+
import { n as checkBranchHealth } from "./branch-lifecycle-CFVpTpNT.mjs";
|
|
7
7
|
import { extname, join } from "node:path";
|
|
8
8
|
//#region src/core/apply-manager.ts
|
|
9
9
|
const MAX_PATCHES = 100;
|
|
@@ -753,4 +753,4 @@ function addImportsToLines(lines, imports) {
|
|
|
753
753
|
//#endregion
|
|
754
754
|
export { detectFileFramework as a, validatePatchPath as c, checkSyntax as i, applyExtract as n, replaceInLine as o, applyReuse as r, validateFrameworkExpression as s, PATCHABLE_EXTENSIONS as t };
|
|
755
755
|
|
|
756
|
-
//# sourceMappingURL=apply-manager-
|
|
756
|
+
//# sourceMappingURL=apply-manager-D5ym5Jba.mjs.map
|