[FEATURE]: Allow per-project MCP enabled/disabled overrides
Feature hasn't been suggested before.
- [x] I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Problem
Currently, OpenCode starts all configured MCP servers regardless of whether any agent has access to their tools. The sidebar shows "Connected" MCPs, but it's not obvious whether they're actually usable or not. For example, if I have Linear, GitHub, and Xcode MCPs configured globally but disable them all with "linear_*": false, "github_*": false, "xcode_*": false, all three MCP servers still start up - they're just not accessible to agents.
Proposed Solution
Only start MCP servers that are accessible to at least one agent based on the tools configuration. This involves:
- Check accessibility before starting - Before initializing an MCP server, check if any agent can access its tools
- Add "inaccessible" status - Mark MCPs that won't be started as "inaccessible" (displayed as "Inactive" in the UI)
- UI improvements - Sort MCP list (connected first), add optional hiding of inactive MCPs, improve status display
Example Use Case
Global config (~/.config/opencode/opencode.jsonc):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"linear": { "type": "remote", "url": "https://mcp.example.com/linear" },
"github": { "type": "remote", "url": "https://mcp.example.com/github" },
"xcode": { "type": "local", "command": ["npx", "-y", "@example/xcode"] },
},
"tools": {
// Disable all MCPs globally by default
"linear_*": false,
"github_*": false,
"xcode_*": false,
},
"tui": {
"sidebar": {
"hide_inactive_mcp": true, // Optional: hide inactive MCPs from UI
},
},
}
Project config (~/project/.opencode/opencode.jsonc):
{
"$schema": "https://opencode.ai/config.json",
"tools": {
// Enable only the MCPs this project needs
"linear_*": true,
"github_*": true,
// xcode remains disabled (inherited from global)
},
}
With this approach:
- All MCP servers are defined once (global config)
- Each project specifies which MCPs it needs (project config)
- Only enabled MCPs start
- Inactive MCPs can be hidden from the UI (cleaner interface)
Why this belongs in OpenCode
This feature enables a more efficient and scalable MCP configuration workflow:
- Doesn't run unnecessary processes
- Can choose to define MCPs once, enable per-project
- Can see at a glance which MCPs are active vs inactive
- Builds on OpenCode's existing layered config system (global + project)
Implementation notes
I have a reference implementation on my fork that includes:
- Core accessibility checking logic (
MCP.isAccessible()) - New "inaccessible" status type
- Sidebar UI improvements/tweaks (sorting, hiding inactive MCPs, better status display)
- Unit tests
- Documentation updates
Reference implementation here: https://github.com/jknlsn/opencode/
I haven't opened a PR yet as I wanted to discuss the feature idea first per the contributing guidelines!
What do you think?
- Does this align with OpenCode's goals?
- Should inactive MCPs be hidden by default, or should that be opt-in (as currently implemented)?
- Any concerns about the approach or edge cases to consider?
+1 I was just trying to understand this myself
This is a little weird because you could blacklist all the mcp tools using wildcarding patterns that may not be relying on mcp server name... And then wed have to connect to all the mcp servers, get all the tools, then mark them as disconnected after....
I get what you are saying but the "tools":... just say if an agent has access to the tool or not, maybe the UI needs to make it more clear what tools are loaded for a given agent instead
Thanks for the feedback @rekram1-node. That's a good point about the tools, it's probably the wrong level for the outcome I want.
I think what I'm really trying to find a way to do, is to define MCP servers once in my global config and leave them disabled, and then be able to selectively enable for individual project configs without needing to define the entire MCP again. I can copy it to each relevant project manually, but then if say the command changes, I need to go update each project. Which is fine, but suboptimal.
After thinking about this more, I agree that using tools config for determining MCP startup conflates two concerns: tool access control vs process lifecycle.
Instead I've reworked my approach to use per-project MCP config overrides via the existing mcp key. This leverages the existing mergeDeep behaviour:
// ~/.config/opencode/opencode.jsonc
{
"mcp": {
"linear": { "type": "remote", "url": "..." , "enabled": false},
"github": { "type": "remote", "url": "...", "enabled": false},
"xcode": { "type": "local", "command": ["..."], "enabled": false}
}
}
// ~/dev/project/.opencode/opencode.jsonc
{
"mcp": {
"linear": { "enabled": true },
"github": { "enabled": true }
// xcode not mentioned - uses global default
}
}
I also right-aligned the MCP status messages to match the modified files layout, but I can remove this if preferred.
I've updated my reference implementation on my fork at https://github.com/jknlsn/opencode/ and I'm happy to open a PR if this direction makes sense!