payloadcms/payload · error · APIError

MCP overrideAccess must be "true" or "false".

Error message

MCP overrideAccess must be "true" or "false".

What it means

When overrideAccess is present in development, mcpEndpoint only accepts the literal strings 'true' or 'false'. Any other value (e.g. '1', 'yes', empty string) throws APIError 400. There is no boolean coercion.

Source

Thrown at packages/plugin-mcp/src/endpoint/index.ts:32

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,
      sessionIdGenerator: undefined, // stateless mode
    })
    transport.onerror = (err) => {
      req.payload.logger.error({ err, msg: 'Error serving legacy MCP request' })
    }

    try {

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Use the literal string 'true' or 'false' for the overrideAccess param.
  2. Omit the param entirely when you want the default (false).
  3. Check the client isn't appending '=1' or an empty value.

Example fix

// before
GET /api/mcp?overrideAccess=1
// after
GET /api/mcp?overrideAccess=true
Defensive patterns

Strategy: validation

Validate before calling

const raw = url.searchParams.get('overrideAccess')
if (raw !== null && raw !== 'true' && raw !== 'false') {
  throw new Error('overrideAccess must be literally "true" or "false"')
}

Type guard

const isValidOverrideAccess = (v: string | null): boolean =>
  v === null || v === 'true' || v === 'false'

Prevention

When it happens

Trigger: Query like ?overrideAccess=1, ?overrideAccess=yes, or ?overrideAccess= (empty) in a development environment.

Common situations: Assuming boolean coercion; typo; URL-encoding mishap producing an empty value; client library stringifying a boolean incorrectly.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/9e332a6078464078. Report an issue: GitHub.