farion1231/cc-switch · warning · Error
stdio 类型的 MCP 服务器必须包含 command 字段
Error message
stdio 类型的 MCP 服务器必须包含 command 字段
What it means
A server entry with no type defaults to 'stdio', and stdio servers must carry a string command ('stdio MCP server must include command field'). The classic trigger is a remote server config pasted without type = "http"/"sse": its url makes the direct-config branch fire, the type defaults to stdio, and command is absent.
Source
Thrown at src/utils/tomlUtils.ts:113
};
/**
* 规范化服务器配置对象为 McpServer 格式
* 保留所有字段(包括扩展字段如 timeout_ms)
*/
function normalizeServerConfig(config: any): McpServerSpec {
if (!config || typeof config !== "object") {
throw new Error("服务器配置必须是对象");
}
const type = (config.type as string) || "stdio";
// 已知字段列表(用于后续排除)
const knownFields = new Set<string>();
if (type === "stdio") {
if (!config.command || typeof config.command !== "string") {
throw new Error("stdio 类型的 MCP 服务器必须包含 command 字段");
}
const server: McpServerSpec = {
type: "stdio",
command: config.command,
};
knownFields.add("type");
knownFields.add("command");
// 可选字段
if (config.args && Array.isArray(config.args)) {
server.args = config.args.map((arg: any) => String(arg));
knownFields.add("args");
}
if (config.env && typeof config.env === "object") {
const env: Record<string, string> = {};
for (const [k, v] of Object.entries(config.env)) {
env[k] = String(v);View on GitHub (pinned to a2e22f3302)
Solutions
- For remote servers add type = "http" (or "sse") so the url branch is taken
- For local servers add a string command, e.g. command = "npx"
- Ensure command is a quoted string, not a bare TOML value
Example fix
# before (throws: defaults to stdio, no command) url = "https://mcp.example.com/sse" # after type = "sse" url = "https://mcp.example.com/sse"
Defensive patterns
Strategy: validation
Validate before calling
function inferServerType(entry: Record<string, unknown>): "stdio" | "http" | "sse" | null {
const type = typeof entry.type === "string" ? entry.type : "stdio";
if (type === "stdio") {
return typeof entry.command === "string" && entry.command ? "stdio" : null;
}
if (type === "http" || type === "sse") {
return typeof entry.url === "string" && entry.url ? type : null;
}
return null;
}
const type = inferServerType(entry);
if (!type) {
setImportError("Remote servers need type + url; local servers need command");
} Type guard
function isStdioEntry(e: Record<string, unknown>): e is { type: "stdio"; command: string } {
const type = typeof e.type === "string" ? e.type : "stdio";
return type === "stdio" && typeof e.command === "string" && e.command.length > 0;
} Try / catch
try {
const server = tomlToMcpServer(tomlText);
} catch (e) {
if (e instanceof Error && e.message.includes("必须包含 command 字段")) {
setImportError("Local stdio servers need a command; remote servers need type = \"http\"/\"sse\" plus url");
} else {
throw e;
}
} Prevention
- Always set type explicitly when the server is remote
- Remember type defaults to stdio when omitted
- Quote command values as strings
When it happens
Trigger: Entry with url but no type line; entry with only args/env fields; command set to a non-string TOML value (e.g. a bare number).
Common situations: Copying a remote server snippet that omits the type line; accidentally deleting or renaming the command key.
Related errors
- TOML 内容不能为空
- ${type} 类型的 MCP 服务器必须包含 url 字段
- 不支持的 MCP 服务器类型: ${type}
- 无法识别的 TOML 格式。请提供单个 MCP 服务器配置,或使用 [mcp_servers.<id>] 格式
- 服务器配置必须是对象
AI-assisted analysis of farion1231/cc-switch@a2e22f3302 (2026-08-16).
Data as JSON: /api/errors/ae6b52a0e15a1a55.
Report an issue: GitHub.