Merge PR #3182: fix(mcp): normalize OpenCode MCP command arrays (@roboomp)

This commit is contained in:
can1357
2026-06-21 16:28:19 +02:00
3 changed files with 147 additions and 4 deletions
@@ -91,15 +91,55 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
/** OpenCode MCP server config (from opencode.json "mcp" key) */
interface OpenCodeMCPConfig {
type?: "local" | "remote";
command?: string;
command?: string | string[];
args?: string[];
env?: Record<string, string>;
environment?: Record<string, string>;
url?: string;
headers?: Record<string, string>;
enabled?: boolean;
timeout?: number;
}
function stringArray(value: unknown): string[] | undefined {
if (!Array.isArray(value)) return undefined;
for (const item of value) {
if (typeof item !== "string") return undefined;
}
return value;
}
function stringRecord(value: unknown): Record<string, string> | undefined {
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
const record: Record<string, string> = {};
for (const [key, item] of Object.entries(value)) {
if (typeof item !== "string") return undefined;
record[key] = item;
}
return record;
}
function normalizeCommand(
commandValue: string | string[] | undefined,
argsValue: unknown,
): { command: string | undefined; args: string[] | undefined } {
const configuredArgs = stringArray(argsValue);
if (Array.isArray(commandValue)) {
const [command, ...commandArgs] = commandValue;
const args = configuredArgs ? [...commandArgs, ...configuredArgs] : commandArgs;
return {
command: typeof command === "string" ? command : undefined,
args: args.length > 0 ? args : undefined,
};
}
return {
command: typeof commandValue === "string" ? commandValue : undefined,
args: configuredArgs && configuredArgs.length > 0 ? configuredArgs : undefined,
};
}
async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>> {
const items: MCPServer[] = [];
const warnings: string[] = [];
@@ -161,11 +201,14 @@ function extractMCPServers(
transport = "stdio";
}
const command = normalizeCommand(serverConfig.command, serverConfig.args);
const env = stringRecord(serverConfig.environment) ?? stringRecord(serverConfig.env);
items.push({
name,
command: serverConfig.command,
args: Array.isArray(serverConfig.args) ? (serverConfig.args as string[]) : undefined,
env: serverConfig.env && typeof serverConfig.env === "object" ? serverConfig.env : undefined,
command: command.command,
args: command.args,
env,
url: typeof serverConfig.url === "string" ? serverConfig.url : undefined,
headers: serverConfig.headers && typeof serverConfig.headers === "object" ? serverConfig.headers : undefined,
enabled: serverConfig.enabled,