coleam00/Archon · error
MCP config must be a JSON object (Record<string, ServerConfi
Error message
MCP config must be a JSON object (Record<string, ServerConfig>): ${mcpPath} What it means
The top-level JSON document must be an object whose keys are server names. JSON files whose root is an array, a string, a number, or null have no server map to iterate, so loadMcpConfig throws with the config path and the expected Record<string, ServerConfig> shape.
Source
Thrown at packages/providers/src/mcp/config.ts:154
raw = await readFile(fullPath, 'utf-8');
} catch (err) {
const e = err as NodeJS.ErrnoException;
if (e.code === 'ENOENT') {
throw new Error(`MCP config file not found: ${mcpPath} (resolved to ${fullPath})`);
}
throw new Error(`Failed to read MCP config file: ${mcpPath} - ${e.message}`);
}
let parsed: Record<string, unknown>;
try {
parsed = JSON.parse(raw) as Record<string, unknown>;
} catch (parseErr) {
const detail = (parseErr as SyntaxError).message;
throw new Error(`MCP config file is not valid JSON: ${mcpPath} - ${detail}`);
}
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error(`MCP config must be a JSON object (Record<string, ServerConfig>): ${mcpPath}`);
}
const normalized = normalizeMcpConfig(parsed, mcpPath);
const { expanded, missingVars } = expandEnvVars(normalized, envSource);
const serverNames = Object.keys(expanded);
return { servers: expanded, serverNames, missingVars };
}
View on GitHub (pinned to 0773b97458)
Solutions
- Wrap the content in an object keyed by server name, or use {"mcpServers": {...}}.
- Convert an array of server descriptors into a map (key by the server's name field).
- For zero servers, write {} rather than null or [].
Example fix
// before
[{"name": "fs", "command": "npx"}]
// after
{"fs": {"command": "npx"}} Defensive patterns
Strategy: type-guard
Validate before calling
const parsed: unknown = JSON.parse(readFileSync(mcpPath, 'utf-8'));
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error(`${mcpPath} must be a JSON object keyed by server name`);
} Type guard
const isJsonObject = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v);
Prevention
- Root the config in an object: {} for empty, keyed servers otherwise.
- Fix generators/scripts that serialize arrays or null at the top level.
- Type the parsed value as unknown and narrow before passing it on.
When it happens
Trigger: loadMcpConfig on files like ["server1", "server2"], "npx ...", or null (JSON 'null' literal), all of which parse fine but are not objects.
Common situations: A list of server names exported by a script instead of a map; an empty file containing just 'null'; pasting a CLI command into the config; a generator serializing an array of server descriptors.
Related errors
- MCP server "${serverName}" must be a JSON object (got ${desc
- MCP config field "mcpServers" must be a JSON object: ${mcpPa
- MCP config ${fieldPath}.${key} must be a string (got ${descr
- MCP config ${serverName}.env must be a JSON object of string
- MCP config ${serverName}.headers must be a JSON object of st
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/10930edd64c2ec23.
Report an issue: GitHub.