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
21 changes: 21 additions & 0 deletions .changeset/mcp-media-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"@contentrain/types": minor
"@contentrain/mcp": minor
"@contentrain/rules": minor
"@contentrain/skills": minor
---

feat(mcp): media tools over an optional provider media facet

**@contentrain/types**: new `MediaProvider` contract (`list`/`get`/`ingest`/`update`/`delete`) plus `MediaAsset`, `MediaListOptions`, `MediaListResult`, `MediaIngestInput`, `MediaUpdateInput`. `RepoProvider` gains an optional `media?: MediaProvider` facet — implemented by hosted providers (Studio MCP Cloud), absent on Local/GitHub/GitLab.

**@contentrain/mcp**: five new tools — `contentrain_media_list`, `contentrain_media_get`, `contentrain_media_ingest`, `contentrain_media_update`, `contentrain_media_delete` — as a deterministic passthrough to the provider's media facet.

- **Capability-aware:** registered only when `RepoProvider.media` is present (new `media` requirement in `TOOL_REQUIREMENTS`). Local stdio servers keep listing exactly the 19 core tools; nothing changes for existing embeddings.
- **URL-based ingest.** MCP has no binary channel; the provider fetches the source URL server-side and owns SSRF/MIME/size policy. `contentrain_media_ingest` is the only tool with `openWorldHint: true`.
- **Safety:** `media_delete` is `destructiveHint: true` and requires `confirm: true`; content references are never rewritten by MCP.
- Closes the discovery loop for external agents: list assets → pick a `media/...` path → reference it via `contentrain_content_save` (absolute delivery URLs via `mediaBaseUrl`).

**@contentrain/rules**: `MCP_TOOLS` now lists 24 tools (19 core + 5 media); essential guardrails document the media flow.

**@contentrain/skills**: `references/mcp-tools.md` gains a Media Tools section covering all five tools (parity-tested against the MCP registry).
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 (19 tools) │────▶│ .contentrain/│
│ AI Agent │────▶│ MCP (24 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
- **MCP engine** — 19 tools over stdio or HTTP transport, works with Claude Code, Cursor, Windsurf, or any MCP client
- **MCP engine** — 24 tools (19 core + 5 media) 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) | 19 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) | 24 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
2 changes: 1 addition & 1 deletion docs/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Contentrain AI inverts the traditional CMS workflow:

### 1. MCP (Infrastructure)

19 tools that AI agents call to manage content:
24 tools (19 core + 5 media) that AI agents call to manage content:

- **Read:** `contentrain_status`, `contentrain_describe`, `contentrain_describe_format`, `contentrain_doctor`, `contentrain_content_list`
- **Project setup:** `contentrain_init`, `contentrain_scaffold`
Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ All packages are published on npm:
| Package | Description | Install |
|---|---|---|
| [`contentrain`](https://www.npmjs.com/package/contentrain) | CLI (init, serve, generate, validate) | `npx contentrain init` |
| [`@contentrain/mcp`](https://www.npmjs.com/package/@contentrain/mcp) | 19 MCP tools for AI agents | `pnpm add @contentrain/mcp` |
| [`@contentrain/mcp`](https://www.npmjs.com/package/@contentrain/mcp) | 24 MCP tools for AI agents | `pnpm add @contentrain/mcp` |
| [`@contentrain/query`](https://www.npmjs.com/package/@contentrain/query) | TypeScript query SDK (optional) | `pnpm add @contentrain/query` |
| [`@contentrain/types`](https://www.npmjs.com/package/@contentrain/types) | Shared TypeScript types | `pnpm add @contentrain/types` |
| [`@contentrain/rules`](https://www.npmjs.com/package/@contentrain/rules) | AI agent quality rules | `pnpm add @contentrain/rules` |
Expand Down Expand Up @@ -276,7 +276,7 @@ Want to skip setup? Start from a production-ready template with content models,

- [Core Concepts](/concepts) — Models, content kinds, domains, and the governance architecture
- [Ecosystem Map](/ecosystem) — How AI packages and Studio fit together
- [MCP Tools](/packages/mcp) — All 19 tools available to your agent
- [MCP Tools](/packages/mcp) — All 24 tools available to your agent
- [Normalize Flow](/guides/normalize) — Extract hardcoded strings from existing code
- [i18n Workflow](/guides/i18n) — Add languages to your content
- [Framework Integration](/guides/frameworks) — Platform-specific setup patterns
Expand Down
6 changes: 4 additions & 2 deletions docs/guides/embedding-mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Studio (`contentrain.io`) is the canonical consumer; the patterns below describe
`@contentrain/mcp` ships three pieces you plug together:

1. **A `RepoProvider`** — Local / GitHub / GitLab (or your own). Wraps whatever git backend you're targeting.
2. **An `McpServer`** — the MCP JSON-RPC surface with all 17 Contentrain tools registered.
2. **An `McpServer`** — the MCP JSON-RPC surface with every Contentrain tool the provider can satisfy registered (19 core + 5 media on media-capable providers).
3. **A transport** — stdio (for IDE agents) or HTTP (for hosted / remote drivers).

The three are orthogonal. Mix them freely.
Expand Down Expand Up @@ -277,6 +277,8 @@ Each provider advertises a `ProviderCapabilities` manifest. `createServer` consu

`init`, `scaffold`, `doctor`, and `bulk` additionally require a local `projectRoot` on disk. Input-dependent checks (`validate --fix`, `apply` reuse) stay as call-time guards and return the structured `capability_required` error above.

The five `contentrain_media_*` tools gate on the provider's optional **media facet** (`RepoProvider.media` — an object implementing `MediaProvider` from `@contentrain/types`, not a boolean flag). Implement it on a custom provider to get the media tools registered; leave it absent and they never appear.

Read-only tools (`status`, `describe`, `describe_format`, `content_list`, `validate` without `--fix`) work on every provider — they use only the reader surface.

## Extension: custom providers
Expand Down Expand Up @@ -339,7 +341,7 @@ A GitHub Actions job:
4. Drive it with an MCP client
5. Let `contentrain_submit` push the `cr/*` branch

All 19 tools are available because the runner has `LocalProvider`.
All 19 core tools are available because the runner has `LocalProvider` (media tools need a media-capable provider).

### Scripted automation

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/http-transport.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Typical drivers:
- **CI runners** — deterministic content operations as part of a pipeline (scaffold, validate, submit).
- **Remote agents** — any MCP client that wants to operate a Contentrain project without a local checkout.

All three tunnel the same 19 tools through the same `RepoProvider` contract. Which backend answers depends on how the server is wired — see [Providers & Transports](/guides/providers) for the capability matrix.
All three tunnel the same tool surface (19 core + 5 media on media-capable providers) through the same `RepoProvider` contract. Which backend answers depends on how the server is wired — see [Providers & Transports](/guides/providers) for the capability matrix.

## Starting the HTTP server

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ slug: providers

# Providers & Transports

Contentrain MCP runs the same 19 tools over three backends:
Contentrain MCP runs the same tool surface (19 core + 5 media on media-capable providers) over three backends:

- **LocalProvider** — simple-git + a temporary worktree on your disk. Default for `npx contentrain serve --stdio` and the HTTP transport when driven by the CLI.
- **GitHubProvider** — Octokit over the GitHub Git Data + Repos APIs. No clone, no worktree.
Expand Down
27 changes: 22 additions & 5 deletions docs/packages/mcp.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: MCP Tools
description: Complete reference for @contentrain/mcp — the provider-agnostic MCP engine powering AI content governance with 19 deterministic tools over stdio or HTTP
description: Complete reference for @contentrain/mcp — the provider-agnostic MCP engine powering AI content governance with 24 deterministic tools over stdio or HTTP
order: 1
slug: mcp
---
Expand Down Expand Up @@ -55,10 +55,10 @@ Use the local stdio server when the agent should work against a checkout on your

## Tool Catalog

The MCP server exposes **19 tools** organized by function. Each tool includes [MCP annotations](https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#annotations) (`readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint: false` — every tool operates on the configured repository only) so clients can distinguish safe reads from writes and destructive operations.
The MCP server exposes **24 tools** — 19 core + 5 media — organized by function. Each tool includes [MCP annotations](https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#annotations) (`readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint: false` everywhere except `contentrain_media_ingest`, which fetches a caller-supplied URL server-side) so clients can distinguish safe reads from writes and destructive operations.

::: info Capability-aware listing
`tools/list` is filtered per session: tools whose requirements (local project root, provider capabilities) cannot be met are not registered at all. A local stdio server lists all 19 tools; a remote-provider session (e.g. Studio MCP Cloud) lists only the remote-safe subset — `status`, `describe`, `describe_format`, `model_save`, `model_delete`, `content_save`, `content_delete`, `content_list`, `validate`. See `TOOL_REQUIREMENTS` in `@contentrain/mcp/tools/availability`.
`tools/list` is filtered per session: tools whose requirements (local project root, provider capabilities) cannot be met are not registered at all. A local stdio server lists the 19 core tools; a remote-provider session lists the remote-safe subset plus — on media-capable providers like Studio MCP Cloudthe 5 `contentrain_media_*` tools. Core remote-safe subset — `status`, `describe`, `describe_format`, `model_save`, `model_delete`, `content_save`, `content_delete`, `content_list`, `validate`. See `TOOL_REQUIREMENTS` in `@contentrain/mcp/tools/availability`.
:::

| Tool | Title | Read-only | Destructive |
Expand All @@ -82,6 +82,11 @@ The MCP server exposes **19 tools** organized by function. Each tool includes [M
| `contentrain_scan` | Scan Source Code | Yes | — |
| `contentrain_apply` | Apply Normalize | — | — |
| `contentrain_bulk` | Bulk Operations | — | — |
| `contentrain_media_list` | List Media Assets | Yes | — |
| `contentrain_media_get` | Get Media Asset | Yes | — |
| `contentrain_media_ingest` | Ingest Media From URL | — | — |
| `contentrain_media_update` | Update Media Metadata | — | — |
| `contentrain_media_delete` | Delete Media Asset | — | **Yes** |

### Detailed Reference

Expand Down Expand Up @@ -119,6 +124,18 @@ The MCP server exposes **19 tools** organized by function. Each tool includes [M
| `contentrain_apply` | Extract or reuse | Two-phase normalize: extract content or patch source files |
| `contentrain_bulk` | Batch operations | Bulk locale copy, status updates, and deletes |

### Media Tools (Provider Media Facet)

A deterministic passthrough to the provider's optional media stack (`RepoProvider.media`) — registered **only when the provider exposes one** (e.g. Studio MCP Cloud). The flow: list assets → pick a `media/...` path → reference it via `contentrain_content_save` (normalized to absolute delivery URLs when `mediaBaseUrl` is set).

| Tool | Purpose | Description |
|------|---------|-------------|
| `contentrain_media_list` | Discover assets | Search, tag filter, cursor pagination — returns storage paths + delivery URLs |
| `contentrain_media_get` | Inspect one asset | Path, URL, mime, size, alt, tags, provider metadata |
| `contentrain_media_ingest` | Add from URL | Provider fetches the URL server-side under its own SSRF/MIME/size policy (MCP never fetches; the only `openWorldHint: true` tool) |
| `contentrain_media_update` | Edit metadata | Alt text, tags, filename — never touches the binary |
| `contentrain_media_delete` | Remove asset | Destructive; content references are NOT rewritten |

## Key Principles

### 1. Deterministic Infrastructure
Expand Down Expand Up @@ -185,7 +202,7 @@ Agent drivers treat `capability_required` as a retry signal. See [Providers & Tr
- **stdio** — `contentrain serve --stdio` or `npx contentrain-mcp`. IDE agents (Claude Code, Cursor, Windsurf) connect over stdin/stdout.
- **HTTP** — `contentrain serve --mcpHttp --authToken $TOKEN` or the programmatic `startHttpMcpServer({...})` / `startHttpMcpServerWith({ provider })` exports. Streamable HTTP at `POST /mcp` with secure-by-default Bearer auth. See the [HTTP Transport guide](/guides/http-transport).

Both transports serve the same 19 tools and the same JSON response shapes.
Both transports serve the same tool surface and the same JSON response shapes.

## Providers

Expand Down Expand Up @@ -317,7 +334,7 @@ This auto-creates the correct MCP config file and installs AI rules/skills.

</details>

Once connected, the agent has access to all 19 MCP tools and can manage your content through natural language.
Once connected, the agent has access to the full MCP tool surface and can manage your content through natural language.

### OpenAI Codex

Expand Down
2 changes: 1 addition & 1 deletion docs/packages/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ import {
} from '@contentrain/rules'

// Check if a tool exists
console.log(MCP_TOOLS.length) // 19
console.log(MCP_TOOLS.length) // 24
console.log(MCP_TOOLS.includes('contentrain_validate')) // true
console.log(MCP_TOOLS.includes('contentrain_merge')) // true
console.log(MCP_TOOLS.includes('contentrain_doctor')) // true
Expand Down
13 changes: 10 additions & 3 deletions packages/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ All write operations are designed around git-backed safety:

## Tool Surface

19 MCP tools with [annotations](https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#annotations) (`readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint: false` — every tool operates on the configured repository only) for client safety hints.
24 MCP tools — 19 core + 5 media — with [annotations](https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#annotations) (`readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint: false` everywhere except `contentrain_media_ingest`, which fetches a caller-supplied URL server-side) for client safety hints.

**Tool listing is capability-aware.** `tools/list` only advertises tools the resolved provider + `projectRoot` pair can actually satisfy. A local stdio server lists all 19; a session driven by a remote provider (GitHub/GitLab, no local checkout) lists only the remote-safe subset — `status`, `describe`, `describe_format`, `model_save`, `model_delete`, `content_save`, `content_delete`, `content_list`, `validate`. The requirement map lives in `TOOL_REQUIREMENTS` (`@contentrain/mcp/tools/availability`).
**Tool listing is capability-aware.** `tools/list` only advertises tools the resolved provider + `projectRoot` pair can actually satisfy. A local stdio server lists the 19 core tools; a session driven by a remote provider (GitHub/GitLab, no local checkout) lists only the remote-safe subset — `status`, `describe`, `describe_format`, `model_save`, `model_delete`, `content_save`, `content_delete`, `content_list`, `validate`. The requirement map lives in `TOOL_REQUIREMENTS` (`@contentrain/mcp/tools/availability`).

| Tool | Purpose | Read-only | Destructive |
| --- | --- | --- | --- |
Expand All @@ -96,6 +96,13 @@ All write operations are designed around git-backed safety:
| `contentrain_scan` | Graph- and candidate-based hardcoded string scan | Yes | — |
| `contentrain_apply` | Normalize extract/reuse execution with dry-run support | — | — |
| `contentrain_bulk` | Bulk locale copy, status updates, and deletes | — | — |
| `contentrain_media_list` | List media assets (search, tag filter, cursor pagination) | Yes | — |
| `contentrain_media_get` | Get one media asset by id | Yes | — |
| `contentrain_media_ingest` | Ingest an asset from a source URL (provider fetches server-side) | — | — |
| `contentrain_media_update` | Update asset metadata (alt, tags, filename) | — | — |
| `contentrain_media_delete` | Delete an asset from the media stack | — | **Yes** |

The five `contentrain_media_*` tools are a deterministic passthrough to the provider's optional media facet (`RepoProvider.media`) and are registered **only when the provider exposes one** (e.g. Studio MCP Cloud). Local stdio servers and plain GitHub/GitLab providers never list them. Ingest is URL-based (MCP has no binary channel); the provider implementation owns SSRF/MIME/size policy for the fetch.

## Quick Start

Expand Down Expand Up @@ -257,7 +264,7 @@ These are intended for Contentrain tooling and advanced integrations, not for di
Key design decisions in this package:

- local-first **by default** — stdio transport + LocalProvider works without any network dependency
- provider-agnostic engine — the same 19 tools run over LocalProvider, GitHubProvider, or GitLabProvider behind a single `RepoProvider` contract
- provider-agnostic engine — the same core tools run over LocalProvider, GitHubProvider, or GitLabProvider behind a single `RepoProvider` contract; media tools ride the provider's optional media facet
- remote provider SDKs (`@octokit/rest`, `@gitbeaker/rest`) are optional peer dependencies — pulled in only when their provider is used
- JSON-only content storage
- git-backed write workflow (worktree transaction locally, single atomic commit over the Git Data / REST APIs remotely)
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.9.0",
"mcpName": "io.github.Contentrain/contentrain",
"license": "MIT",
"description": "Local-first MCP server for AI-generated content governance — 19 deterministic tools, stdio + HTTP transports, Local / GitHub / GitLab providers",
"description": "Local-first MCP server for AI-generated content governance — 24 deterministic tools (19 core + 5 media), stdio + HTTP transports, Local / GitHub / GitLab providers",
"type": "module",
"repository": {
"type": "git",
Expand Down
Loading
Loading