Compare commits

...

1 Commits

Author SHA1 Message Date
Claude
cad2569360 Add mcp-context-warning plugin to warn about high MCP context usage
This plugin warns users when their MCP servers are consuming significant
context (>20k tokens). Many users don't realize MCP servers take up context
space, which can lead to unexpectedly fast context exhaustion.

The plugin:
- Runs a SessionStart hook to check MCP configurations
- Estimates token usage based on server and tool counts
- Shows a warning with server breakdown if estimated usage > 20k tokens
- Provides guidance on how to disable unused MCP servers

Slack thread: https://anthropic.slack.com/archives/C07VBSHV7EV/p1765989316572149
2025-12-17 16:44:01 +00:00
4 changed files with 201 additions and 0 deletions

View File

@@ -102,6 +102,17 @@
"source": "./plugins/learning-output-style",
"category": "learning"
},
{
"name": "mcp-context-warning",
"description": "Warns users when MCP servers are consuming significant context (>20k tokens), helping prevent unexpected context exhaustion",
"version": "1.0.0",
"author": {
"name": "Anthropic",
"email": "support@anthropic.com"
},
"source": "./plugins/mcp-context-warning",
"category": "productivity"
},
{
"name": "plugin-dev",
"description": "Comprehensive toolkit for developing Claude Code plugins. Includes 7 expert skills covering hooks, MCP integration, commands, agents, and best practices. AI-assisted plugin creation and validation.",

View File

@@ -0,0 +1,9 @@
{
"name": "mcp-context-warning",
"version": "1.0.0",
"description": "Warns users when MCP servers are consuming significant context (>20k tokens), helping prevent unexpected context exhaustion",
"author": {
"name": "Anthropic",
"email": "support@anthropic.com"
}
}

View File

@@ -0,0 +1,164 @@
#!/usr/bin/env python3
"""
MCP Context Warning Hook for Claude Code
This hook runs at session start and warns users when their MCP servers
are consuming significant context (>20k tokens). This helps users understand
why they might be burning through context quickly.
"""
import json
import os
import sys
from pathlib import Path
# Threshold in tokens for showing a warning
TOKEN_WARNING_THRESHOLD = 20000
# Estimated tokens per MCP tool (based on real-world data:
# Asana: ~836/tool, Gmail: ~833/tool, Google Calendar: ~1867/tool, Google Drive: ~1260/tool)
# Using 1000 as a conservative average
TOKENS_PER_TOOL_ESTIMATE = 1000
# Base overhead per MCP server (connection info, auth, etc.)
BASE_TOKENS_PER_SERVER = 500
def find_mcp_configs(cwd: str) -> list[tuple[str, dict]]:
"""
Find all MCP configuration files that might be loaded.
Returns list of (path, config) tuples.
"""
configs = []
# Check project-level .mcp.json
project_mcp = Path(cwd) / ".mcp.json"
if project_mcp.exists():
try:
with open(project_mcp) as f:
configs.append((str(project_mcp), json.load(f)))
except (json.JSONDecodeError, IOError):
pass
# Check user-level MCP config (~/.claude/.mcp.json)
user_mcp = Path.home() / ".claude" / ".mcp.json"
if user_mcp.exists():
try:
with open(user_mcp) as f:
configs.append((str(user_mcp), json.load(f)))
except (json.JSONDecodeError, IOError):
pass
return configs
def count_servers_and_estimate_tools(configs: list[tuple[str, dict]]) -> tuple[dict, int]:
"""
Count MCP servers and estimate their tool counts.
Returns (server_info dict, total_estimated_tokens).
"""
server_info = {}
for path, config in configs:
# MCP config format: {"mcpServers": {"server-name": {...}}}
mcp_servers = config.get("mcpServers", {})
for server_name, server_config in mcp_servers.items():
if server_name in server_info:
continue # Skip duplicates
# Try to get tool count from config if available
# Otherwise use a default estimate
tool_count = server_config.get("toolCount", 10) # Default 10 tools
server_info[server_name] = {
"source": path,
"estimated_tools": tool_count,
}
# Calculate total estimated tokens
total_tokens = 0
for server_name, info in server_info.items():
server_tokens = BASE_TOKENS_PER_SERVER + (info["estimated_tools"] * TOKENS_PER_TOOL_ESTIMATE)
info["estimated_tokens"] = server_tokens
total_tokens += server_tokens
return server_info, total_tokens
def format_warning_message(server_info: dict, total_tokens: int) -> str:
"""Format a warning message about MCP context usage."""
# Build server breakdown table
lines = [
f"Your MCP servers are using an estimated ~{total_tokens:,} tokens of context.",
"",
"Server breakdown:",
]
# Sort servers by token usage (highest first)
sorted_servers = sorted(
server_info.items(),
key=lambda x: x[1]["estimated_tokens"],
reverse=True
)
for server_name, info in sorted_servers:
tokens = info["estimated_tokens"]
tools = info["estimated_tools"]
lines.append(f" - {server_name}: ~{tokens:,} tokens ({tools} tools)")
lines.extend([
"",
"Consider disabling MCP servers you're not actively using to conserve context.",
"You can manage MCP servers with `/mcp disable <server-name>` or by editing .mcp.json.",
])
return "\n".join(lines)
def main():
"""Main hook function."""
# Read input from stdin
try:
raw_input = sys.stdin.read()
input_data = json.loads(raw_input) if raw_input.strip() else {}
except json.JSONDecodeError:
# If we can't parse input, exit silently
sys.exit(0)
# Get current working directory from hook input or environment
cwd = input_data.get("cwd", os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd()))
# Find MCP configurations
configs = find_mcp_configs(cwd)
if not configs:
# No MCP configs found, nothing to warn about
sys.exit(0)
# Count servers and estimate tokens
server_info, total_tokens = count_servers_and_estimate_tools(configs)
if not server_info:
# No servers configured
sys.exit(0)
# Check if we're over the warning threshold
if total_tokens >= TOKEN_WARNING_THRESHOLD:
warning_message = format_warning_message(server_info, total_tokens)
# Output JSON with systemMessage for Claude to see
output = {
"continue": True,
"systemMessage": warning_message
}
print(json.dumps(output))
sys.exit(0)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,17 @@
{
"description": "Warns users when MCP servers consume significant context (>20k tokens)",
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/check_mcp_context.py",
"timeout": 10
}
]
}
]
}
}