payloadcms/payload · error · APIError

Missing request URL

Error message

Missing request URL

What it means

The mcpEndpoint handler requires req.url because it parses query parameters (overrideAccess). If req.url is falsy it throws APIError 400. This normally only happens for synthetic/programmatic requests, not real HTTP requests which always carry a URL.

Source

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

import type { PayloadHandler, PayloadRequest } from 'payload'

import {
  createMcpHandler,
  isLegacyRequest,
  WebStandardStreamableHTTPServerTransport,
} 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)
  }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Ensure req.url is set (e.g. 'http://localhost/api/mcp') before invoking the handler.
  2. In tests, build the request through Payload's normal HTTP path or a complete mock.
  3. If writing a custom adapter, populate url from the incoming request line.
Defensive patterns

Strategy: validation

Validate before calling

if (!req.url) {
  // in tests/adapters, set a URL before invoking the handler
  req.url = 'http://localhost/api/mcp'
}

Type guard

const hasUrl = (req: PayloadRequest): boolean => typeof req.url === 'string' && req.url.length > 0

Prevention

When it happens

Trigger: Invoking the handler directly in tests without setting req.url; a request adapter that strips the url; a job/programmatic context constructing a PayloadRequest manually.

Common situations: Unit tests calling mcpEndpoint(req) with a minimal mock; a custom server adapter that fails to populate url; integration harness building requests by hand.

Related errors


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