mastra-ai/mastra · error · MastraError

MCP_SERVER_MODERN_HTTP_OPTIONS_INCOMPATIBLE

MCP_SERVER_MODERN_HTTP_OPTIONS_INCOMPATIBLE

Error message

startHTTP options ${names.map(name => `"${name}"`).join(', ')} are incompatible with protocolVersion "2026-07-28"

What it means

`startHTTP` with protocolVersion "2026-07-28" runs in the modern serverless-capable HTTP era, so legacy options that opt out of that behavior are rejected. `assertModernEraHTTPOptions` collects options such as `serverless: false` or `serverlessStreaming: false` and throws this MastraError (USER category) listing the incompatible names.

Source

Thrown at packages/mcp/src/server/server.ts:583

  private servesModernEra(): boolean {
    return this.protocolVersion === '2026-07-28';
  }

  private assertModernEraHTTPOptions(options?: MCPServerStreamableHTTPOptions): void {
    if (!options) return;

    const incompatibleOptions = new Set(
      Object.keys(options).filter(option => !ACCEPTED_MODERN_ERA_HTTP_OPTION_KEYS.has(option)),
    );

    if (options.sessionIdGenerator !== undefined) incompatibleOptions.add('sessionIdGenerator');
    if (options.serverless === false) incompatibleOptions.add('serverless');
    if (options.serverlessStreaming === false) incompatibleOptions.add('serverlessStreaming');

    if (incompatibleOptions.size === 0) return;

    const names = [...incompatibleOptions].sort();
    throw new MastraError({
      id: 'MCP_SERVER_MODERN_HTTP_OPTIONS_INCOMPATIBLE',
      domain: ErrorDomain.MCP,
      category: ErrorCategory.USER,
      text: `startHTTP options ${names.map(name => `"${name}"`).join(', ')} are incompatible with protocolVersion "2026-07-28"`,
      details: { incompatibleOptions: names.join(', ') },
    });
  }

  private validateHTTPRequestHeaders(
    req: http.IncomingMessage,
    res: http.ServerResponse<http.IncomingMessage>,
    options?: MCPServerStreamableHTTPOptions,
  ): boolean {
    if (!options?.enableDnsRebindingProtection) return true;

    if (options.allowedHosts?.length) {
      const allowedHostnames = options.allowedHosts.map(host => new URL(`http://${host}`).hostname);
      if (!hostHeaderValidation(allowedHostnames)(req, res)) return false;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Remove the `serverless: false` / `serverlessStreaming: false` options from the startHTTP call; modern-era defaults apply.
  2. If you truly need the legacy behavior, keep the older protocolVersion instead of "2026-07-28".
  3. Read `details.incompatibleOptions` in the thrown MastraError to see exactly which options to drop.

Example fix

// before
await server.startHTTP({ protocolVersion: '2026-07-28', serverless: false });
// after
await server.startHTTP({ protocolVersion: '2026-07-28' });
Defensive patterns

Strategy: validation

Validate before calling

if (opts.protocolVersion === '2026-07-28' && (opts.serverless === false || opts.serverlessStreaming === false)) throw new Error('Legacy serverless:false options are incompatible with protocolVersion 2026-07-28');

Try / catch

try { await server.startHTTP(opts); } catch (e) { if (e?.id === 'MCP_SERVER_MODERN_HTTP_OPTIONS_INCOMPATIBLE') { const { incompatibleOptions } = e.details; for (const name of incompatibleOptions.split(', ')) delete opts[name.trim()]; await server.startHTTP(opts); } else throw e; }

Prevention

When it happens

Trigger: Calling `server.startHTTP({ protocolVersion: '2026-07-28', serverless: false })` (or `serverlessStreaming: false`, or other legacy HTTP options collected into `incompatibleOptions`) — any explicitly-`false` legacy flag combined with the modern protocol version.

Common situations: Upgrading an existing server to the 2026-07-28 protocol version while keeping old `serverless: false` config copied from pre-modern-era examples or migration guides.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/350c44c8b3953ddb. Report an issue: GitHub.