Feature Request: CLI Commands for MCP Server Enable/Disable (Hook Automation Support)

Status Open
Maintainer reply None cached
Activity 15 comments · opened Oct 27, 2025

Feature Request: CLI Commands for MCP Server Enable/Disable (Hook Automation Support)

Problem Statement

Claude Code v2.0.10 introduced the ability to enable/disable MCP servers within a session via the @ UI menu. This is excellent for manual control, but there's currently no way to programmatically toggle MCP servers via CLI commands. This prevents automation through hooks and scripts.

Current Limitations:

  1. The claude mcp CLI only supports add, remove, list, and get - no enable/disable/toggle
  2. MCP servers consume context window even when not actively needed
  3. No way to automate MCP lifecycle based on project context, skills, or workflows
  4. The @ menu toggle is UI-only with no programmatic equivalent

Use Case: Skill-Based MCP Management

I have several Claude Code skills that require specific MCP servers, but only occasionally:

Example Skills:

  • accessibility-compliance-expert skill → Needs Playwright MCP for visual testing
  • library-documentation research → Needs Context7 MCP for API docs
  • database-analysis tasks → Needs database MCP tools

Current Problem:

  • All MCP servers load at session start, consuming 15-20% of context window
  • Playwright MCP alone: ~8-10k tokens, but only needed for visual testing tasks
  • Context7 MCP: ~5k tokens, but only needed for documentation lookup
  • These servers sit idle 90% of the time, wasting valuable context

Desired Workflow:

# SessionStart hook - enable only baseline MCPs
claude mcp disable playwright
claude mcp disable context7

# PreToolUse hook - enable when specific skill triggers
if [[ "$context" =~ "accessibility-compliance-expert" ]]; then
  claude mcp enable playwright
fi

# Stop hook - disable when skill completes to free context
claude mcp disable playwright

Proposed CLI Commands

Add these commands to the claude mcp CLI:

# Enable an MCP server in current session (doesn't modify config files)
claude mcp enable <server-name>

# Disable an MCP server in current session (doesn't modify config files)  
claude mcp disable <server-name>

# Toggle an MCP server's state
claude mcp toggle <server-name>

# Show current enabled/disabled state of all servers
claude mcp status

Example Usage:

$ claude mcp status
✓ pieces-mcp          enabled   (3.2k tokens)
✗ playwright          disabled  
✓ sequential-thinking enabled   (1.8k tokens)
✗ context7            disabled
✓ stripe              enabled   (4.1k tokens)

Total active: 3/5 servers (9.1k tokens)

$ claude mcp disable stripe
✓ Disabled stripe (freed 4.1k tokens)

$ claude mcp enable playwright  
✓ Enabled playwright (loaded 8.3k tokens)

Hook Integration Example

SessionStart Hook (.claude/hooks/session-start.sh):

#!/bin/bash
# Disable rarely-used MCPs at session start

claude mcp disable playwright
claude mcp disable context7

# Enable based on project type
if [[ -f "package.json" ]] && grep -q "@playwright/test" package.json; then
  claude mcp enable playwright
  echo "📊 Enabled Playwright MCP for testing project"
fi

PreToolUse Hook (.claude/hooks/pre-tool-use.sh):

#!/bin/bash
# Enable MCP when specific skill triggers

# Read context from environment
context="$CLAUDE_CONTEXT"

if [[ "$context" =~ "accessibility-compliance-expert" ]]; then
  # Enable Playwright only when accessibility skill is active
  claude mcp enable playwright
fi

SubagentStop Hook (.claude/hooks/subagent-stop.sh):

#!/bin/bash
# Free up context when specialized subagent completes

subagent_name="$CLAUDE_SUBAGENT_NAME"

if [[ "$subagent_name" == "accessibility-compliance-expert" ]]; then
  claude mcp disable playwright
  echo "♻️ Freed context: disabled Playwright MCP"
fi

Benefits

  1. Context Window Optimization
  • Load MCP servers on-demand instead of all-at-once
  • Free context by disabling servers when done
  • Optimize for long development sessions with varying needs
  1. Skill-Based Automation
  • Skills can automatically enable their required MCPs
  • Clean up after themselves to avoid context bloat
  • Smooth integration with subagent workflows
  1. Project-Based Profiles
  • SessionStart hooks enable relevant MCPs based on project type
  • Testing projects get Playwright, database projects get DB tools
  • No manual toggling required
  1. Hook Ecosystem Integration
  • PreToolUse, Stop, SubagentStop hooks manage MCP lifecycle
  • Automated workflows without manual intervention
  • ADHD-friendly: reduces decision fatigue

Implementation Considerations

Session-Level Only:

  • These commands affect current session only (not config files)
  • Changes don't persist across session restarts
  • Config files (.mcp.json, settings.json) remain unchanged

Relationship to @ Menu:

  • CLI commands should mirror the behavior of the UI @ toggle
  • Both methods (UI and CLI) modify the same session state
  • claude mcp status should reflect current state regardless of how it was set

Security:

  • Respect existing approval workflows for project-scoped servers
  • Honor managed-mcp.json enterprise policies
  • Enabling a disabled server may still prompt for project approval if not yet granted

Error Handling:

$ claude mcp enable nonexistent-server
❌ Error: MCP server 'nonexistent-server' not found in configuration
   Available servers: pieces-mcp, playwright, sequential-thinking

$ claude mcp disable playwright
✓ Disabled playwright

$ claude mcp disable playwright  
⚠️ Warning: playwright is already disabled

Why This is Different from Existing Issues

While several issues request runtime toggling (#6309, #6638), this request specifically focuses on:

  1. CLI automation (not just UI toggle, which already exists)
  2. Hook integration (SessionStart, PreToolUse, Stop, SubagentStop)
  3. Skill-based workflows (automated MCP lifecycle management)
  4. Concrete implementation (specific command syntax and examples)

Alternative Solutions Considered

  1. Project-scoped .mcp.json with enabledMcpjsonServers
  • Problem: Only works at session start, not mid-session
  • Problem: Requires session restart to change
  1. PreToolUse hooks blocking MCP tools
  • Problem: Doesn't free context, server still loaded
  • Problem: Shows confusing errors instead of smooth workflow
  1. Multiple Claude Code profiles/sessions
  • Problem: Fragments workflow across sessions
  • Problem: Loses conversation context when switching

Related Issues

  • #6309 - Runtime MCP Server Toggle (general request)
  • #6638 - Dynamic loading/unloading (context optimization focus)
  • #7328 - Tool-level filtering (related but different scope)
  • #3036 - MCP servers eating context window

Priority

High - This enables a powerful automation workflow that significantly improves context management and integrates with Claude Code's existing hook system.

---

Environment:

  • Claude Code Version: 2.0.22 (latest)
  • MCP Servers: 5-7 servers configured per project
  • Context Impact: 15-20k tokens consumed by idle MCP servers

View original on GitHub ↗

15 Comments

github-actions[bot] · 10 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/6309
  2. https://github.com/anthropics/claude-code/issues/6638
  3. https://github.com/anthropics/claude-code/issues/7172

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

mtrefilek · 10 months ago

@claude

Found 3 possible duplicate issues: https://github.com/anthropics/claude-code/issues/6309

I don't think this fully encapsulates this issue which would allow for running in hooks

dlecan · 9 months ago

That's exactly what I'm looking for

ppf · 9 months ago

It's exactly what I need. It could be the massive update for context management.
Anthropic introduced some great tools in the API SDK recently:

  • Tool Search Tool, which allows Claude to use search tools to access thousands of tools without consuming its context window
  • Programmatic Tool Calling, which allows Claude to invoke tools in a code execution environment reducing the impact on the model’s context window
  • Tool Use Examples, which provides a universal standard for demonstrating how to effectively use a given tool

https://www.anthropic.com/engineering/advanced-tool-use
CC should use these features.

github-actions[bot] · 8 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

yakimoto · 8 months ago

Looking for this as well -- this would enable context auto load / offload dependent on hooks

ratio-dd · 7 months ago

I think that's an really excellent feature and will massively enhance context control

BnSmth · 6 months ago

+1 on this

I currently run two MCP servers (Things + Google Calendar) that together consume ~12.4K tokens of context on every session. After analysing my usage history across all sessions, I found that roughly 3K tokens worth of tools have never been called once, and the remaining tools are only needed in maybe 30-40% of my sessions (planning and daily reviews, not coding).

Combined with the 33K autocompact buffer and ~20K of system prompts/tools, I'm losing nearly 65K tokens of my 200K context window before I've even started working. That's a third of the window gone.

The ability to claude mcp enable/disable mid-session — especially via hooks — would let me:

  1. Start every session lean with MCP servers off by default
  2. Enable on-demand when a skill or prompt needs them (e.g., "what are my todos today?" triggers Things)
  3. Disable after use to reclaim context for the rest of the session

This would effectively give me back ~12K tokens in sessions where I don't need these integrations, which is most of them. That's a meaningful difference — it delays autocompaction and extends the useful life of a conversation.

The @ menu toggle already proves this works at the UI level. Having a CLI equivalent for hooks would make context management significantly more practical.

csferi27 · 6 months ago

+1

BEEFF · 5 months ago

+1

dk-cuttable · 5 months ago

+1

ithiria894 · 5 months ago

For the management side of this — knowing which MCP servers are configured at which scope and cleaning up the ones you don't need — I'm building a visual dashboard that shows all your MCP servers (and memories, skills, hooks) across every scope in a hierarchy view (global, workspace, project).

You can move servers between scopes with drag-and-drop and delete them directly. Doesn't give you runtime enable/disable mid-session yet, but it helps with the "I have 12K tokens of MCP servers loaded and I don't even know which scope they're coming from" problem.

We just launched and this kind of MCP management is exactly what we're building towards — give us a ⭐ to follow along: https://github.com/mcpware/claude-code-organizer

kazukinakai · 5 months ago

I had the exact same frustration — 12K+ tokens of MCP tool definitions eating my context window every session, with no way to toggle them programmatically.

I ended up building a gateway that sits between Claude Code and all MCP servers. Instead of exposing 60+ tools at startup, it exposes just 7 meta-tools (airis-find, airis-exec, airis-schema) and routes to the right server on demand. Tool definitions went from ~42K tokens to ~1.4K — a 97% reduction.

Servers start lazily on first call and auto-terminate after 120s idle, so there's no resource waste either. Effectively gives you the enable/disable behavior at the tool level without needing CLI commands.

docker compose up -d
claude mcp add --scope user --transport sse airis-mcp-gateway http://localhost:9400/sse

Repo: https://github.com/agiletec-inc/airis-mcp-gateway

Not a replacement for native CLI enable/disable (which I still want too), but it solved the context window problem for me today.

yurukusa · 5 months ago

A hook-based approach can toggle MCP servers programmatically:

PROMPT=$(cat | jq -r '.userPrompt // empty' 2>/dev/null)
SETTINGS="$HOME/.claude/settings.json"
if echo "$PROMPT" | grep -qiE 'disable (mcp|server)\s+(\w+)'; then
    SERVER=$(echo "$PROMPT" | grep -oiE 'disable (mcp|server)\s+(\w+)' | awk '{print $NF}')
    if [ -n "$SERVER" ]; then
        jq --arg s "$SERVER" '
            .disabledMcpServers[$s] = .mcpServers[$s] |
            del(.mcpServers[$s])
        ' "$SETTINGS" > "${SETTINGS}.tmp" && mv "${SETTINGS}.tmp" "$SETTINGS"
        jq -n --arg s "$SERVER" '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"MCP server disabled: " + $s + ". Restart session for changes to take effect."}}'
        exit 0
    fi
fi
if echo "$PROMPT" | grep -qiE 'enable (mcp|server)\s+(\w+)'; then
    SERVER=$(echo "$PROMPT" | grep -oiE 'enable (mcp|server)\s+(\w+)' | awk '{print $NF}')
    if [ -n "$SERVER" ]; then
        jq --arg s "$SERVER" '
            .mcpServers[$s] = .disabledMcpServers[$s] |
            del(.disabledMcpServers[$s])
        ' "$SETTINGS" > "${SETTINGS}.tmp" && mv "${SETTINGS}.tmp" "$SETTINGS"
        jq -n --arg s "$SERVER" '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"MCP server enabled: " + $s + ". Restart session for changes to take effect."}}'
        exit 0
    fi
fi
exit 0

Or use a wrapper script for CLI use:

ACTION=$1; SERVER=$2
SETTINGS="$HOME/.claude/settings.json"
case "$ACTION" in
    list)
        echo "Active:" && jq -r '.mcpServers // {} | keys[]' "$SETTINGS"
        echo "Disabled:" && jq -r '.disabledMcpServers // {} | keys[]' "$SETTINGS"
        ;;
    disable)
        jq --arg s "$SERVER" '.disabledMcpServers[$s] = .mcpServers[$s] | del(.mcpServers[$s])' "$SETTINGS" | sponge "$SETTINGS"
        echo "Disabled $SERVER"
        ;;
    enable)
        jq --arg s "$SERVER" '.mcpServers[$s] = .disabledMcpServers[$s] | del(.disabledMcpServers[$s])' "$SETTINGS" | sponge "$SETTINGS"
        echo "Enabled $SERVER"
        ;;
esac

Combine with a Notification start hook to auto-disable context-inappropriate servers:

[ ! -f docker-compose.yml ] && ~/bin/mcp-toggle disable database 2>/dev/null
sudara · 3 months ago

It would be great to see this feature in the CLI.

The Claude Code app seems to be able to programmatically restart mcp servers (in my case, a stdio app that needs to recompile).