diff --git a/rootfs/usr/local/lib/opencode-devbox/generate-config.py b/rootfs/usr/local/lib/opencode-devbox/generate-config.py index 6f9de7c..4674be6 100755 --- a/rootfs/usr/local/lib/opencode-devbox/generate-config.py +++ b/rootfs/usr/local/lib/opencode-devbox/generate-config.py @@ -96,6 +96,14 @@ def register_mcp_servers(config: dict) -> list[str]: "enabled": False, } + # Context7 — up-to-date library documentation for LLMs (remote). + # Free tier works without an API key; set CONTEXT7_API_KEY for higher + # rate limits. No local binary needed — purely a remote MCP endpoint. + servers["context7"] = { + "type": "remote", + "url": "https://mcp.context7.com/mcp", + } + if servers: config["mcp"] = servers @@ -110,14 +118,17 @@ def main() -> int: home = Path(os.environ.get("HOME", "/home/developer")) config_dir = home / ".config" / "opencode" - config_file = config_dir / "opencode.json" + config_file = config_dir / "opencode.jsonc" + config_file_legacy = config_dir / "opencode.json" # CRITICAL: never overwrite an existing config. Users may have # bind-mounted their host config directory, or their config may be # persisted in a named volume from a previous run. - if config_file.exists(): + # Check both .json and .jsonc variants. + if config_file.exists() or config_file_legacy.exists(): + existing = config_file if config_file.exists() else config_file_legacy print( - f"Existing opencode.json found at {config_file} — " + f"Existing config found at {existing} — " "skipping generation.", file=sys.stderr, ) @@ -140,8 +151,23 @@ def main() -> int: added = register_mcp_servers(config) config_dir.mkdir(parents=True, exist_ok=True) + + # Write as JSONC so we can include helpful comments. + content = json.dumps(config, indent=2) + + # Insert a comment about Context7 API key after the context7 url line. + context7_comment = ( + ' "url": "https://mcp.context7.com/mcp"\n' + " // For higher rate limits, sign up at https://context7.com/dashboard\n" + ' // and add: "headers": { "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}" }' + ) + content = content.replace( + ' "url": "https://mcp.context7.com/mcp"', + context7_comment, + ) + with config_file.open("w") as f: - json.dump(config, f, indent=2) + f.write(content) f.write("\n") if added: diff --git a/scripts/smoke-test.sh b/scripts/smoke-test.sh index 6b4fa34..da93c7b 100755 --- a/scripts/smoke-test.sh +++ b/scripts/smoke-test.sh @@ -160,11 +160,11 @@ else fi rm -f "$tmpout" -# Config generation with anthropic provider writes valid JSON with the +# Config generation with anthropic provider writes valid JSONC with the # expected shape. The script's log message goes to stderr (line 1 of # generate-config.py uses file=sys.stderr) so capturing only stdout -# gives us clean JSON. -label="generate-config produces valid opencode.json" +# gives us clean JSONC. We strip // comments before validating JSON. +label="generate-config produces valid opencode.jsonc" tmp=$(mktemp -d) if docker run --rm \ -e OPENCODE_PROVIDER=anthropic \ @@ -173,24 +173,28 @@ if docker run --rm \ "$IMAGE" sh -c ' mkdir -p /tmp/home python3 /usr/local/lib/opencode-devbox/generate-config.py 2>/dev/null - cat /tmp/home/.config/opencode/opencode.json - ' > "$tmp/out.json" 2>/dev/null; then + cat /tmp/home/.config/opencode/opencode.jsonc + ' > "$tmp/out.jsonc" 2>/dev/null; then + # Strip single-line // comments for JSON validation + sed 's|//.*$||' "$tmp/out.jsonc" > "$tmp/out.json" if python3 -c " import json, sys c = json.load(open('$tmp/out.json')) assert c['model'].startswith('anthropic/'), c assert c['autoupdate'] is False assert c['share'] == 'disabled' +assert 'context7' in c.get('mcp', {}), 'context7 MCP not registered' " 2>&1; then pass "$label" else - fail "$label: output doesn't match expected shape: $(cat "$tmp/out.json")" + fail "$label: output doesn't match expected shape: $(cat "$tmp/out.jsonc")" fi else - fail "$label: container failed: $(cat "$tmp/out.json")" + fail "$label: container failed: $(cat "$tmp/out.jsonc")" fi # Config generation is idempotent — running twice must not overwrite. +# Tests both legacy .json and new .jsonc detection. label="generate-config never overwrites existing config" if docker run --rm \ -e OPENCODE_PROVIDER=anthropic \