Skip to content

feat(config): enabled_tools/disabled_tools per-server allowlist/denylist in mcp_config.json#468

Open
nlaurance wants to merge 1 commit into
smart-mcp-proxy:mainfrom
nlaurance:feat/config-tool-allowlist
Open

feat(config): enabled_tools/disabled_tools per-server allowlist/denylist in mcp_config.json#468
nlaurance wants to merge 1 commit into
smart-mcp-proxy:mainfrom
nlaurance:feat/config-tool-allowlist

Conversation

@nlaurance
Copy link
Copy Markdown

@nlaurance nlaurance commented May 14, 2026

Summary

  • Adds enabled_tools (allowlist) and disabled_tools (denylist) fields to ServerConfig so operators can declare tool visibility statically in mcp_config.json without needing to call the API or CLI after every fresh install
  • The two fields are mutually exclusive — config validation rejects a server with both set
  • On every applyDifferentialToolUpdate (server connect / tool refresh), the new applyConfigToolFilter syncs the config declarations into BBolt ToolApprovalRecord.Disabled flags, so all existing enforcement paths (isToolCallable, retrieve_tools pre-ranking, call_tool_*, direct mode) pick up the change automatically

Usage

{
  "mcpServers": [
    {
      "name": "github",
      "url": "https://api.github.com/mcp",
      "enabled_tools": ["list_issues", "get_issue", "list_repos"]
    },
    {
      "name": "filesystem",
      "url": "...",
      "disabled_tools": ["write_file", "delete_file", "execute_code"]
    }
  ]
}

Test plan

  • go test ./internal/config/ ./internal/runtime/ — 349 tests pass
  • TestApplyConfigToolFilter_EnabledTools_DisablesNonListedTools — allowlist hides unlisted tools
  • TestApplyConfigToolFilter_DisabledTools_DisablesListedTools — denylist hides specified tools
  • TestApplyConfigToolFilter_NoFilter_NoChanges — no records written when neither field is set
  • TestApplyConfigToolFilter_EnabledTools_ReEnablesTool — tool moved back into allowlist is re-enabled
  • TestApplyDifferentialToolUpdate_RespectsEnabledToolsConfig — end-to-end through applyDifferentialToolUpdate
  • TestValidateDetailed/enabled_tools_and_disabled_tools_are_mutually_exclusive — validation rejects both fields set simultaneously
  • go build ./... — clean build

🤖 Generated with Claude Code

…enylist

Adds two mutually exclusive fields to ServerConfig that let operators
declare tool visibility statically in mcp_config.json rather than
having to call the API or CLI after every fresh install.

  enabled_tools: ["list_issues", "get_issue"]   // allowlist — only these visible
  disabled_tools: ["delete_repo", "force_push"]  // denylist  — hide these, allow rest

Config validation rejects a server that has both fields set.

On every applyDifferentialToolUpdate (server connect / tool refresh),
applyConfigToolFilter walks the in-memory config, computes the desired
enabled/disabled state for each discovered tool, and calls
setToolEnabledNoEmit to persist it in BBolt. All existing enforcement
paths (isToolCallable, retrieve_tools pre-ranking, call_tool_*) pick
up the change automatically with no further modifications.

Five unit tests cover: allowlist disables unlisted tools, allowlist
re-enables a tool moved back into the list, denylist disables listed
tools, no-op when neither field is set, and end-to-end integration
through applyDifferentialToolUpdate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant