Claude.ai MCP servers auto-injected into Claude Code without opt-in — causes OOM crashes on resource-constrained systems

Resolved 💬 38 comments Opened Jan 23, 2026 by MattStarfield Closed Jun 22, 2026
💡 Likely answer: A maintainer (localden, collaborator) responded on this thread — see the highlighted reply below.

Bug Description

Claude Code 2.1.x silently syncs MCP servers from the user's Claude.ai web account into Claude Code sessions without any opt-in, notification, or consent. This creates duplicate MCP servers and significant memory overhead that causes OOM kills on resource-constrained systems.

Environment

  • Claude Code version: 2.1.17
  • Platform: Raspberry Pi 5 (16GB RAM, 2GB swap, aarch64)
  • OS: Debian Bookworm (Raspberry Pi OS), kernel 6.12.62+rpt-rpi-2712

The Problem

After updating to 2.1.x, I discovered 6 "claude.ai" remote MCP servers were automatically loaded into my Claude Code sessions:

claude.ai Remote MCP Lookup Directory: https://mcp.remote-mcp.com - ✓ Connected
claude.ai PayPal: https://mcp.paypal.com/mcp - ✗ Failed to connect
claude.ai AWS Knowledge: https://knowledge-mcp.global.api.aws - ✓ Connected
claude.ai CORE Memory: https://core.heysol.ai/api/v1/mcp?source=claude - ✓ Connected
claude.ai Notion: https://mcp.notion.com/mcp - ⚠ Needs authentication
claude.ai Hugging Face: https://huggingface.co/mcp?login&gradio=none - ⚠ Needs authentication

I never asked for these to be added to Claude Code. These were MCP integrations I connected through the Claude.ai web interface for use in the web UI — not for CLI use.

Impact

1. Duplicate MCP servers consuming double memory

Three of the injected servers are duplicates of servers I already configured locally:

  • aws-knowledge (local) + claude.ai AWS Knowledge (injected)
  • core-memory (local) + claude.ai CORE Memory (injected)
  • notion (local) + claude.ai Notion (injected)

2. Unwanted servers I never intended to use in Claude Code

  • PayPal MCP (why is this in my CLI coding tool?)
  • Hugging Face MCP (never configured for CLI use)
  • Remote MCP Lookup Directory (unnecessary overhead)

3. OOM kills crashing active sessions

On my Raspberry Pi 5 (16GB RAM, 2GB swap), the additional memory overhead from these injected servers pushed the system over the edge. The Linux OOM killer started killing Claude processes:

dmesg output:
oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,
    oom_memcg=/user.slice/user-1000.slice/user@1000.service,
    task_memcg=/user.slice/user-1000.slice/user@1000.service,task=claude,pid=XXXX

Swap was 100% exhausted (2.0Gi/2.0Gi, 5.7Mi free). Sessions were being SIGKILL'd mid-work.

4. Cannot be removed via CLI

claude mcp remove "claude.ai PayPal" returns "No MCP server found" — these servers bypass the normal MCP management system entirely.

Root Cause

The feature flag tengu_claudeai_mcp_connectors (in cachedGrowthBookFeatures) was set to True without user consent. This causes Claude Code to pull MCP integrations from the user's Claude.ai account and load them into every CLI session.

Workaround

Manually editing ~/.claude.json to set:

"cachedGrowthBookFeatures": {
    "tengu_claudeai_mcp_connectors": false
}

However, this is a cached flag and may be overwritten on next update/startup.

Expected Behavior

  1. This should be opt-in, not opt-out. Users should explicitly choose to sync Claude.ai MCP servers to Claude Code.
  2. At minimum, there should be a claude config setting to disable this (e.g., claude config set syncRemoteMcps false)
  3. Duplicate detection — if a user already has notion configured locally, don't also load claude.ai Notion
  4. Resource awareness — on constrained systems, loading 6 additional MCP servers (each with HTTP connection overhead, memory for tool schemas, etc.) is not free
  5. claude mcp remove should work for these servers, or there should be a claude mcp remove --remote option

Requested Fix

  • Add a user-facing configuration option to disable Claude.ai MCP sync
  • Make this feature opt-in rather than opt-out
  • Implement duplicate detection to avoid loading the same MCP endpoint twice
  • Allow removal of remote MCPs via the standard claude mcp remove command

View original on GitHub ↗

38 Comments

MattStarfield · 5 months ago

Additional Issue: Selective/Inconsistent Sync

To make this even more confusing, the sync between Claude.ai and Claude Code is selective and inconsistent. Looking at the MCP integrations connected to my Claude.ai account, not all of them are being synced to Claude Code.

For example:

  • Google MCPs (Drive, Calendar, Gmail, Sheets, Docs, Slides) — connected on Claude.ai but NOT synced to Claude Code
  • PayPal — connected on Claude.ai and IS synced to Claude Code
  • Hugging Face — connected on Claude.ai and IS synced (but can't authenticate)

There's no apparent logic to which integrations get pulled in and which don't. This makes it impossible for users to predict or control what will appear in their Claude Code MCP list.

This inconsistency compounds the original issue:

  1. Users can't reason about what's happening ("why is PayPal here but not Google?")
  2. It creates a false sense of separation ("I set up Google on Claude.ai, it didn't appear in Claude Code, so I assumed nothing syncs")
  3. The injected servers aren't clearly communicated as coming from a remote source until you notice the "claude.ai" prefix in claude mcp list

The behavior should be all-or-nothing with explicit user control — not a mysterious partial sync that silently loads some integrations while ignoring others.

MattStarfield · 5 months ago

Additional Issue: Claude.ai Connector "Remove" Button Non-Functional

After discovering the auto-injected MCPs, I went to Claude.ai's Connectors settings to remove them entirely.

What I found:

  • There is a "Remove" button next to each connector
  • Clicking it does nothing — the connector remains in the list
  • The only functional action is "Disconnect", which toggles the connector off but doesn't delete it
  • Disconnected connectors remain in the list indefinitely with no way to permanently remove them

Concern: If these "disconnected" connectors can still be synced to Claude Code when the tengu_claudeai_mcp_connectors feature flag is active (which gets re-enabled server-side on every startup), then there is truly no way for a user to prevent unwanted MCP servers from being injected into their Claude Code environment.

Expected behavior: The Remove button should permanently delete the connector registration, preventing any future sync to Claude Code regardless of feature flag state.

Current workaround: None. Users cannot permanently remove connectors from their account, and the local feature flag override gets refreshed from the server on every Claude Code startup.

wayum999 · 5 months ago

yes the first is unacceptable, i saw my claude code performance diminish to the point of almost unusable until i figured out this was why. also, disabling them in the claude code CLI should disable them globally for the CLI, comparable to the user scope. this is a big issue.

Kunatredwood · 5 months ago

This is a serious issue that breaks our project based MCP set up and management with team plan. Claude Desktop and Code are used by different teams with different policies, now we need to ask team members to disable Claude ai MCPs from each project one by one manually.

mpenza · 5 months ago

Workaround: SessionStart hook to auto-disable synced connectors

Until there's an official toggle, here's a workaround. This uses a SessionStart hook to automatically add the synced connectors to disabledMcpServers for every project on startup.

1. Create the hook script (e.g., ~/.claude/hooks/disable-claudeai-connectors.sh):

#!/bin/bash
# Auto-disable claude.ai MCP connectors synced from claude.ai account.
# Runs as a SessionStart hook to patch ~/.claude.json per-project.

set -euo pipefail

CLAUDE_JSON="$HOME/.claude.json"

# Add your unwanted connectors here
CONNECTORS='["claude.ai Home Assistant", "claude.ai Stripe"]'

# Read hook input to get current working directory
CWD=$(jq -r '.cwd' < /dev/stdin)

if [ -z "$CWD" ] || [ "$CWD" = "null" ]; then
  exit 0
fi

if [ ! -f "$CLAUDE_JSON" ]; then
  exit 0
fi

# Add connectors to the project's disabledMcpServers array (deduplicated).
# Creates the project entry and array if they don't exist.
jq --arg cwd "$CWD" --argjson connectors "$CONNECTORS" '
  .projects[$cwd].disabledMcpServers = (
    (.projects[$cwd].disabledMcpServers // []) + $connectors | unique
  )
' "$CLAUDE_JSON" > "${CLAUDE_JSON}.tmp" && mv "${CLAUDE_JSON}.tmp" "$CLAUDE_JSON"

Make it executable: chmod +x ~/.claude/hooks/disable-claudeai-connectors.sh

  1. Register the hook in ~/.claude/settings.json:
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "$HOME/.claude/hooks/disable-claudeai-connectors.sh"
          }
        ]
      }
    ]
  }
}

How it works:

  • On every new session, the hook reads the working directory from the hook input
  • It patches ~/.claude.json to add the unwanted connectors to that project's disabledMcpServers array
  • Idempotent — deduplicates entries, safe to run repeatedly
  • Edit the CONNECTORS array in the script to match whatever connectors are being synced to your instance

Requirements: jq must be installed.

This won't prevent the connectors from syncing, but it ensures they're disabled before you interact with them. Still hoping for a proper opt-out setting.

nick-youngblut · 5 months ago

Why is there no way of disabling the MCP servers by default across sessions? Suddenly, all of my claude code sessions show:

 Context Usage Warnings
 └ ⚠ Large MCP tools context (~90,551 tokens > 25,000)
   └ MCP servers:

...and all I can do is disable each of the 15 connectors manually for EACH claude code project.

jamie-tm · 5 months ago

Using ENABLE_TOOL_SEARCH=true helps a lot with the performance issues, as it prevents the unwanted MCPs from being loaded into context until they're needed. But that's not the only issue here.

For me, the issue is that I use Claude in different contexts. I have multiple user accounts on my dev server, with different configurations. For example: I use Linear both at work and at home, so my work and personal users both have Linear MCPs set up. This works fine until Claude Code auto-syncs the "Claude.ai Linear" in my personal projects and Claude starts trying to read (or worse, write!) issues in my work account.

I have to be able to turn this off, or at least globally disable an MCP server at the user level in ~/.claude.json. (The tengu_claudeai_mcp_connectors setting seems to have worked, at least temporarily.)

sunir · 5 months ago

MCP servers I use on Claude web have a different security perimeter than the ones I use on a given local machine. This has granted a local Claude on a controlled machine means to exfiltrate data or access the public Internet or tools like Zapier without my awareness.

No tool should be yoloing a Unix environment without the owner's explicit consent. Please revert this change immediately.

nerveband · 5 months ago

Dynamic MCP Loader: SessionStart hook + mcporter for on-demand loading

Building on @mpenza's excellent SessionStart hook workaround above, I packaged a more complete solution that not only disables the cloud connectors but also lets you call them on demand using mcporter — so you get the tools when you need them without the constant context token cost.

The problem this solves

The SessionStart hook disables the connectors, but then you lose access entirely. With mcporter, you can call any disabled connector's tools ad-hoc from the CLI without re-enabling them:

# List what tools a connector exposes
npx mcporter list --http-url https://an-mcp-server.com/mcp --name craft

# Call a tool directly (zero context cost)
npx mcporter call --http-url https://an-mcp-server.com/mcp --name craft 'documents_list()'
Setup

1. Create the hook at ~/.claude/hooks/disable-claudeai-connectors.sh:

#!/bin/bash
set -euo pipefail

CLAUDE_JSON="$HOME/.claude.json"

# List your unwanted connectors
CONNECTORS='["claude.ai Figma", "claude.ai Canva", "claude.ai Your Connector"]'

CWD=$(jq -r '.cwd' < /dev/stdin)
[ -z "$CWD" ] || [ "$CWD" = "null" ] && exit 0
[ ! -f "$CLAUDE_JSON" ] && exit 0

jq --arg cwd "$CWD" --argjson connectors "$CONNECTORS" '
  .projects[$cwd].disabledMcpServers = (
    (.projects[$cwd].disabledMcpServers // []) + $connectors | unique
  )
' "$CLAUDE_JSON" > "${CLAUDE_JSON}.tmp" && mv "${CLAUDE_JSON}.tmp" "$CLAUDE_JSON"
chmod +x ~/.claude/hooks/disable-claudeai-connectors.sh

2. Register in ~/.claude/settings.json:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "$HOME/.claude/hooks/disable-claudeai-connectors.sh"
          }
        ]
      }
    ]
  }
}

3. Install mcporter (optional, for on-demand access):

brew tap steipete/tap && brew install steipete/tap/mcporter
# or just: npx mcporter (zero-install)
Full skill package

I published the complete solution as a reusable AI skill (works with Claude Code, Cursor, Codex, etc.):

Gist: https://gist.github.com/nerveband/4d5ebc42444cc0abc04d5e33e982fb63**

Includes the hook script, setup guide, and a SKILL.md that teaches AI agents how to use mcporter to dynamically load disabled connectors when needed.

When to use mcporter vs re-enabling

| Scenario | Approach |
|----------|----------|
| One-off tool call | npx mcporter call ... (no context cost) |
| Extended session with many calls | Re-enable via /mcp |
| Automation/hooks | mcporter programmatically |

Still hoping for a proper "mcpConnectors": "disabled" setting, but this keeps things usable in the meantime.

mattheworiordan · 4 months ago

This keeps coming back after every login/re-auth. I have to patch tengu_claudeai_mcp_connectors back to false in .claude.json every single time, and it gets silently overwritten again on the next auth sync.

I'm running a file watcher as a workaround now. That's how bad this is - I need a background daemon to defend my CLI tool's configuration from itself 🤯

A few things that make this particularly frustrating:

  • Claude Code has claude mcp add/remove for managing MCP servers. That's the correct, explicit CLI workflow. But there's no equivalent command to manage or disable the servers being injected from claude.ai. You give us a

proper tool, then bypass it.

  • I now have duplicate MCPs. I configure my company MCP locally for my CLI workflow, and then claude.ai injects its own company MCP on top. Duplicate tools, wasted context tokens, confusion about which one is active.
  • CLI and web are different environments with different needs. Figma, Miro, Stripe - these are desktop integrations that make sense in a browser. They're completely irrelevant in a terminal coding session and just add noise.
  • There's no opt-out. No CLI flag, no config setting that persists. The only defence is patching a cached feature flag that the server keeps overwriting.

This is a developer tool. Silently injecting MCP servers that users didn't ask for, can't disable through any official mechanism, and that keep reappearing after every login - that's not a feature, it's a hostile UX pattern.

Please give us a persistent opt-out or, better yet, make this opt-in.

chrisvaillancourt · 4 months ago

+1 on this. I have my own locally-configured MCP servers for Atlassian and Slack via .mcp.json, so the auto-injected "claude.ai" duplicates are unwanted. They show up in every new project and have to be manually disabled each time via /mcp.

Attempted to use deniedMcpServers in user settings to block them globally, but the serverName regex (^[a-zA-Z0-9_-]+$) rejects the "claude.ai" naming format (dots and spaces). Related: #23838.

Would appreciate either an opt-in toggle for the claude.ai MCP sync, or fixing deniedMcpServers to accept these server names so users can selectively block them.

gwpl · 4 months ago

+1 on needing a persistent opt-out for cloud MCP connector injection.

My use case: I have Hugging Face MCP enabled in claude.ai for research in the web UI chatbot. It works great there. But when I'm coding in Claude Code CLI, I don't need it — it just consumes context tokens and clutters the tool list. The two environments (web chatbot vs. local CLI) have fundamentally different needs, and the current behavior forces them to share the same MCP configuration with no separation.

I discovered the injected servers only after noticing Claude Code sessions engaging with Hugging Face tools I never configured locally. After investigating all local config files (~/.claude.json, .mcp.json, ~/.claude/settings.json) and finding nothing, I concluded they were being injected server-side. The official docs confirm this under "Use MCP servers from Claude.ai".

What I'd like to see (in order of preference):

  1. "mcpConnectors": "disabled" setting in ~/.claude/settings.json — simple, persistent, doesn't affect claude.ai web UI. This was proposed in #22301 before it was closed as a duplicate of this issue.
  1. Granular per-connector control — e.g., "disabledMcpConnectors": ["claude.ai Hugging Face"] in settings.json, persisting across sessions and projects. This would also resolve the duplicate server problem others have reported.
  1. At minimum, make claude mcp remove work for cloud connectors, or add claude mcp disable --cloud <name> as a persistent toggle.

The current workarounds (/mcp per-session, feature flag hacking tengu_claudeai_mcp_connectors that gets overwritten on re-auth, SessionStart hooks) are all fragile and require ongoing maintenance. A first-class setting would resolve this cleanly.

Additional workaround for others landing here: you can force-disable all MCP servers (including cloud connectors) for a session with:

claude --strict-mcp-config --mcp-config '{}'

This is a nuclear option (kills local MCPs too), but useful when you need a clean coding session with zero MCP overhead.

Also noting that deniedMcpServers in managed settings can't block these servers because the serverName regex rejects the "claude.ai ..." naming format (#23838) — so even the enterprise tooling can't address this.

jamie-tm · 4 months ago

Another possible workaround might be to make a dedicated MCP config file and inject it with

claude --strict-mcp-config --mcp-config "$(cat ~/.claude-local-mcp.json)"

But that's a brutish workaround that shouldn't be necessary.

cleggypdc · 4 months ago

+1 on this. My use case is slightly different but related:

I need different authentication credentials for the same MCP server type across different Claude Code projects (different orgs/contexts), while still keeping the MCP server enabled for
claude.com web chats.

Current options are all bad:

  • Keep global enabled + add project-scoped = duplicate tools (both appear)
  • Disable globally = loses MCP in web chats
  • The cachedGrowthBookFeatures hack = not per-project, and unreliable

What would solve this:

  • Project-scoped servers should fully override/hide global servers with the same name (not coexist)
  • Or: a per-project setting to ignore specific claude.ai MCP servers

The duplicate tools issue is the main friction - if local configs could shadow global ones cleanly, this would be a non-issue.

GitJuhb · 4 months ago

This bug was costing me an extra 75% ON MY USAGE! FIX IT ALREADY. Thanks to everyone on the thread who help workaround it.

marco-machado · 4 months ago

Set this environment variable in your Claude Code settings:

```
// In ~/.claude/settings.json, add to the "env" object:
"env": {
"ENABLE_CLAUDEAI_MCP_SERVERS": "false"
}


  Or export it in your shell before launching Claude Code:
  `export ENABLE_CLAUDEAI_MCP_SERVERS=false`
nick-youngblut · 4 months ago
Set this environment variable in your Claude Code settings:

That completely removes the claude.ai MCPs instead of just deactivating them. I think most users would like the cluade.ai MCP servers available for activation when needed, but deactivate by default.

bdmorin · 4 months ago

Adding my experience here. I had no idea this was happening until I ran claude mcp list and saw three servers I never configured locally:

claude.ai Vercel: https://mcp.vercel.com - Connected
claude.ai Google Calendar: https://gcal.mcp.claude.com/mcp - Connected
claude.ai Gmail: https://gmail.mcp.claude.com/mcp - Connected

I set these up on claude.ai months ago for the web UI — never intended them for CLI use. A terminal tool silently establishing outbound HTTP connections to third-party services based on web dashboard config set in a completely different context violates the principle of least surprise.

What makes this worse:

  • No local config to prevent the connections (only disallowedTools to muzzle usage after they're already connected and consuming context)
  • settingSources: [] in the SDK doesn't block them either — confirmed via testing
  • The only real kill switch is the web dashboard, which per other comments here has its own issues

This should require explicit local opt-in per environment, not silent auto-loading. Something like disableAccountMcp: true in settings.json, or at minimum a first-session prompt: "Your account has 3 MCP integrations. Enable in CLI? [y/N]"

firatoezcan · 4 months ago

https://claude.ai/settings/connectors

You probably have those added here. Just remove them

Yaakov-Belch · 4 months ago

Warning to reporters and readers of this issue:

This issue has no assignee. Of the ~5,947 currently open issues in this repository, only ~96 have assignees. Unassigned issues are subject to automatic "stale" labeling and auto-closure after 14 days of inactivity via sweep.ts. The "stale" label cannot be removed by the issue creator, and new activity does not remove it. Additionally, the duplicate-detection bot creates circular chains of duplicate references, leading to further automatic closures. See #19267 and this comment for documentation of this behavior.

This means your privacy concern will likely be silently deleted from the record without being addressed.

If you believe that auto-installing OAuth connectors to your private email and calendar without consent is a privacy violation, you may want to pursue channels that cannot be auto-closed:

  • Anthropic Privacy Team: privacy@anthropic.com
  • Data Protection Officer: dpo@anthropic.com
  • Formal Data Subject Access Request (DSAR): Email the above addresses citing your applicable privacy law (GDPR, CCPA, Israel's Protection of Privacy Law Amendment 13, etc.) requesting what data was collected and on what legal basis these connectors were installed without consent
  • Regulatory complaint: If Anthropic does not respond adequately, file with your jurisdiction's data protection authority (EU: national supervisory authority; US/California: Attorney General; Israel: Privacy Protection Authority at gov.il; UK: ICO; Brazil: ANPD)

Anthropic's own privacy policy states: "You'll always be in control and can turn off these features in your account settings." Auto-installing connectors to private email via server-side feature flags, with no notification and no clean opt-out, contradicts this commitment.

ch4zm · 4 months ago
You probably have those added here. Just remove them

This is incorrect. Disabling them in https://claude.ai/settings/connectors does NOT disable them or remove them from Claude Code. They still still be enabled because the local MCP settings are CACHED, so disabling connectors has ZERO effect.

Anthropic needs to set ENABLE_CLAUDEAI_MCP_SERVERS to false by default and stop angering their customers with this wasteful, sneaky behavior users did not ask for and did not expect

autemetry-james · 4 months ago

I noticed unsolicited MCP auth prompts for gmail.mcp.claude.com appearing in claude code without explicitly configuring them, which set off alarm bells in my head.

These should be opt-in, and not just because they might be wasting resources.

poiurewq · 4 months ago

Took me about twenty minutes to find a way to disable the two MCP servers (the Gmail and Calendar MCPs) that showed up one day without my consent. /mcp only showed what they were but didn't let me disable them.

Instead, I found out you can type /plugin, tab to the Installed tab, and arrow all the way down to find the MCP servers and disable each using spacebar granularly (instead of the ENABLE_CLAUDEAI_MCP_SERVERS env var, which disables all of them at once).

But my gripe is that I never consented to enabling these third-party MCPs in the first place. Furthermore, once I found out, I had a hard time finding how to disable them. They weren't enabled on my claude.ai account in the first place, nor were they found in my settings.json. I ended up finding the line "tengu_claudeai_mcp_connectors": true under .claude.json which is a hidden config file.

The behavior of claude code automatically trying to auth with services I didn't set up myself bypasses user consent and is also plain annoying, as "claude.ai connectors need auth" warnings kept popping up in my sessions. Hey, at least it's failing loudly, so I could tell that they're trying to access these servers in the first place. I don't want to imagine what would happen if they just all connected silently and claude's attempts to read my third-party data just got buried underneath a whole wall of rapid tool calls you'd need ctrl+o and a sharp eye to find.

coreystanford · 4 months ago

Adding another use case: I want these MCP servers available in the claude.ai web app but not in Claude Code CLI sessions, where they add noise and context bloat.

Tried adding disabledMcpServers to ~/.claude/settings.json with the server display names (e.g. "claude.ai Fathom", "claude.ai Slack", etc.) but it has no effect on OAuth-connected servers — only locally-configured ones seem to be affected by that setting.

A per-client toggle (web vs. CLI) or making disabledMcpServers work for OAuth servers (with documented name format) would solve this.

beverm2391 · 4 months ago

Another data point: this is not just cosmetic/noisy on my machine.

Environment:

  • Claude Code 2.1.75 (also saw it on 2.1.74)
  • macOS 26.3.1 on Apple Silicon

What I am seeing:

  • In ~/.claude.json, the current project already has disabledMcpServers set to "claude.ai Gmail" and "claude.ai Google Calendar".
  • Despite that, claude mcp list still shows both connectors in Claude Code as Needs authentication.
  • claude mcp get/remove cannot target them by name, so they are still in a weird half-managed state.

More importantly, I am also seeing Claude Code occasionally drop straight back to the shell after a turn with the red footer showing 1 MCP server failed immediately beforehand. I cannot prove causality from logs yet, but in practice this feels correlated with unexpected session termination, not just an annoying status warning.

So from this setup: per-project disable state is already present, but the claude.ai Gmail/Calendar connectors still surface as failed, and the bug appears severe enough to coincide with sessions unexpectedly ending.

yurukusa · 3 months ago

A Notification hook on start can detect and warn about duplicate MCP servers:

SETTINGS_FILES=(
    "$HOME/.claude/settings.json"
    ".claude/settings.json"
)
ALL_SERVERS=""
for f in "${SETTINGS_FILES[@]}"; do
    [ -f "$f" ] || continue
    SERVERS=$(jq -r '.mcpServers // {} | keys[]' "$f" 2>/dev/null)
    ALL_SERVERS+="$SERVERS
"
done
DUPES=$(echo "$ALL_SERVERS" | sort | uniq -d)
if [ -n "$DUPES" ]; then
    echo "⚠️ Duplicate MCP servers detected:" >&2
    echo "$DUPES" >&2
    echo "These may be auto-synced from claude.ai. Remove duplicates from ~/.claude/settings.json" >&2
fi
TOTAL=$(echo "$ALL_SERVERS" | grep -c .)
if [ "$TOTAL" -gt 5 ]; then
    echo "⚠️ $TOTAL MCP servers loaded — this may cause high memory usage" >&2
fi
exit 0

To proactively prevent OOM, add a memory monitor:

COUNTER="/tmp/cc-mcp-check"
COUNT=$(cat "$COUNTER" 2>/dev/null || echo 0)
COUNT=$((COUNT + 1))
echo "$COUNT" > "$COUNTER"
[ $((COUNT % 20)) -ne 0 ] && exit 0
FREE_MB=$(free -m 2>/dev/null | awk '/Mem:/ {print $7}')
if [ -n "$FREE_MB" ] && [ "$FREE_MB" -lt 1000 ]; then
    echo "🔴 LOW MEMORY: ${FREE_MB}MB free. Consider disabling unused MCP servers." >&2
fi
exit 0

Until there's an official opt-out for cloud-synced MCP servers, you can also remove them from the settings file on session start:

SETTINGS="$HOME/.claude/settings.json"
[ -f "$SETTINGS" ] || exit 0
jq '.mcpServers = (.mcpServers // {} | with_entries(select(.value.command != null or .value.url != null)))' "$SETTINGS" > "${SETTINGS}.tmp" && mv "${SETTINGS}.tmp" "$SETTINGS"
exit 0
cderv · 3 months ago

Adding a use case: I run Claude Code across multiple project directories, each with different needs. I want each project to act as a sandbox where I explicitly allowlist which MCP servers are available — opening access case by case.

But cloud connectors get injected into every project uniformly, with no per-project control.

A proper allowedMcpServers or disabledMcpServers setting at project scope (in .claude/settings.json) would solve this cleanly.

For now, using ENABLE_CLAUDEAI_MCP_SERVERS=false as a workaround.

happyclap · 3 months ago

adding on, having MCP's injected in from the desktop app into a claude code session is really annoying, and chews up so many tokens for no reason. I added gmail, calendar and slack because i wanted the desktop app todo stuff, that added 10K tokens to every session i opened in claude code, which i never used.

need a real fix for this.

anphex · 3 months ago

Endorsed. This eats away tokens like crazy. 60k tokens just for a "session init" per each new chat in claude code is insane.

yaisme · 2 months ago

+1 — adding a data point + a workaround that's a bit different from the SessionStart hook approach upthread.

Use case: two-tier default by path

  • Inside /home/me/WORKSPACE/** → only Linear + Mixpanel enabled (team workflow)
  • Everywhere else → all claude.ai MCPs off (context bloat + different trust boundary — cf. @sunir upthread)

What I tried

  1. disabledMcpServers: [...] in ~/.claude/settings.jsonschema validator rejects the field (not declared in settings schema)
  2. deniedMcpServers: [{serverName: "claude.ai Linear"}]regex ^[a-zA-Z0-9_-]+$ rejects dots/spaces so actual server names never match
  3. SessionStart hook writing ~/.claude.json → fires after MCP connect — too late for current session
  4. --strict-mcp-config --mcp-config <file> → doesn't affect claude.ai OAuth first-party servers
  5. ENABLE_CLAUDEAI_MCP_SERVERS=false → too nuclear (per @nick-youngblut — removes instead of deactivating, losing per-project granularity)

Workaround: wrapper function that pre-populates state BEFORE claude runs

clauded() {
  local cfg=$HOME/.claude.json cwd=$PWD list
  case "$cwd" in
    /home/me/WORKSPACE|/home/me/WORKSPACE/*)
      list='["claude.ai Canva","claude.ai Figma","claude.ai Gmail","claude.ai Google Calendar","claude.ai Google Drive","claude.ai Microsoft 365"]' ;;
    *)
      list='["claude.ai Canva","claude.ai Figma","claude.ai Gmail","claude.ai Google Calendar","claude.ai Google Drive","claude.ai Linear","claude.ai Microsoft 365","claude.ai Mixpanel"]' ;;
  esac
  if [ -f "$cfg" ] && command -v jq >/dev/null; then
    local t; t=$(mktemp)
    jq --arg p "$cwd" --argjson l "$list" \
       '.projects //= {} | .projects[$p] //= {} | .projects[$p].disabledMcpServers = $l' \
       "$cfg" > "$t" && mv "$t" "$cfg" || rm -f "$t"
  fi
  claude "$@"
}

Works — but I'm mutating Claude Code's internal state file from bash, which shouldn't be my job. Also likely subject to @mattheworiordan's observation that tengu_claudeai_mcp_connectors gets silently reset on re-auth.

API proposal

A unified policy field, applied before MCP connections initialize:

{
  "mcpPolicy": {
    "default": "disabled",
    "overrides": [
      {
        "pathPattern": "/home/me/WORKSPACE/**",
        "enabled": ["claude.ai Linear", "claude.ai Mixpanel"]
      }
    ]
  }
}

Properties wanted:

  • Works across all MCP sources uniformly (claude.ai OAuth, .mcp.json, plugin-provided) — not 5 overlapping fields
  • Cascades by path prefix (no per-subproject config needed)
  • Live /mcp changes still work but reset to policy on next session start
  • Separate from existing allowedMcpServers / deniedMcpServers / disabledMcpjsonServers — doesn't collide with the existing enterprise surfaces

Current field surface is (as far as I can tell) 5 overlapping layers with inconsistent semantics:

| Field | Applies to | Scope | Takes OAuth names? |
|---|---|---|---|
| enabledMcpjsonServers / disabledMcpjsonServers | .mcp.json sourced | user/project | No |
| allowedMcpServers / deniedMcpServers | Enterprise policy | managed | No (regex blocks ./ ) |
| disabledMcpServers | Runtime state | per-abs-path in ~/.claude.json | Yes (but not in settings schema) |
| pluginConfigs.*.mcpServers | Plugin-provided | plugin | N/A |
| ENABLE_CLAUDEAI_MCP_SERVERS env | All claude.ai | global on/off | N/A |

It'd be great if one unified mechanism could replace the ad-hoc state file dance.

Happy to help test if this gets picked up.

didiator · 2 months ago

I did create an additional - duplicate issue #57235. Sorry for that. I just closed it. But perhaps you'll find some additional information that help solving the problem!

didiator · 2 months ago

I can reproduce this issue on Claude Code v2.1.133 (Linux, Ubuntu 24.04) with a Claude Pro subscription and API key auth.
Findings:

Normal startup: System tools: 2.9M tokens (1454%) — context is full before any user input
With --bare flag: System tools: 1.4k tokens (0.7%) — completely normal

What I ruled out:

No MCP servers configured (claude mcp list returns empty)
No active VS Code Extension connection (IDE lock directory empty)
All plugins moved to backup directory — 2.9M tokens persist
No credentials.json (logged out) — 2.9M tokens persist with API key
Without any auth (no API key, no OAuth) — 721 tokens (normal)

Key observation: The 2.9M tokens appear whenever any authentication is active (API key or OAuth), regardless of whether MCP servers, plugins, or VS Code are running. The --bare flag is the only workaround that produces a clean context.
The ENABLE_CLAUDEAI_MCP_SERVERS=false flag from #50062 does not resolve the issue in v2.1.133.
Environment:

Claude Code version: 2.1.133
Platform: Ubuntu 24.04 LTS, linux-x64
Model: claude-sonnet-4-6
Auth: Claude Pro OAuth + API key (both tested separ

didiator · 2 months ago

Additional comment for Issue #20412:
After extensive debugging, I found that the root cause of the 2.9M token "System tools" bloat in my case is the sandbox block in .claude/settings.json.
Reproduction:

Start claude in any directory without a .claude/settings.json → System tools: ~13k tokens (normal)
Add a .claude/settings.json with "sandbox": { "enabled": true } → System tools: 2.9M tokens

Even a minimal sandbox config triggers the issue:
json{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true
}
}
What I ruled out:

Plugins (moved entire plugin directory to backup — 2.9M persists)
MCP servers (claude mcp list returns empty)
VS Code Extension (closed VS Code — 2.9M persists)
Project files (renamed .claude directory — drops to 13k)
credentials.json / OAuth login (API key only — same result)
ENABLE_CLAUDEAI_MCP_SERVERS=false flag — no effect

Workaround: Remove the sandbox block entirely from settings.json.
Environment:

Claude Code version: 2.1.133
Platform: Ubuntu 24.04 LTS, linux-x64
Model: claude-sonnet-4-6

notexpected · 2 months ago

TurboTax Connector suddenly started like an MCP today and attempted to prompt inject my subagent...

UNIXTCPIP · 1 month ago

any update? hello??

cardoso-neto · 1 month ago

export ENABLE_CLAUDEAI_MCP_SERVERS=false on your .bashrc or equivalent fixes this.

eytanhanig · 1 month ago

@cardoso-neto Unfortunately that disables everything, rather than just specific MCP servers.

localden collaborator · 24 days ago

Thank you all for the reports and workarounds here.

As of v2.1.182:

  • "disableClaudeAiConnectors": true in .claude/settings.json (project, user, or managed-policy level) opts out before any connection is attempted. A project-level false cannot override a user- or policy-level true.
  • deniedMcpServers accepts connector display names with spaces and dots (e.g., {"serverName": "claude.ai Slack"}) for per-connector denial. Match is exact and case-sensitive.

ENABLE_CLAUDEAI_MCP_SERVERS=0 and --safe-mode continue to work. Tool-search deferral is now on by default, so connector schemas aren't loaded into context until used.

The default is unchanged — connectors still load unless disabled. Closing as completed for the opt-out controls; please open a fresh issue for opt-in default, first-run consent, or per-project credentials.