Skip to content

feat: add --enabled-tools flag to filter available MCP tools#173

Merged
korotovsky merged 10 commits intokorotovsky:masterfrom
RedSlowpoke:feature/enabled-tools-flag
Feb 8, 2026
Merged

feat: add --enabled-tools flag to filter available MCP tools#173
korotovsky merged 10 commits intokorotovsky:masterfrom
RedSlowpoke:feature/enabled-tools-flag

Conversation

@RedSlowpoke
Copy link

Summary

  • Add a new CLI flag --enabled-tools (alias -e) to specify which MCP tools to load
  • Add SLACK_MCP_ENABLED_TOOLS environment variable as fallback
  • If not set, all tools are enabled (backward compatible)
  • Provides flexibility to limit tool exposure based on security requirements or use case

Changes

  • cmd/slack-mcp-server/main.go: Add flag parsing and env var support
  • pkg/server/server.go: Add shouldAddTool() helper and conditional tool registration
  • README.md and docs/03-configuration-and-usage.md: Document the new feature

Example Usage

# Enable only read-only tools
slack-mcp-server --enabled-tools=conversations_history,conversations_replies,channels_list

# Via environment variable
SLACK_MCP_ENABLED_TOOLS=conversations_history,channels_list slack-mcp-server

Available Tools

conversations_history, conversations_replies, conversations_add_message, reactions_add, reactions_remove, attachment_get_data, conversations_search_messages, channels_list

Test plan

  • Build passes: go build ./cmd/slack-mcp-server
  • Existing tests pass: go test ./...
  • Verify --help shows new flags

Add a new CLI flag `--enabled-tools` (alias `-e`) and environment variable
`SLACK_MCP_ENABLED_TOOLS` to allow users to specify which MCP tools should
be loaded. This provides flexibility to limit tool exposure based on
security requirements or use case.

- If not set, all tools are enabled (backward compatible)
- Accepts comma-separated tool names
- CLI flag takes precedence over environment variable

Available tools: conversations_history, conversations_replies,
conversations_add_message, reactions_add, reactions_remove,
attachment_get_data, conversations_search_messages, channels_list

Example usage:
  slack-mcp-server --enabled-tools=conversations_history,channels_list
  SLACK_MCP_ENABLED_TOOLS=channels_list slack-mcp-server

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@korotovsky
Copy link
Owner

Somehow closes #167

@korotovsky
Copy link
Owner

How does this work when for example you need explicitly enable SLACK_MCP_ADD_MESSAGE_TOOL since default value is all tools?

@RedSlowpoke
Copy link
Author

How does this work when for example you need explicitly enable SLACK_MCP_ADD_MESSAGE_TOOL since default value is all tools?

These are separate concerns:

  • SLACK_MCP_ENABLED_TOOLS controls which tools are exposed via MCP.
  • SLACK_MCP_ADD_MESSAGE_TOOL controls whether conversations_add_message and reactions_add are allowed (checked by the handler).

If ENABLED_TOOLS is empty, all tools are exposed. But even then, ADD_MESSAGE_TOOL must be set for the handler to accept message actions.

When both are used, they act together restrictively:
To use conversations_add_message, the tool must be both exposed and explicitly enabled.

My vision is that it's enough to rely on ENABLED_TOOLS going forward — it’s more generic and precise. The per-tool flags still work but are optional if exposure is already controlled.

@korotovsky
Copy link
Owner

The problem with "If ENABLED_TOOLS is empty, all tools are exposed" is everyone who is running MCP on @latest and eventually with your new default empty string, then once we will add new tools, then their deployments will get new tools out of blue (tools injection)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@RedSlowpoke RedSlowpoke marked this pull request as draft January 31, 2026 13:16
sspiridonov and others added 3 commits January 31, 2026 14:50
Simplify the logic so that:
- ENABLED_TOOLS only controls which tools are registered/exposed via MCP
- Empty ENABLED_TOOLS = all tools registered (no filtering)
- Runtime permissions (ADD_MESSAGE_TOOL, REACTION_TOOL, ATTACHMENT_TOOL)
  are always enforced in handlers regardless of ENABLED_TOOLS

This keeps the two concerns separate:
1. Registration/visibility (ENABLED_TOOLS)
2. Runtime permissions (individual tool env vars)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Tool* constants to avoid magic strings in tool registration
- Add ValidToolNames slice and ValidateEnabledTools function
- Validate tool names at startup, fail with helpful error message
- Update tests to use constants

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@RedSlowpoke RedSlowpoke marked this pull request as ready for review January 31, 2026 14:23
@RedSlowpoke
Copy link
Author

@korotovsky I've added tests and some more changes. But my understanding that those 2 flags work in a different "layers". The current one in runtime, and the one that I've proposed should work on registration.

Let me know what should i add or change further, to achive the goal. Thanks.

@korotovsky
Copy link
Owner

It is a secondary layer, right, but then it somehow becomes confusing when we set empty value for "all tools", but then later on somehow the tool would be disfunctional (but enabled) so +1 extra env is needed.

What is the goal of the PR? Do you want to automatically get all new tools once MCP gets updated, or you just one to get control over selectivity what is enabled in the MCP server when it's running?

@RedSlowpoke
Copy link
Author

My goals

  1. Granular, transparent control
    I want to control which tools are registered, not just checked at runtime. This is useful for our internal plugin, where allowed tools are defined in .mcp.json.
  2. Save context
    Don’t register tools that won’t be used. This slightly reduces context and keeps things cleaner.

Behavior
• No changes for existing users — changing how current flags affect registration would be breaking, so this PR keeps today’s behavior.
• An empty SLACK_MCP_ENABLED_TOOLS works exactly as it does now (all tools exposed by default).
• I can add a concrete usage example showing how to enable conversations_add_message correctly.

@RedSlowpoke
Copy link
Author

@korotovsky could you kindly tell me what should I do to progress with MR or could you close it as not desired change?

@korotovsky
Copy link
Owner

korotovsky commented Feb 5, 2026

Hi @RedSlowpoke, I see main issue with existing SLACK_MCP_ADD_MESSAGE_TOOL, if it's not defined and you also not set any configuration for this new PR == default value equals all tools, which results in a very contradictory config in my opinion - your "feature" dictate all tools are enabled (incl. message tool? That would have been logical), but fact that SLACK_MCP_ADD_MESSAGE_TOOL is not set would take priority over and user will get an error and it will be very awkward behavior.

@RedSlowpoke
Copy link
Author

I may propose the following strategy:

Slack message sending behavior

ENABLED_TOOLS ↓ \ SLACK_MCP_ADD_MESSAGE_TOOL → absent / empty true list (channels/users)
absent / empty - (currently denied in runtime, will be not registered) YES (current behaviour) YES (scoped, current behaviour)
NOT absent and does NOT include slack.add_message - - -
includes slack.add_message YES YES YES (scoped)

Legend:
- = send tool is NOT registered
YES = user can send messages
YES (scoped) = user can send messages only to specified channels/users

Do you think it's transparent and awkward, or how can I do this better?

Write tools (conversations_add_message, reactions_add, reactions_remove,
attachment_get_data) now require explicit enablement:
- If ENABLED_TOOLS explicitly includes the tool, register it
- If ENABLED_TOOLS is empty, only register if tool-specific env var is set
- If ENABLED_TOOLS excludes the tool, don't register

This resolves the conflict where ENABLED_TOOLS="" would register all tools
but SLACK_MCP_ADD_MESSAGE_TOOL="" would fail at runtime with an error.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@korotovsky
Copy link
Owner

From what I could see here 2ef39fe#diff-fe7a244e18e92d8f347af17363209172e1d79224f086b0585a1bbeef3b626c4eR268-R275 did I understand correctly, that SLACK_MCP_ENABLED_TOOLS has now higher priority over old SLACK_MCP_ADD_MESSAGE_TOOL but there is a special logic if they both NOT set (disarm tool) because default value for SLACK_MCP_ENABLED_TOOLS for SLACK_MCP_ENABLED_TOOLS is actually enable tools?

- Merge shouldAddTool and shouldAddWriteTool into single function
- Remove redundant comments
- Add envVarName parameter for write tools requiring explicit enablement

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@RedSlowpoke
Copy link
Author

did I understand correctly, that SLACK_MCP_ENABLED_TOOLS has now higher priority

yes, if set

there is a special logic if they both NOT set (disarm tool)

Yes

Basically the idea, that if you use the latest introduced flag - you understand how it works, and if you don't use it. It works (almost) as it was when the oldest flags were introduced.

| `SLACK_MCP_USERS_CACHE` | No | `.users_cache.json` | Path to the users cache file. Used to cache Slack user information to avoid repeated API calls on startup. |
| `SLACK_MCP_CHANNELS_CACHE` | No | `.channels_cache_v2.json` | Path to the channels cache file. Used to cache Slack channel information to avoid repeated API calls on startup. |
| `SLACK_MCP_LOG_LEVEL` | No | `info` | Log-level for stdout or stderr. Valid values are: `debug`, `info`, `warn`, `error`, `panic` and `fatal` |
| `SLACK_MCP_ENABLED_TOOLS` | No | `nil` | Comma-separated list of tools to register. If not set, all tools are registered. Use this to limit which tools are exposed via MCP. Note: Runtime permissions (e.g., `SLACK_MCP_ADD_MESSAGE_TOOL`) are still enforced regardless of this setting. Available tools: `conversations_history`, `conversations_replies`, `conversations_add_message`, `reactions_add`, `reactions_remove`, `attachment_get_data`, `conversations_search_messages`, `channels_list`. |
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's the docs also cover SLACK_MCP_ADD_MESSAGE_MARK.

@korotovsky
Copy link
Owner

OK I think we are quite close to get that merged, could you improve a general docs about how new functionality works with a couple of examples (not tool prompts), (I will also use it in the release notes later) and then we will merge it.

sspiridonov and others added 3 commits February 8, 2026 22:13
- SLACK_MCP_ADD_MESSAGE_MARK now mentions both enablement methods
- SLACK_MCP_ENABLED_TOOLS clarifies write tools behavior
- SLACK_MCP_ADD_MESSAGE_TOOL clarifies fallback to ENABLED_TOOLS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add dedicated documentation section explaining ENABLED_TOOLS feature with:
- Overview of two-layer system (registration vs runtime permissions)
- Four practical configuration examples
- Behavior matrix showing all combinations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolve conflict in README.md by keeping updated env var descriptions
that document the SLACK_MCP_ENABLED_TOOLS interaction.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@korotovsky
Copy link
Owner

korotovsky commented Feb 8, 2026

As I understand this is a breaking change for people for a) updates on @latest and b) had some write tools, right? (just wanted to double check for release notes)

@RedSlowpoke
Copy link
Author

Write tools are no longer registered by default

Write tools (conversations_add_message, reactions_add, reactions_remove, attachment_get_data)
are no longer registered by default. Previously they appeared in the tool list but failed at
runtime without their respective permission env vars.

If you had these env vars configured:

  • SLACK_MCP_ADD_MESSAGE_TOOL for conversations_add_message
  • SLACK_MCP_REACTION_TOOL for reactions_add/remove
  • SLACK_MCP_ATTACHMENT_TOOL for attachment_get_data

No action needed - tools will be registered and work as before.

If you didn't: You'll see fewer tools in the list. This is intentional - they weren't
functional anyway.

Alternative: Use SLACK_MCP_ENABLED_TOOLS to explicitly list tools without permission restrictions.

@korotovsky korotovsky merged commit 6065e51 into korotovsky:master Feb 8, 2026
3 checks passed
@RedSlowpoke RedSlowpoke deleted the feature/enabled-tools-flag branch February 8, 2026 22:27
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.

2 participants