Skip to main content
Glama
metehankasapp

safe-strapi-mcp

Safe Strapi MCP

CI npm license

Run content operations against your own Strapi 5 installation from a local MCP client. The service creates draft copies, applies ordered component changes, and verifies the result and source hash. It does not publish pages.

Install

Requires Node.js 22.5 or newer. SQLite may need native build tools on platforms without prebuilt binaries.

npm install --global safe-strapi-mcp
safe-strapi-mcp --help

You can also run it without a global install using npx safe-strapi-mcp.

Related MCP server: MCP Strapi Server

Configure your project

1. Create a Strapi API token

In Strapi Admin, open Settings → Global settings → API Tokens → Create new API Token. Choose Custom and grant only:

  • find and findOne for every collection the page populates, including related content;

  • find and findOne for Upload/media when the page contains assets;

  • create and update for the collection types whose drafts the MCP may create.

delete and publish permissions are not required. Save the token when Strapi displays it; Strapi does not show the full value again. A token that can list pages but cannot read populated relations or media may fail during inspect_page with HTTP 403.

2. Store it locally

Create a private env file outside version control:

STRAPI_URL=http://localhost:1337
STRAPI_API_TOKEN=

Paste the token after STRAPI_API_TOKEN=. Use the Strapi origin for STRAPI_URL, without /admin or /api. Never commit this file or paste the token into chat. No hosted account or MCP access key is needed for stdio.

Add the local state and env file to the Strapi project's .gitignore:

.env.safe-strapi
.safe-strapi/

3. Connect your MCP client

Configure your MCP client to run:

safe-strapi-mcp --env-file /absolute/path/strapi/.env --project-root /absolute/path/strapi

Codex CLI can register the published package directly:

codex mcp add safe-strapi -- \
  npm exec --yes --package=safe-strapi-mcp -- safe-strapi-mcp \
  --env-file /absolute/path/strapi/.env.safe-strapi \
  --project-root /absolute/path/strapi

Restart Codex, then begin with a read-only request: Use safe-strapi. List projects, find the homepage, and inspect it. Do not create or update anything. Only continue to preview after this succeeds.

Use the absolute executable path if your desktop client does not inherit your shell PATH. The tool loads the env file directly; do not paste secrets into chat. Environment variables already present in the process take precedence over the file.

The source directory must contain src/api and src/components. Collection types with Draft & Publish, a UID field, and dynamic zones are discovered automatically. Each zone is named content-type:zone in list_projects. Single types are not supported by automatic setup.

Optional env variables: STRAPI_CONTENT_TYPE, STRAPI_BLOCKS_FIELD, STRAPI_SLUG_FIELD, STRAPI_ROUTE_FIELD, STRAPI_TITLE_FIELD, STRAPI_LOCALE (defaults to en). Set STRAPI_ROUTE_FIELD=url only when the frontend routes by a separate top-level field that must track cloned slugs. The field must exist in the content-type schema and be string-like; preview reports the change explicitly. Set STRAPI_TOKEN_ENV=MY_EXISTING_TOKEN to read a differently named token variable. Use HTTPS for remote CMS connections.

Only a remote URL and token? Obtain the schema source from the project owner, or pass --config /absolute/path/projects.json with this structure:

{
  "projects": {
    "my-site": {
      "baseUrl": "https://cms.example.com",
      "tokenEnv": "STRAPI_API_TOKEN",
      "collection": "pages",
      "blocksField": "blocks",
      "slugField": "slug",
      "routeField": "url",
      "titleField": "title",
      "schemaRoot": "/absolute/path/strapi",
      "contentType": "page",
      "populate": "*"
    }
  }
}

For custom config, populate must include every nested component, media and relation required for the full document. Embedded componentSchemas (UID to schema object) and contentTypeSchema can replace source files. Automatic local setup generates nested populate queries from discovered schemas. Custom Strapi routes, permissions and plugins still require integration validation.

Use

Ask your client to list projects, inspect the page, preview operations, and create the reviewed draft with its source hash and a stable idempotency key. Then validate and compare it. Source pages remain read-only. Existing drafts must be registered in this installation's ownership database.

Tools: list_projects, find_pages, inspect_page, list_components, get_component_schema, preview_clone_and_modify, clone_page_and_modify, inspect_owned_draft, modify_owned_draft, duplicate_component, replace_component, validate_draft, compare_pages.

Copy-ready workflows for discovery, JSON insertion, component reordering, long pages, team review drafts, and conflict recovery are available in the prompt cookbook. AI clients can read the same guide directly as Markdown or discover key resources through llms.txt.

Indexes are zero-based. Operations run sequentially, so later indexes refer to the current order. Ambiguous selectors must include an occurrence or index. Writes require revision hashes and idempotency keys; retries with a different operation hash are rejected.

If a create response is lost before its document ID can be recorded, the retry fails closed with WRITE_OUTCOME_UNKNOWN; it never submits another create or adopts a page by slug. Inspect the CMS through its API and use a new operation only after resolving the uncertain result. A lost update response is safely reconciled from the recorded intended content without a second PUT.

Concurrent MCP writes sharing the same audit database are serialized. Draft and source hashes are checked immediately before writes and results are fetched and verified afterward. Owned-draft updates send only the configured dynamic-zone field. Strapi REST does not expose an atomic revision precondition, so a writer outside this MCP can still race inside the final GET/PUT interval; preventing that last race requires a Strapi-side conditional-update endpoint.

Local state

The audit database defaults to .safe-strapi/audit.sqlite inside the selected project; set AUDIT_DB to override it. Preserve this database between sessions. Add .safe-strapi/ and env files to your project's gitignore. Protect them with local filesystem permissions.

Each installation uses its own local credentials and state. The package supports stdio only and does not require or accept an MCP access key.

Development checks

npm install
npm run typecheck
npm run build
npm test
npm pack --dry-run

Tests include a 100-component preservation scenario, owned-draft checks, idempotency conflicts, lost-response recovery, cross-instance serialization, and env-file onboarding through the real stdio protocol against mocked Strapi REST. Local acceptance additionally exercises a real Strapi 5 API without using the admin UI. These tests do not certify every Strapi plugin or version.

Independent tooling; not affiliated with or endorsed by Strapi.

Community and security

Bug reports and contributions are welcome on GitHub. Read CONTRIBUTING.md before opening a pull request. Report vulnerabilities privately as described in SECURITY.md.

Released under the MIT License.

Related MCP Connectors

Related MCP Servers