upstash/context7 · error · Error

Unterminated TOML array in MCP args

Error message

Unterminated TOML array in MCP args

What it means

The args array was opened with '[' but the scanning loop reached the end of the file without finding the matching ']' — the array is never closed.

Source

Thrown at packages/cli/src/setup/toml-editor.ts:115

    }
    if (source.slice(index, index + 3) === quote.repeat(3)) {
      throw new Error("Multiline strings are not supported in MCP args");
    }

    const token =
      quote === '"' ? parseTomlBasicString(source, index) : parseTomlLiteralString(source, index);
    tokens.push(token);
    index = skipTomlArrayTrivia(source, token.end);

    if (source[index] === ",") {
      index++;
      continue;
    }
    if (source[index] !== "]") {
      throw new Error("Expected a comma or closing bracket in MCP args");
    }
  }
  throw new Error("Unterminated TOML array in MCP args");
}

function findTomlServerArgs(
  raw: string,
  serverName: string
): { start: number; end: number; tokens: TomlStringToken[] } | null {
  const escapedName = serverName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  const tableKey = `(?:mcp_servers|"mcp_servers"|'mcp_servers')`;
  const serverKey = `(?:${escapedName}|"${escapedName}"|'${escapedName}')`;
  const headerRe = new RegExp(
    `^[\\uFEFF\\t ]*\\[[\\t ]*${tableKey}[\\t ]*\\.[\\t ]*${serverKey}[\\t ]*\\][\\t ]*(?:#.*)?\\r?$`,
    "m"
  );
  const header = headerRe.exec(raw);
  if (!header) return null;

  const bodyStart = raw.indexOf("\n", header.index + header[0].length) + 1;
  const effectiveBodyStart = bodyStart === 0 ? raw.length : bodyStart;

View on GitHub (pinned to edc9eeb77b)

Solutions

  1. Add the closing ] on the args array
  2. Check for ) or } typed instead of ]
  3. Run a TOML validator before saving

Example fix

// before
args = ["--a", "--b"
// after
args = ["--a", "--b"]
Defensive patterns

Strategy: validation

Validate before calling

// bracket balance ignoring quotes (file already known to have no multiline strings)
let depth = 0;
for (const ch of raw) { if (ch === '[') depth++; else if (ch === ']') depth--; }
if (depth !== 0) throw new Error('unbalanced brackets');

Type guard

function bracketsBalanced(raw: string): boolean {
  let d = 0;
  for (const ch of raw.replace(/"[^"\\n]*"|'[^'\\n]*'/g, '')) {
    if (ch === '[') d++; else if (ch === ']') d--;
  }
  return d === 0;
}

Try / catch

catch (e) { if (/Unterminated TOML array/.test(e.message)) { /* add missing ] */ } throw e; }

Prevention

When it happens

Trigger: args = ["--flag" followed by EOF, or a ']' deleted/typo'd as ')' or '}'.

Common situations: Truncating the file while editing; mismatched bracket types from manual editing; nested brackets elsewhere confusing hand edits.

Related errors


AI-assisted analysis of upstash/context7@edc9eeb77b (2026-08-28). Data as JSON: /api/errors/8b839d8488bf071f. Report an issue: GitHub.