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

  1. Ensure the document has a top-level mcpServers key whose value is a plain object mapping server names to server configs.
  2. If migrating from another schema, rename the key before passing to filterMcpConfig.
  3. 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

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


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/abf14b29bf02e79a. Report an issue: GitHub.