Scoped Admin tokens, least-privilege access, HTTPS, token rotation, and practical audit logging strengthen MCP server security in Strapi.
A Model Context Protocol (MCP) server hands an AI agent real write access to your content: the ability to create, update, delete, and publish entries without a human clicking anything. MCP server security therefore centers on a practical question a security lead will eventually ask you: if this agent goes off the rails, or its token leaks, what exactly can it touch?
The Strapi MCP server runs in Strapi, an open-source headless CMS. Its permission model lets you scope tokens down to the minimum an agent needs, while token handling and network hardening protect the token and the path in front of it.
In brief:
- The Strapi MCP server (5.47.0+) authenticates every request with an Admin token and scopes it to exactly that token's permissions, with no session state to exploit.
- Four enforcement layers (tool visibility, field filtering, locale filtering, and runtime checks) mean a properly scoped token never even exposes tools the agent shouldn't use.
- Issue one dedicated Admin token per AI client, store it in a secrets manager, and serve the
/mcpendpoint over HTTPS behind a reverse proxy. - Because the server is stateless, revoking or re-scoping a token takes effect on the next request, and Audit Logs tag agent actions with
origin: mcp.
Together, these controls limit what an agent can access and make compromised tokens easier to contain.
How Strapi's MCP Server Handles Security
The Strapi MCP server, available from Strapi 5.47.0, authenticates every request with an Admin token and scopes each request to exactly that token's permission boundaries. There are no sessions. Per the official docs: "Each POST request to the /mcp endpoint creates a fresh, ephemeral MCP server instance scoped to the authenticated token's permissions. There is no session persistence between requests: every request is independently authenticated and authorized."
That statelessness matters for security. There's no session ID to hijack, no cached authorization state to go stale, and no lingering access after you change a token's permissions. The server enforces the same permission model as the Strapi Admin Panel, so an AI agent gets exactly what a human with that permission set would get, and nothing more.
The tokens themselves have guardrails too. Admin tokens are designed "for automation workflows such as MCP agents, CI/CD pipelines, and scripts," and each one is "strictly bounded to that owner's permission ceiling" and "automatically re-clamped when the owner's roles change or revoked the moment the owner is deactivated," per the MCP server GA announcement.
The Risks of an Unsecured MCP Server
- Over-permissioned tokens. An Admin token with full
create,update,delete, andpublishrights gives the connected AI client, and any attacker who compromises it, full authority over all CMS content within that token's permission boundaries. The MCP security guidance identifies two costs of broad scopes: an "expanded blast radius" where a "stolen broad token enables unrelated tool/resource access" and "higher friction on revocation" because killing a max-privilege token disrupts every workflow at once. - Leaked credentials and exposed endpoints. This isn't hypothetical. Trend Micro research found 492 MCP servers "running without any client authentication or traffic encryption." Local configuration files that store MCP tokens also create a risk of plaintext token exposure.
- Agents acting beyond their intended scope. Prompt injection sits at the top of the OWASP LLM risk list (LLM01:2025), and injected content can redirect an agent with
writeorpublishrights into creating or publishing entries nobody approved. Invariant Labs demonstrated a malicious GitHub issue causing an AI assistant, asked only to "check open issues," to access private repositories and leak data through an autonomous PR. Agents can also fail without any attacker involved, which makes destructive permissions risky even in otherwise trusted workflows.
Token scope is what limits the fallout from both model failures and prompt injection: the tighter the scope, the less a mistaken or hijacked agent can reach.
Understand the Permission Model Before You Configure It
The MCP server's four permission enforcement layers reduce the tools and content visible to the agent.
Tool Visibility
When an AI client connects, Strapi checks the Admin token's permissions and only exposes the tools that token grants. From the docs: "If the token does not grant delete on Article, the AI client will not see a delete tool for articles at all." The agent can't be prompt-injected into calling a tool it doesn't know exists.
The mapping for Collection Types is direct:
| Tool | Permission required |
|---|---|
list, get | read |
create | create |
update | update |
delete | delete |
publish, unpublish, discard_draft | publish |
Single Types generate up to six tools with no list, and create/update merge into a single write tool.
Field and Locale Filtering
Layers two and three narrow what flows through the tools that are exposed. Input and output schemas shrink to the fields the token can access: "If the token grants read on Article but excludes the body field, the AI client will not see or receive body content," per the permission boundaries documentation. Write schemas only include fields permitted for that specific action. Restricted data never reaches the agent's context window, which also means it can never leak from there.
Locale filtering works the same way when Internationalization (i18n) is installed. A token might allow reading content in en and fr but only creating content in en, and the locale parameter narrows per action accordingly.
Runtime Enforcement
Schema narrowing alone would leave a gap: what about rules that depend on which document is being touched? The fourth layer closes it. Each handler calls Strapi's permission checker at request time to perform document access checks on the specific document being read, written, or published. Condition-based permissions, such as "only update entries you own," are enforced here. And because the architecture is stateless, these checks run from scratch on every POST, with no cached authorization from a previous call.
Token Scoping and Least Privilege
Strapi's docs recommend: "Create dedicated Admin tokens for each AI client or use case. Use the most restrictive permissions that still allow the AI to accomplish its task." You create these under Admin Token settings, and the four enforcement layers do the rest.
The MCP server authenticates exclusively via Admin tokens. Content API tokens work on separate routes, and each token type is rejected on the other's routes.
Create a Separate Admin Token per AI Client
One token per client (or per use case) limits the blast radius of any single compromise and makes revocation surgical. If your Cursor integration leaks its token, you revoke that one token, and your Claude Desktop workflow keeps running untouched.
Creating one takes four steps in the Admin Tokens interface:
- Click Create new Admin Token.
- Fill in a descriptive per-client Name, an optional Description, and a Token duration (7 days, 30 days, 90 days, or Unlimited).
- Use the permission category tabs to allow or deny individual permissions.
- Click Save, then copy the token immediately. The plaintext token is shown only once.
Prefer a finite duration over Unlimited where the workflow allows it; short-lived tokens shrink the window a leaked token stays useful. Note also that permissions the token creator doesn't hold appear disabled and can't be selected, so the token can never exceed its owner's ceiling.
Scope by Content-Type, Field, and Locale
Selecting a Content-Type in the permissions table permits all actions for all fields until you change the settings. Strapi's RBAC system lets you cut that down precisely:
- In the Collection Types or Single Types category, tick the Content-Types the agent actually needs.
- Untick the action boxes (
create,read,update,delete,publish) the agent doesn't need. - Click the Content-Type name to expand its field list, and untick fields you want excluded from read or write schemas.
- If i18n is installed, set permissions per locale at this step.
- Repeat per Content-Type and save.
A concrete example: an agent that drafts blog articles needs create and update on Article, probably read on Category, and nothing on User, Settings, or your pricing Content-Types. It almost certainly doesn't need publish; keeping that human-gated provides a confirmation step before state changes.
Use Read-Only and Condition-Based Tokens
For retrieval-only agents (such as a support bot answering questions from your docs), issue a token with read permission only. The tool visibility layer then exposes nothing but listing and reading tools, so there is no write path to abuse.
For agents that do need write access, condition-based permissions add an ownership boundary. Each permission in the RBAC UI has a Settings button with two built-in conditions: the administrator must be the creator, or must have the same role as the creator. A token carrying the "must be the creator" condition can only update entries its own automation created, which is enforced per-document at runtime. Conditions applied to the token owner's role show as read-only in the token panel and apply automatically.
Secure Authentication, Transport, and Token Lifecycle
MCP requests are blocked by default. Once MCP is active, an Admin token authenticates the endpoint. Configure MCP in config/server.js, or use the TypeScript server configuration in config/server.ts.
Whoever holds the Admin token holds the access because the endpoint has no OAuth dance, refresh flow, or second factor. That puts all the weight on two practices.
Pass the Token in the Authorization Header
The MCP server uses the Streamable HTTP transport, and any MCP-compatible client connects by pointing at the /mcp endpoint with a Bearer token in the Authorization header, per the client connection docs. Cursor's .cursor/mcp.json shows the shape:
// .cursor/mcp.json
{
"mcpServers": {
"strapi-mcp": {
"type": "streamable-http",
"url": "http://localhost:1337/mcp",
"headers": {
"Authorization": "Bearer YOUR_ADMIN_TOKEN"
}
}
}
}Claude Code takes the same header on the command line:
claude mcp add strapi-mcp --transport http http://localhost:1337/mcp -H "Authorization: Bearer YOUR_ADMIN_TOKEN"Both examples place the token in a configuration file on a developer's machine.
Store Tokens as Secrets, Never in Committed Config
Strapi's guidance is blunt: "Never expose Admin tokens in client-side code. Store them in a secrets manager or environment variable." Storage requirements differ between local and deployed environments:
- Development: keep the token in a
.envfile, listed in.gitignore. Strapi's environment configuration already works this way forAPP_KEYS,ADMIN_JWT_SECRET, and the other generated secrets, and the sameenv()utility reads your values in config files. - Docker and production: add
.envto.dockerignoreso the token never lands in an image layer, and use a private registry, per Strapi's Docker guidance. For Production deployment, move to a dedicated secrets manager. The OWASP secrets guidance warns that environment variables are "generally accessible to all processes and may be included in logs or system dumps," so a vault (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault) that retrieves tokens at runtime is the stronger option.
This approach keeps local setup practical while reducing token exposure in production.
Files like .cursor/mcp.json deserve the same treatment as .env: fine locally, never committed to a shared repository. Running gitleaks or git-secrets in your pipeline also helps catch the token that slips through anyway.
Network and Transport Hardening
Serve the /mcp endpoint over HTTPS in production. The Strapi FAQ recommends you "terminate TLS in front of Strapi (for example with Nginx, Caddy, Traefik, a load balancer, or your cloud provider)" and forward headers such as X-Forwarded-Proto so Strapi detects the secure connection. When Strapi sits behind that proxy, set proxy.koa to true in your server configuration:
// config/server.js
module.exports = ({ env }) => ({
proxy: {
koa: true,
},
});And never expose a development instance to the public internet. The docs' http://localhost:1337/mcp examples work locally precisely because that environment skips production hardening; binding a dev instance to 0.0.0.0 with no TLS exposes it on all available network interfaces without traffic encryption. The MCP transport guidance says local servers should bind to 127.0.0.1 rather than all interfaces.
Restrict Access to the /mcp Endpoint
The endpoint's stateless architecture accepts only POST requests; GET and DELETE return a 405 Method Not Allowed JSON-RPC error at the application layer. Application-layer method restrictions provide a useful floor and still require network controls. Put /mcp behind the same reverse proxy rules, IP allowlists, and firewall policies you'd apply to any admin surface, and consider allowlisting POST only at the proxy for defense in depth. If no external agent needs the endpoint, it shouldn't be reachable from outside your network at all.
Set Timeouts to Protect Availability
Two advanced options bound how long any single MCP request can tie up server resources:
// config/server.js
module.exports = ({ env }) => ({
mcp: {
connectTimeoutMs: 10000, // default: 5000
requestTimeoutMs: 120000, // default: 60000
},
});connectTimeoutMs caps how long the internal MCP transport waits to connect before aborting, and requestTimeoutMs caps how long a single request may run. The defaults (5 and 60 seconds) are reasonable starting points; raise them only if legitimate agent workloads hit them, since generous timeouts hand a misbehaving or malicious client more room to hold connections open.
Rotation and Revocation
Statelessness pays off most during incident response. Because every POST to /mcp is authenticated from scratch, the docs confirm that "permission changes (such as revoking a token or updating its permissions) take effect on the next request." No server restart, no session teardown, no grace period during which a revoked token still works. Delete a compromised token in the stateless MCP architecture and the next agent request fails.
Deactivating or blocking the token owner's account causes any request with that owner's tokens to be rejected; the tokens survive and resume working if the owner is reactivated. Deleting the owner's account deletes all their Admin tokens permanently, with no recovery path. Removing a permission from a role automatically strips that permission from tokens owned by users of that role.
For scheduled rotation, use the Regenerate button on the token's edit screen (visible only to the token's owner), copy the new token from its one-time display, and update your secrets manager. Rotating on a calendar rather than after an incident is cheap insurance, especially for tokens created with Unlimited duration.
Monitoring and Audit Logging
From Strapi 5.52.0, entry actions performed through the MCP server appear in Audit Logs alongside their Admin Panel equivalents, with one field that makes agent oversight practical: the origin key in the log payload reads mcp for agent-originated actions and admin for human ones. You can answer "what did the AI change last Tuesday?" without guessing.
Some caveats to plan around, per the Audit Logs documentation. The feature is available exclusively on the CMS Enterprise plan and requires the Super Admin role to view. Read-only actions aren't logged, from the MCP server or anywhere else; the trail covers mutations (create, update, delete, publish, unpublish) plus events like logins and role changes. Default retention is 120 days.
Teams on Community or Growth plans have no built-in way to separate an agent's writes from a human editor's, so compensate at the network layer: reverse proxy access logs on /mcp capture who called, what method, and the response code. Application middleware can add Content-Type-level detail if you need it. Whatever the plan, watch for anomalies: an agent that normally writes five drafts a day suddenly issuing hundreds of requests is a signal worth alerting on, and behavioral profiling can help surface that shift quickly.
Your MCP Server Security Checklist
Run your deployment against this list before pointing any agent at production. Everything here maps to controls covered above, grounded in the Strapi MCP server docs:
- Running Strapi 5.47.0+ (5.52.0+ if you need
origin: mcpaudit tagging) - One dedicated Admin token per AI client or use case, named descriptively
- Tokens scoped to the minimum Content-Types, fields, locales, and actions the agent needs
- Read-only tokens for retrieval-only agents;
publishwithheld unless a human gate exists - Condition-based (ownership) permissions applied where write access is granted
- Tokens stored in a secrets manager or environment variables;
.envand MCP client configs excluded from version control and Docker images /mcpserved over HTTPS behind a TLS-terminating proxy, withproxy.koa: trueset- No development instance exposed publicly; local servers bound to
127.0.0.1 connectTimeoutMsandrequestTimeoutMsreviewed against real agent workloads- Rotation schedule in place, with finite token durations preferred over Unlimited
- Audit Logs in use (Enterprise) or reverse proxy logging in place for
/mcpactivity
If each item is covered, you have a defensible baseline for connecting an agent to production content.
Scope Tight, Then Harden the Transport
Least-privilege Admin tokens shrink what an agent can see and do, secure token handling keeps Admin tokens out of repos and images, and HTTPS plus network controls protect the transport those tokens travel over. Strapi's four-layer permission model and stateless architecture do a lot of the enforcement work for you, but only after you've scoped the token correctly; that configuration step is where the real decisions live.
A good next step is an audit of your current setup against the checklist above, starting with the permissions on any Admin token an agent already holds. The Strapi MCP server documentation covers every boundary and option discussed here, and the Admin Tokens and role-based access control docs go deeper on the permission mechanics when you're ready to tighten things further.






