Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .changeset/mcp-phase-10-alignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
"@contentrain/mcp": minor
---

chore(mcp): phase 10 alignment — docs parity, cohesion fixes, P1 bug fixes, new subpath exports

Follow-up to the phase-0-through-9 provider-agnostic refactor. Ships
in one PR because the pieces are interlocking: the bug fixes rely on
new primitives, the new primitives unlock the feature gaps the docs
claimed were already covered.

### New public subpath exports

- `@contentrain/mcp/core/contracts` — `RepoProvider` / `RepoReader` /
`RepoWriter` / capabilities / file-change / branch / commit types,
re-exported from `@contentrain/types` for backward compat.
- `@contentrain/mcp/providers/local` — `LocalProvider`, `LocalReader`,
related types. Previously internal-only.

These paths were referenced in package documentation since phase 5
but had no `exports` entry, so external imports failed with
`ERR_PACKAGE_PATH_NOT_EXPORTED`. Now callable.

### Bug fixes (P1)

- **Remote write base branch invariant** — `commit-plan.ts` and its
call sites now always fork remote feature branches from the
`contentrain` singleton branch, matching the local flow. Previous
behaviour forked from `config.repository.default_branch` (usually
`main`), breaking the single-source-of-truth invariant in any
project that set the repository's default branch explicitly.
- **Stale remote context / validation** — the new `OverlayReader`
primitive layers pending `FileChange`s on top of the underlying
reader. `buildContextChange` and post-save `validateProject` now
see the state the pending commit produces instead of the
pre-change base branch. Fixes commits whose context.json entry
counts or validation result reflected the old state.

### Read-only tools on HTTP + remote providers (P2)

- `contentrain_status`, `contentrain_describe`, and
`contentrain_content_list` no longer gate on `!projectRoot`. They
work against any `ToolProvider` — `LocalProvider`, `GitHubProvider`,
`GitLabProvider` — through the reader surface. Branch health + stack
detection (local-only) are skipped gracefully when no project root
is available.
- `contentrain_content_list` with `resolve: true` still requires local
disk (cross-model relation hydration walks other models' content
files); the reader path rejects it with a descriptive error.

### Cohesion

- `commitThroughProvider` — shared helper that encapsulates the
`LocalProvider` vs remote `RepoProvider` dispatch. The eight
repeated `if (provider instanceof LocalProvider) { … } else { … }`
blocks across `content.ts` / `model.ts` collapse to single calls.
Uniform `{ commitSha, workflowAction, sync? }` return shape.
- `providers/shared/{errors,paths}.ts` — consolidated
`isNotFoundError` + `normaliseContentRoot` / `resolveRepoPath` used
by both GitHub and GitLab providers. Removes four duplicate
`isNotFound` helpers with asymmetric semantics (GitLab's lenient
description-match fallback is gone — status-based check only).
- `workflow.ts` — `contentrain_submit` and `contentrain_merge` now
gate on explicit `provider.capabilities.X` instead of the
`!projectRoot` proxy. Matches the pattern `normalize.ts` adopted in
phase 6.
- `util/serializer.ts` was previously dead-code removed in phase 9.

### Test coverage

- `tests/providers/local/reader.test.ts` — new, 11 cases
- `tests/core/overlay-reader.test.ts` — new, 11 cases
- `tests/server/http.test.ts` — +5 cases (content_delete, model_save,
model_delete, validate, status remote) and an updated
capability-error test that now exercises `contentrain_submit`
(genuinely local-only) instead of `contentrain_status`.

### Tool surface

No changes. Same 16 tools, same parameters, same response shapes.
Stdio + LocalProvider flows behave identically to the previous
release.
47 changes: 47 additions & 0 deletions .changeset/mcp-phase-11-studio-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
"@contentrain/mcp": minor
---

feat(mcp): phase 11 — embedding surface + two more P2 fixes

Follow-up to phase 10. Extends the public surface Studio (and any
third-party integrator) consumes, and closes two additional bugs
surfaced while writing the handoff documentation.

### New public subpath exports

- `@contentrain/mcp/core/ops` — plan helpers (`planContentSave`,
`planContentDelete`, `planModelSave`, `planModelDelete`) plus the
path helpers (`contentDirPath`, `contentFilePath`,
`documentFilePath`, `metaFilePath`) integrators need to compose
their own write paths against a `RepoProvider`.
- `@contentrain/mcp/core/overlay-reader` — the `OverlayReader`
primitive required by any non-local write path that needs
`buildContextChange` / `validateProject` to see post-commit state.

### Bug fixes (P2)

- **`ApplyPlanInput.base` contract alignment.** `GitHubProvider` and
`GitLabProvider` previously fell back to the repository's default
branch (main / master / trunk) when `base` was omitted — in direct
conflict with the docstring that said "defaults to provider's
content-tracking branch". Both implementations now default to
`CONTENTRAIN_BRANCH`, matching the documented contract and the
`LocalProvider` transaction behaviour. Tests that locked in the old
behaviour are rewritten; the docstring is tightened to be
unambiguous.
- **`contentrain_status` context field on remote.** When the session
has no `projectRoot`, `contentrain_status` previously returned
`context: null` unconditionally, even though remote writes do
commit `.contentrain/context.json`. `readContext` gains a reader
overload; `tools/context.ts` uses it for remote flows. Remote
`status` calls now surface the last operation + stats.

### Tests

- `tests/server/http.test.ts` — `status works read-only over a
remote provider` now seeds `.contentrain/context.json` and asserts
the committed `lastOperation` + `stats` propagate.
- `tests/providers/{github,gitlab}/apply-plan.test.ts` — the
old "falls back to repo default branch" cases are rewritten to
assert the new CONTENTRAIN_BRANCH default.
18 changes: 18 additions & 0 deletions .changeset/types-provider-alignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"@contentrain/types": minor
---

feat(types): RepoProvider contracts + widened `repository.provider`

- `ContentrainConfig.repository.provider` is now `'github' | 'gitlab'` (was a hardcoded `'github'`). Reflects the two remote providers `@contentrain/mcp` ships today.
- The provider-agnostic engine contracts used by `@contentrain/mcp` are now exposed directly from `@contentrain/types`:
- `RepoReader`, `RepoWriter`, `RepoProvider`
- `ProviderCapabilities`, `LOCAL_CAPABILITIES`
- `ApplyPlanInput`, `Commit`, `CommitAuthor`
- `FileChange`, `Branch`, `FileDiff`, `MergeResult`

Third-party tools can now implement a custom `RepoProvider` without
taking a runtime dependency on `@contentrain/mcp`.

`@contentrain/mcp/core/contracts` keeps re-exporting every symbol, so
existing MCP-based imports are unchanged.
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ MIT-licensed monorepo for Contentrain's open-source packages: MCP tools, CLI, Ty
```
contentrain-ai/
├── packages/
│ ├── mcp/ — 15 MCP tools (simple-git + zod + MCP SDK)
│ ├── mcp/ — 16 MCP tools, stdio + HTTP transports, Local / GitHub / GitLab providers (simple-git + zod + MCP SDK)
│ ├── cli/ — citty + tsdown (init/serve/validate/normalize/connect)
│ ├── types/ — Shared TypeScript types (@contentrain/types)
│ ├── rules/ — AI agent quality rules & conventions
Expand Down Expand Up @@ -90,7 +90,7 @@ When working with Contentrain content operations (models, content, normalize, va

| Package | Name | Description |
|---|---|---|
| packages/mcp | @contentrain/mcp | 15 MCP tools |
| packages/mcp | @contentrain/mcp | 16 MCP tools, stdio + HTTP transports, Local / GitHub / GitLab providers |
| packages/cli | contentrain | CLI (npx contentrain) |
| packages/types | @contentrain/types | Shared TypeScript types |
| packages/rules | @contentrain/rules | AI agent quality rules & conventions |
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ This is the strongest entry point into the product:

```
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
│ AI Agent │────▶│ MCP (15 tools) │────▶│ .contentrain/│
│ AI Agent │────▶│ MCP (16 tools) │────▶│ .contentrain/│
│ (decides) │ │ (enforces) │ │ (stores) │
└─────────────┘ └──────────────────┘ └──────┬───────┘
Expand Down Expand Up @@ -145,7 +145,7 @@ Works with Nuxt, Next.js, Astro, SvelteKit, Vue, React, Node, Go, Python, Swift,

- **Git-native** — every write goes through worktree isolation + review branches
- **Normalize flow** — scan codebase for hardcoded strings → extract → create i18n-ready content → patch source files
- **Local-first MCP** — 15 tools, stdio transport, works with Claude Code, Cursor, Windsurf, or any MCP client
- **MCP engine** — 16 tools over stdio or HTTP transport, works with Claude Code, Cursor, Windsurf, or any MCP client
- **Provider-agnostic engine** — the same tool surface runs over a local worktree, GitHub, or GitLab (self-hosted included) with zero tool-code changes. HTTP transport available for remote drivers such as Studio.
- **Canonical serialization** — sorted keys, deterministic output, clean git diffs, conflict-free parallel edits
- **Agent rules & skills** — behavioral policies and step-by-step workflows ship as npm packages
Expand Down Expand Up @@ -176,7 +176,7 @@ See [`AGENTS.md`](AGENTS.md) for the full skill catalog and agent guidance.

| Package | npm | Role |
|---|---|---|
| [`@contentrain/mcp`](packages/mcp) | [![npm](https://img.shields.io/npm/v/%40contentrain%2Fmcp)](https://www.npmjs.com/package/@contentrain/mcp) | 15 MCP tools + stdio / HTTP transport + Local / GitHub / GitLab providers |
| [`@contentrain/mcp`](packages/mcp) | [![npm](https://img.shields.io/npm/v/%40contentrain%2Fmcp)](https://www.npmjs.com/package/@contentrain/mcp) | 16 MCP tools + stdio / HTTP transport + Local / GitHub / GitLab providers |
| [`contentrain`](packages/cli) | [![npm](https://img.shields.io/npm/v/contentrain)](https://www.npmjs.com/package/contentrain) | CLI + Serve UI + MCP stdio entrypoint |
| [`@contentrain/query`](packages/sdk/js) | [![npm](https://img.shields.io/npm/v/%40contentrain%2Fquery)](https://www.npmjs.com/package/@contentrain/query) | Generated TypeScript query SDK |
| [`@contentrain/types`](packages/types) | [![npm](https://img.shields.io/npm/v/%40contentrain%2Ftypes)](https://www.npmjs.com/package/@contentrain/types) | Shared type definitions + constants |
Expand Down
8 changes: 8 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export default defineConfig({
{ text: 'Types', link: '/packages/types' },
]},
{ text: 'Guides', items: [
{ text: 'Providers & Transports', link: '/guides/providers' },
{ text: 'HTTP Transport', link: '/guides/http-transport' },
{ text: 'Embedding MCP', link: '/guides/embedding-mcp' },
{ text: 'Normalize Flow', link: '/guides/normalize' },
{ text: 'Framework Integration', link: '/guides/frameworks' },
{ text: 'i18n Workflow', link: '/guides/i18n' },
Expand All @@ -56,6 +59,7 @@ export default defineConfig({
{ text: 'Model Kinds', link: '/reference/model-kinds' },
{ text: 'Field Types', link: '/reference/field-types' },
{ text: 'Configuration', link: '/reference/config' },
{ text: 'RepoProvider', link: '/reference/providers' },
]},
{ text: 'Starters', link: 'https://github.com/orgs/Contentrain/repositories?q=contentrain-starter&type=template' },
],
Expand Down Expand Up @@ -84,6 +88,9 @@ export default defineConfig({
{
text: 'Guides',
items: [
{ text: 'Providers & Transports', link: '/guides/providers' },
{ text: 'HTTP Transport', link: '/guides/http-transport' },
{ text: 'Embedding MCP', link: '/guides/embedding-mcp' },
{ text: 'Normalize Flow', link: '/guides/normalize' },
{ text: 'Framework Integration', link: '/guides/frameworks' },
{ text: 'i18n Workflow', link: '/guides/i18n' },
Expand All @@ -96,6 +103,7 @@ export default defineConfig({
{ text: 'Model Kinds', link: '/reference/model-kinds' },
{ text: 'Field Types', link: '/reference/field-types' },
{ text: 'Configuration', link: '/reference/config' },
{ text: 'RepoProvider', link: '/reference/providers' },
],
},
],
Expand Down
6 changes: 4 additions & 2 deletions docs/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,18 @@ Contentrain AI inverts the traditional CMS workflow:

### 1. MCP (Infrastructure)

15 tools that AI agents call to manage content:
16 tools that AI agents call to manage content:

- **Read:** `contentrain_status`, `contentrain_describe`, `contentrain_describe_format`, `contentrain_content_list`
- **Project setup:** `contentrain_init`, `contentrain_scaffold`
- **Content and schema writes:** `contentrain_model_save`, `contentrain_model_delete`, `contentrain_content_save`, `contentrain_content_delete`
- **Normalize:** `contentrain_scan`, `contentrain_apply`
- **Workflow and operations:** `contentrain_validate`, `contentrain_submit`, `contentrain_bulk`
- **Workflow and operations:** `contentrain_validate`, `contentrain_submit`, `contentrain_merge`, `contentrain_bulk`

MCP is **deterministic infrastructure** — it doesn't make content decisions. The agent decides what to create; MCP executes it.

MCP runs over two transports (stdio for IDE agents, HTTP for Studio / CI / remote drivers) and three provider backends: **Local** (simple-git + worktree), **GitHub** (Octokit over the Git Data API), and **GitLab** (gitbeaker over the REST API). The tool surface is identical across all three; some tools require `LocalProvider` — see [Providers and transports](/guides/providers) for the capability matrix.

### 2. Agent (Intelligence)

The AI agent (Claude, GPT, etc.) is the intelligence layer:
Expand Down
10 changes: 10 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ If your IDE is detected during `contentrain init`, the MCP config is created aut

</details>

::: tip HTTP Transport
In addition to stdio, MCP also serves over HTTP at `POST /mcp`. Useful for Studio / CI runners / remote agents that drive Contentrain operations without a local IDE:

```bash
npx contentrain serve --mcpHttp --authToken $(openssl rand -hex 32)
```

See the [HTTP Transport guide](/guides/http-transport) for auth, deployment patterns, and programmatic embedding.
:::

### 3. Create a content model

Tell your agent:
Expand Down
Loading
Loading