Skip to content

config: published schema at opencode.ai/config.json rejects documented V2 fields (skills, mcp.*, permissions) #43748

Closed

Description

@Sugamsss

Summary

The JSON Schema served at https://opencode.ai/config.json — the URL referenced by $schema in every V2 config — describes an older/hybrid shape that does not match current V2 documentation. As a result, editor IntelliSense and any standards-based validator flag valid V2 configs as invalid, including configs whose fields are copied verbatim from the V2 docs. This also actively misleads users: for MCP, the stale schema suggests adding an enabled key, while V2 explicitly has no enabled field.

Environment

  • opencode version: 0.0.0-beta-17759
  • OS: Darwin 27.0.0 (arm64)
  • Terminal: Apple_Terminal (xterm-256color)
  • Shell: /bin/zsh
  • Install/channel: beta
  • Active plugins: one local plugin (subagent-session-guard.ts); unrelated to this issue

Reproduction

  1. Create ~/.config/opencode/opencode.json using examples taken verbatim from the V2 docs:
{
  "$schema": "https://opencode.ai/config.json",
  "permissions": [{ "action": "shell", "resource": "git push *", "effect": "ask" }],
  "skills": ["./team-skills"],
  "mcp": {
    "timeout": { "startup": 45000, "catalog": 30000, "execution": 600000 },
    "servers": {
      "everything": {
        "type": "local",
        "command": ["npx", "-y", "@modelcontextprotocol/server-everything"]
      }
    }
  }
}
  1. Run opencode2 debug config → exits 0, parses and normalizes everything. opencode2 mcp list shows the server connecting. The runtime accepts all fields.

  2. Validate the same file against the published schema with any JSON-Schema validator:

curl -sS https://opencode.ai/config.json -o schema.json
python3 - <<'EOF'
import json, jsonschema
schema = json.load(open("schema.json"))
config = json.load(open("opencode.json"))
for err in jsonschema.Draft202012Validator(schema).iter_errors(config):
    print("/".join(map(str, err.absolute_path)), "->", err.message)
EOF

Expected Behavior

A config following current V2 documentation should validate cleanly against the schema its own $schema field points to.

Actual Behavior

The validator reports errors on documented V2 fields:

/skills -> ['~/.config/opencode/skills'] is not of type 'object'
/mcp/timeout -> {'startup': 45000, ...} is not valid under any of the given schemas
/mcp/servers -> {'everything': {...}} is not valid under any of the given schemas
/ -> Additional properties are not allowed ('permissions' was unexpected)

Specific mismatches between the published schema and the V2 docs:

Field Published schema expects V2 docs specify
skills object { "paths": [], "urls": [] } plain array of strings: "skills": ["./team-skills", ...]
mcp flat map of server entries, each with optional enabled boolean mcp.servers.<name> entries + mcp.timeout.{startup,catalog,execution}; no enabled field exists in V2 (servers connect unless disabled: true)
permissions only singular legacy permission object ordered array of { action, resource, effect } rules

Also flagged on a real-world config: experimental.subagent_depth and model-level reasoning_efforts.

The MCP case is worse than cosmetic: because the schema's only accepted shapes mention enabled, anyone "fixing" their config to satisfy validators will add a field that V2 does not support.

Additional Context

  • This is pure schema/docs drift — the beta runtime handles all of these fields correctly, so the schema appears to predate the V2 config format.
  • Since V2 configs ship with this $schema URL, editors (VS Code, Zed, etc.) show spurious diagnostics on doc-recommended configs, and third-party tooling built on the schema reports the same false positives.
  • Reproduced consistently with jsonschema Draft202012Validator (18 errors on a real-world V2 config that loads cleanly in the CLI).
  • Suggestion: regenerate the published schema from the current V2 types, and/or serve a versioned schema (e.g. /v2/config.json) so older editors keep working while V2 configs get accurate validation.

Activity

  1. github-actions commented on Aug 21, 2026

    @github-actions
    Contributor

    This issue might be related to an existing open issue. Please check:

  2. Sugamsss commented on Aug 21, 2026

    @Sugamsss
    Author

    Follow-up with the complete validator output for a neutral config (generic provider/model names, everything else taken verbatim from the V2 docs — including experimental.subagent_depth and model-level reasoning_efforts, which the original report also saw flagged):

    Neutral test config
    {
      "$schema": "https://opencode.ai/config.json",
      "permissions": [{ "action": "shell", "resource": "git push *", "effect": "ask" }],
      "skills": ["./team-skills"],
      "experimental": { "subagent_depth": 3 },
      "provider": {
        "my-provider": {
          "npm": "@ai-sdk/openai-compatible",
          "models": {
            "model-a": {
              "name": "Model A",
              "reasoning_efforts": ["low", "medium", "high"]
            }
          }
        }
      },
      "mcp": {
        "timeout": { "startup": 45000, "catalog": 30000, "execution": 600000 },
        "servers": {
          "everything": {
            "type": "local",
            "command": ["npx", "-y", "@modelcontextprotocol/server-everything"]
          }
        }
      }
    }
    Full jsonschema Draft202012Validator output — 6 errors, zero warnings from the runtime itself
    /
        -> Additional properties are not allowed ('permissions' was unexpected)
    /experimental
        -> Additional properties are not allowed ('subagent_depth' was unexpected)
    /mcp/servers
        -> {'everything': {'type': 'local', 'command': ['npx', '-y', '@modelcontextprotocol/server-everything']}} is not valid under any of the given schemas
    /mcp/timeout
        -> {'startup': 45000, 'catalog': 30000, 'execution': 600000} is not valid under any of the given schemas
    /provider/my-provider/models/model-a
        -> Additional properties are not allowed ('reasoning_efforts' was unexpected)
    /skills
        -> ['./team-skills'] is not of type 'object'
    

    Meanwhile opencode2 debug config exits 0 on this exact file and opencode2 mcp list connects the server — so every flagged field is accepted and honored by the beta runtime.

  3. santhiprakash commented on Aug 21, 2026

    @santhiprakash

    I'd like to help on this. Tracing the published schema to packages/opencode/script/schema.ts:72, it currently calls generateEffect(ConfigV1.Info) — that's why the public schema carries the V1 shapes (skills as {paths, urls}, mcp as a flat map with enabled, only singular permission, etc.). The runtime accepts V2 shapes via ConfigParse.schema because it uses onExcessProperty: "ignore", but a published JSON-Schema document cannot express that.

    The V2 schema already exists at @opencode-ai/core/config (exported as Config.Info, a Schema.Class with the right shapes: skills as string[], mcp as {timeout?, servers?} (ConfigV2.MCP), permissions: Permission.Ruleset, experimental: ConfigExperimental.Experimental, providers plural). I locally ran Schema.toJsonSchemaDocument(Config.Info) against the current dev tip and confirmed those fields are emitted correctly with the V2 shapes.

    Proposed schema.ts change at dev tip 2859603cbb:

    -import { Config } from "@/config/config"
     import { ConfigV1 } from "@opencode-ai/core/v1/config/config"
     import { TuiConfig } from "@opencode-ai/tui/config"
     ...
    -await Bun.write(configFile, JSON.stringify(generateEffect(ConfigV1.Info), null, 2))
    +import { Config } from "@opencode-ai/core/config"
    +await Bun.write(configFile, JSON.stringify(generateEffect(Config.Info), null, 2))

    (This also removes the dead @/config/config import, which is the same line #41127 is touching. If both fixes land, they'll conflict at that import line — happy to coordinate, or to defer to whoever lands first.)

    I see you're assigned here, kitlangton — happy to either open this as a PR or hand the verified analysis over if you'd rather drive it yourself. Let me know which.

  4. d3bt3ch commented on Sep 22, 2026

    @d3bt3ch

    Has it been fixed ?

  5. chuangye-gu commented on Sep 23, 2026

    @chuangye-gu

    Adding one thing that isn't covered above: removing $schema from the config does not escape this, because the SchemaStore catalog has an opencode entry that matches by filename:

    {
      "name": "opencode",
      "description": "opencode AI coding agent configuration file",
      "fileMatch": ["opencode.json", "opencode.jsonc", "**/.opencode/opencode.json", "**/.opencode/opencode.jsonc"],
      "url": "https://opencode.ai/config.json"
    }

    So VS Code (1.136.1 here — default catalog, no json.schemas override, no user settings.json), JetBrains IDEs and neovim's jsonls all apply the V1 document automatically, and there is no V2 URL to point a per-file $schema at either: https://opencode.ai/v2/config.json, https://opencode.ai/v2/schema.json, https://opencode.ai/config.v2.json and https://opencode.ai/schema.json are all 404. Fixing the published document (the schema.ts:72 change above) fixes the editors as well — the SchemaStore entry already points at the right URL.

    Two smaller mismatches from the same V1 shapes, for completeness (opencode 2.0.13):

    • providers is missing entirely, while V1's provider (singular) is now silently ignored by the runtime — opencode debug config drops it with no diagnostic.
    • V1's model shape requires both context and output in limit, but V2 only needs context, so "limit": { "context": 100000 } is flagged with 'output' is a required property.

    Repro with a neutral V2-shaped config (mcp.servers + providers), validated against https://opencode.ai/config.json:

    Additional properties are not allowed ('providers' was unexpected)
    {'demo': {'type': 'remote', 'url': 'https://example.com/mcp'}} is not valid under any of the given schemas
    

    (The same config is accepted and used by the runtime.)

  6. YoelCieno commented on Sep 24, 2026

    @YoelCieno

    Still reproducible on released v2.0.13 (verified 2026-09-25)

    Fetched https://opencode.ai/config.json fresh today (39,039 bytes) — still generated from the V1 shapes:

    • "servers" → 0 occurrences anywhere in the published schema JSON
    • mcp def is the V1 flat map:
    "mcp": {
      "type": "object",
      "additionalProperties": {
        "anyOf": [
          { "$ref": "#/$defs/McpLocalConfig" },
          { "$ref": "#/$defs/McpRemoteConfig" },
          { "type": "object", "properties": { "enabled": { "type": "boolean" } },
            "required": ["enabled"], "additionalProperties": false }
        ]
      }
    }
    • $defs.McpLocalConfig.properties = type, command, cwd, environment, enabled, timeout
    • $defs.McpRemoteConfig.properties = type, url, enabled, headers, oauth, timeout

    → neither MCP def has disabled; the only "disabled" occurrences in the whole schema belong to unrelated defs (variants, share, extensions).

    So a V2 config copied from https://opencode.ai/v2/docs/mcp-servers gets Property servers is not allowed, and per-server disabled gets Property disabled is not allowed — while the schema still suggests the removed enabled key.

    Environment: opencode v2.0.13 (npm @opencode/cli, channel latest), Linux 6.17.0-40-generic, VS Code built-in JSON LS, fish. Reproduces consistently (JSON LS, no overrides).

    Workaround in use: vendored patched schema + relative $schema path; will revert once the published schema ships the V2 shape.

  7. yaohwu commented on Sep 28, 2026

    @yaohwu

    Looking forward to this issue being fixed

  8. BananaAcid commented on Oct 6, 2026

    @BananaAcid

    as of today, https://opencode.ai/config.json is still referenced in docs and not fixed.

  9. raulparada commented on Oct 9, 2026

    @raulparada

    wow, been migrating to v2 for the last hour and this is like the third hard-to-swallow pill already. Basic stuff like this should never go wrong! you're asking users "move to v2", and one of the most obvious things needed when doing that move is to have the schema LSP help you, not the full opposite of yelling at you on new fields (well, how would you know, LSP support also removed 🙄).

    I appreciate the effort that went into the (v1) tool of course! was a proselytiser, but this shows something is broken at anomalyco and it's time for us to go look elsewhere. Cheers!

  10. Gobutah commented on Oct 12, 2026

    @Gobutah

    Please fix asap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions