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
Bug
When generating a TypeScript MCP server (
enableMCPServer: true), the generated CLI code inimpl.tsdefaults the--api-keyflag to""(empty string) instead ofundefined. This prevents the env var fallback from ever being reached.Generated code (impl.ts)
When
--api-keyis not passed on the CLI,flags["api-key"]isundefined, soundefined ?? ""yields"".Security resolution (security.ts)
Since
""is notnullorundefined, the nullish coalescing operator (??) treats it as a valid value and never falls through to theLAUNCHDARKLY_API_KEYenv var. TheAuthorizationheader 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-keyas a CLI flag gets silent auth failures. This is the default integration pattern for many MCP hosts — users setLAUNCHDARKLY_API_KEYin their shell environment and expect the SDK to pick it up.This is particularly confusing because:
env.tsmodule correctly defines theLAUNCHDARKLY_API_KEYenv varsecurity.tsmodule has correct fallback logic with??""instead ofundefinedFix
In the TypeScript MCP server template, change:
This appears in both
startStdio()andstartSSE()in the generatedimpl.ts.Speakeasy versions
1.736.12.845.15mcpServerfeature:0.9.4envVarSecurityUsagefeature:0.1.2Downstream report