upstash/context7 · warning

Skipped ${mcpPath}: could not parse (${err instanceof Error

Error message

Skipped ${mcpPath}: could not parse (${err instanceof Error ? err.message : String(err)})

What it means

Thrown while context7 checks whether the context7 MCP server is registered for an agent (during remove/setup). The resolved agent config path that does not end in .toml is read with readJsonConfig(), which does JSON.parse(stripJsonComments(raw)). If the parse throws, the file is skipped with this warning and hasMcp() returns false, so the agent is treated as 'not configured' instead of the command crashing.

Source

Thrown at packages/cli/src/commands/remove.ts:211

  const agent = getAgent(agentName);
  // Agents with no project-level MCP (e.g. Antigravity) only have a global
  // config — there's nothing to detect at project scope.
  if (scope === "project" && agent.mcp.projectPaths.length === 0) return false;
  const candidates =
    scope === "global"
      ? agent.mcp.globalPaths
      : agent.mcp.projectPaths.map((path) => join(process.cwd(), path));
  const mcpPath = await resolveMcpPath(candidates);

  if (mcpPath.endsWith(".toml")) {
    return readTomlServerExists(mcpPath, "context7");
  }

  let existing: Record<string, unknown>;
  try {
    existing = await readJsonConfig(mcpPath);
  } catch (err) {
    log.warn(
      `Skipped ${mcpPath}: could not parse (${err instanceof Error ? err.message : String(err)})`
    );
    return false;
  }
  const section = existing[agent.mcp.configKey];
  return (
    !!section && typeof section === "object" && !Array.isArray(section) && "context7" in section
  );
}

async function hasRule(agentName: SetupAgent, scope: Scope): Promise<boolean> {
  const agent = getAgent(agentName);
  const rule = agent.rule;

  if (rule.kind === "file") {
    const ruleDir =
      scope === "global" ? rule.dir("global") : join(process.cwd(), rule.dir("project"));
    return pathExists(join(ruleDir, rule.filename));

View on GitHub (pinned to 5284672feb)

Solutions

  1. Validate the file and fix the reported syntax error: jq . '<configPath>' (or npx jsonlint <configPath>)
  2. Remove git merge-conflict markers (<<<<<<< / ======= / >>>>>>>) or editor backup blocks from the config
  3. Restore the config from source control, or regenerate it with the agent's own CLI, then re-run the context7 command
  4. Keep hand-written configs strict JSON: no comments, no trailing commas

Example fix

// before (.cursor/mcp.json — unparsable)
{
  "mcpServers": {
    "context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] }, // trailing comma + comment
}

// after
{
  "mcpServers": {
    "context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// before running context7 remove, confirm the agent's config parses
import { readFile } from "node:fs/promises";
const raw = await readFile(configPath, "utf-8");
try {
  JSON.parse(raw.replace(/^\uFEFF/, ""));
} catch (e) {
  console.error(`Fix ${configPath} first: ${(e as Error).message}`);
}

Type guard

function isJsonRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === "object" && v !== null && !Array.isArray(v);
}

Prevention

When it happens

Trigger: Running `context7 remove <agent>` (or any flow calling hasMcp) when the agent's JSON MCP config exists but is unparsable: truncated file, trailing commas or single quotes that survive stripJsonComments, merge-conflict markers, or YAML pasted into a .json file. A missing file does NOT trigger this (readJsonConfig returns {} silently); only an existing, syntactically broken file does.

Common situations: Hand-edited ~/.claude.json or .cursor/mcp.json with comments or trailing commas; configs corrupted by an interrupted write or an unresolved git merge; configs emitted by other tools that write non-strict JSON (BOM, unquoted keys).

Related errors


AI-assisted analysis of upstash/context7@5284672feb (2026-08-18). Data as JSON: /api/errors/eae802c6bab885df. Report an issue: GitHub.