affaan-m/ECC · error · Error
MCP config must include an mcpServers object
Error message
MCP config must include an mcpServers object
What it means
Thrown by filterMcpConfig() when the config object has no mcpServers field, or that field is not a plain object (it is null, an array, or a scalar). The mcpServers object is the contract for every MCP config document ECC consumes.
Source
Thrown at scripts/lib/mcp-config.js:19
'use strict';
function parseDisabledMcpServers(value) {
return [...new Set(
String(value || '')
.split(',')
.map((entry) => entry.trim())
.filter(Boolean)
)];
}
function filterMcpConfig(config, disabledServerNames = []) {
if (!config || typeof config !== 'object' || Array.isArray(config)) {
throw new Error('MCP config must be a JSON object');
}
const servers = config.mcpServers;
if (!servers || typeof servers !== 'object' || Array.isArray(servers)) {
throw new Error('MCP config must include an mcpServers object');
}
const disabled = new Set(parseDisabledMcpServers(disabledServerNames));
if (disabled.size === 0) {
return {
config: {
...config,
mcpServers: { ...servers },
},
removed: [],
};
}
const nextServers = {};
const removed = [];
for (const [name, serverConfig] of Object.entries(servers)) {
if (disabled.has(name)) {View on GitHub (pinned to 01e15490f0)
Solutions
- Ensure the document has a top-level mcpServers key whose value is a plain object mapping server names to server configs.
- If migrating from another schema, rename the key before passing to filterMcpConfig.
- Validate the shape with a JSON schema before invoking the function.
Example fix
// before
{ "servers": { "foo": {...} } }
// after
{ "mcpServers": { "foo": {...} } } Defensive patterns
Strategy: validation
Validate before calling
function hasMcpServers(config) {
return config !== null
&& typeof config === 'object'
&& !Array.isArray(config)
&& config.mcpServers !== null
&& typeof config.mcpServers === 'object'
&& !Array.isArray(config.mcpServers);
}
if (!hasMcpServers(config)) {
throw new Error('Config must include an mcpServers object.');
} Type guard
function isMcpServersMap(config) {
return config != null
&& typeof config === 'object'
&& !Array.isArray(config)
&& config.mcpServers != null
&& typeof config.mcpServers === 'object'
&& !Array.isArray(config.mcpServers);
} Try / catch
try {
result = filterMcpConfig(config, disabled);
} catch (e) {
if (/mcpServers object/.test(e.message)) {
if (config.servers) config = { ...config, mcpServers: config.servers };
result = filterMcpConfig(config, disabled);
} else throw e;
} Prevention
- Standardize on the mcpServers key across all config producers.
- Validate config files with a JSON schema that requires mcpServers as an object.
- When merging configs, ensure mcpServers survives the merge as an object.
When it happens
Trigger: A config file with {"servers": {}} (wrong key), {"mcpServers": []} (array instead of object), or {"mcpServers": null}; a config produced by a tool that names the key differently.
Common situations: Typos in the key name; merging configs where mcpServers was deleted; output from a generator that uses a different schema.
Related errors
- MCP config must be a JSON object
- Policy file ${resolvedPath} must contain a JSON object, got
- Invalid install-state${label ? ` (${label})` : ''}: ${format
- Invalid JSON in config: {path}
- ECC_PROJECT_DIR must be a child path within /workspace.
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/abf14b29bf02e79a.
Report an issue: GitHub.