can1357/oh-my-pi · error · Error
Invalid server config: ${errors.join("; ")}
Error message
Invalid server config: ${errors.join("; ")} What it means
addMCPServer() validates the server name and config shape before writing to the MCP config JSON file. This error is thrown when validateServerConfig() returns one or more problems: the config mixes "command" and "url", a stdio server lacks "command", an http/sse server lacks "url", or an unknown "type" was given. All problems are joined with "; " in the message so one throw reports everything wrong.
Source
Thrown at packages/coding-agent/src/mcp/config-writer.ts:120
}
/**
* Add an MCP server to a config file.
* Validates the config before writing.
*
* @throws Error if server name already exists or validation fails
*/
export async function addMCPServer(filePath: string, name: string, config: MCPServerConfig): Promise<void> {
// Validate server name
const nameError = validateServerName(name);
if (nameError) {
throw new Error(nameError);
}
// Validate the config
const errors = validateServerConfig(name, config);
if (errors.length > 0) {
throw new Error(`Invalid server config: ${errors.join("; ")}`);
}
// Serialize the read-modify-write under a per-file lock so a concurrent
// mutation cannot overwrite this one (lost update). The lock also guards
// against cross-process writers sharing the same config file.
await withConfigLock(filePath, async () => {
const existing = await readMCPConfigFile(filePath);
// Check for duplicate name
if (existing.mcpServers?.[name]) {
throw new Error(`Server "${name}" already exists in ${filePath}`);
}
const updated: MCPConfigFile = {
...existing,
mcpServers: {
...existing.mcpServers,
[name]: config,View on GitHub (pinned to 9690622007)
Solutions
- Read the joined messages in the error; each names the server and the exact missing/conflicting field.
- For stdio servers keep "command" (plus optional args/env) and delete any "url" field.
- For http/sse servers set "url" and delete "command"/"args".
- Set "type" to one of "stdio" (default), "http", or "sse".
- Pre-validate with validateServerConfig(name, config) before calling addMCPServer in scripts/UI flows.
Example fix
// before
await addMCPServer(cfgPath, "docs", { type: "stdio", command: "npx", url: "https://mcp.example.com" } as any);
// after
await addMCPServer(cfgPath, "docs", { type: "http", url: "https://mcp.example.com" }); Defensive patterns
Strategy: validation
Validate before calling
import { validateServerConfig } from "@oh-my-pi/pi-coding-agent/mcp/config";
const errors = validateServerConfig(name, config);
if (errors.length > 0) throw new Error(errors.join("; ")); Type guard
function isStdioConfig(c: { type?: string; command?: string; url?: string }): boolean {
const t = c.type ?? "stdio";
return t === "stdio" ? !!c.command && !c.url : false;
} Try / catch
try {
await addMCPServer(cfgPath, name, config);
} catch (e) {
if (e instanceof Error && e.message.startsWith("Invalid server config:")) {
showValidationHint(e.message);
return;
}
throw e;
} Prevention
- Always run validateServerConfig() before any write API call.
- Keep transport fields disjoint: command OR url, never both.
- Omit "type" for stdio instead of inventing new type strings.
- Build configs through a typed schema/form rather than hand-written JSON.
When it happens
Trigger: Calling addMCPServer(filePath, name, config) (directly or via handleAddCommand or the MCP wizard's #handleWizardComplete) with: config containing both command and url; a stdio config with no command; type "http" or "sse" with no url; or type set to an unrecognized value.
Common situations: Copying a config entry from a different MCP client and leaving stale fields (e.g. adding a url while keeping command); hand-editing JSON and dropping the command field; misspelling type (e.g. "streamable" instead of "http"); a wizard/UI form submitting an empty command.
Related errors
- Failed to load tree-sitter language: {err}
- Destination option ${key} must be a string
- Destination option ${key} must be a finite number
- Destination option ${key} must be a boolean
- ${destination} returned an invalid upload URL
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/13d1857bbcc240ef.
Report an issue: GitHub.