payloadcms/payload · error · APIError
MCP overrideAccess is only available in development.
Error message
MCP overrideAccess is only available in development.
What it means
The overrideAccess query parameter bypasses Payload and MCP item access checks, so it is gated to development. If the param is present (any value) and NODE_ENV !== 'development', mcpEndpoint throws APIError 400. This is a deliberate security guard against bypassing auth outside dev.
Source
Thrown at packages/plugin-mcp/src/endpoint/index.ts:25
} from '@modelcontextprotocol/server'
import { APIError } from 'payload'
import { buildMcpServer } from '../mcp/buildMcpServer.js'
import { getPluginConfig } from '../utils/getPluginConfig.js'
import { getAuthorizedMCP } from './access.js'
export const mcpEndpoint: PayloadHandler = async (req) => {
if (!req.url) {
throw new APIError('Missing request URL', 400)
}
req.payloadAPI = 'MCP' as const
const pluginConfig = getPluginConfig({ config: req.payload.config })
const overrideAccessParam = new URL(req.url).searchParams.get('overrideAccess')
if (overrideAccessParam !== null && process.env.NODE_ENV !== 'development') {
throw new APIError('MCP overrideAccess is only available in development.', 400)
}
let overrideAccess = false
if (overrideAccessParam === 'true') {
overrideAccess = true
} else if (overrideAccessParam !== null && overrideAccessParam !== 'false') {
throw new APIError('MCP overrideAccess must be "true" or "false".', 400)
}
const authorizedMCP = await getAuthorizedMCP({ overrideAccess, req })
// Payload augments the original web-standard Request in place.
const mcpRequest = req as PayloadRequest & Request
// Keep the old JSON-only, stateless behavior because the SDK's 2025 fallback uses SSE.
if (await isLegacyRequest(mcpRequest)) {
const server = buildMcpServer({ authorizedMCP, pluginConfig, req })
const transport = new WebStandardStreamableHTTPServerTransport({
enableJsonResponse: true,View on GitHub (pinned to 00c58b35c0)
Solutions
- Remove the overrideAccess query param in any non-development environment.
- Set NODE_ENV=development only on local/dev machines when you need the bypass.
- Audit MCP client URLs to ensure the param isn't hardcoded.
Example fix
// before (prod) GET /api/mcp?overrideAccess=true // after (prod) GET /api/mcp
Defensive patterns
Strategy: validation
Validate before calling
const url = new URL(req.url)
if (url.searchParams.has('overrideAccess') && process.env.NODE_ENV !== 'development') {
url.searchParams.delete('overrideAccess') // never bypass access outside dev
} Prevention
- Never include overrideAccess in client URLs destined for non-dev environments.
- Keep NODE_ENV=development only on local/dev machines.
- Audit MCP client configs for stray dev query params.
When it happens
Trigger: Hitting the MCP endpoint with ?overrideAccess=true (or any value) in production, staging, or any non-development NODE_ENV.
Common situations: A dev URL with the param copied into a production client; NODE_ENV not set to 'development' locally; CI/staging inheriting a dev query string.
Related errors
- Unauthorized, you must be logged in to make this request.
- Stripe secret key is required
- Stripe secret key is required.
- Missing request URL
- MCP overrideAccess must be "true" or "false".
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/33567ec540aadc63.
Report an issue: GitHub.