Skip to content

TypeScript MCP server: --api-key flag defaults to empty string, breaking env var fallback #2028

Description

@alohaninja

Bug

When generating a TypeScript MCP server (enableMCPServer: true), the generated CLI code in impl.ts defaults the --api-key flag to "" (empty string) instead of undefined. This prevents the env var fallback from ever being reached.

Generated code (impl.ts)

// startStdio() and startSSE() both have:
const server = createMCPServer({
  ...
  ...{ apiKey: flags["api-key"] ?? "" },
  ...
});

When --api-key is not passed on the CLI, flags["api-key"] is undefined, so undefined ?? "" yields "".

Security resolution (security.ts)

export function resolveGlobalSecurity(security) {
  return resolveSecurity([{
    fieldName: "Authorization",
    type: "apiKey:header",
    value: security?.apiKey ?? env().LAUNCHDARKLY_API_KEY,
  }]);
}

Since "" is not null or undefined, the nullish coalescing operator (??) treats it as a valid value and never falls through to the LAUNCHDARKLY_API_KEY env var. The Authorization header is sent as an empty string, producing 401 errors.

Impact

Any MCP client that sets environment variables on the spawned process (Claude Code, VS Code, Cursor, etc.) instead of passing --api-key as a CLI flag gets silent auth failures. This is the default integration pattern for many MCP hosts — users set LAUNCHDARKLY_API_KEY in their shell environment and expect the SDK to pick it up.

This is particularly confusing because:

  • The env.ts module correctly defines the LAUNCHDARKLY_API_KEY env var
  • The security.ts module has correct fallback logic with ??
  • The bug is solely in the CLI flag defaulting to "" instead of undefined

Fix

In the TypeScript MCP server template, change:

// From:
...{ apiKey: flags["api-key"] ?? "" },

// To:
...{ apiKey: flags["api-key"] ?? undefined },

This appears in both startStdio() and startSSE() in the generated impl.ts.

Speakeasy versions

  • CLI: 1.736.1
  • Generation engine: 2.845.15
  • mcpServer feature: 0.9.4
  • envVarSecurityUsage feature: 0.1.2
  • Target: TypeScript

Downstream report

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions