Search by

nobrainer / silverstripe-mcp

Nobrainer

MCP (Model Context Protocol) server for SilverStripe CMS - lets AI assistants interact with the CMS over Streamable HTTP

Package info

bitbucket.org/nobrainerweb/silverstripe-mcp

Type:silverstripe-vendormodule

pkg:composer/nobrainer/silverstripe-mcp

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

v0.9 2026-09-16 14:32 UTC

This package is auto-updated.

Last update: 2026-09-16 15:28:34 UTC


README

An MCP (Model Context Protocol) server for SilverStripe CMS 6. Lets AI assistants like Claude read and manage pages, query the ORM, inspect the database schema and run dev/build — all gated by SilverStripe's normal permission system.

The server implements the MCP Streamable HTTP transport: clients POST JSON-RPC messages to /mcp and receive JSON responses. The server is stateless, which fits PHP's request/response model. (The older, deprecated HTTP+SSE transport requires a persistent server-push channel and is not supported under PHP-FPM.)

Installation

composer require nobrainer/silverstripe-mcp
vendor/bin/sake db:build --flush

dev/build creates an MCP Access group holding the MCP_ACCESS permission, and the three OAuth database tables (MCPOAuthClient, MCPOAuthCode, MCPOAuthToken).

Configuration

Create (or pick) a member that the AI should act as, add it to the MCP Access group, and give it whatever CMS permissions it should have (e.g. content author). Every operation respects that member's canView() / canEdit() / canPublish() / canDelete().

Connecting a client

Claude Desktop (OAuth — recommended)

Claude Desktop supports OAuth autodiscovery. Add the server URL in the Claude Desktop settings and it will handle authentication automatically:

  1. Open Claude Desktop → Settings → MCP Servers → Add Server
  2. Enter the URL: https://your-site.com/mcp
  3. Claude Desktop discovers OAuth endpoints via /.well-known/oauth-authorization-server
  4. Your browser opens and you log in with your SilverStripe credentials
  5. Claude Desktop receives a Bearer token (valid 90 days) and connects

The member you log in as must be in the MCP Access group.

OAuth token lifetime is configurable (default 90 days):

Nobrainer\MCP\OAuth\OAuthController:
  token_lifetime: 7776000  # seconds

Claude Code (API key)

claude mcp add --transport http silverstripe https://your-site.com/mcp \
  --header "Authorization: Bearer your-api-key"

API key via environment

Set in .env on the server:

MCP_API_KEY="some-long-random-string"
MCP_MEMBER_EMAIL="mcp@example.com"

API key via YAML (multiple keys / members)

Nobrainer\MCP\Auth\MCPAuthenticator:
  api_keys:
    'some-long-random-string': 'mcp@example.com'
    'another-key': 'editor@example.com'

HTTP Basic auth

Pass a member's email and password as HTTP Basic credentials. Disable if not needed:

Nobrainer\MCP\Auth\MCPAuthenticator:
  allow_basic_auth: false

OAuth endpoints

URLPurpose
/.well-known/oauth-authorization-serverAutodiscovery metadata (RFC 8414)
POST /mcp/oauth/registerDynamic client registration (RFC 7591)
GET /mcp/oauth/authorizeAuthorization endpoint — redirects to SS login
POST /mcp/oauth/tokenToken endpoint — authorization code → Bearer token

These are consumed by MCP clients automatically; you do not call them directly.

Tools

ToolDescription
page_listList pages (draft or live) with publication status
page_getAll fields of a page, including Content
page_createCreate a page as draft
page_updateUpdate draft fields
page_publish / page_unpublishPublication workflow
page_deleteArchive a page (draft + live)
dataobject_classesList available DataObject classes
dataobject_queryFilter/sort/paginate any DataObject list
dataobject_get / dataobject_create / dataobject_update / dataobject_deleteGeneric ORM CRUD
dataobject_publishPublish/unpublish versioned DataObjects
dev_buildRun dev/build (requires ADMIN or CAN_DEV_BUILD)
flushFlush manifests and caches (requires ADMIN)

Resources

URIContent
silverstripe://schemaOverview of all DataObject classes
silverstripe://schema/{class}Fields and relations for one class (use . instead of \ in the FQCN)

Security notes

  • Every request must authenticate and the member must hold the MCP_ACCESS permission.
  • All reads and writes go through the ORM and respect record-level can*() checks; drafts and live stages are handled explicitly (writes always target draft).
  • Sensitive member fields (password hashes, login tokens, …) are stripped from output and rejected on write — see RecordSerializer.blocked_fields.
  • Password/session storage classes are hidden entirely — see DataObjectTool.excluded_classes.
  • OAuth authorization codes are single-use and expire after 5 minutes.
  • OAuth Bearer tokens are stored as SHA-256 hashes in the database.
  • Browser-origin requests are rejected unless the origin is whitelisted in MCPController.allowed_origins (DNS-rebinding protection).
  • Always serve the endpoint over HTTPS.

License

BSD-3-Clause