HTTP Transport
The MCP server ships two transports. The default — stdio — is for IDE integration. The HTTP transport serves tool calls at POST /mcp so agents running on a different machine can drive Contentrain operations against a project.
Typical drivers:
- Contentrain Studio — hosts an agent that talks to MCP over HTTP, backed by a GitHubProvider or GitLabProvider pointed at a team's content repo.
- 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 for the capability matrix.
Starting the HTTP server
The simplest path is the CLI:
contentrain serve --mcpHttp --authToken $(openssl rand -hex 32)This binds to localhost:3333 by default, uses the current working directory as the project root, and wraps it in a LocalProvider. Flags:
--port <n>(CONTENTRAIN_PORT) — listen port--host <bind>(CONTENTRAIN_HOST) — bind address. Defaultlocalhost; set to0.0.0.0to accept remote connections--authToken <token>(CONTENTRAIN_AUTH_TOKEN) — Bearer token required for every request--root <path>(CONTENTRAIN_PROJECT_ROOT) — project root when not the cwd
MCP tool calls land at POST <host>:<port>/mcp. Any other path returns 404.
Authentication
When --authToken is set (or CONTENTRAIN_AUTH_TOKEN is exported), every request must carry Authorization: Bearer <token>. Missing or mismatched tokens get 401 Unauthorized before the MCP session initialises.
curl -X POST http://localhost:3333/mcp \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"contentrain_describe_format","arguments":{}}}'Auth is optional in dev — omit --authToken when binding to localhost. Production deployments should always set one.
Programmatic embedding
CLI-wrapped HTTP always uses LocalProvider. To run HTTP against a remote provider (GitHub, GitLab) embed the server programmatically:
import { createGitHubProvider } from '@contentrain/mcp/providers/github'
import { startHttpMcpServerWith } from '@contentrain/mcp/server/http'
const provider = await createGitHubProvider({
auth: { type: 'pat', token: process.env.GITHUB_TOKEN! },
repo: { owner: 'acme', name: 'site' },
})
const handle = await startHttpMcpServerWith({
provider,
port: 3333,
host: '0.0.0.0',
authToken: process.env.MCP_BEARER_TOKEN,
})
// handle.url contains the fully-qualified URL, e.g. http://0.0.0.0:3333/mcp
// handle.close() stops the serverThe same pattern works for createGitLabProvider with a GitLabProvider. Both require their respective optional peers (@octokit/rest, @gitbeaker/rest).
Deployment patterns
Studio MCP Cloud
Studio MCP Cloud is the hosted version of the HTTP transport for connected Studio projects. It exposes:
https://studio.contentrain.io/api/mcp/v1/{projectId}/mcpAuthentication uses a project-scoped MCP Cloud API key:
Authorization: Bearer <mcp-cloud-key>Studio handles the gates around that endpoint: project matching, plan access, per-key rate limits, optional tool allowlists, monthly call quotas, usage metering, and branch reconciliation. External clients such as OpenAI Codex, Claude Desktop, Claude Code, Cursor, and custom MCP drivers connect to the same Streamable HTTP shape as a self-hosted contentrain serve --mcpHttp server.
Studio (hosted agent)
Studio's agent builds a GitHubProvider or GitLabProvider per tenant, points it at the tenant's content repo, and talks to an embedded MCP server over HTTP+LocalProvider-style wiring but with a remote provider. Each session is ephemeral.
CI
A GitHub Actions job can:
- Check out the repository
pnpm install- Start
contentrain serve --mcpHttp --authToken $CI_TOKEN & - Drive it with an MCP client (Claude, Cursor-headless, or a custom JSON-RPC client)
- Let
contentrain_submitpush the review branch
Because contentrain serve --mcpHttp uses LocalProvider, every tool — including normalize and submit — is available.
Remote agent
An agent running on a laptop can drive a Contentrain project that lives on a server by connecting to the server's HTTP MCP endpoint (over a VPN or behind a reverse proxy with TLS + Bearer auth). The agent sees the full tool surface; capability gates still apply based on the backing provider.
Capability gates over HTTP
Not every tool works on every provider. A tool driven by an HTTP client against a remote provider returns a structured capability error when the required capability is missing:
{
"error": "contentrain_scan requires local filesystem access.",
"capability_required": "astScan",
"hint": "This tool is unavailable when MCP is driven by a remote provider. Use a LocalProvider or the stdio transport."
}Agent drivers should treat capability_required as a retry signal — prompt the user to switch transports, or fall back to a local-checkout session for that specific tool.
Security notes
- Never expose HTTP MCP without
--authTokenon a non-localhostbind. - Rotate tokens regularly; MCP does not support ACLs at the tool level, so a token is full project access.
- When Studio connects, the token is managed per workspace — see the Studio docs for the rotation workflow.
- All writes create feature branches from
contentrain; the singleton source-of-truth branch is protected from direct pushes in team configurations.
Next steps
- Providers & Transports — deeper reference for each backend.
- MCP package docs — tool catalogue and response shapes.
- Contentrain Studio — the hosted surface that drives HTTP MCP.