Skip to content

mcp: project config can re-enable user-disabled MCP servers #512

Description

@Ashwinhegde19

Version / branch / commit

main at commit 3c81fea

OS and environment

macOS 26.5.2 / darwin arm64 / Go 1.26.4

Summary

A user-level MCP disable can be overridden by project config. If the user disables an MCP server in their user config, a repository's project config can set the same server to disabled: false and cause it to be active again when Zero resolves MCP servers for that workspace.

This is a trust-boundary issue because zero mcp disable <server> looks like an operator/user-level opt-out, but a cloned repo can reverse that choice in .zero/config.json.

Steps to reproduce

  1. User config disables a default MCP server:
{
  "mcp": {
    "servers": {
      "firecrawl": { "disabled": true }
    }
  }
}
  1. Project config in the workspace re-enables the same server:
{
  "mcp": {
    "servers": {
      "firecrawl": { "disabled": false }
    }
  }
}
  1. Resolve MCP config for that workspace.

I verified this locally with a temporary regression test against config.ResolveMCP: the resolved firecrawl server has Disabled == false.

Expected behavior

A project config should not be able to re-enable an MCP server that the user explicitly disabled in user config. User-level disable should be sticky/authoritative unless the user re-enables it from user scope or via an explicit command/flag.

Actual behavior

Project config wins during MCP server merging. mergeMCPServer applies disabled:false when the later layer sets the disabled field, so the resolved MCP server becomes enabled again.

Relevant code/tests:

  • internal/config/resolver.go merges user and project MCP config in order.
  • internal/config/resolver.go / mergeMCPServer applies next.disabledSet and assigns base.Disabled = next.Disabled.
  • internal/config/resolver_test.go currently has a test showing project config can clear and re-enable a disabled MCP server.

Impact

A repo can restore a network MCP server or stdio MCP server that the user had intentionally disabled. For default/network MCP servers this can re-enable outbound connections; for stdio MCP servers this can restore startup-time process execution for a server the user opted out of.

I did not find an existing issue or open PR covering this exact user-disable override behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions