affaan-m/ECC · error
MCP config must be a JSON object
Error message
MCP config must be a JSON object
What it means
filterMcpConfig filters disabled MCP servers out of a parsed mcp config. It requires the config to be a plain JSON object; null, arrays, and primitives cannot carry an mcpServers mapping and are rejected before any filtering occurs.
Solutions
- Pass the parsed JSON object, e.g. JSON.parse(fs.readFileSync(path,'utf8')).
- Fix the config file so its top level is an object, not an array.
- Check for a null/undefined return from an earlier load step before filtering.
Example fix
// before filterMcpConfig(rawConfigText, ['legacy']) // after const parsed = JSON.parse(rawConfigText) filterMcpConfig(parsed, ['legacy'])
Defensive patterns
Strategy: type-guard
Validate before calling
let parsed
try { parsed = typeof cfg === 'string' ? JSON.parse(cfg) : cfg } catch { throw new Error('Config is not valid JSON') }
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('MCP config must be a JSON object') Type guard
function isJsonObject(x) {
return x !== null && typeof x === 'object' && !Array.isArray(x)
}
if (!isJsonObject(config)) throw new TypeError('Expected a JSON object for MCP config') Try / catch
try {
const filtered = filterMcpConfig(config, disabled)
} catch (err) {
if (err.message === 'MCP config must be a JSON object') {
console.error('Config must be a parsed JSON object with an mcpServers key')
} else throw err
} Prevention
- Always JSON.parse config file contents before filtering.
- Validate config file top-level shape after editing mcp-configs files.
- Never pass null from a failed loader straight into downstream calls.
- Keep mcp config files as a single top-level object, not arrays.
When it happens
Trigger: Calling filterMcpConfig(null), filterMcpConfig([]), filterMcpConfig('...'), or passing a parsed JSON file whose top level is an array instead of an object.
Common situations: An mcp-configs file saved as a JSON array of configs; a failed read yielding null passed straight through; passing the raw file text string instead of JSON.parse output.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- -32602
- A normalized install request is required
- application request must be a JSON object
- bundle collections must be lists
- bundle values must be finite JSON data
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/559543d91d353d3e.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/mcp-config.js:14
'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: [],
};
}
View on GitHub (pinned to 8321021c54)