Skip to content

OpenCode 1.17.16 drops mcp.<name>.env from resolved config, causing MCP servers to miss environment variables #36434

Closed as not planned

Description

@Gelly52

Description

What happened?

MCP server entries under mcp in ~/.config/opencode/opencode.json can include an env object, but opencode debug config shows the resolved config with the env field missing entirely. As a result, the spawned MCP child processes never receive the environment variables, and any MCP server that depends on per-server env vars fails at runtime.

This reproduces with at least two different MCP servers, so it doesn't appear to be specific to one server implementation:

  • grok-search (needs GROK_API_URL, GROK_API_KEY, etc.)
  • mysql (needs MYSQL_HOST, MYSQL_DATABASE, etc.)

This is not a credentials/provider issue:

  • The same grok-search MCP config (same command, same env values) works correctly in Claude Code (claude mcp list shows it connected, and tool calls succeed).
  • The configured API endpoint responds successfully to both /v1/models and /v1/chat/completions when called directly.

So the problem is isolated to how OpenCode resolves/passes mcp.<name>.env.

Expected behavior

mcp.<name>.env should remain present after config resolution, and should be passed to the spawned MCP child process's environment.

Actual behavior

env is silently dropped during config resolution, and the MCP processes report missing configuration at runtime (e.g. missing API URL, missing DB config), even though the raw config file has the values.

Raw config (~/.config/opencode/opencode.json, secrets redacted)

{
  "mcp": {
    "grok-search": {
      "type": "local",
      "command": [
        "uvx",
        "--from",
        "git+https://github.com/GuDaStudio/GrokSearch@grok-with-tavily",
        "grok-search"
      ],
      "enabled": true,
      "env": {
        "GROK_API_URL": "https://example.com/v1",
        "GROK_API_KEY": "sk-***",
        "GROK_MODEL": "grok-4.5"
      }
    },
    "mysql": {
      "type": "local",
      "command": ["uvx", "mysql_mcp_server"],
      "enabled": true,
      "env": {
        "MYSQL_HOST": "localhost",
        "MYSQL_PORT": "13306",
        "MYSQL_USER": "root",
        "MYSQL_PASSWORD": "***",
        "MYSQL_DATABASE": "testdb"
      }
    }
  }
}

Resolved config (opencode debug config)

"mcp": {
  "grok-search": {
    "command": [
      "uvx",
      "--from",
      "git+https://github.com/GuDaStudio/GrokSearch@grok-with-tavily",
      "grok-search"
    ],
    "enabled": true,
    "type": "local"
  },
  "mysql": {
    "command": ["uvx", "mysql_mcp_server"],
    "enabled": true,
    "type": "local"
  }
}

Note env is absent from both entries, despite being present in the raw file.

Plugins

/Users/agiuser/.config/opencode/superpowers/.opencode/plugins/superpowers.js

OpenCode version

1.17.16

Steps to reproduce

  1. Add an MCP server under mcp in ~/.config/opencode/opencode.json with an env object (e.g. any local type server needing an API key).
  2. Restart OpenCode.
  3. Run opencode debug config and inspect the mcp.<name> entry.
  4. Observe that env is missing from the resolved output, even though it's present in the raw config file.
  5. Call a tool from that MCP server that depends on the env vars.
  6. Observe the tool call fails with a "missing configuration" style error, even though the raw config has the correct values.

Screenshot and/or share link

cat ~/.config/opencode/opencode.json
Image

opencode debug config

Image

Operating System

macOS 26.5.2

Terminal

Ghostty 1.3.1

Activity

  1. github-actions commented on Jul 11, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    The env → environment field naming discrepancy described in #35860 may be the direct cause of what you're seeing: if the correct field name is environment, renaming it in your config may resolve the issue while the underlying bug is tracked.

  2. Gelly52 commented on Jul 13, 2026

    @Gelly52
    Author

    Confirmed — renaming env → environment in my opencode.json fixed it.

    Before:

    "grok-search": {
      "type": "local",
      "command": ["uvx", "--from", "git+https://github.com/GuDaStudio/GrokSearch@grok-with-tavily", "grok-search"],
      "enabled": true,
      "env": {
        "GROK_API_URL": "...",
        "GROK_API_KEY": "..."
      }
    }

    → silently dropped, opencode debug config showed no env at all.

    After:

    "grok-search": {
      "type": "local",
      "command": ["uvx", "--from", "git+https://github.com/GuDaStudio/GrokSearch@grok-with-tavily", "grok-search"],
      "enabled": true,
      "environment": {
        "GROK_API_URL": "...",
        "GROK_API_KEY": "..."
      }
    }

    → opencode debug config now shows the full environment block, and the MCP tool reports config_status: fully configured.

    This is the same root cause as #30892 and #35860 — the built-in customize-opencode skill docs use env, but the actual schema/runtime expects environment, and the config loader silently drops unknown keys instead of erroring. Feel free to close this as a duplicate of #35860 (which already has a fix PR, #35867, for the docs). Thanks for the pointer!

  3. hazlamahedich commented on Jul 20, 2026

    @hazlamahedich

    Confirming this still reproduces in 1.18.0 (upgraded from 1.17.16 where I first saw it).

    opencode debug config drops the env block on every mcp.<name> entry — even for servers that have no env in the source file, so it's not just a redaction artifact. For servers that do require env vars, the spawned child genuinely never receives them, which I confirmed with a logging wrapper:

    #!/bin/bash
    { echo "PEXELS_API_KEY len: ${#PEXELS_API_KEY}"; } >> /tmp/invocation.log
    exec npx -y mcp-pexels

    → PEXELS_API_KEY len: 0 when opencode launches it (the value is present in opencode.json). open-design fails the same way because ELECTRON_RUN_AS_NODE=1 is dropped, so the Electron Helper tries to launch as a GUI app and the stdio MCP handshake dies with -32000 Connection closed.

    Two of the three affected servers (pexels, open-design) report MCP error -32000: Connection closed, not a missing-config error — so this may be part of why the issue is under-diagnosed: failures look like protocol/transport bugs rather than an env regression.

    Workaround that works reliably on 1.18.0: point the command at a small wrapper script that exports the env vars itself before exec-ing the real server. Local MCP servers are then fully functional.

  4. jond34 commented on Jul 29, 2026

    @jond34

    Cross-linking: I filed #39431 for the underlying validation gap that makes this class of bug silent.

    Verified on 1.18.9, the inconsistency is one level of nesting:

    • unknown key at config root → Error: Configuration is invalid ... ↳ Unrecognized key: <name>
    • same unknown key nested inside mcp.<name> → silently discarded, no error, no warning, server reports healthy

    So env (vs environment) is stripped with no diagnostic. @Gelly52 your read that "the config loader silently drops unknown keys instead of erroring" is exactly right, and @hazlamahedich the opaque -32000 Connection closed is the downstream symptom of that.

    Worth noting the docs half is now fixed — the bundled customize-opencode skill says environment in 1.18.9 (it said env in 1.18.5, per #39135). But the silent-drop behavior is unchanged, so configs written against the older skill keep failing silently after upgrade. Homebrew is also still shipping 1.18.5, so new brew users still get the skill that teaches the stripped key.

    In my case this silently loaded a different dbt-mcp toolset than configured — every DISABLE_* flag ignored, and write tools exposed despite being explicitly disabled, while the server reported healthy. Details in #39431.

  5. github-actions commented on Sep 27, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions